From ea7fb9cc590a198d438d44a2aec7b0393194a07d Mon Sep 17 00:00:00 2001
From: gaoluyang <2820782392@qq.com>
Date: 星期一, 21 九月 2026 20:52:43 +0800
Subject: [PATCH] 新疆-融邦环保 1.新增到货记录模块:销售台账页入口,车辆随出库单联动,到货上限=该台账分摊量,附件走永久链接

---
 src/views/salesManagement/deliveryLedger/index.vue                 |  124 ++++++-------------------------
 src/views/salesManagement/salesLedger/components/ArrivalDialog.vue |   66 ++++++++++++----
 2 files changed, 72 insertions(+), 118 deletions(-)

diff --git a/src/views/salesManagement/deliveryLedger/index.vue b/src/views/salesManagement/deliveryLedger/index.vue
index c238f77..83a49e5 100644
--- a/src/views/salesManagement/deliveryLedger/index.vue
+++ b/src/views/salesManagement/deliveryLedger/index.vue
@@ -45,18 +45,13 @@
           <el-button type="danger" plain @click="handleDelete">鍒犻櫎</el-button>
         </div>
       </div>
-      <!-- 娌瑰搧鍑哄簱鐖惰鐨� children 鏄埌璐ц褰曪紝闈� row-key + children 娓叉煋鎴愬瓙琛� -->
+      <!-- 鍒拌揣璁板綍涓嶅湪鍒楄〃閲屽睍寮�锛屽彧鍦ㄨ鎯呭脊妗嗗睍绀� -->
       <el-table
         :data="tableData"
         border
         v-loading="tableLoading"
         @selection-change="handleSelectionChange"
-        :row-key="
-          (row) =>
-            row.source
-              ? `${row.source}-${row.stockOutRecordId ?? row.id}`
-              : `arrival-${row.id}`
-        "
+        :row-key="deliveryRowKey"
         style="width: 100%"
         height="calc(100vh - 21.5em)"
       >
@@ -171,18 +166,6 @@
           show-overflow-tooltip
         />
         <el-table-column
-          label="瀹℃牳鐘舵��"
-          prop="status"
-          align="center"
-          width="100"
-        >
-          <template #default="scope">
-            <el-tag :type="getApprovalStatusType(scope.row.status)">
-              {{ getApprovalStatusText(scope.row.status) }}
-            </el-tag>
-          </template>
-        </el-table-column>
-        <el-table-column
           label="鍑哄簱鍗曞彿"
           prop="outboundBatches"
           show-overflow-tooltip
@@ -197,7 +180,6 @@
             <!--                @click="openForm('edit', scope.row)">鍙戣揣-->
             <!--            </el-button>-->
             <el-button
-              v-if="!isArrivalRow(scope.row)"
               link
               type="primary"
               style="color: #67c23a"
@@ -317,9 +299,6 @@
           <el-descriptions-item label="鍙戣揣鏃ユ湡">{{
             detailRow.shippingDate || "--"
           }}</el-descriptions-item>
-          <el-descriptions-item label="瀹℃牳鐘舵��">{{
-            getApprovalStatusText(detailRow.status)
-          }}</el-descriptions-item>
           <el-descriptions-item label="鍙戣揣杞︾墝鍙�">{{
             detailRow.shippingCarNumber || "--"
           }}</el-descriptions-item>
@@ -431,8 +410,10 @@
 const detailDialogVisible = ref(false);
 const detailRow = ref(null);
 const detailProductList = ref([]);
-// 娌瑰搧鍑哄簱鐖惰鐨勫埌璐ц褰曪紙瀛愯锛�
+// 娌瑰搧鍑哄簱鐖惰鐨勫埌璐ц褰曪細鍒楄〃涓嶅睍寮�锛屽彧鍦ㄨ鎯呭脊妗嗛噷灞曠ず
 const detailArrivalList = ref([]);
