From be7fb5b515ccd11aa3378160863aee5f0a4be1b0 Mon Sep 17 00:00:00 2001
From: huminmin <mac@MacBook-Pro.local>
Date: 星期二, 27 一月 2026 11:38:36 +0800
Subject: [PATCH] Merge branch 'dev_New' of http://114.132.189.42:9002/r/product-inventory-management into dev_New

---
 src/views/collaborativeApproval/approvalProcess/components/approvalDia.vue |   82 ++++++++++
 src/views/equipmentManagement/upkeep/index.vue                             |  101 ++++++++++++++
 src/views/salesManagement/deliveryLedger/index.vue                         |   38 +++-
 src/api/procurementManagement/procurementLedger.js                         |    8 +
 src/views/collaborativeApproval/approvalProcess/index.vue                  |    3 
 src/views/salesManagement/salesLedger/index.vue                            |  149 ++++++++++++++++----
 src/views/collaborativeApproval/approvalProcess/components/infoFormDia.vue |    2 
 src/api/equipmentManagement/maintenanceTaskFile.js                         |   28 ++++
 8 files changed, 356 insertions(+), 55 deletions(-)

diff --git a/src/api/equipmentManagement/maintenanceTaskFile.js b/src/api/equipmentManagement/maintenanceTaskFile.js
new file mode 100644
index 0000000..8373ae3
--- /dev/null
+++ b/src/api/equipmentManagement/maintenanceTaskFile.js
@@ -0,0 +1,28 @@
+import request from "@/utils/request";
+
+// 鏌ヨ淇濆吇浠诲姟闄勪欢鍒楄〃
+export function listMaintenanceTaskFiles(query) {
+  return request({
+    url: "/maintenanceTaskFile/listPage",
+    method: "get",
+    params: query,
+  });
+}
+
+// 鏂板淇濆吇浠诲姟闄勪欢
+export function addMaintenanceTaskFile(data) {
+  return request({
+    url: "/maintenanceTaskFile/add",
+    method: "post",
+    data,
+  });
+}
+
+// 鍒犻櫎淇濆吇浠诲姟闄勪欢
+export function delMaintenanceTaskFile(id) {
+  return request({
+    url: "/maintenanceTaskFile/del",
+    method: "delete",
+    data: Array.isArray(id) ? id : [id],
+  });
+}
diff --git a/src/api/procurementManagement/procurementLedger.js b/src/api/procurementManagement/procurementLedger.js
index c9a2da8..5f9df05 100644
--- a/src/api/procurementManagement/procurementLedger.js
+++ b/src/api/procurementManagement/procurementLedger.js
@@ -114,4 +114,12 @@
         method: "delete",
         data: id,
     });
+}
+// 鏌ヨ閲囪喘璇︽儏
+export function getPurchaseByCode(id) {
+    return request({
+        url: "/purchase/ledger/getPurchaseByCode",
+        method: "get",
+        params: id,
+    });
 }
\ No newline at end of file
diff --git a/src/views/collaborativeApproval/approvalProcess/components/approvalDia.vue b/src/views/collaborativeApproval/approvalProcess/components/approvalDia.vue
index 44a0bcd..c3fb6d1 100644
--- a/src/views/collaborativeApproval/approvalProcess/components/approvalDia.vue
+++ b/src/views/collaborativeApproval/approvalProcess/components/approvalDia.vue
@@ -2,7 +2,7 @@
   <div>
     <el-dialog
       v-model="dialogFormVisible"
-      :title="operationType === 'add' ? '鏂板瀹℃壒娴佺▼' : '缂栬緫瀹℃壒娴佺▼'"
+      :title="operationType === 'approval' ? '瀹℃壒' : '璇︽儏'"
       width="700px"
       @close="closeDia"
     >
@@ -32,9 +32,9 @@
 						</el-form-item>
 					</el-col>
 				</el-row>
-				<el-row v-if="!isQuotationApproval">
+				<el-row v-if="!isQuotationApproval && !isPurchaseApproval">
 					<el-col :span="24">
-						<el-form-item label="瀹℃壒浜嬬敱锛�" prop="approveReason">
+						<el-form-item :label="props.approveType == 5 ? '閲囪喘鍚堝悓鍙凤細' : '瀹℃壒浜嬬敱锛�'" prop="approveReason">
 							<el-input v-model="form.approveReason" placeholder="璇疯緭鍏�" clearable type="textarea" disabled/>
 						</el-form-item>
 					</el-col>
@@ -74,7 +74,7 @@
 				</el-row>
 			</el-form>
 
