From 8f8dcdae7e40ba4e94a363aa8eb91c7665810bc3 Mon Sep 17 00:00:00 2001
From: gaoluyang <2820782392@qq.com>
Date: 星期一, 31 八月 2026 15:29:17 +0800
Subject: [PATCH] fix: 新疆-绿能 1.报工自动生成产品入库单 + 勾选入库 + 不合格仓库兜底

---
 src/views/wls/productreceipt/modules/line-list.vue |  104 ++++++++++++++++++++++++++++++++++++++++++++++++++--
 1 files changed, 100 insertions(+), 4 deletions(-)

diff --git a/src/views/wls/productreceipt/modules/line-list.vue b/src/views/wls/productreceipt/modules/line-list.vue
index 26442fb..a68891c 100644
--- a/src/views/wls/productreceipt/modules/line-list.vue
+++ b/src/views/wls/productreceipt/modules/line-list.vue
@@ -2,6 +2,7 @@
 import type { FormType } from '../data';
 
 import type { VxeTableGridOptions } from '#/adapter/vxe-table';
+import type { MesWmProductReceiptApi } from '#/api/mes/wm/productreceipt';
 import type { MesWmProductReceiptDetailApi } from '#/api/mes/wm/productreceipt/detail';
 import type { MesWmProductReceiptLineApi } from '#/api/mes/wm/productreceipt/line';
 
@@ -10,9 +11,10 @@
 import { useVbenModal } from '@vben/common-ui';
 import { BarcodeBizTypeEnum } from '@vben/constants';
 
-import { message } from 'ant-design-vue';
+import { Button, Checkbox, message } from 'ant-design-vue';
 
 import { ACTION_ICON, TableAction, useVbenVxeGrid } from '#/adapter/vxe-table';
