Преглед изворни кода

fix: 优化上货记录列宽 + 实现详情弹窗

- 列宽调整:原minWidth改固定width减少横向滚动
- 详情弹窗:显示记录信息+明细商品列表(商品/数量/补货前后库存)
- 后端getRecordDetail增加返回明细items
- 取消按钮status判断从row.status===0修正为===1

Co-Authored-By: Claude <noreply@anthropic.com>
skyline пре 6 часа
родитељ
комит
e96154190a

+ 57 - 1
haha-admin-web/src/views/inventory/records/index.vue

@@ -20,6 +20,12 @@ const {
   columns,
   dataList,
   pagination,
+  statusMap,
+  stockTypeMap,
+  detailVisible,
+  detailLoading,
+  detailRecord,
+  detailItems,
   onSearch,
   resetForm,
   handleCancel,
@@ -109,7 +115,7 @@ const {
               详情
             </el-button>
             <el-popconfirm
-              v-if="row.status === 0"
+              v-if="row.status === 1"
               title="是否确认取消该上货记录?"
               @confirm="handleCancel(row)"
             >
@@ -129,6 +135,42 @@ const {
         </pure-table>
       </template>
     </PureTableBar>
+
+    <!-- 详情弹窗 -->
+    <el-dialog
+      v-model="detailVisible"
+      title="上货记录详情"
+      width="680px"
+      destroy-on-close
+    >
+      <el-descriptions :column="2" border size="small" v-if="detailRecord">
+        <el-descriptions-item label="记录ID">{{ detailRecord.id }}</el-descriptions-item>
+        <el-descriptions-item label="状态">
+          <el-tag :type="(statusMap[detailRecord.status] || {}).type" size="small">
+            {{ (statusMap[detailRecord.status] || {}).text || '未知' }}
+          </el-tag>
+        </el-descriptions-item>
+        <el-descriptions-item label="设备ID">{{ detailRecord.deviceId }}</el-descriptions-item>
+        <el-descriptions-item label="设备名称">{{ detailRecord.deviceName || detailRecord.device_name || '-' }}</el-descriptions-item>
+        <el-descriptions-item label="上货类型">{{ stockTypeMap[detailRecord.stockType] || '未知' }}</el-descriptions-item>
+        <el-descriptions-item label="上货员">{{ detailRecord.stockerName }}</el-descriptions-item>
+        <el-descriptions-item label="电话">{{ detailRecord.stockerPhone || '-' }}</el-descriptions-item>
+        <el-descriptions-item label="创建时间">{{ detailRecord.createTime }}</el-descriptions-item>
+      </el-descriptions>
+
+      <div class="detail-items-title">明细列表</div>
+      <el-table :data="detailItems" v-loading="detailLoading" size="small" max-height="300">
+        <el-table-column prop="productName" label="商品" min-width="140" show-overflow-tooltip />
+        <el-table-column prop="quantity" label="数量" width="70" align="center" />
+        <el-table-column prop="beforeStock" label="补货前" width="80" align="center">
+          <template #default="{ row }">{{ row.beforeStock != null ? row.beforeStock : '-' }}</template>
+        </el-table-column>
+        <el-table-column prop="afterStock" label="补货后" width="80" align="center">
+          <template #default="{ row }">{{ row.afterStock != null ? row.afterStock : '-' }}</template>
+        </el-table-column>
+      </el-table>
+      <div class="detail-empty" v-if="!detailLoading && detailItems.length === 0">暂无明细</div>
+    </el-dialog>
   </div>
 </template>
 
@@ -142,4 +184,18 @@ const {
     margin-bottom: 12px;
   }
 }
+
+.detail-items-title {
+  font-size: 14px;
+  font-weight: 600;
+  color: var(--el-text-color-primary);
+  margin: 20px 0 12px;
+}
+
+.detail-empty {
+  text-align: center;
+  padding: 24px 0;
+  font-size: 13px;
+  color: var(--el-text-color-secondary);
+}
 </style>

+ 45 - 24
haha-admin-web/src/views/inventory/records/utils/hook.tsx

@@ -3,7 +3,7 @@ import { message } from "@/utils/message";
 import { getStockRecords, getStockRecordDetail, cancelStockRecord } from "@/api/inventory";
 import type { PaginationProps } from "@pureadmin/table";
 import type { SearchFormProps } from "./types";
-import { onMounted, reactive, ref, toRaw } from "vue";
+import { onMounted, reactive, ref } from "vue";
 
 export function useStockRecords() {
   const form = reactive<SearchFormProps>({
@@ -19,6 +19,10 @@ export function useStockRecords() {
     currentPage: 1,
     background: true
   });
+  const detailVisible = ref(false);
+  const detailLoading = ref(false);
+  const detailRecord = ref<any>({});
+  const detailItems = ref<any[]>([]);
 
   const statusMap = {
     1: { text: "进行中", type: "primary" },
@@ -41,66 +45,66 @@ export function useStockRecords() {
     {
       label: "设备ID",
       prop: "deviceId",
-      minWidth: 120
+      width: 120
     },
     {
       label: "设备名称",
       prop: "deviceName",
-      minWidth: 120
+      minWidth: 130
     },
     {
       label: "上货类型",
       prop: "stockType",
-      minWidth: 100,
+      width: 90,
       formatter: ({ stockType }) => stockTypeMap[stockType] || "未知"
     },
     {
       label: "上货员",
       prop: "stockerName",
-      minWidth: 100
+      width: 90
     },
     {
-      label: "上货员电话",
+      label: "电话",
       prop: "stockerPhone",
-      minWidth: 120
+      width: 120
     },
     {
-      label: "商品种类",
+      label: "种类",
       prop: "totalItems",
-      minWidth: 90
+      width: 60
     },
     {
-      label: "数量",
+      label: "数量",
       prop: "totalQuantity",
-      minWidth: 90
+      width: 60
     },
     {
       label: "状态",
       prop: "status",
-      minWidth: 100,
+      width: 80,
       cellRenderer: ({ row }) => {
         const item = statusMap[row.status] || { text: "未知", type: "info" };
-        return <el-tag type={item.type}>{item.text}</el-tag>;
+        return <el-tag type={item.type} size="small">{item.text}</el-tag>;
       }
     },
     {
       label: "创建时间",
       prop: "createTime",
-      minWidth: 160,
+      width: 160,
       formatter: ({ createTime }) =>
         createTime ? dayjs(createTime).format("YYYY-MM-DD HH:mm:ss") : ""
     },
     {
       label: "完成时间",
-      prop: "completeTime",
-      minWidth: 160,
-      formatter: ({ completeTime }) =>
-        completeTime ? dayjs(completeTime).format("YYYY-MM-DD HH:mm:ss") : "-"
+      prop: "endTime",
+      width: 160,
+      formatter: ({ endTime }) =>
+        endTime ? dayjs(endTime).format("YYYY-MM-DD HH:mm:ss") : "-"
     },
     {
       label: "操作",
       fixed: "right",
-      width: 150,
+      width: 120,
       slot: "operation"
     }
   ];
@@ -112,12 +116,11 @@ export function useStockRecords() {
         page: pagination.currentPage,
         pageSize: pagination.pageSize
       };
-      
-      // 只添加非空的搜索条件
+
       if (form.deviceId) searchParams.deviceId = form.deviceId;
       if (form.stockerId !== undefined) searchParams.stockerId = form.stockerId;
       if (form.status !== undefined) searchParams.status = form.status;
-      
+
       const { data } = await getStockRecords(searchParams);
       if (data) {
         dataList.value = data.list || [];
@@ -144,8 +147,21 @@ export function useStockRecords() {
   }
 
   async function handleViewDetail(row) {
-    const { data } = await getStockRecordDetail(row.id);
-    console.log("详情:", data);
+    detailVisible.value = true;
+    detailLoading.value = true;
+    detailRecord.value = row;
+    detailItems.value = [];
+    try {
+      const { data } = await getStockRecordDetail(row.id);
+      if (data) {
+        detailRecord.value = data;
+        detailItems.value = data.items || [];
+      }
+    } catch {
+      message("加载详情失败", { type: "error" });
+    } finally {
+      detailLoading.value = false;
+    }
   }
 
   function handleSizeChange(val: number) {
@@ -169,6 +185,11 @@ export function useStockRecords() {
     dataList,
     pagination,
     statusMap,
+    stockTypeMap,
+    detailVisible,
+    detailLoading,
+    detailRecord,
+    detailItems,
     onSearch,
     resetForm,
     handleCancel,

+ 6 - 0
haha-admin/src/main/java/com/haha/admin/controller/InventoryController.java

@@ -11,7 +11,9 @@ import com.haha.common.vo.Result;
 import com.haha.entity.DeviceInventory;
 import com.haha.entity.InventoryLog;
 import com.haha.entity.StockRecord;
+import com.haha.entity.StockRecordItem;
 import com.haha.entity.dto.*;
+import com.haha.mapper.StockRecordItemMapper;
 import com.haha.service.AdminService;
 import com.haha.service.DeviceInventoryService;
 import com.haha.service.InventoryLogService;
@@ -40,6 +42,8 @@ public class InventoryController {
 
     private final StockRecordService stockRecordService;
 
+    private final StockRecordItemMapper stockRecordItemMapper;
+
     private final AdminService adminService;
 
     // ==================== 库存查询 ====================
@@ -189,6 +193,8 @@ public class InventoryController {
     @GetMapping("/records/{id}")
     public Result<Map<String, Object>> getRecordDetail(@PathVariable Long id) {
         Map<String, Object> detail = stockRecordService.getDetailWithDeviceName(id);
+        List<StockRecordItem> items = stockRecordItemMapper.selectByRecordId(id);
+        detail.put("items", items != null ? items : java.util.Collections.emptyList());
         return Result.success(detail);
     }
 

+ 10 - 0
haha-mapper/src/main/java/com/haha/mapper/StockRecordItemMapper.java

@@ -3,10 +3,20 @@ package com.haha.mapper;
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.haha.entity.StockRecordItem;
 import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+import org.apache.ibatis.annotations.Select;
+
+import java.util.List;
 
 /**
  * 上货记录明细Mapper
  */
 @Mapper
 public interface StockRecordItemMapper extends BaseMapper<StockRecordItem> {
+
+    /**
+     * 根据上货记录ID查询明细列表
+     */
+    @Select("SELECT * FROM t_stock_record_item WHERE record_id = #{recordId} ORDER BY id")
+    List<StockRecordItem> selectByRecordId(@Param("recordId") Long recordId);
 }