-      <!-- 鎶ヤ环瀹℃壒锛氬睍绀烘姤浠疯鎯咃紙澶嶇敤閿�鍞姤浠封�滄煡鐪嬭鎯呭璇濇鈥濆唴瀹圭粨鏋勶級 -->
+      <!-- 鎶ヤ环瀹℃壒锛氬睍绀烘姤浠疯鎯咃紙澶嶇敤閿�鍞姤浠�"鏌ョ湅璇︽儏瀵硅瘽妗�"鍐呭缁撴瀯锛� -->
       <div v-if="isQuotationApproval" style="margin: 10px 0 18px;">
         <el-divider content-position="left">鎶ヤ环璇︽儏</el-divider>
         <el-skeleton :loading="quotationLoading" animated>
@@ -104,7 +104,7 @@
                 <h4>浜у搧鏄庣粏</h4>
                 <el-table :data="currentQuotation.products || []" border style="width: 100%">
                   <el-table-column prop="product" label="浜у搧鍚嶇О" />
-                  <el-table-column prop="specification" label="瑙勬牸鍨嬪彿" />
+                  <el-table-column prop="specificationModel" label="瑙勬牸鍨嬪彿" />
                   <el-table-column prop="unit" label="鍗曚綅" />
                   <el-table-column prop="unitPrice" label="鍗曚环">
                     <template #default="scope">楼{{ Number(scope.row.unitPrice ?? 0).toFixed(2) }}</template>
@@ -115,6 +115,53 @@
               <div v-if="currentQuotation.remark" style="margin-top: 20px;">
                 <h4>澶囨敞</h4>
                 <p>{{ currentQuotation.remark }}</p>
+              </div>
+            </template>
+          </template>
+        </el-skeleton>
+      </div>
+
+      <!-- 閲囪喘瀹℃壒锛氬睍绀洪噰璐鎯� -->
+      <div v-if="isPurchaseApproval" style="margin: 10px 0 18px;">
+        <el-divider content-position="left">閲囪喘璇︽儏</el-divider>
+        <el-skeleton :loading="purchaseLoading" animated>
+          <template #template>
+            <el-skeleton-item variant="h3" style="width: 30%" />
+            <el-skeleton-item variant="text" style="width: 100%" />
+            <el-skeleton-item variant="text" style="width: 100%" />
+          </template>
+          <template #default>
+            <el-empty v-if="!currentPurchase || !currentPurchase.purchaseContractNumber" description="鏈煡璇㈠埌瀵瑰簲閲囪喘璇︽儏" />
+            <template v-else>
+              <el-descriptions :column="2" border>
+                <el-descriptions-item label="閲囪喘鍚堝悓鍙�">{{ currentPurchase.purchaseContractNumber }}</el-descriptions-item>
+                <el-descriptions-item label="渚涘簲鍟嗗悕绉�">{{ currentPurchase.supplierName }}</el-descriptions-item>
+                <el-descriptions-item label="椤圭洰鍚嶇О">{{ currentPurchase.projectName }}</el-descriptions-item>
+                <el-descriptions-item label="閿�鍞悎鍚屽彿">{{ currentPurchase.salesContractNo }}</el-descriptions-item>
+                <el-descriptions-item label="绛捐鏃ユ湡">{{ currentPurchase.executionDate }}</el-descriptions-item>
+                <el-descriptions-item label="褰曞叆鏃ユ湡">{{ currentPurchase.entryDate }}</el-descriptions-item>
+                <el-descriptions-item label="浠樻鏂瑰紡">{{ currentPurchase.paymentMethod }}</el-descriptions-item>
+                <el-descriptions-item label="鍚堝悓閲戦" :span="2">
+                  <span style="font-size: 18px; color: #e6a23c; font-weight: bold;">
+                    楼{{ Number(currentPurchase.contractAmount ?? 0).toFixed(2) }}
+                  </span>
+                </el-descriptions-item>
+              </el-descriptions>
+
+              <div style="margin-top: 20px;">
+                <h4>浜у搧鏄庣粏</h4>
+                <el-table :data="currentPurchase.productData || []" border style="width: 100%">
+                  <el-table-column prop="productCategory" label="浜у搧鍚嶇О" />
+                  <el-table-column prop="specificationModel" label="瑙勬牸鍨嬪彿" />
+                  <el-table-column prop="unit" label="鍗曚綅" />
+                  <el-table-column prop="quantity" label="鏁伴噺" />
+                  <el-table-column prop="taxInclusiveUnitPrice" label="鍚◣鍗曚环">
+                    <template #default="scope">楼{{ Number(scope.row.taxInclusiveUnitPrice ?? 0).toFixed(2) }}</template>
+                  </el-table-column>
+                  <el-table-column prop="taxInclusiveTotalPrice" label="鍚◣鎬讳环">
+                    <template #default="scope">楼{{ Number(scope.row.taxInclusiveTotalPrice ?? 0).toFixed(2) }}</template>
+                  </el-table-column>
+                </el-table>
               </div>
             </template>
           </template>