+import { submitProductReceiptStock } from '#/api/mes/wm/productreceipt';
 import { getProductReceiptDetailListByLineId } from '#/api/mes/wm/productreceipt/detail';
 import {
   deleteProductReceiptLine,
@@ -29,16 +31,22 @@
 const props = defineProps<{
   formType: FormType;
   receiptId: number;
+  autoGenerated?: boolean; // 鏄惁鐢辨姤宸ヨ嚜鍔ㄧ敓鎴愶紙鑷姩鐢熸垚鐨勮涓嶅彲鎵嬪伐澧炲垹鏀癸級
 }>();
 
 const isEditable = computed(() =>
   // 鏄惁鍙紪杈戞槑缁嗚
   ['create', 'update'].includes(props.formType),
 );
+const canEditLine = computed(
+  // 鑷姩鐢熸垚鐨勫叆搴撳崟琛屼笉鍙墜宸ュ鍒犳敼
+  () => isEditable.value && !props.autoGenerated,
+);
 const isStock = computed(() => props.formType === 'stock'); // 鏄惁涓轰笂鏋舵ā寮�
 const detailMap = reactive<
   Record<number, MesWmProductReceiptDetailApi.ProductReceiptDetail[]>
 >({}); // 宸插睍寮�琛岀殑涓婃灦鏄庣粏缂撳瓨
+const checkedMap = reactive<Record<number, boolean>>({}); // 琛屾槸鍚﹀叆搴撳嬀閫夌姸鎬佺紦瀛�
 const barcodeDetailRef = ref(); // 鏉$爜璇︽儏寮圭獥瀹炰緥
 
 const [LineFormModal, lineFormModalApi] = useVbenModal({
@@ -55,6 +63,9 @@
 function handleRefresh() {
   for (const id of Object.keys(detailMap)) {
     delete detailMap[Number(id)];
+  }
+  for (const id of Object.keys(checkedMap)) {
+    delete checkedMap[Number(id)];
   }
   gridApi.query();
 }
@@ -99,6 +110,80 @@
     row.itemCode,
     row.itemName,
   );
+}
+
+/** 琛屾槸鍚﹀叆搴撳嬀閫夌姸鎬侊紙鏈墜鍔ㄥ嬀閫夋椂鍥為��鍒拌鑷甫鍊硷級 */
+function isLineStock(row: MesWmProductReceiptLineApi.ProductReceiptLine) {
+  return checkedMap[row.id!] ?? row.isStock ?? false;
+}
+
+/** 鍒囨崲琛屾槸鍚﹀叆搴� */
+function setLineStock(
+  row: MesWmProductReceiptLineApi.ProductReceiptLine,
+  checked: boolean,
+) {
+  checkedMap[row.id!] = checked;
+}
+
+/** 淇濆瓨涓婃灦鍒嗛厤锛氭敹闆嗘墍鏈夎鐨勫嬀閫夌姸鎬佷笌浠撳簱/搴撳尯/搴撲綅鍒嗛厤锛岃皟鐢ㄦ壒閲忎笂鏋舵帴鍙� */
+async function handleSaveStock() {
+  if (!props.receiptId) {
+    return;
+  }
+  const hideLoading = message.loading({
+    content: '姝e湪淇濆瓨涓婃灦鍒嗛厤...',
+    duration: 0,
+  });
+  try {
+    const { list } = await getProductReceiptLinePage({
+      pageNo: 1,
+      pageSize: 10000,
+      receiptId: props.receiptId,
+    });
+    const rows: MesWmProductReceiptApi.StockRow[] = [];
+    for (const line of list) {
+      const isStock = isLineStock(line);
+      const row: MesWmProductReceiptApi.StockRow = {
+        lineId: line.id!,
+        isStock,
+      };
+      if (isStock) {
+        let details = detailMap[line.id!];
+        if (!details) {
+          details = await getProductReceiptDetailListByLineId(line.id!);
+          detailMap[line.id!] = details;
+        }
+        // 鍕鹃�夊叆搴撶殑琛屽繀椤诲凡鏈変笂鏋舵槑缁嗭紝涓旀槑缁嗘暟閲忎箣鍜岀瓑浜庤鏀惰揣鏁伴噺
+        if (!details.length) {
+          message.error(`鐗╂枡銆�${line.itemName}銆嶅凡鍕鹃�夊叆搴擄紝璇峰厛娣诲姞涓婃灦鏄庣粏`);
+          return;
+        }
+        const lineQty = Number(line.quantity ?? 0);
+        const sumQty = details.reduce(
+          (acc, detail) => acc + Number(detail.quantity ?? 0),
+          0,
+        );
+        if (lineQty !== sumQty) {
+          message.error(
+            `鐗╂枡銆�${line.itemName}銆嶄笂鏋舵槑缁嗘暟閲忎箣鍜岋紙${sumQty}锛変笌鏀惰揣鏁伴噺锛�${lineQty}锛変笉涓�鑷碻,
+          );
+          return;
+        }
+        row.details = details.map((detail) => ({
+          warehouseId: detail.warehouseId!,
+          locationId: detail.locationId!,
+          areaId: detail.areaId!,
+          quantity: detail.quantity!,
+        }));
+      }
+      rows.push(row);
+    }
+    await submitProductReceiptStock({ receiptId: props.receiptId, rows });
+    message.success('涓婃灦鍒嗛厤淇濆瓨鎴愬姛');
+    handleRefresh();
+  } finally {
+    hideLoading();
+  }
 }
 
 /** 鎵撳紑涓婃灦鏄庣粏琛ㄥ崟 */
@@ -185,7 +270,7 @@
     <LineFormModal @success="handleRefresh" />
     <DetailFormModal @success="handleDetailSuccess" />
     <Grid table-title="鐗╂枡淇℃伅">
-      <template v-if="isEditable" #toolbar-tools>
+      <template v-if="canEditLine" #toolbar-tools>
         <TableAction
           :actions="[
             {
@@ -197,6 +282,9 @@
           ]"
         />
       </template>
+      <template v-if="isStock" #toolbar-tools>
+        <Button type="primary" @click="handleSaveStock">淇濆瓨涓婃灦鍒嗛厤</Button>
+      </template>
       <template #detail="{ row }">
         <DetailList
           :details="getExpandedDetails(row)"
@@ -204,6 +292,14 @@
           @edit="(detailId) => openDetailForm(row.id!, row.itemId, detailId)"
           @refresh="loadLineDetails(row.id!)"
         />
+      </template>
+      <template #isStock="{ row }">
+        <div class="flex justify-center">
+          <Checkbox
+            :checked="isLineStock(row)"
+            @update:checked="(checked: boolean) => setLineStock(row, checked)"
+          />
+        </div>
       </template>
       <template #actions="{ row }">
         <div class="flex items-center justify-center">
@@ -213,7 +309,7 @@
                 label: $t('common.edit'),
                 type: 'link',
                 icon: ACTION_ICON.EDIT,
-                ifShow: isEditable,
+                ifShow: canEditLine,
                 onClick: handleEdit.bind(null, row),
               },
               {
@@ -221,7 +317,7 @@
                 type: 'link',
                 danger: true,
                 icon: ACTION_ICON.DELETE,
-                ifShow: isEditable,
+                ifShow: canEditLine,
                 popConfirm: {
                   title: $t('ui.actionMessage.deleteConfirm', [row.itemName]),
                   confirm: handleDelete.bind(null, row),

--
Gitblit v1.9.3