+// 鐖惰 row-key -> 璇ヨ鐨勫埌璐ц褰曪紝鍒楄〃鎺ュ彛鐨� children 鎽樹笅鏉ユ斁杩欓噷
+const arrivalMap = new Map();
 
 // 鍒拌揣闄勪欢鍚庣瀛� JSON 瀛楃涓诧紝鍑哄弬鍙兘鏄暟缁勪篃鍙兘鏄覆
 const toAttachmentList = (value) => {
@@ -462,7 +443,7 @@
 const data = reactive({
   searchForm: {
     shippingNo: "", // 鍙戣揣鍗曞彿锛堜袱绫绘潵婧愰兘鍖归厤锛�
-    salesContractNo: "", // 閿�鍞悎鍚屽彿锛堝彧鍖归厤鍙戣揣鍗曡锛�
+    salesContractNo: "", // 閿�鍞悎鍚屽彿锛堝鍙拌处鍑哄簱鍛戒腑浠讳竴鍚堝悓鍙峰嵆杩斿洖璇ヨ锛�
     shippingCarNumber: "", // 杞︾墝鍙�
   },
   form: {
@@ -505,7 +486,17 @@
   deliveryLedgerListPage({ ...searchForm.value, ...page })
     .then((res) => {
       tableLoading.value = false;
-      tableData.value = res.data.records || [];
+      const records = res.data.records || [];
+      // 鍒拌揣璁板綍涓嶅仛灞傜骇灞曞紑锛坋l-table 瑙佸埌 children 灏变細娓叉煋鎴愬瓙琛岋級锛�
+      // 浣嗚鎯呭脊妗嗚繕瑕佸睍绀猴紝鍏堟寜鐖惰鎽樺嚭鏉ュ瓨鐫�
+      arrivalMap.clear();
+      records.forEach((row) => {
+        if (Array.isArray(row.children) && row.children.length) {
+          arrivalMap.set(deliveryRowKey(row), row.children);
+        }
+        delete row.children;
+      });
+      tableData.value = records;
       total.value = res.data.total || 0;
     })
     .catch(() => {
@@ -516,17 +507,12 @@
 // 娌瑰搧鍑哄簱琛屾潵鑷� stock_out_record锛宨d 涓� shipping_info 浼氭挒鍙凤紝
 // 鍙戣揣/鍒犻櫎/璇︽儏绛夋帴鍙h儗鍚庨兘鏄� shipping_info锛屼笉鑳界敤浜庤繖绫昏
 const isOilOutRow = (row) => row?.source === "oilOut";
-// 灞傜骇灞曠ず鏃跺埌璐ц褰曟寕鍦ㄧ埗琛岀殑 children 涓婏紝瀛愯娌℃湁 source
-const isArrivalRow = (row) => !row?.source;
-const sourceLabel = (row) => {
-  if (isArrivalRow(row)) return "鍒拌揣";
-  return isOilOutRow(row) ? "娌瑰搧鍑哄簱" : "鍙戣揣鍗�";
-};
-const sourceTagType = (row) => {
-  if (isArrivalRow(row)) return "warning";
-  return isOilOutRow(row) ? "success" : "info";
-};
-const isRowSelectable = (row) => !isOilOutRow(row) && !isArrivalRow(row);
+// 涓や釜鏉ユ簮鐨� id 涓嶅悓鍩燂紝row-key 蹇呴』甯︿笂鏉ユ簮锛涘埌璐ц褰曡鑳芥寜鐖惰鍙嶆煡鍥炴潵
+const deliveryRowKey = (row) =>
+  `${row?.source ?? "shipping"}-${row?.stockOutRecordId ?? row?.id}`;
+const sourceLabel = (row) => (isOilOutRow(row) ? "娌瑰搧鍑哄簱" : "鍙戣揣鍗�");
+const sourceTagType = (row) => (isOilOutRow(row) ? "success" : "info");
+const isRowSelectable = (row) => !isOilOutRow(row);
 
 // 琛ㄦ牸閫夋嫨鏁版嵁
 const handleSelectionChange = (selection) => {
@@ -560,7 +546,7 @@
 const openDetail = async (row) => {
   detailRow.value = row || null;
   detailProductList.value = [];
-  detailArrivalList.value = Array.isArray(row?.children) ? row.children : [];
+  detailArrivalList.value = arrivalMap.get(deliveryRowKey(row)) || [];
   detailDialogVisible.value = true;
   // 娌瑰搧鍑哄簱琛屼笉璧板彂璐у崟璇︽儏鎺ュ彛锛坕d 浼氭挒鍙凤級锛岀洿鎺ョ敤鍒楄〃琛屾暟鎹睍绀�
   if (!row?.id || isOilOutRow(row)) return;
@@ -819,68 +805,6 @@
     }
   }
 }
-
-// 鑾峰彇瀹℃牳鐘舵�佹枃鏈�
-const getApprovalStatusText = (status) => {
-  if (status === null || status === undefined || status === "") {
-    return "寰呭鏍�";
-  }
-  // 濡傛灉鏄暟瀛�
-  if (typeof status === "number") {
-    const statusMap = {
-      0: "寰呭鏍�",
-      1: "瀹℃牳涓�",
-      2: "瀹℃牳鎷掔粷",
-      3: "瀹℃牳閫氳繃",
-    };
-    return statusMap[status] || "寰呭鏍�";
-  }
-  // 濡傛灉鏄瓧绗︿覆锛岀洿鎺ヨ繑鍥炴垨鏄犲皠
-  const statusStr = String(status).trim();
-  const statusTextMap = {
-    寰呭鏍�: "寰呭鏍�",
-    瀹℃牳涓�: "瀹℃牳涓�",
-    瀹℃牳鎷掔粷: "瀹℃牳鎷掔粷",
-    瀹℃牳閫氳繃: "瀹℃牳閫氳繃",
-    宸插彂璐�: "宸插彂璐�",
-    0: "寰呭鏍�",
-    1: "瀹℃牳涓�",
-    2: "瀹℃牳鎷掔粷",
-    3: "瀹℃牳閫氳繃",
-  };
-  return statusTextMap[statusStr] || statusStr || "寰呭鏍�";
-};
-
-// 鑾峰彇瀹℃牳鐘舵�佹爣绛剧被鍨嬶紙棰滆壊锛�
-const getApprovalStatusType = (status) => {
-  if (status === null || status === undefined || status === "") {
-    return "info";
-  }
-  // 濡傛灉鏄暟瀛�
-  if (typeof status === "number") {
-    const typeMap = {
-      0: "info", // 寰呭鏍� - 鐏拌壊
-      1: "warning", // 瀹℃牳涓� - 榛勮壊
-      2: "danger", // 瀹℃牳鎷掔粷 - 绾㈣壊
-      3: "success", // 瀹℃牳閫氳繃 - 缁胯壊
-    };
-    return typeMap[status] || "info";
-  }
-  // 濡傛灉鏄瓧绗︿覆
-  const statusStr = String(status).trim();
-  const typeTextMap = {
-    寰呭鏍�: "info",
-    瀹℃牳涓�: "warning",
-    瀹℃牳鎷掔粷: "danger",
-    瀹℃牳閫氳繃: "success",
-    宸插彂璐�: "success",
-    0: "info",
-    1: "warning",
-    2: "danger",
-    3: "success",
-  };
-  return typeTextMap[statusStr] || "info";
-};
 
 // 妫�鏌ュ鏍哥姸鎬佹槸鍚︿负"瀹℃牳閫氳繃"
 const isApproved = (status) => {
diff --git a/src/views/salesManagement/salesLedger/components/ArrivalDialog.vue b/src/views/salesManagement/salesLedger/components/ArrivalDialog.vue
index 1ab76ed..70b0662 100644
--- a/src/views/salesManagement/salesLedger/components/ArrivalDialog.vue
+++ b/src/views/salesManagement/salesLedger/components/ArrivalDialog.vue
@@ -24,9 +24,13 @@
                        min-width="150"
                        show-overflow-tooltip />
       <el-table-column label="杞︾墝鍙�"
-                       prop="truckPlateNo"
                        min-width="110"
-                       show-overflow-tooltip />
+                       show-overflow-tooltip>
+        <!-- 鍑哄簱鍗曟病鐧昏杞﹁締鏃跺埌璐ц褰曡溅杈嗕负绌猴紝涓嶈兘娓叉煋鎴愮┖鐧芥牸 -->
+        <template #default="scope">
+          {{ scope.row.truckPlateNo || "--" }}
+        </template>
+      </el-table-column>
       <el-table-column label="鍒拌揣鏁伴噺(鍚�)"
                        prop="arrivalQuantity"
                        min-width="110"
@@ -112,20 +116,14 @@
             </el-form-item>
           </el-col>
           <el-col :span="12">
+            <!-- 杞﹁締涓嶅己鍒讹細鍑哄簱鍗曟病鐧昏杞﹁締锛堜唬鍌�/瀹㈠瓨鍑哄簱锛夋椂鐣欑┖鍗冲彲 -->
             <el-form-item label="杞﹁締"
-                          prop="vehicleId"
-                          :rules="[
-                {
-                required: true,
-                message: '璇烽�夋嫨杞﹁締',
-                trigger: 'change',
-              }
-              ]">
+                          prop="vehicleId">
               <el-select v-model="form.vehicleId"
-                         placeholder="璇峰厛閫夋嫨鍑哄簱鍗�"
+                         :placeholder="vehiclePlaceholder"
                          clearable
                          filterable
-                         :disabled="!form.stockOutRecordId"
+                         :disabled="!form.stockOutRecordId || !vehicleOptions.length"
                          style="width: 100%"
                          @change="handleVehicleChange">
                 <el-option v-for="item in vehicleOptions"
@@ -142,8 +140,7 @@
                           prop="arrivalQuantity"
                           :rules="[
                 {
-                required: true,
-                message: '璇疯緭鍏ュ埌璐ф暟閲�',
+                validator: validateArrivalQuantity,
                 trigger: 'blur',
               }
               ]">
@@ -286,11 +283,22 @@
     return [...map.values()];
   });
 
+  // 娌$櫥璁拌溅杈嗙殑鍑哄簱鍗曪紙浠e偍/瀹㈠瓨涓嶅己鍒堕�夎溅锛夋嬁涓嶅嚭杞﹁締鍊欓�夛紝涓嶈褰撴垚涓�涓┖閫夐」
   const vehicleOptions = computed(() =>
     bindableRows.value.filter(
-      item => item.stockOutRecordId === form.value.stockOutRecordId
+      item =>
+        item.stockOutRecordId === form.value.stockOutRecordId &&
+        item.vehicleId !== null &&
+        item.vehicleId !== undefined
     )
   );
+
+  const vehiclePlaceholder = computed(() => {
+    if (!form.value.stockOutRecordId) return "璇峰厛閫夋嫨鍑哄簱鍗�";
+    return vehicleOptions.value.length
+      ? "璇烽�夋嫨杞﹁締"
+      : "璇ュ嚭搴撳崟鏈櫥璁拌溅杈嗭紝鍙暀绌�";
+  });
 
   const selectedOutbound = computed(() =>
     outboundOptions.value.find(
@@ -305,6 +313,19 @@
 
   // 缂栬緫鏃舵湰鏉″凡鍗犵殑閲忚浠庛�屽凡鍒拌揣銆嶉噷鍔犲洖鏉ワ紝鍚﹀垯鏁伴噺鏀逛笉澶т簬鍘熷��
   const originalArrivalQuantity = ref(0);
+
+  // 0 鍦� required 鐪奸噷绠椼�屽凡濉�嶏紝鎷︿笉浣忥紝杩欓噷鎸夊悗绔彛寰勮姹� > 0
+  const validateArrivalQuantity = (rule, value, callback) => {
+    if (value === null || value === undefined || value === "") {
+      callback(new Error("璇疯緭鍏ュ埌璐ф暟閲�"));
+      return;
+    }
+    if (!(Number(value) > 0)) {
+      callback(new Error("鍒拌揣鏁伴噺蹇呴』澶т簬0"));
+      return;
+    }
+    callback();
+  };
 
   // 鍒拌揣涓婇檺 = 璇ュ彴璐﹀湪杩欏紶鍑哄簱鍗曚笂鍒嗘憡鍒扮殑鏁伴噺
   const arrivalMax = computed(() => {
@@ -395,7 +416,7 @@
         form.value.id = row.id ?? null;
         form.value.stockOutRecordId = row.stockOutRecordId;
         // 杞﹁締/杞︾墝浠ュ嚭搴撳崟鐧昏涓哄噯锛屼絾鍒楄〃琛岄噷甯﹀洖鐨勬槸褰撴椂鐨勫�硷紝鐩存帴鍥炴樉
-        form.value.vehicleId = row.vehicleId;
+        form.value.vehicleId = row.vehicleId ?? undefined;
         form.value.truckPlateNo = row.truckPlateNo || "";
         form.value.arrivalQuantity = row.arrivalQuantity ?? null;
         form.value.arrivalDate = row.arrivalDate || "";
@@ -413,6 +434,12 @@
     // 杞﹁締闅忓嚭搴撳崟鑱斿姩锛氭崲浜嗗嚭搴撳崟锛屽師鏉ラ�夌殑杞﹁締鍙兘涓嶅湪鍊欓�夐噷
     form.value.vehicleId = undefined;
     form.value.truckPlateNo = "";
+    // 涓�寮犲嚭搴撳崟鍙櫥璁颁竴涓溅杈嗭紝鑳藉畾灏辩洿鎺ュ甫鍑烘潵锛堜唬鍌�/瀹㈠瓨娌$櫥璁拌溅杈嗗垯鐣欑┖锛�
+    const only = vehicleOptions.value[0];
+    if (vehicleOptions.value.length === 1) {
+      form.value.vehicleId = only.vehicleId;
+      form.value.truckPlateNo = only.truckPlateNo || "";
+    }
   };
 
   const handleVehicleChange = id => {
@@ -433,14 +460,17 @@
       const payload = {
         stockOutRecordId: form.value.stockOutRecordId,
         salesLedgerId: props.ledgerId,
-        vehicleId: form.value.vehicleId,
-        truckPlateNo: form.value.truckPlateNo,
         arrivalQuantity: form.value.arrivalQuantity,
         arrivalDate: form.value.arrivalDate,
         // 鍙瓨姘镐箙閾炬帴锛�2 灏忔椂澶辨晥鐨勭鍚� URL 杩囨湡鍚庨檮浠朵細鎵撲笉寮�
         attachments: form.value.attachmentList.map(getPhotoUrl).filter(Boolean),
         remark: form.value.remark,
       };
+      // 杞﹁締/杞︾墝浠ュ嚭搴撳崟涓哄噯锛屽彧鏈夐�変簡杞︽墠浼狅紝绌哄�间笉鍙備笌鍚庣鐨勬瘮瀵�
+      if (form.value.vehicleId !== undefined && form.value.vehicleId !== null) {
+        payload.vehicleId = form.value.vehicleId;
+        payload.truckPlateNo = form.value.truckPlateNo;
+      }
       const submit = form.value.id
         ? updateSalesLedgerArrival({ ...payload, id: form.value.id })
         : addSalesLedgerArrival(payload);

--
Gitblit v1.9.3