@@ -188,6 +235,7 @@
 import {userListNoPageByTenantId} from "@/api/system/user.js";
 import { WarningFilled, Edit, Check, MoreFilled } from '@element-plus/icons-vue'
 import { getQuotationList } from "@/api/salesManagement/salesQuotation.js";
+import { getPurchaseByCode } from "@/api/procurementManagement/procurementLedger.js";
 const emit = defineEmits(['close'])
 const { proxy } = getCurrentInstance()
 
@@ -207,7 +255,10 @@
 const userList = ref([])
 const quotationLoading = ref(false)
 const currentQuotation = ref({})
+const purchaseLoading = ref(false)
+const currentPurchase = ref({})
 const isQuotationApproval = computed(() => Number(props.approveType) === 6)
+const isPurchaseApproval = computed(() => Number(props.approveType) === 5)
 
 const data = reactive({
 	form: {
@@ -247,6 +298,7 @@
   operationType.value = type;
   dialogFormVisible.value = true;
   currentQuotation.value = {}
+  currentPurchase.value = {}
 	userListNoPageByTenantId().then((res) => {
 		userList.value = res.data;
 	});
@@ -277,7 +329,7 @@
 		});
 	});
 
-  // 鎶ヤ环瀹℃壒锛氱敤瀹℃壒浜嬬敱瀛楁鎵胯浇鐨勨�滄姤浠峰崟鍙封�濆幓鏌ユ姤浠峰垪琛�
+  // 鎶ヤ环瀹℃壒锛氱敤瀹℃壒浜嬬敱瀛楁鎵胯浇鐨�"鎶ヤ环鍗曞彿"鍘绘煡鎶ヤ环鍒楄〃
   if (isQuotationApproval.value) {
     const quotationNo = row?.approveReason;
     if (quotationNo) {
@@ -287,6 +339,22 @@
         currentQuotation.value = records[0] || {}
       }).finally(() => {
         quotationLoading.value = false
+      })
+    }
+  }
+
+  // 閲囪喘瀹℃壒锛氱敤瀹℃壒浜嬬敱瀛楁鎵胯浇鐨�"閲囪喘鍚堝悓鍙�"鍘绘煡閲囪喘璇︽儏
+  if (isPurchaseApproval.value) {
+    const purchaseContractNumber = row?.approveReason;
+    if (purchaseContractNumber) {
+      purchaseLoading.value = true
+      getPurchaseByCode({ purchaseContractNumber }).then((res) => {
+        currentPurchase.value = res
+      }).catch((err) => {
+        console.error('鏌ヨ閲囪喘璇︽儏澶辫触:', err)
+        proxy.$modal.msgError('鏌ヨ閲囪喘璇︽儏澶辫触')
+      }).finally(() => {
+        purchaseLoading.value = false
       })
     }
   }
@@ -341,6 +409,8 @@
   dialogFormVisible.value = false;
   quotationLoading.value = false
   currentQuotation.value = {}
+  purchaseLoading.value = false
+  currentPurchase.value = {}
   emit('close')
 };
 defineExpose({
diff --git a/src/views/collaborativeApproval/approvalProcess/components/infoFormDia.vue b/src/views/collaborativeApproval/approvalProcess/components/infoFormDia.vue
index 67a635c..998fa33 100644
--- a/src/views/collaborativeApproval/approvalProcess/components/infoFormDia.vue
+++ b/src/views/collaborativeApproval/approvalProcess/components/infoFormDia.vue
@@ -35,7 +35,7 @@
         </el-row>
         <el-row>
           <el-col :span="24">
-            <el-form-item :label="props.approveType == 5 ? '閲囪喘璇存槑锛�' : '瀹℃壒浜嬬敱锛�'" prop="approveReason">
+            <el-form-item :label="props.approveType == 5 ? '閲囪喘鍚堝悓鍙凤細' : '瀹℃壒浜嬬敱锛�'" prop="approveReason">
               <el-input v-model="form.approveReason" placeholder="璇疯緭鍏�" clearable type="textarea" />
             </el-form-item>
           </el-col>
diff --git a/src/views/collaborativeApproval/approvalProcess/index.vue b/src/views/collaborativeApproval/approvalProcess/index.vue
index 95d97cb..bd281dd 100644
--- a/src/views/collaborativeApproval/approvalProcess/index.vue
+++ b/src/views/collaborativeApproval/approvalProcess/index.vue
@@ -113,6 +113,7 @@
   const isLeaveType = currentApproveType.value === 2; // 璇峰亣绠$悊
   const isReimburseType = currentApproveType.value === 4; // 鎶ラ攢绠$悊
   const isQuotationType = currentApproveType.value === 6; // 鎶ヤ环瀹℃壒
+  const isPurchaseType = currentApproveType.value === 5; // 閲囪喘瀹℃壒
   
   // 鍩虹鍒楅厤缃�
   const baseColumns = [
@@ -159,7 +160,7 @@
       width: 220
     },
     {
-      label: isQuotationType ? "鎶ヤ环鍗曞彿" : "瀹℃壒浜嬬敱",
+      label: isQuotationType ? "鎶ヤ环鍗曞彿" : isPurchaseType ? "閲囪喘鍚堝悓鍙�" : "瀹℃壒浜嬬敱",
       prop: "approveReason",
       width: 200
     },
diff --git a/src/views/equipmentManagement/upkeep/index.vue b/src/views/equipmentManagement/upkeep/index.vue
index 046c0fa..543e37b 100644
--- a/src/views/equipmentManagement/upkeep/index.vue
+++ b/src/views/equipmentManagement/upkeep/index.vue
@@ -203,6 +203,13 @@
           >
             鍒犻櫎
           </el-button>
+          <el-button
+            type="primary"
+            link
+            @click="openFileDialog(row)"
+          >
+            闄勪欢
+          </el-button>
         </template>
       </PIMTable>
         </div>
@@ -211,6 +218,15 @@
     <PlanModal ref="planModalRef" @ok="getTableData" />
         <MaintenanceModal ref="maintainModalRef" @ok="getTableData" />
         <FormDia ref="formDiaRef" @closeDia="getScheduledTableData" />
+    <FileListDialog 
+      ref="fileListDialogRef"
+      v-model="fileDialogVisible"
+      :show-upload-button="true"
+      :show-delete-button="true"
+      :delete-method="handleAttachmentDelete"
+      :name-column-label="'闄勪欢鍚嶇О'"
+      :rulesRegulationsManagementId="currentMaintenanceTaskId"
+      @upload="handleAttachmentUpload" />
   </div>
 </template>
 
@@ -221,12 +237,18 @@
 import PlanModal from './Form/PlanModal.vue'
 import MaintenanceModal from './Form/MaintenanceModal.vue'
 import FormDia from './Form/formDia.vue'
+import FileListDialog from '@/components/Dialog/FileListDialog.vue'
 import {
   getUpkeepPage,
   delUpkeep,
   deviceMaintenanceTaskList,
   deviceMaintenanceTaskDel,
 } from '@/api/equipmentManagement/upkeep'
+import {
+  listMaintenanceTaskFiles,
+  addMaintenanceTaskFile,
+  delMaintenanceTaskFile,
+} from '@/api/equipmentManagement/maintenanceTaskFile'
 import dayjs from 'dayjs'
 
 const { proxy } = getCurrentInstance()
@@ -240,6 +262,10 @@
 const maintainModalRef = ref()
 // 瀹氭椂浠诲姟寮圭獥鎺у埗鍣�
 const formDiaRef = ref()
+// 闄勪欢寮圭獥
+const fileListDialogRef = ref(null)
+const fileDialogVisible = ref(false)
+const currentMaintenanceTaskId = ref(null)
 
 // 浠诲姟璁板綍tab锛堝師璁惧淇濆吇椤甸潰锛夌浉鍏冲彉閲�
 const filters = reactive({
@@ -385,7 +411,7 @@
 		dataType: "slot",
 		slot: "operation",
 		align: "center",
-		width: "300px",
+		width: "350px",
 	},
 ])
 
@@ -571,6 +597,79 @@
   getTableData()
 }
 
+// 闄勪欢鐩稿叧鏂规硶
+// 鏌ヨ闄勪欢鍒楄〃
+const fetchMaintenanceTaskFiles = async (deviceMaintenanceId) => {
+  try {
+    const params = {
+      current: 1,
+      size: 100,
+      deviceMaintenanceId,
+      rulesRegulationsManagementId:deviceMaintenanceId
+    }
+    const res = await listMaintenanceTaskFiles(params)
+    const records = res?.data?.records || []
+    const mapped = records.map(item => ({
+      id: item.id,
+      name: item.fileName || item.name,
+      url: item.fileUrl || item.url,
+      raw: item,
+    }))
+    fileListDialogRef.value?.setList(mapped)
+  } catch (error) {
+    ElMessage.error('鑾峰彇闄勪欢鍒楄〃澶辫触')
+  }
+}
+
+// 鎵撳紑闄勪欢寮圭獥
+const openFileDialog = async (row) => {
+  currentMaintenanceTaskId.value = row.id
+  fileDialogVisible.value = true
+  await fetchMaintenanceTaskFiles(row.id)
+}
+
+// 鍒锋柊闄勪欢鍒楄〃
+const refreshFileList = async () => {
+  if (!currentMaintenanceTaskId.value) return
+  await fetchMaintenanceTaskFiles(currentMaintenanceTaskId.value)
+}
+
+// 涓婁紶闄勪欢
+const handleAttachmentUpload = async (filePayload) => {
+  if (!currentMaintenanceTaskId.value) return
+  try {
+    const payload = {
+      name: filePayload?.fileName || filePayload?.name,
+      url: filePayload?.fileUrl || filePayload?.url,
+      deviceMaintenanceId: currentMaintenanceTaskId.value,
+    }
+    await addMaintenanceTaskFile(payload)
+    ElMessage.success('鏂囦欢涓婁紶鎴愬姛')
+    await refreshFileList()
+  } catch (error) {
+    ElMessage.error('鏂囦欢涓婁紶澶辫触')
+  }
+}
+
+// 鍒犻櫎闄勪欢
+const handleAttachmentDelete = async (row) => {
+  if (!row?.id) return false
+  try {
+    await ElMessageBox.confirm('纭鍒犻櫎璇ラ檮浠讹紵', '鎻愮ず', { type: 'warning' })
+  } catch {
+    return false
+  }
+  try {
+    await delMaintenanceTaskFile(row.id)
+    ElMessage.success('鍒犻櫎鎴愬姛')
+    await refreshFileList()
+    return true
+  } catch (error) {
+    ElMessage.error('鍒犻櫎澶辫触')
+    return false
+  }
+}
+
 onMounted(() => {
   // 鏍规嵁榛樿婵�娲荤殑 Tab 璋冪敤瀵瑰簲鐨勬煡璇㈡帴鍙�
   if (activeTab.value === 'scheduled') {
diff --git a/src/views/salesManagement/deliveryLedger/index.vue b/src/views/salesManagement/deliveryLedger/index.vue
index 688741b..983a3e5 100644
--- a/src/views/salesManagement/deliveryLedger/index.vue
+++ b/src/views/salesManagement/deliveryLedger/index.vue
@@ -51,13 +51,13 @@
               link 
               type="primary" 
               size="small" 
-              :disabled="!isApproved(scope.row.status)"
+              :disabled="isApproving(scope.row.status)"
               @click="openForm('edit', scope.row)">缂栬緫</el-button>
             <el-button 
               link 
               type="danger" 
               size="small" 
-              :disabled="!isApproved(scope.row.status)"
+              :disabled="isApproving(scope.row.status)"
               @click="handleDeleteSingle(scope.row)">鍒犻櫎</el-button>
           </template>
         </el-table-column>
@@ -284,9 +284,9 @@
 
 // 鎵撳紑寮规
 const openForm = async (type, row) => {
-  // 缂栬緫鏃舵鏌ュ鏍哥姸鎬�
-  if (type === 'edit' && row && !isApproved(row.status)) {
-    proxy.$modal.msgWarning("鍙兘缂栬緫瀹℃牳閫氳繃鐨勬暟鎹�");
+  // 缂栬緫鏃舵鏌ュ鏍哥姸鎬侊紝鍙湁瀹℃牳涓笉鑳界紪杈�
+  if (type === 'edit' && row && isApproving(row.status)) {
+    proxy.$modal.msgWarning("瀹℃牳涓殑鏁版嵁涓嶈兘缂栬緫");
     return;
   }
   
@@ -430,10 +430,10 @@
     return;
   }
   
-  // 妫�鏌ラ�変腑鐨勮鏄惁閮芥槸"瀹℃牳閫氳繃"鐘舵��
-  const notApprovedRows = selectedRows.value.filter(row => !isApproved(row.status));
-  if (notApprovedRows.length > 0) {
-    proxy.$modal.msgWarning("鍙兘鍒犻櫎瀹℃牳閫氳繃鐨勬暟鎹�");
+  // 妫�鏌ラ�変腑鐨勮鏄惁鏈�"瀹℃牳涓�"鐘舵��
+  const approvingRows = selectedRows.value.filter(row => isApproving(row.status));
+  if (approvingRows.length > 0) {
+    proxy.$modal.msgWarning("瀹℃牳涓殑鏁版嵁涓嶈兘鍒犻櫎");
     return;
   }
   
@@ -456,9 +456,9 @@
 
 // 鍗曚釜鍒犻櫎
 const handleDeleteSingle = (row) => {
-  // 妫�鏌ユ槸鍚︿负"瀹℃牳閫氳繃"鐘舵��
-  if (!isApproved(row.deliveryLedger)) {
-    proxy.$modal.msgWarning("鍙兘鍒犻櫎瀹℃牳閫氳繃鐨勬暟鎹�");
+  // 妫�鏌ユ槸鍚︿负"瀹℃牳涓�"鐘舵��
+  if (isApproving(row.status)) {
+    proxy.$modal.msgWarning("瀹℃牳涓殑鏁版嵁涓嶈兘鍒犻櫎");
     return;
   }
   
@@ -635,6 +635,20 @@
   return statusStr === '瀹℃牳閫氳繃' || statusStr === '3';
 };
 
+// 妫�鏌ュ鏍哥姸鎬佹槸鍚︿负"瀹℃牳涓�"
+const isApproving = (status) => {
+  if (status === null || status === undefined || status === '') {
+    return false;
+  }
+  // 濡傛灉鏄暟瀛楋紝1 琛ㄧず瀹℃牳涓�
+  if (typeof status === 'number') {
+    return status === 1;
+  }
+  // 濡傛灉鏄瓧绗︿覆
+  const statusStr = String(status).trim();
+  return statusStr === '瀹℃牳涓�' || statusStr === '1';
+};
+
 onMounted(() => {
   getList();
 });
diff --git a/src/views/salesManagement/salesLedger/index.vue b/src/views/salesManagement/salesLedger/index.vue
index f273d54..d9a180f 100644
--- a/src/views/salesManagement/salesLedger/index.vue
+++ b/src/views/salesManagement/salesLedger/index.vue
@@ -6,10 +6,6 @@
           <el-input v-model="searchForm.customerName" placeholder="璇疯緭鍏�" clearable prefix-icon="Search"
             @change="handleQuery" />
         </el-form-item>
-        <el-form-item label="瀹㈡埛鍚堝悓鍙凤細">
-          <el-input v-model="searchForm.customerContractNo" placeholder="璇疯緭鍏�" clearable prefix-icon="Search"
-            @change="handleQuery" />
-        </el-form-item>
         <el-form-item label="閿�鍞悎鍚屽彿锛�">
           <el-input v-model="searchForm.salesContractNo" placeholder="璇疯緭鍏�" clearable prefix-icon="Search"
             @change="handleQuery" />
@@ -61,14 +57,20 @@
 													type="danger">涓嶈冻</el-tag>
                 </template>
               </el-table-column>
-							<el-table-column label="鍙戣揣鐘舵��" prop="shippingStatus" width="140" align="center" show-overflow-tooltip />
+							<el-table-column label="鍙戣揣鐘舵��" width="140" align="center">
+								<template #default="scope">
+									<el-tag :type="getShippingStatusType(scope.row)" size="small">
+										{{ getShippingStatusText(scope.row) }}
+									</el-tag>
+								</template>
+							</el-table-column>
 							<el-table-column label="蹇�掑叕鍙�" prop="expressCompany" show-overflow-tooltip />
 							<el-table-column label="蹇�掑崟鍙�" prop="expressNumber" show-overflow-tooltip />
               <el-table-column label="鍙戣揣杞︾墝" minWidth="100px" align="center">
                 <template #default="scope">
                   <div>
                     <el-tag type="success" v-if="scope.row.shippingCarNumber">{{ scope.row.shippingCarNumber }}</el-tag>
-                    <el-tag v-else type="info">鏈彂璐�</el-tag>
+                    <el-tag v-else type="info">-</el-tag>
                   </div>
                 </template>
               </el-table-column>
@@ -94,8 +96,8 @@
                   <el-button 
                     link 
                     type="primary" 
-                    size="small" 
-                    :disabled="scope.row.approveStatus !== 1 || !!scope.row.shippingDate || !!scope.row.shippingCarNumber"
+                    size="small"
+                    :disabled="!canShip(scope.row)"
                     @click="openDeliveryForm(scope.row)">
                     鍙戣揣
                   </el-button>
@@ -106,7 +108,6 @@
         </el-table-column>
         <el-table-column align="center" label="搴忓彿" type="index" width="60" />
         <el-table-column label="閿�鍞悎鍚屽彿" prop="salesContractNo" width="180" show-overflow-tooltip />
-        <el-table-column label="瀹㈡埛鍚堝悓鍙�" prop="customerContractNo" width="180" show-overflow-tooltip />
         <el-table-column label="瀹㈡埛鍚嶇О" prop="customerName" width="300" show-overflow-tooltip />
         <el-table-column label="涓氬姟鍛�" prop="salesman" width="100" show-overflow-tooltip />
         <el-table-column label="椤圭洰鍚嶇О" prop="projectName" width="180" show-overflow-tooltip />
@@ -148,11 +149,6 @@
         </el-row>
         <el-row :gutter="30">
           <el-col :span="12">
-            <el-form-item label="瀹㈡埛鍚堝悓鍙凤細" prop="customerContractNo">
-              <el-input v-model="form.customerContractNo" placeholder="璇疯緭鍏�" clearable :disabled="operationType === 'view'"/>
-            </el-form-item>
-          </el-col>
-          <el-col :span="12">
             <el-form-item label="瀹㈡埛鍚嶇О锛�" prop="customerId">
               <el-select v-model="form.customerId" placeholder="璇烽�夋嫨" clearable :disabled="operationType === 'view'">
                 <el-option v-for="item in customerOption" :key="item.id" :label="item.customerName" :value="item.id">
@@ -163,17 +159,22 @@
               </el-select>
             </el-form-item>
           </el-col>
+					<el-col :span="12">
+						<el-form-item label="椤圭洰鍚嶇О锛�" prop="projectName">
+							<el-input v-model="form.projectName" placeholder="璇疯緭鍏�" clearable :disabled="operationType === 'view'" />
+						</el-form-item>
+					</el-col>
         </el-row>
         <el-row :gutter="30">
-          <el-col :span="12">
-            <el-form-item label="椤圭洰鍚嶇О锛�" prop="projectName">
-              <el-input v-model="form.projectName" placeholder="璇疯緭鍏�" clearable :disabled="operationType === 'view'" />
-            </el-form-item>
-          </el-col>
 					<el-col :span="12">
 						<el-form-item label="绛捐鏃ユ湡锛�" prop="executionDate">
 							<el-date-picker style="width: 100%" v-model="form.executionDate" value-format="YYYY-MM-DD"
 															format="YYYY-MM-DD" type="date" placeholder="璇烽�夋嫨" clearable :disabled="operationType === 'view'" />
+						</el-form-item>
+					</el-col>
+					<el-col :span="12">
+						<el-form-item label="浠樻鏂瑰紡">
+							<el-input v-model="form.paymentMethod" placeholder="璇疯緭鍏�" clearable :disabled="operationType === 'view'" />
 						</el-form-item>
 					</el-col>
 				</el-row>
@@ -195,7 +196,6 @@
 						</el-form-item>
 					</el-col>
 				</el-row>
-				
 				<el-row>
 					<el-form-item label="浜у搧淇℃伅锛�" prop="entryDate">
 						<el-button v-if="operationType !== 'view'" type="primary" @click="openProductForm('add')">娣诲姞</el-button>
@@ -1186,19 +1186,15 @@
 const openProductForm = async (type, row, index) => {
 	productOperationType.value = type;
 	productForm.value = {};
-	modelOptions.value = []; // 娓呯┖瑙勬牸鍨嬪彿閫夐」
 	proxy.resetForm("productFormRef");
-
-	// 纭繚浜у搧澶х被鏁版嵁宸插姞杞�
-	const options = productOptions.value && productOptions.value.length > 0
-		? productOptions.value
-		: await getProductOptions();
-
 	if (type === "edit") {
 		productForm.value = { ...row };
 		productIndex.value = index;
 		// 缂栬緫鏃舵牴鎹骇鍝佸ぇ绫诲悕绉板弽鏌� tree 鑺傜偣 id锛屽苟鍔犺浇瑙勬牸鍨嬪彿鍒楄〃
 		try {
+			const options = productOptions.value && productOptions.value.length > 0
+				? productOptions.value
+				: await getProductOptions();
 			const categoryId = findNodeIdByLabel(options, productForm.value.productCategory);
 			if (categoryId) {
 				const models = await modelList({ id: categoryId });
@@ -1215,6 +1211,8 @@
 			// 鍔犺浇澶辫触鏃朵繚鎸佸彲缂栬緫锛屼笉涓柇寮圭獥
 			console.error("鍔犺浇浜у搧瑙勬牸鍨嬪彿澶辫触", e);
 		}
+	} else {
+		getProductOptions()
 	}
 	productFormVisible.value = true;
 };
@@ -1884,6 +1882,92 @@
 	isCalculating.value = false;
 };
 /**
+ * 鑾峰彇鍙戣揣鐘舵�佹枃鏈�
+ * @param row 琛屾暟鎹�
+ */
+const getShippingStatusText = (row) => {
+	// 濡傛灉宸插彂璐э紙鏈夊彂璐ф棩鏈熸垨杞︾墝鍙凤級锛屾樉绀�"宸插彂璐�"
+	if (row.shippingDate || row.shippingCarNumber) {
+		return '宸插彂璐�';
+	}
+	
+	// 鑾峰彇鍙戣揣鐘舵�佸瓧娈�
+	const status = row.shippingStatus;
+	
+	// 濡傛灉鐘舵�佷负绌烘垨鏈畾涔夛紝榛樿涓�"寰呭彂璐�"
+	if (status === null || status === undefined || status === '') {
+		return '寰呭彂璐�';
+	}
+	
+	// 鐘舵�佹槸瀛楃涓�
+	const statusStr = String(status).trim();
+	const statusTextMap = {
+		'寰呭彂璐�': '寰呭彂璐�',
+		'寰呭鏍�': '寰呭鏍�',
+		'瀹℃牳涓�': '瀹℃牳涓�',
+		'瀹℃牳鎷掔粷': '瀹℃牳鎷掔粷',
+		'瀹℃牳閫氳繃': '瀹℃牳閫氳繃',
+		'宸插彂璐�': '宸插彂璐�'
+	};
+	return statusTextMap[statusStr] || '寰呭彂璐�';
+};
+
+/**
+ * 鑾峰彇鍙戣揣鐘舵�佹爣绛剧被鍨嬶紙棰滆壊锛�
+ * @param row 琛屾暟鎹�
+ */
+const getShippingStatusType = (row) => {
+	// 濡傛灉宸插彂璐э紙鏈夊彂璐ф棩鏈熸垨杞︾墝鍙凤級锛屾樉绀虹豢鑹�
+	if (row.shippingDate || row.shippingCarNumber) {
+		return 'success';
+	}
+	
+	// 鑾峰彇鍙戣揣鐘舵�佸瓧娈�
+	const status = row.shippingStatus;
+	
+	// 濡傛灉鐘舵�佷负绌烘垨鏈畾涔夛紝榛樿涓虹伆鑹诧紙寰呭彂璐э級
+	if (status === null || status === undefined || status === '') {
+		return 'info';
+	}
+	
+	// 鐘舵�佹槸瀛楃涓�
+	const statusStr = String(status).trim();
+	const typeTextMap = {
+		'寰呭彂璐�': 'info',
+		'寰呭鏍�': 'info',
+		'瀹℃牳涓�': 'warning',
+		'瀹℃牳鎷掔粷': 'danger',
+		'瀹℃牳閫氳繃': 'success',
+		'宸插彂璐�': 'success'
+	};
+	return typeTextMap[statusStr] || 'info';
+};
+
+/**
+ * 鍒ゆ柇鏄惁鍙互鍙戣揣
+ * 鍙湁鍦ㄤ骇鍝佺姸鎬佹槸鍏呰冻锛屽彂璐х姸鎬佹槸寰呭彂璐у拰瀹℃牳鎷掔粷鐨勬椂鍊欐墠鍙互鍙戣揣
+ * @param row 琛屾暟鎹�
+ */
+const canShip = (row) => {
+	// 浜у搧鐘舵�佸繀椤绘槸鍏呰冻锛坅pproveStatus === 1锛�
+	if (row.approveStatus !== 1) {
+		return false;
+	}
+	
+	// 鑾峰彇鍙戣揣鐘舵��
+	const shippingStatus = row.shippingStatus;
+	
+	// 濡傛灉宸插彂璐э紙鏈夊彂璐ф棩鏈熸垨杞︾墝鍙凤級锛屼笉鑳藉啀娆″彂璐�
+	if (row.shippingDate || row.shippingCarNumber) {
+		return false;
+	}
+	
+	// 鍙戣揣鐘舵�佸繀椤绘槸"寰呭彂璐�"鎴�"瀹℃牳鎷掔粷"
+	const statusStr = shippingStatus ? String(shippingStatus).trim() : '';
+	return statusStr === '寰呭彂璐�' || statusStr === '瀹℃牳鎷掔粷';
+};
+
+/**
  * 涓嬭浇鏂囦欢
  *
  * @param row 涓嬭浇鏂囦欢鐨勭浉鍏充俊鎭璞�
@@ -1900,15 +1984,12 @@
 
 // 鎵撳紑鍙戣揣寮规
 const openDeliveryForm = (row) => {
-	// 鏍¢獙锛氬彧鏈変骇鍝佺姸鎬佷负鍏呰冻涓旀湭鍙戣揣鏃舵墠鑳藉彂璐�
-	if (row.approveStatus !== 1) {
-		proxy.$modal.msgWarning("浜у搧鐘舵�佷笉瓒筹紝鏃犳硶鍙戣揣");
+	// 妫�鏌ユ槸鍚﹀彲浠ュ彂璐�
+	if (!canShip(row)) {
+		proxy.$modal.msgWarning("鍙湁鍦ㄤ骇鍝佺姸鎬佹槸鍏呰冻锛屽彂璐х姸鎬佹槸寰呭彂璐ф垨瀹℃牳鎷掔粷鐨勬椂鍊欐墠鍙互鍙戣揣");
 		return;
 	}
-	if (row.shippingDate || row.shippingCarNumber) {
-		proxy.$modal.msgWarning("璇ヤ骇鍝佸凡鍙戣揣锛屾棤娉曢噸澶嶅彂璐�");
-		return;
-	}
+	
 	currentDeliveryRow.value = row;
   deliveryForm.value = {
     type: "璐ц溅",

--
Gitblit v1.9.3