From 3739a47340c8d8b6edf5fdcbb0534f5fc8d96530 Mon Sep 17 00:00:00 2001
From: spring <2396852758@qq.com>
Date: 星期四, 29 一月 2026 15:02:38 +0800
Subject: [PATCH] Merge branch 'dev_New' of http://114.132.189.42:9002/r/product-inventory-management into dev_New

---
 src/api/safeProduction/emergencyPlanReview.js                                    |   35 +
 src/views/collaborativeApproval/notificationManagement/summary/index.vue         |    2 
 src/views/salesManagement/deliveryLedger/index.vue                               |   10 
 src/views/collaborativeApproval/notificationManagement/meetExamine/index.vue     |    2 
 src/views/procurementManagement/invoiceEntry/index.vue                           |    2 
 src/views/collaborativeApproval/approvalProcess/index.vue                        |    2 
 src/views/safeProduction/emergencyPlanReview/index.vue                           |  810 ++++++++++++++++++++++++++++++++++++++
 src/views/procurementManagement/paymentEntry/index.vue                           |    6 
 src/views/salesManagement/salesLedger/index.vue                                  |   38 +
 src/views/salesManagement/salesQuotation/index.vue                               |   57 +
 src/views/collaborativeApproval/notificationManagement/meetApplication/index.vue |    4 
 src/api/salesManagement/deliveryLedger.js                                        |    8 
 src/views/collaborativeApproval/sealManagement/index.vue                         |  120 ++++-
 src/views/collaborativeApproval/approvalProcess/components/approvalDia.vue       |    4 
 src/views/collaborativeApproval/notificationManagement/meetPublish/index.vue     |    2 
 src/views/productionManagement/productionOrder/index.vue                         |   34 +
 src/views/collaborativeApproval/knowledgeBase/index.vue                          |  105 +++-
 src/views/safeProduction/hazardousMaterialsControl/index.vue                     |    6 
 18 files changed, 1,157 insertions(+), 90 deletions(-)

diff --git a/src/api/safeProduction/emergencyPlanReview.js b/src/api/safeProduction/emergencyPlanReview.js
new file mode 100644
index 0000000..7eac73e
--- /dev/null
+++ b/src/api/safeProduction/emergencyPlanReview.js
@@ -0,0 +1,35 @@
+// 鍙戣揣鍙拌处椤甸潰鎺ュ彛
+import request from "@/utils/request";
+
+// 鍒嗛〉鏌ヨ
+export function safeContingencyPlanListPage(query) {
+  return request({
+    url: "/safeContingencyPlan/page",
+    method: "get",
+    params: query,
+  });
+}
+
+export function safeContingencyPlanAdd(query) {
+    return request({
+        url: '/safeContingencyPlan',
+        method: 'post',
+        data: query
+    })
+}
+
+export function safeContingencyPlanUpdate(query) {
+    return request({
+        url: '/safeContingencyPlan',
+        method: 'put',
+        data: query
+    })
+}
+
+export function safeContingencyPlanDel(ids) {
+    return request({
+        url: '/safeContingencyPlan/' + ids,
+        method: 'delete',
+        data: ids
+    })
+}
\ No newline at end of file
diff --git a/src/api/salesManagement/deliveryLedger.js b/src/api/salesManagement/deliveryLedger.js
index bb8689f..4be5829 100644
--- a/src/api/salesManagement/deliveryLedger.js
+++ b/src/api/salesManagement/deliveryLedger.js
@@ -18,6 +18,14 @@
     data: query,
   });
 }
+// 淇敼鍙戣揣鍙拌处
+export function deductStock(query) {
+  return request({
+    url: "/shippingInfo/deductStock",
+    method: "post",
+    data: query,
+  });
+}
 
 // 鍒犻櫎鍙戣揣鍙拌处
 export function delDeliveryLedger(query) {
diff --git a/src/views/collaborativeApproval/approvalProcess/components/approvalDia.vue b/src/views/collaborativeApproval/approvalProcess/components/approvalDia.vue
index aad5b23..20a4ee6 100644
--- a/src/views/collaborativeApproval/approvalProcess/components/approvalDia.vue
+++ b/src/views/collaborativeApproval/approvalProcess/components/approvalDia.vue
@@ -197,10 +197,6 @@
               <div v-if="!activity.isShen" class="node-reason">
                 <span>瀹℃壒鎰忚锛�</span>{{ activity.approveNodeReason }}
               </div>
-              <div v-if="!activity.isShen" class="node-reason">
-                <span>绛惧悕锛�</span>
-								<img :src="activity.urlTem" class="signImg" alt="" v-if="activity.urlTem"/>
-              </div>
               <div v-else-if="activity.isShen">
                 <el-form-item
                   :prop="'activities.' + index + '.approveNodeReason'"
diff --git a/src/views/collaborativeApproval/approvalProcess/index.vue b/src/views/collaborativeApproval/approvalProcess/index.vue
index bd281dd..65941e1 100644
--- a/src/views/collaborativeApproval/approvalProcess/index.vue
+++ b/src/views/collaborativeApproval/approvalProcess/index.vue
@@ -45,7 +45,7 @@
           type="danger"
           plain
           @click="handleDelete"
-          v-if="currentApproveType !== 7"
+          v-if="currentApproveType !== 5 && currentApproveType !== 6 && currentApproveType !== 7"
         >鍒犻櫎</el-button>
       </div>
     </div>
diff --git a/src/views/collaborativeApproval/knowledgeBase/index.vue b/src/views/collaborativeApproval/knowledgeBase/index.vue
index aeb1ba4..f7a1ef3 100644
--- a/src/views/collaborativeApproval/knowledgeBase/index.vue
+++ b/src/views/collaborativeApproval/knowledgeBase/index.vue
@@ -46,11 +46,13 @@
     </div>
 
     <!-- 鏂板/缂栬緫鐭ヨ瘑寮圭獥 -->
-    <el-dialog
+    <FormDialog
       v-model="dialogVisible"
       :title="dialogTitle"
-      width="800px"
-      :close-on-click-modal="false"
+      :width="'800px'"
+      @close="closeKnowledgeDialog"
+      @confirm="submitForm"
+      @cancel="closeKnowledgeDialog"
     >
       <el-form ref="formRef" :model="form" :rules="rules" label-width="120px">
         <el-row :gutter="20">
@@ -115,7 +117,14 @@
         <el-row :gutter="20">
           <el-col :span="12">
             <el-form-item label="鍒涘缓浜�" prop="creator">
-              <el-input v-model="form.creator" placeholder="璇疯緭鍏ュ垱寤轰汉" />
+              <el-select v-model="form.creator" placeholder="璇烽�夋嫨鍒涘缓浜�" style="width: 100%" filterable>
+                <el-option
+                  v-for="user in userList"
+                  :key="user.userId"
+                  :label="user.nickName"
+                  :value="user.nickName"
+                />
+              </el-select>
             </el-form-item>
           </el-col>
           <el-col :span="12">
@@ -125,20 +134,16 @@
           </el-col>
         </el-row>
       </el-form>
-      <template #footer>
-        <span class="dialog-footer">
-          <el-button @click="dialogVisible = false">鍙栨秷</el-button>
-          <el-button type="primary" @click="submitForm">纭畾</el-button>
-        </span>
-      </template>
-    </el-dialog>
+    </FormDialog>
 
     <!-- 鏌ョ湅鐭ヨ瘑璇︽儏寮圭獥 -->
-    <el-dialog
+    <FormDialog
       v-model="viewDialogVisible"
       title="鐭ヨ瘑璇︽儏"
-      width="900px"
-      :close-on-click-modal="false"
+      :width="'900px'"
+      @close="closeViewDialog"
+      @confirm="handleViewDialogConfirm"
+      @cancel="closeViewDialog"
     >
       <div class="knowledge-detail">
         <el-descriptions :column="2" border>
@@ -183,7 +188,7 @@
           <h4>鍏抽敭瑕佺偣</h4>
           <div class="key-points">
             <el-tag
-              v-for="(point, index) in currentKnowledge.keyPoints.split(',')"
+              v-for="(point, index) in currentKnowledge.keyPoints?.split(',') || []"
               :key="index"
               type="success"
               style="margin-right: 8px; margin-bottom: 8px;"
@@ -219,24 +224,19 @@
           </div>
         </div>
       </div>
-
-      <template #footer>
-        <span class="dialog-footer">
-          <el-button @click="viewDialogVisible = false">鍏抽棴</el-button>
-          <el-button type="primary" @click="copyKnowledge">澶嶅埗鐭ヨ瘑</el-button>
-          <!-- <el-button type="success" @click="markAsFavorite">鏀惰棌@</el-button> -->
-        </span>
-      </template>
-    </el-dialog>
+    </FormDialog>
   </div>
 </template>
 
 <script setup>
 import { Search } from "@element-plus/icons-vue";
-import { onMounted, ref, reactive, toRefs, getCurrentInstance, computed } from "vue";
+import { onMounted, ref, reactive, toRefs, getCurrentInstance, computed, watch } from "vue";
 import { ElMessage, ElMessageBox } from "element-plus";
 import PIMTable from "@/components/PIMTable/PIMTable.vue";
+import FormDialog from '@/components/Dialog/FormDialog.vue';
 import { listKnowledgeBase, delKnowledgeBase,addKnowledgeBase,updateKnowledgeBase } from "@/api/collaborativeApproval/knowledgeBase.js";
+import useUserStore from '@/store/modules/user';
+import { userListNoPageByTenantId } from '@/api/system/user.js';
 
 // 琛ㄥ崟楠岃瘉瑙勫垯
 const rules = {
@@ -302,6 +302,9 @@
 
 // 琛ㄥ崟寮曠敤
 const formRef = ref();
+// 鐢ㄦ埛鐩稿叧
+const userStore = useUserStore();
+const userList = ref([]);
 
 // 琛ㄦ牸鍒楅厤缃�
 const tableColumn = ref([
@@ -389,6 +392,15 @@
   }
 ]);
 
+// 鐩戝惉瀵硅瘽妗嗘墦寮�锛岃幏鍙栫敤鎴峰垪琛�
+watch(dialogVisible, (newVal) => {
+  if (newVal) {
+    userListNoPageByTenantId().then((res) => {
+      userList.value = res.data || [];
+    });
+  }
+});
+
 // 鐢熷懡鍛ㄦ湡
 onMounted(() => {
   getList();
@@ -414,7 +426,7 @@
   .then(res => {
     tableLoading.value = false;
     tableData.value = res.data.records
-    page.total = res.data.total;
+    page.value.total = res.data.total;
   }).catch(err => {
     tableLoading.value = false;
   })
@@ -437,7 +449,7 @@
   dialogType.value = type;
   if (type === "add") {
     dialogTitle.value = "鏂板鐭ヨ瘑";
-    // 閲嶇疆琛ㄥ崟
+    // 閲嶇疆琛ㄥ崟锛岄粯璁ゅ垱寤轰汉涓哄綋鍓嶇敤鎴�
     Object.assign(form.value, {
       title: "",
       type: "",
@@ -446,7 +458,7 @@
       problem: "",
       solution: "",
       keyPoints: "",
-      creator: "",
+      creator: userStore.nickName || "",
       usageCount: 0
     });
   } else if (type === "edit" && row) {
@@ -550,6 +562,39 @@
   });
 };
 
+// 鍏抽棴鐭ヨ瘑琛ㄥ崟瀵硅瘽妗�
+const closeKnowledgeDialog = () => {
+  // 娓呯┖琛ㄥ崟鏁版嵁锛岄粯璁ゅ垱寤轰汉涓哄綋鍓嶇敤鎴�
+  Object.assign(form.value, {
+    id: undefined,
+    title: "",
+    type: "",
+    scenario: "",
+    efficiency: "",
+    problem: "",
+    solution: "",
+    keyPoints: "",
+    creator: userStore.nickName || "",
+    usageCount: 0
+  });
+  // 娓呴櫎琛ㄥ崟楠岃瘉鐘舵��
+  if (formRef.value) {
+    formRef.value.clearValidate();
+  }
+  dialogVisible.value = false;
+};
+
+// 鍏抽棴鏌ョ湅璇︽儏瀵硅瘽妗�
+const closeViewDialog = () => {
+  viewDialogVisible.value = false;
+};
+
+// 澶勭悊鏌ョ湅璇︽儏瀵硅瘽妗嗙‘璁わ紙鎵ц澶嶅埗鎿嶄綔锛�
+const handleViewDialogConfirm = () => {
+  copyKnowledge();
+  closeViewDialog();
+};
+
 // 鎻愪氦鐭ヨ瘑琛ㄥ崟
 const submitForm = async () => {
   try {
@@ -559,7 +604,7 @@
       addKnowledgeBase({...form.value}).then(res => {
         if(res.code == 200){
           ElMessage.success("娣诲姞鎴愬姛");
-          dialogVisible.value = false;
+          closeKnowledgeDialog();
           getList();
         }
       }).catch(err => {
@@ -569,7 +614,7 @@
       updateKnowledgeBase({...form.value}).then(res => {
         if(res.code == 200){
           ElMessage.success("鏇存柊鎴愬姛");
-          dialogVisible.value = false;
+          closeKnowledgeDialog();
           getList();
         }
       }).catch(err => {
diff --git a/src/views/collaborativeApproval/notificationManagement/meetApplication/index.vue b/src/views/collaborativeApproval/notificationManagement/meetApplication/index.vue
index ed2dafa..4fc7088 100644
--- a/src/views/collaborativeApproval/notificationManagement/meetApplication/index.vue
+++ b/src/views/collaborativeApproval/notificationManagement/meetApplication/index.vue
@@ -127,7 +127,7 @@
             <el-option
                 v-for="person in employees"
                 :key="person.id"
-                :label="`${person.staffName} (${person.postName})`"
+                :label="`${person.staffName}${person.postName ? ` (${person.postName})` : ''}`"
                 :value="person.id"
             />
           </el-select>
@@ -307,7 +307,7 @@
     size: -1,
     staffState: 1
   }).then(res => {
-    employees.value = res.data.records.sort((a, b) => a.postName.localeCompare(b.postName))
+    employees.value = res.data.records.sort((a, b) => (a.postName || '').localeCompare(b.postName || ''))
   })
 })
 </script>
diff --git a/src/views/collaborativeApproval/notificationManagement/meetExamine/index.vue b/src/views/collaborativeApproval/notificationManagement/meetExamine/index.vue
index 157b6b5..26e2c24 100644
--- a/src/views/collaborativeApproval/notificationManagement/meetExamine/index.vue
+++ b/src/views/collaborativeApproval/notificationManagement/meetExamine/index.vue
@@ -240,7 +240,7 @@
     it.participants = staffList.value.filter(staff => staffs.some(id=>id === staff.id)).map(staff => {
       return {
         id: staff.id,
-        name: `${staff.staffName}(${staff.postName})`
+        name:  `${staff.staffName}${staff.postName ? ` (${staff.postName})` : ''}`
       }
     })
 
diff --git a/src/views/collaborativeApproval/notificationManagement/meetPublish/index.vue b/src/views/collaborativeApproval/notificationManagement/meetPublish/index.vue
index a85de7f..dace531 100644
--- a/src/views/collaborativeApproval/notificationManagement/meetPublish/index.vue
+++ b/src/views/collaborativeApproval/notificationManagement/meetPublish/index.vue
@@ -239,7 +239,7 @@
     it.participants = staffList.value.filter(staff => staffs.some(id=>id === staff.id)).map(staff => {
       return {
         id: staff.id,
-        name: `${staff.staffName}(${staff.postName})`
+        name: `${staff.staffName}${staff.postName ? ` (${staff.postName})` : ''}`
       }
     })
 
diff --git a/src/views/collaborativeApproval/notificationManagement/summary/index.vue b/src/views/collaborativeApproval/notificationManagement/summary/index.vue
index f94e548..2b26723 100644
--- a/src/views/collaborativeApproval/notificationManagement/summary/index.vue
+++ b/src/views/collaborativeApproval/notificationManagement/summary/index.vue
@@ -214,7 +214,7 @@
     it.participants = staffList.value.filter(staff => staffs.some(id => id === staff.id)).map(staff => {
       return {
         id: staff.id,
-        name: `${staff.staffName}(${staff.postName})`
+        name:  `${staff.staffName}${staff.postName ? ` (${staff.postName})` : ''}`
       }
     })
 
diff --git a/src/views/collaborativeApproval/sealManagement/index.vue b/src/views/collaborativeApproval/sealManagement/index.vue
index 04ecfc4..5193aa9 100644
--- a/src/views/collaborativeApproval/sealManagement/index.vue
+++ b/src/views/collaborativeApproval/sealManagement/index.vue
@@ -82,7 +82,14 @@
     </el-card>
 
     <!-- 鐢ㄥ嵃鐢宠瀵硅瘽妗� -->
-    <el-dialog v-model="showSealApplyDialog" title="鐢宠鐢ㄥ嵃" width="600px">
+    <FormDialog
+      v-model="showSealApplyDialog"
+      title="鐢宠鐢ㄥ嵃"
+      :width="'600px'"
+      @close="closeSealApplyDialog"
+      @confirm="submitSealApplication"
+      @cancel="closeSealApplyDialog"
+    >
       <el-form :model="sealForm" :rules="sealRules" ref="sealFormRef" label-width="100px">
         <el-form-item label="鐢宠缂栧彿" prop="applicationNum">
           <el-input v-model="sealForm.applicationNum" placeholder="璇疯緭鍏ョ敵璇风紪鍙�" />
@@ -119,13 +126,7 @@
           </el-radio-group>
         </el-form-item>
       </el-form>
-      <template #footer>
-        <span class="dialog-footer">
-          <el-button @click="showSealApplyDialog = false">鍙栨秷</el-button>
-          <el-button type="primary" @click="submitSealApplication">鎻愪氦鐢宠</el-button>
-        </span>
-      </template>
-    </el-dialog>
+    </FormDialog>
 
     <!-- 瑙勭珷鍒跺害鍙戝竷瀵硅瘽妗� -->
     <!-- <el-dialog v-model="showRegulationDialog" :title="operationType === 'add' ? '鍙戝竷鍒跺害' : '缂栬緫鍒跺害'" width="800px">
@@ -177,10 +178,17 @@
     </el-dialog> -->
 
     <!-- 鐢ㄥ嵃璇︽儏瀵硅瘽妗� -->
-    <el-dialog v-model="showSealDetailDialog" title="鐢ㄥ嵃鐢宠璇︽儏" width="700px">
+    <FormDialog
+      v-model="showSealDetailDialog"
+      title="鐢ㄥ嵃鐢宠璇︽儏"
+      :width="'700px'"
+      @close="closeSealDetailDialog"
+      @confirm="closeSealDetailDialog"
+      @cancel="closeSealDetailDialog"
+    >
       <div v-if="currentSealDetail" class="mb10">
         <el-descriptions :column="2" border>
-          <el-descriptions-item label="鐢宠缂栧彿">{{ currentSealDetail.id }}</el-descriptions-item>
+          <el-descriptions-item label="鐢宠缂栧彿">{{ currentSealDetail.applicationNum }}</el-descriptions-item>
           <el-descriptions-item label="鐢宠鏍囬">{{ currentSealDetail.title }}</el-descriptions-item>
           <el-descriptions-item label="鐢宠浜�">{{ currentSealDetail.createUserName }}</el-descriptions-item>
           <el-descriptions-item label="鎵�灞為儴闂�">{{ currentSealDetail.department }}</el-descriptions-item>
@@ -194,10 +202,17 @@
           <el-descriptions-item label="鐢宠鍘熷洜" :span="2">{{ currentSealDetail.reason }}</el-descriptions-item>
         </el-descriptions>
       </div>
-    </el-dialog>
+    </FormDialog>
 
     <!-- 瑙勭珷鍒跺害璇︽儏瀵硅瘽妗� -->
-    <el-dialog v-model="showRegulationDetailDialog" title="瑙勭珷鍒跺害璇︽儏" width="800px">
+    <FormDialog
+      v-model="showRegulationDetailDialog"
+      title="瑙勭珷鍒跺害璇︽儏"
+      :width="'800px'"
+      @close="closeRegulationDetailDialog"
+      @confirm="handleRegulationDetailConfirm"
+      @cancel="closeRegulationDetailDialog"
+    >
       <div v-if="currentRegulationDetail">
         <el-descriptions :column="2" border>
           <el-descriptions-item label="鍒跺害缂栧彿">{{ currentRegulationDetail.id }}</el-descriptions-item>
@@ -216,10 +231,17 @@
           <el-button type="success" @click="resetForm(currentRegulationDetail)">纭鏌ョ湅</el-button>
         </div>
       </div>
-    </el-dialog>
+    </FormDialog>
 
     <!-- 鐗堟湰鍘嗗彶瀵硅瘽妗� -->
-    <el-dialog v-model="showVersionHistoryDialog" title="鐗堟湰鍘嗗彶" width="800px">
+    <FormDialog
+      v-model="showVersionHistoryDialog"
+      title="鐗堟湰鍘嗗彶"
+      :width="'800px'"
+      @close="closeVersionHistoryDialog"
+      @confirm="closeVersionHistoryDialog"
+      @cancel="closeVersionHistoryDialog"
+    >
       <el-table :data="versionHistory" style="width: 100%;margin-bottom: 10px">
         <el-table-column prop="version" label="鐗堟湰鍙�" width="100" />
         <el-table-column prop="updateTime" label="鏇存柊鏃堕棿" width="180" />
@@ -232,10 +254,17 @@
           </template>
         </el-table-column>
       </el-table>
-    </el-dialog>
+    </FormDialog>
 
     <!-- 闃呰鐘舵�佸璇濇 -->
-    <el-dialog v-model="showReadStatusDialog" title="闃呰鐘舵��" width="800px">
+    <FormDialog
+      v-model="showReadStatusDialog"
+      title="闃呰鐘舵��"
+      :width="'800px'"
+      @close="closeReadStatusDialog"
+      @confirm="closeReadStatusDialog"
+      @cancel="closeReadStatusDialog"
+    >
       <el-table :data="readStatusList" style="width: 100%;margin-bottom: 10px">
         <el-table-column prop="employee" label="鍛樺伐濮撳悕" width="120" />
         <el-table-column prop="department" label="鎵�灞為儴闂�" width="150" />
@@ -249,7 +278,7 @@
           </template>
         </el-table-column>
       </el-table>
-    </el-dialog>
+    </FormDialog>
   </div>
 </template>
 
@@ -263,7 +292,8 @@
 import { getUserProfile, userListNoPageByTenantId } from '@/api/system/user.js'
 import useUserStore from '@/store/modules/user'
 import { userLoginFacotryList } from "@/api/system/user.js"
-import {staffOnJobListPage} from "@/api/personnelManagement/staffOnJob.js";
+import {staffOnJobListPage} from "@/api/personnelManagement/staffOnJob.js"
+import FormDialog from '@/components/Dialog/FormDialog.vue'
 
 // 鍝嶅簲寮忔暟鎹�
 const currentUser = ref(null)
@@ -434,7 +464,7 @@
     addSealApplication(sealForm).then(res => {
       if(res.code == 200){
         ElMessage.success('鐢宠鎻愪氦鎴愬姛')
-        showSealApplyDialog.value = false
+        closeSealApplyDialog()
         getSealApplicationList()
         Object.assign(sealForm, {
         applicationNum: '',
@@ -447,12 +477,53 @@
       })
       }
     }).catch(err => {
-      ElMessage.error(err.msg)
+      console.log(err.msg)
     })
   
   } catch (error) {
-    ElMessage.error('璇峰畬鍠勭敵璇蜂俊鎭�')
   }
+}
+// 鍏抽棴鐢ㄥ嵃鐢宠瀵硅瘽妗�
+const closeSealApplyDialog = () => {
+  // 娓呯┖琛ㄥ崟鏁版嵁
+  Object.assign(sealForm, {
+    applicationNum: '',
+    title: '',
+    sealType: '',
+    reason: '',
+    approveUserId: '',
+    urgency: 'normal',
+    status: 'pending'
+  })
+  // 娓呴櫎琛ㄥ崟楠岃瘉鐘舵��
+  if (sealFormRef.value) {
+    sealFormRef.value.clearValidate()
+  }
+  showSealApplyDialog.value = false
+}
+// 鍏抽棴鐢ㄥ嵃璇︽儏瀵硅瘽妗�
+const closeSealDetailDialog = () => {
+  showSealDetailDialog.value = false
+}
+// 鍏抽棴瑙勭珷鍒跺害璇︽儏瀵硅瘽妗�
+const closeRegulationDetailDialog = () => {
+  showRegulationDetailDialog.value = false
+}
+// 澶勭悊瑙勭珷鍒跺害璇︽儏纭
+const handleRegulationDetailConfirm = () => {
+  // 濡傛灉tableData>0锛屾墽琛岀‘璁ゆ煡鐪嬫搷浣�
+  if (currentRegulationDetail.value && tableData.value && tableData.value.length > 0) {
+    resetForm(currentRegulationDetail.value)
+  }
+  closeRegulationDetailDialog()
+}
+// 鍏抽棴鐗堟湰鍘嗗彶瀵硅瘽妗�
+const closeVersionHistoryDialog = () => {
+  showVersionHistoryDialog.value = false
+}
+// 鍏抽棴闃呰鐘舵�佸璇濇
+const closeReadStatusDialog = () => {
+  showReadStatusDialog.value = false
 }
 // 鏂板
 const handleAdd = () => {
@@ -735,6 +806,13 @@
   })
 }
 
+// 鍒嗛〉鍙樺寲澶勭悊
+const paginationChange = (obj) => {
+  page.current = obj.page;
+  page.size = obj.limit;
+  getSealApplicationList();
+};
+
 // 鐩戝惉瀵硅瘽妗嗘墦寮�锛岃幏鍙栫敤鎴峰垪琛�
 watch(showSealApplyDialog, (newVal) => {
   if (newVal) {
diff --git a/src/views/procurementManagement/invoiceEntry/index.vue b/src/views/procurementManagement/invoiceEntry/index.vue
index 11a6b4b..00a6881 100644
--- a/src/views/procurementManagement/invoiceEntry/index.vue
+++ b/src/views/procurementManagement/invoiceEntry/index.vue
@@ -112,6 +112,8 @@
   gePurchaseListPage,
   {
     purchaseContractNumber: undefined,
+    // 鍙煡璇㈠凡瀹℃壒閫氳繃锛堟垨鎸囧畾鐘舵�佷负 3锛夌殑璁板綍
+    approvalStatus: 3,
   },
   [
     {
diff --git a/src/views/procurementManagement/paymentEntry/index.vue b/src/views/procurementManagement/paymentEntry/index.vue
index 5ee8d17..3f4512b 100644
--- a/src/views/procurementManagement/paymentEntry/index.vue
+++ b/src/views/procurementManagement/paymentEntry/index.vue
@@ -261,7 +261,6 @@
   {
     label: "渚涘簲鍟嗗悕绉�",
     prop: "supplierName",
-    width:240
   },
 	{
 		label: "浠樻鐘舵��",
@@ -282,7 +281,6 @@
 		label: "浜у搧澶х被",
 		prop: "productCategory",
 		showOverflowTooltip: true,
-		width: 100
 	},
 	{
 		label: "瑙勬牸鍨嬪彿",
@@ -293,7 +291,6 @@
   {
     label: "宸蹭粯娆鹃噾棰�(鍏�)",
     prop: "ticketsTotal",
-    width: 120,
     formatData: (params) => {
       return params ? parseFloat(params).toFixed(2) : 0;
     },
@@ -301,7 +298,6 @@
   {
     label: "寰呬粯娆鹃噾棰�(鍏�)",
     prop: "pendingTicketsTotal",
-    width: 120,
     formatData: (params) => {
       return params ? parseFloat(params).toFixed(2) : 0;
     },
@@ -327,6 +323,8 @@
   searchForm: {
     supplierNameOrContractNo: "",
     status: false,
+    // 鍙煡璇㈠鎵圭姸鎬佷负 3 鐨勮褰�
+    approvalStatus: 3,
   },
   form: {
     purchaseContractNumber: "",
diff --git a/src/views/productionManagement/productionOrder/index.vue b/src/views/productionManagement/productionOrder/index.vue
index 51b42ac..4c09ac7 100644
--- a/src/views/productionManagement/productionOrder/index.vue
+++ b/src/views/productionManagement/productionOrder/index.vue
@@ -50,6 +50,7 @@
                 :tableData="tableData"
                 :page="page"
                 :tableLoading="tableLoading"
+                :row-class-name="tableRowClassName"
                 @pagination="pagination">
         <template #completionStatus="{ row }">
           <el-progress
@@ -163,6 +164,12 @@
       width: 120,
     },
     {
+      label: "浜や粯鏃ユ湡",
+      prop: "deliveryDate",
+      formatData: val => (val ? dayjs(val).format("YYYY-MM-DD") : ""),
+      width: 120,
+    },
+    {
       dataType: "action",
       label: "鎿嶄綔",
       align: "center",
@@ -228,6 +235,18 @@
     if (p < 50) return "#e6a23c";
     if (p < 80) return "#409eff";
     return "#67c23a";
+  };
+
+  // 娣诲姞琛ㄨ绫诲悕鏂规硶
+  const tableRowClassName = ({ row }) => {
+    switch (row.deliveryDaysDiff) {
+      case 15:
+        return 'yellow'
+      case 10:
+        return 'red'
+      case 2:
+        return 'purple'
+    }
   };
 
   // 缁戝畾宸ヨ壓璺嚎寮规
@@ -388,4 +407,17 @@
 <style scoped lang="scss">
 .search_form{
   align-items: start;
-}</style>
+}
+
+::v-deep .yellow {
+  background-color: #FAF0DE;
+}
+
+::v-deep .red {
+  background-color: #FAE1DE;
+}
+
+::v-deep .purple{
+  background-color: #F4DEFA;
+}
+</style>
diff --git a/src/views/safeProduction/emergencyPlanReview/index.vue b/src/views/safeProduction/emergencyPlanReview/index.vue
new file mode 100644
index 0000000..07bf56e
--- /dev/null
+++ b/src/views/safeProduction/emergencyPlanReview/index.vue
@@ -0,0 +1,810 @@
+<template>
+  <div class="app-container">
+    <div class="search_form">
+      <div>
+        <span class="search_title">搴旀�ラ妗堝悕绉帮細</span>
+        <el-input v-model="searchForm.planName"
+                  style="width: 240px"
+                  placeholder="璇疯緭鍏ュ簲鎬ラ妗堝悕绉版悳绱�"
+                  @change="handleQuery"
+                  clearable
+                  :prefix-icon="Search" />
+        <span class="search_title ml10">搴旀�ラ妗堢被鍨嬶細</span>
+        <el-select v-model="searchForm.planType"
+                   clearable
+                   @change="handleQuery"
+                   style="width: 240px">
+          <el-option v-for="item in emergencyPlanTypeOptions"
+                     :key="item.value"
+                     :label="item.label"
+                     :value="item.value" />
+        </el-select>
+        <el-button type="primary"
+                   @click="handleQuery"
+                   style="margin-left: 10px">
+          鎼滅储
+        </el-button>
+      </div>
+      <div>
+        <el-button type="primary"
+                   @click="openForm('add')">鏂板搴旀�ラ妗�</el-button>
+        <el-button type="danger"
+                   plain
+                   @click="handleDelete">鍒犻櫎</el-button>
+      </div>
+    </div>
+    <div class="table_list">
+      <PIMTable rowKey="id"
+                :column="tableColumn"
+                :tableData="tableData"
+                :page="page"
+                :isSelection="true"
+                @selection-change="handleSelectionChange"
+                :tableLoading="tableLoading"
+                @pagination="pagination"
+                :total="page.total"></PIMTable>
+    </div>
+    <!-- 鏂板/缂栬緫搴旀�ラ妗堝脊绐� -->
+    <el-dialog v-model="dialogVisible"
+               :title="dialogTitle"
+               width="800px"
+               :close-on-click-modal="false">
+      <el-form ref="formRef"
+               :model="form"
+               :rules="rules"
+               label-width="120px">
+        <el-row :gutter="20">
+          <el-col :span="12">
+            <el-form-item label="搴旀�ラ妗堢紪鐮�"
+                          prop="planCode">
+              <el-input v-model="form.planCode"
+                        placeholder="璇疯緭鍏ュ簲鎬ラ妗堢紪鐮�" />
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="搴旀�ラ妗堝悕绉�"
+                          prop="planName">
+              <el-input v-model="form.planName"
+                        placeholder="璇疯緭鍏ュ簲鎬ラ妗堝悕绉�" />
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <el-row :gutter="20">
+          <el-col :span="12">
+            <el-form-item label="鍙戝竷鐢熸晥鏃堕棿锛�"
+                          prop="publishTime">
+              <el-date-picker style="width: 100%"
+                              v-model="form.publishTime"
+                              value-format="YYYY-MM-DD"
+                              format="YYYY-MM-DD"
+                              type="date"
+                              placeholder="璇烽�夋嫨"
+                              clearable />
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="鏍稿績璐d换浜猴細"
+                          prop="coreResponsorUserId">
+              <el-select v-model="form.coreResponsorUserId"
+                         placeholder="璇烽�夋嫨"
+                         @change="handleChange"
+                         clearable>
+                <el-option v-for="item in userList"
+                           :key="item.userId"
+                           :label="item.nickName"
+                           :value="item.userId" />
+              </el-select>
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <el-row :gutter="20">
+          <el-col :span="12">
+            <el-form-item label="棰勬绫诲瀷"
+                          prop="planType">
+              <el-select v-model="form.planType"
+                         placeholder="璇烽�夋嫨棰勬绫诲瀷"
+                         style="width: 100%">
+                <el-option v-for="item in emergencyPlanTypeOptions"
+                           :key="item.value"
+                           :label="item.label"
+                           :value="item.value" />
+              </el-select>
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="澶囨敞"
+                          prop="remark">
+              <el-input v-model="form.remark"
+                        placeholder="璇疯緭鍏ュ娉�" />
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <el-form-item label="閫傜敤鑼冨洿"
+                      prop="applyScope">
+          <el-checkbox-group v-model="form.applyScope">
+            <el-checkbox label="all">鍏ㄤ綋鍛樺伐</el-checkbox>
+            <el-checkbox label="manager">绠$悊灞�</el-checkbox>
+            <el-checkbox label="hr">浜轰簨閮ㄩ棬</el-checkbox>
+            <el-checkbox label="finance">璐㈠姟閮ㄩ棬</el-checkbox>
+            <el-checkbox label="tech">鎶�鏈儴闂�</el-checkbox>
+          </el-checkbox-group>
+        </el-form-item>
+        <el-form-item label="搴旀�ュ缃楠�"
+                      prop="execSteps">
+          <div class="exec-steps-container"
+               style="width:100%">
+            <div v-for="(step, index) in execStepsList"
+                 :key="index"
+                 class="exec-step-item">
+              <div class="step-header">
+                <div>
+                  <el-input v-model="step.step"
+                            placeholder="姝ラ"
+                            style="width: 200px; margin-right: 10px" />
+                  <el-button type="danger"
+                             size="small"
+                             @click="removeExecStep(index)"
+                             style="margin-left: 10px">鍒犻櫎</el-button>
+                </div>
+                <div style="margin-top: 5px;width: 100%;">
+                  <el-input v-model="step.description"
+                            placeholder="鎺柦"
+                            type="textarea"
+                            :rows="2"
+                            style="flex: 1" />
+                </div>
+              </div>
+            </div>
+            <el-button type="primary"
+                       size="small"
+                       @click="addExecStep"
+                       style="margin-top: 10px">娣诲姞姝ラ</el-button>
+          </div>
+        </el-form-item>
+      </el-form>
+      <template #footer>
+        <span class="dialog-footer">
+          <el-button @click="dialogVisible = false">鍙栨秷</el-button>
+          <el-button type="primary"
+                     @click="submitForm">纭畾</el-button>
+        </span>
+      </template>
+    </el-dialog>
+    <!-- 鏌ョ湅搴旀�ラ妗堣鎯呭脊绐� -->
+    <el-dialog v-model="viewDialogVisible"
+               title="搴旀�ラ妗堣鎯�"
+               width="900px"
+               :close-on-click-modal="false">
+      <div class="knowledge-detail">
+        <el-descriptions :column="2"
+                         border>
+          <el-descriptions-item label="搴旀�ラ妗堝悕绉�"
+                                :span="2">
+            <span class="detail-title">{{ currentKnowledge.planName }}</span>
+          </el-descriptions-item>
+          <el-descriptions-item label="搴旀�ラ妗堢紪鐮�">
+            <span>{{ currentKnowledge.planCode }}</span>
+          </el-descriptions-item>
+          <el-descriptions-item label="鍙戝竷鐢熸晥鏃堕棿">
+            {{ currentKnowledge.publishTime }}
+          </el-descriptions-item>
+          <el-descriptions-item label="鏍稿績璐d换浜�">
+            {{ currentKnowledge.coreResponsorUserName }}
+          </el-descriptions-item>
+          <el-descriptions-item label="棰勬绫诲瀷">
+            <el-tag type="warning"> {{ currentKnowledge.planType }}</el-tag>
+          </el-descriptions-item>
+          <el-descriptions-item label="澶囨敞">
+            {{ currentKnowledge.remark }}
+          </el-descriptions-item>
+        </el-descriptions>
+        <div class="detail-section">
+          <h4>閫傜敤鑼冨洿</h4>
+          <div class="key-points">
+            <el-tag v-for="(point, index) in currentKnowledge.applyScope.split(',')"
+                    :key="index"
+                    type="primary"
+                    style="margin-right: 8px; margin-bottom: 8px;">
+              {{ getApplyScopeLabel(point.trim()) }}
+            </el-tag>
+          </div>
+        </div>
+        <div class="detail-section">
+          <h4>搴旀�ュ缃楠�</h4>
+          <div class="detail-content">
+            <div v-if="currentKnowledge.execSteps">
+              <div v-for="(step, index) in JSON.parse(currentKnowledge.execSteps)"
+                   :key="index"
+                   class="exec-step-view">
+                <span class="step-number">{{ index + 1 }}.</span>
+                <span class="step-title">{{ step.step }}锛�</span>
+                <span>{{ step.description }}</span>
+              </div>
+            </div>
+            <div v-else
+                 class="no-data">鏃犲簲鎬ュ缃楠�</div>
+          </div>
+        </div>
+      </div>
+      <template #footer>
+        <span class="dialog-footer">
+          <el-button @click="viewDialogVisible = false">鍏抽棴</el-button>
+          <!-- <el-button type="success" @click="markAsFavorite">鏀惰棌@</el-button> -->
+        </span>
+      </template>
+    </el-dialog>
+  </div>
+</template>
+
+<script setup>
+  import { Search } from "@element-plus/icons-vue";
+  import {
+    onMounted,
+    ref,
+    reactive,
+    toRefs,
+    getCurrentInstance,
+    computed,
+  } from "vue";
+  import { ElMessage, ElMessageBox } from "element-plus";
+  import PIMTable from "@/components/PIMTable/PIMTable.vue";
+  import { userListNoPage } from "@/api/system/user.js";
+  import {
+    safeContingencyPlanListPage,
+    safeContingencyPlanAdd,
+    safeContingencyPlanUpdate,
+    safeContingencyPlanDel,
+  } from "@/api/safeProduction/emergencyPlanReview.js";
+
+  // 琛ㄥ崟楠岃瘉瑙勫垯
+  const rules = {
+    planCode: [
+      { required: true, message: "璇疯緭鍏ュ簲鎬ラ妗堢紪鐮�", trigger: "blur" },
+    ],
+    applyScope: [
+      { required: true, message: "璇烽�夋嫨閫傜敤鑼冨洿", trigger: "change" },
+    ],
+    planType: [{ required: true, message: "璇烽�夋嫨棰勬绫诲瀷", trigger: "change" }],
+    planName: [
+      { required: true, message: "璇疯緭鍏ュ簲鎬ラ妗堝悕绉�", trigger: "blur" },
+    ],
+    publishTime: [
+      { required: true, message: "璇烽�夋嫨鍙戝竷鐢熸晥鏃堕棿", trigger: "change" },
+    ],
+    coreResponsorUserId: [
+      { required: true, message: "璇烽�夋嫨鏍稿績璐d换浜�", trigger: "change" },
+    ],
+  };
+
+  // 鍝嶅簲寮忔暟鎹�
+  const data = reactive({
+    searchForm: {
+      planName: "",
+      planType: "",
+    },
+    tableLoading: false,
+    page: {
+      current: 1,
+      size: 20,
+      total: 0,
+    },
+    tableData: [],
+    selectedIds: [],
+    form: {
+      planCode: "", // 棰勬缂栧彿
+      applyScope: [], // 閫傜敤鑼冨洿
+      planType: "", // 棰勬绫诲瀷
+      planName: "", // 棰勬鍚嶇О
+      publishTime: "", // 鍙戝竷鏃堕棿
+      coreResponsorUserId: "", // 鏍稿績璐熻矗浜虹敤鎴稩D
+      coreResponsorUserName: "", // 鏍稿績璐熻矗浜虹敤鎴峰悕
+      remark: "", // 澶囨敞
+      execSteps: "", // 鎵ц姝ラ
+    },
+    dialogVisible: false,
+    dialogTitle: "",
+    dialogType: "add",
+    viewDialogVisible: false,
+    currentKnowledge: {},
+  });
+
+  const {
+    searchForm,
+    tableLoading,
+    page,
+    tableData,
+    selectedIds,
+    form,
+    dialogVisible,
+    dialogTitle,
+    dialogType,
+    viewDialogVisible,
+    currentKnowledge,
+  } = toRefs(data);
+
+  // 琛ㄥ崟寮曠敤
+  const formRef = ref();
+  const execStepsList = ref([]);
+
+  // 琛ㄦ牸鍒楅厤缃�
+  const tableColumn = ref([
+    {
+      label: "搴旀�ラ妗堢紪鐮�",
+      prop: "planCode",
+      showOverflowTooltip: true,
+    },
+    {
+      label: "搴旀�ラ妗堝悕绉�",
+      prop: "planName",
+      showOverflowTooltip: true,
+    },
+    {
+      label: "鍙戝竷鐢熸晥鏃堕棿",
+      prop: "publishTime",
+      showOverflowTooltip: true,
+    },
+    {
+      label: "鏍稿績璐d换浜�",
+      prop: "coreResponsorUserName",
+      showOverflowTooltip: true,
+    },
+    {
+      label: "棰勬绫诲瀷",
+      prop: "planType",
+      showOverflowTooltip: true,
+    },
+    {
+      label: "澶囨敞",
+      prop: "remark",
+      showOverflowTooltip: true,
+    },
+    {
+      dataType: "action",
+      label: "鎿嶄綔",
+      align: "center",
+      fixed: "right",
+      width: 200,
+      operation: [
+        {
+          name: "缂栬緫",
+          type: "text",
+          clickFun: row => {
+            openForm("edit", row);
+          },
+        },
+        {
+          name: "鏌ョ湅",
+          type: "text",
+          clickFun: row => {
+            viewKnowledge(row);
+          },
+        },
+      ],
+    },
+  ]);
+  const userList = ref([]);
+  // 鐢熷懡鍛ㄦ湡
+  onMounted(() => {
+    userListNoPage().then(res => {
+      userList.value = res.data;
+    });
+    getList();
+    startAutoRefresh();
+  });
+  const handleChange = userId => {
+    const selectedUser = userList.value.find(user => user.userId === userId);
+    if (selectedUser) {
+      form.value.coreResponsorUserName = selectedUser.nickName;
+    }
+  };
+
+  // 搴旀�ュ缃楠ょ鐞�
+  const addExecStep = () => {
+    const stepNumber = execStepsList.value.length + 1;
+    execStepsList.value.push({
+      step: `姝ラ${stepNumber}`,
+      description: "",
+    });
+  };
+
+  const removeExecStep = index => {
+    execStepsList.value.splice(index, 1);
+  };
+
+  const initExecSteps = execSteps => {
+    if (execSteps) {
+      try {
+        execStepsList.value = JSON.parse(execSteps);
+      } catch (e) {
+        execStepsList.value = [];
+      }
+    } else {
+      execStepsList.value = [];
+    }
+  };
+  // 寮�濮嬭嚜鍔ㄥ埛鏂�
+  const startAutoRefresh = () => {
+    setInterval(() => {
+      getList();
+    }, 600000); // 10鍒嗛挓鍒锋柊涓�娆� (10 * 60 * 1000 = 600000ms)
+  };
+
+  // 鏌ヨ鏁版嵁
+  const handleQuery = () => {
+    page.value.current = 1;
+    getList();
+  };
+
+  const getList = () => {
+    tableLoading.value = true;
+    safeContingencyPlanListPage({ ...page.value, ...searchForm.value })
+      .then(res => {
+        tableLoading.value = false;
+        tableData.value = res.data.records;
+        page.total = res.data.total;
+      })
+      .catch(err => {
+        tableLoading.value = false;
+      });
+  };
+
+  // 鍒嗛〉澶勭悊
+  const pagination = obj => {
+    page.value.current = obj.page;
+    page.value.size = obj.limit;
+    handleQuery();
+  };
+
+  // 閫夋嫨鍙樺寲澶勭悊
+  const handleSelectionChange = selection => {
+    selectedIds.value = selection.map(item => item.id);
+  };
+
+  // 鎵撳紑琛ㄥ崟
+  const openForm = (type, row = null) => {
+    dialogType.value = type;
+    if (type === "add") {
+      dialogTitle.value = "鏂板搴旀�ラ妗�";
+      // 閲嶇疆琛ㄥ崟
+      Object.assign(form.value, {
+        planCode: "", // 棰勬缂栧彿
+        applyScope: [], // 閫傜敤鑼冨洿
+        planType: "", // 棰勬绫诲瀷
+        planName: "", // 棰勬鍚嶇О
+        publishTime: "", // 鍙戝竷鏃堕棿
+        coreResponsorUserId: "", // 鏍稿績璐熻矗浜虹敤鎴稩D
+        coreResponsorUserName: "", // 鏍稿績璐熻矗浜虹敤鎴峰悕
+        remark: "", // 澶囨敞
+        execSteps: "", // 鎵ц姝ラ
+      });
+      initExecSteps("");
+    } else if (type === "edit" && row) {
+      dialogTitle.value = "缂栬緫搴旀�ラ妗�";
+      Object.assign(form.value, {
+        id: row.id,
+        planCode: row.planCode, // 棰勬缂栧彿
+        applyScope: row.applyScope ? row.applyScope.split(",") : [], // 閫傜敤鑼冨洿
+        planType: row.planType, // 棰勬绫诲瀷
+        planName: row.planName, // 棰勬鍚嶇О
+        publishTime: row.publishTime, // 鍙戝竷鏃堕棿
+        coreResponsorUserId: row.coreResponsorUserId, // 鏍稿績璐熻矗浜虹敤鎴稩D
+        coreResponsorUserName: row.coreResponsorUserName, // 鏍稿績璐熻矗浜虹敤鎴峰悕
+        remark: row.remark, // 澶囨敞
+        execSteps: row.execSteps, // 鎵ц姝ラ
+      });
+      initExecSteps(row.execSteps);
+    }
+    dialogVisible.value = true;
+  };
+
+  // 鏌ョ湅搴旀�ラ妗堣鎯�
+  const viewKnowledge = row => {
+    currentKnowledge.value = { ...row };
+    viewDialogVisible.value = true;
+  };
+  const getApplyScopeLabel = scope => {
+    const scopeMap = {
+      all: "鍏ㄤ綋鍛樺伐",
+      manager: "绠$悊灞�",
+      hr: "浜轰簨閮ㄩ棬",
+      finance: "璐㈠姟閮ㄩ棬",
+      tech: "鎶�鏈儴闂�",
+    };
+    return scopeMap[scope] || scope;
+  };
+
+  // 鑾峰彇绫诲瀷鏍囩绫诲瀷
+  const getTypeTagType = type => {
+    const typeMap = {
+      contract: "success",
+      approval: "warning",
+      solution: "primary",
+      experience: "info",
+      guide: "danger",
+    };
+    return typeMap[type] || "info";
+  };
+
+  // 鑾峰彇绫诲瀷鏍囩鏂囨湰
+  const getTypeLabel = type => {
+    return getKnowledgeTypeLabel(type);
+  };
+
+  // 鑾峰彇鏁堢巼鏍囩绫诲瀷
+  const getEfficiencyTagType = efficiency => {
+    const typeMap = {
+      high: "success",
+      medium: "warning",
+      low: "info",
+    };
+    return typeMap[efficiency] || "info";
+  };
+
+  // 鑾峰彇鏁堢巼鏍囩鏂囨湰
+  const getEfficiencyLabel = efficiency => {
+    const efficiencyMap = {
+      high: "鏄捐憲鎻愬崌",
+      medium: "涓�鑸彁鍗�",
+      low: "杞诲井鎻愬崌",
+    };
+    return efficiencyMap[efficiency] || efficiency;
+  };
+
+  // 鑾峰彇鏁堢巼鎻愬崌鐧惧垎姣�
+  const getEfficiencyScore = efficiency => {
+    const scoreMap = {
+      high: 40,
+      medium: 25,
+      low: 15,
+    };
+    return scoreMap[efficiency] || 0;
+  };
+
+  // 鑾峰彇骞冲潎鑺傜渷鏃堕棿
+  const getTimeSaved = efficiency => {
+    const timeMap = {
+      high: "2-3澶�",
+      medium: "1-2澶�",
+      low: "0.5-1澶�",
+    };
+    return timeMap[efficiency] || "鏈煡";
+  };
+  const emergencyPlanTypeOptions = computed(() => [
+    {
+      value: "棰勯槻鎬у簲鎬ラ妗�",
+      label: "棰勯槻鎬у簲鎬ラ妗�",
+    },
+    {
+      value: "搴旀�ュ鐞嗛妗�",
+      label: "搴旀�ュ鐞嗛妗�",
+    },
+    {
+      value: "鎭㈠鎬у簲鎬ラ妗�",
+      label: "鎭㈠鎬у簲鎬ラ妗�",
+    },
+  ]);
+  // 鎻愪氦搴旀�ラ妗堣〃鍗�
+  const submitForm = async () => {
+    try {
+      await formRef.value.validate();
+
+      // 楠岃瘉搴旀�ュ缃楠�
+      for (let i = 0; i < execStepsList.value.length; i++) {
+        const step = execStepsList.value[i];
+        if (!step.step || !step.step.trim()) {
+          ElMessage.error(`绗�${i + 1}鏉℃楠ょ殑"姝ラ"涓嶈兘涓虹┖`);
+          return;
+        }
+        if (!step.description || !step.description.trim()) {
+          ElMessage.error(`绗�${i + 1}鏉℃楠ょ殑"鎺柦"涓嶈兘涓虹┖`);
+          return;
+        }
+      }
+
+      // 灏嗗簲鎬ュ缃楠よ浆鎹负JSON瀛楃涓�
+      form.value.execSteps = JSON.stringify(execStepsList.value);
+      if (dialogType.value === "add") {
+        // 鏂板搴旀�ラ妗�
+        form.value.applyScope = form.value.applyScope.join(",");
+        safeContingencyPlanAdd({ ...form.value })
+          .then(res => {
+            if (res.code == 200) {
+              ElMessage.success("娣诲姞鎴愬姛");
+              dialogVisible.value = false;
+              getList();
+            }
+          })
+          .catch(err => {
+            ElMessage.error(err.msg);
+          });
+      } else {
+        form.value.applyScope = form.value.applyScope.join(",");
+        safeContingencyPlanUpdate({ ...form.value })
+          .then(res => {
+            if (res.code == 200) {
+              ElMessage.success("鏇存柊鎴愬姛");
+              dialogVisible.value = false;
+              getList();
+            }
+          })
+          .catch(err => {
+            ElMessage.error(err.msg);
+          });
+      }
+    } catch (error) {
+      console.error("琛ㄥ崟楠岃瘉澶辫触:", error);
+    }
+  };
+
+  // 鍒犻櫎搴旀�ラ妗�
+  const handleDelete = () => {
+    if (selectedIds.value.length === 0) {
+      ElMessage.warning("璇烽�夋嫨瑕佸垹闄ょ殑搴旀�ラ妗�");
+      return;
+    }
+
+    ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚垹闄わ紝鏄惁纭鍒犻櫎锛�", "鍒犻櫎", {
+      confirmButtonText: "纭",
+      cancelButtonText: "鍙栨秷",
+      type: "warning",
+    })
+      .then(() => {
+        // console.log(selectedIds.value);
+        safeContingencyPlanDel(selectedIds.value).then(res => {
+          if (res.code == 200) {
+            ElMessage.success("鍒犻櫎鎴愬姛");
+            selectedIds.value = [];
+            getList();
+          }
+        });
+      })
+      .catch(() => {
+        // 鐢ㄦ埛鍙栨秷
+      });
+  };
+
+  // 瀵煎嚭
+  const { proxy } = getCurrentInstance();
+  const { knowledge_type } = proxy.useDict("knowledge_type");
+
+  // 瀛楀吀宸ュ叿
+  const knowledgeTypeOptions = computed(() => knowledge_type?.value || []);
+  const getKnowledgeTypeLabel = val => {
+    const item = knowledgeTypeOptions.value.find(
+      i => String(i.value) === String(val)
+    );
+    return item ? item.label : val;
+  };
+  const getKnowledgeTypeTagType = val => {
+    const item = knowledgeTypeOptions.value.find(
+      i => String(i.value) === String(val)
+    );
+    return item?.elTagType || "info";
+  };
+  const handleExport = () => {
+    proxy.download(
+      "/knowledgeBase/export",
+      { ...searchForm.value },
+      "搴旀�ラ妗堝簱.xlsx"
+    );
+  };
+</script>
+
+<style scoped>
+  .auto-refresh-info {
+    margin-bottom: 15px;
+  }
+
+  .auto-refresh-info .el-alert {
+    border-radius: 8px;
+  }
+
+  .dialog-footer {
+    text-align: right;
+  }
+
+  .knowledge-detail {
+    padding: 20px 0;
+  }
+
+  .detail-title {
+    font-size: 18px;
+    font-weight: bold;
+    color: #303133;
+  }
+
+  .detail-section {
+    margin-top: 24px;
+  }
+
+  .detail-section h4 {
+    margin: 0 0 12px 0;
+    font-size: 16px;
+    font-weight: 600;
+    color: #303133;
+    border-left: 4px solid #409eff;
+    padding-left: 12px;
+  }
+
+  .detail-content {
+    background: #f8f9fa;
+    padding: 16px;
+    border-radius: 6px;
+    line-height: 1.6;
+    color: #606266;
+    white-space: pre-wrap;
+  }
+
+  .key-points {
+    display: flex;
+    flex-wrap: wrap;
+    gap: 8px;
+  }
+
+  .usage-stats {
+    margin-top: 16px;
+  }
+
+  .stat-item {
+    text-align: center;
+    padding: 20px;
+    background: #f8f9fa;
+    border-radius: 8px;
+  }
+
+  .stat-number {
+    font-size: 24px;
+    font-weight: bold;
+    color: #409eff;
+    margin-bottom: 8px;
+  }
+
+  .stat-label {
+    font-size: 14px;
+    color: #909399;
+  }
+
+  .exec-steps-container {
+    border: 1px solid #e4e7ed;
+    border-radius: 4px;
+    padding: 15px;
+    background-color: #f9fafc;
+  }
+
+  .exec-step-item {
+    margin-bottom: 10px;
+    padding: 10px;
+    background-color: #ffffff;
+    border: 1px solid #e4e7ed;
+    border-radius: 4px;
+  }
+
+  .step-header {
+    display: flex;
+    align-items: flex-start;
+    flex-direction: column;
+  }
+
+  .exec-step-view {
+    margin-bottom: 8px;
+    padding-left: 20px;
+    position: relative;
+  }
+
+  .step-number {
+    position: absolute;
+    left: 0;
+    font-weight: bold;
+    color: #409eff;
+  }
+
+  .step-title {
+    font-weight: bold;
+    margin-right: 5px;
+  }
+
+  .no-data {
+    color: #909399;
+    font-style: italic;
+  }
+</style>
diff --git a/src/views/safeProduction/hazardousMaterialsControl/index.vue b/src/views/safeProduction/hazardousMaterialsControl/index.vue
index 63d9a5b..5be4bdc 100644
--- a/src/views/safeProduction/hazardousMaterialsControl/index.vue
+++ b/src/views/safeProduction/hazardousMaterialsControl/index.vue
@@ -53,7 +53,8 @@
                v-if="dialogType === 'add'"
                :model="form"
                :rules="rules"
-               label-width="120px">
+               label-width="140px"
+               label-position="top">
         <el-row :gutter="20">
           <el-col :span="12">
             <el-form-item label="鍗遍櫓婧�"
@@ -200,7 +201,8 @@
                v-if="dialogType === 'edit'"
                :model="form"
                :rules="rules1"
-               label-width="120px">
+               label-width="140px"
+               label-position="top">
         <el-row :gutter="20">
           <el-col :span="12">
             <el-form-item label="褰掕繕浜�"
diff --git a/src/views/salesManagement/deliveryLedger/index.vue b/src/views/salesManagement/deliveryLedger/index.vue
index 983a3e5..52e14cb 100644
--- a/src/views/salesManagement/deliveryLedger/index.vue
+++ b/src/views/salesManagement/deliveryLedger/index.vue
@@ -52,7 +52,7 @@
               type="primary" 
               size="small" 
               :disabled="isApproving(scope.row.status)"
-              @click="openForm('edit', scope.row)">缂栬緫</el-button>
+              @click="openForm('edit', scope.row)">琛ュ厖鍙戣揣淇℃伅</el-button>
             <el-button 
               link 
               type="danger" 
@@ -177,9 +177,9 @@
 import { getToken } from "@/utils/auth";
 import { getCurrentDate } from "@/utils/index.js";
 import {
-  deliveryLedgerListPage,
-  addOrUpdateDeliveryLedger,
-  delDeliveryLedger,
+	deliveryLedgerListPage,
+	addOrUpdateDeliveryLedger,
+	delDeliveryLedger, deductStock,
 } from "@/api/salesManagement/deliveryLedger.js";
 import { delLedgerFile } from "@/api/salesManagement/salesLedger.js";
  
@@ -392,7 +392,7 @@
         expressNumber: form.value.type === "蹇��" ? form.value.expressNumber : "",
         tempFileIds: tempFileIds,
       };
-      addOrUpdateDeliveryLedger(payload).then((res) => {
+			deductStock(payload).then((res) => {
         proxy.$modal.msgSuccess("鎿嶄綔鎴愬姛");
         closeDia();
         getList();
diff --git a/src/views/salesManagement/salesLedger/index.vue b/src/views/salesManagement/salesLedger/index.vue
index da26ba7..457f0f1 100644
--- a/src/views/salesManagement/salesLedger/index.vue
+++ b/src/views/salesManagement/salesLedger/index.vue
@@ -37,7 +37,7 @@
         </div>
       </div>
       <el-table :data="tableData" border v-loading="tableLoading" @selection-change="handleSelectionChange"
-        :expand-row-keys="expandedRowKeys" :row-key="(row) => row.id" show-summary style="width: 100%"
+        :expand-row-keys="expandedRowKeys" :row-key="(row) => row.id" :row-class-name="tableRowClassName" show-summary style="width: 100%"
         :summary-method="summarizeMainTable" @expand-change="expandChange" height="calc(100vh - 18.5em)">
         <el-table-column align="center" type="selection" width="55" fixed="left"/>
         <el-table-column type="expand" width="60" fixed="left">
@@ -117,6 +117,7 @@
         <el-table-column label="褰曞叆浜�" prop="entryPersonName" width="100" show-overflow-tooltip />
         <el-table-column label="褰曞叆鏃ユ湡" prop="entryDate" width="120" show-overflow-tooltip />
         <el-table-column label="绛捐鏃ユ湡" prop="executionDate" width="120" show-overflow-tooltip />
+        <el-table-column label="浜や粯鏃ユ湡" prop="deliveryDate" width="120" show-overflow-tooltip />
         <el-table-column fixed="right" label="鎿嶄綔" min-width="100" align="center">
           <template #default="scope">
             <el-button link type="primary" size="small" @click="openForm('edit', scope.row)">缂栬緫</el-button>
@@ -204,6 +205,14 @@
 						</el-form-item>
 					</el-col>
 				</el-row>
+        <el-row :gutter="30">
+          <el-col :span="12">
+            <el-form-item label="浜よ揣鏃ユ湡锛�" prop="entryDate">
+              <el-date-picker style="width: 100%" v-model="form.deliveryDate" value-format="YYYY-MM-DD" format="YYYY-MM-DD"
+                              type="date" placeholder="璇烽�夋嫨" clearable />
+            </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>
@@ -694,6 +703,7 @@
 		customerId: "",
 		entryPerson: "",
 		entryDate: "",
+    deliveryDate: "",
 		maintenanceTime: "",
 		productData: [],
 		executionDate: "",
@@ -703,6 +713,7 @@
 		customerId: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
 		entryPerson: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
 		entryDate: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
+    deliveryDate: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
 		executionDate: [{ required: true, message: "璇烽�夋嫨", trigger: "change" }],
 	},
 });
@@ -986,6 +997,18 @@
 	} else {
 		expandedRowKeys.value = [];
 	}
+};
+
+// 娣诲姞琛ㄨ绫诲悕鏂规硶
+const tableRowClassName = ({ row }) => {
+  switch (row.deliveryDaysDiff) {
+    case 15:
+      return 'yellow'
+    case 10:
+      return 'red'
+    case 2:
+      return 'purple'
+  }
 };
 // 涓昏〃鍚堣鏂规硶
 const summarizeMainTable = (param) => {
@@ -2084,6 +2107,19 @@
 	margin-left: 10px;
 }
 
+::v-deep .yellow {
+  background-color: #FAF0DE;
+}
+
+::v-deep .red {
+  background-color: #FAE1DE;
+}
+
+::v-deep .purple{
+  background-color: #F4DEFA;
+}
+
+
 .table_list {
 	margin-top: unset;
 }
diff --git a/src/views/salesManagement/salesQuotation/index.vue b/src/views/salesManagement/salesQuotation/index.vue
index cbbc4f8..d6f6c80 100644
--- a/src/views/salesManagement/salesQuotation/index.vue
+++ b/src/views/salesManagement/salesQuotation/index.vue
@@ -51,7 +51,7 @@
         height="calc(100vh - 22em)"
       >
 				<el-table-column align="center" label="搴忓彿" type="index" width="60" />
-        <el-table-column prop="quotationNo" label="鎶ヤ环鍗曞彿" width="150" />
+        <el-table-column prop="quotationNo" label="鎶ヤ环鍗曞彿" />
         <el-table-column prop="customer" label="瀹㈡埛鍚嶇О" />
         <el-table-column prop="salesperson" label="涓氬姟鍛�" width="100" />
         <el-table-column prop="quotationDate" label="鎶ヤ环鏃ユ湡" width="120" />
@@ -252,7 +252,7 @@
 									@change="getProductModel($event, scope.row)"
 								>
 									<el-option
-										v-for="item in modelOptions"
+										v-for="item in scope.row.modelOptions || []"
 										:key="item.id"
 										:label="item.model"
 										:value="item.id"
@@ -322,7 +322,7 @@
         </el-descriptions-item>
       </el-descriptions>
       
-      <div style="margin-top: 20px;">
+      <div style="margin: 20px 0;">
         <h4>浜у搧鏄庣粏</h4>
         <el-table :data="currentQuotation.products" border style="width: 100%">
           <el-table-column prop="product" label="浜у搧鍚嶇О" />
@@ -521,7 +521,7 @@
 	if (!value) {
 		row.productId = '';
 		row.product = '';
-		modelOptions.value = [];
+		row.modelOptions = [];
 		row.specificationId = '';
 		row.specification = '';
 		row.unit = '';
@@ -534,9 +534,9 @@
 	if (label) {
 		row.product = label;
 	}
-	// 鑾峰彇瑙勬牸鍨嬪彿鍒楄〃
+	// 鑾峰彇瑙勬牸鍨嬪彿鍒楄〃锛岃缃埌褰撳墠琛岀殑 modelOptions
 	modelList({ id: value }).then((res) => {
-		modelOptions.value = res || [];
+		row.modelOptions = res || [];
 	});
 };
 const getProductModel = (value, row) => {
@@ -550,10 +550,11 @@
 	}
 	// 鏇存柊 specificationId锛坴-model 宸茬粡鑷姩鏇存柊锛岃繖閲岀‘淇濅竴鑷存�э級
 	row.specificationId = value;
-	const index = modelOptions.value.findIndex((item) => item.id === value);
+	const modelOptions = row.modelOptions || [];
+	const index = modelOptions.findIndex((item) => item.id === value);
 	if (index !== -1) {
-		row.specification = modelOptions.value[index].model;
-		row.unit = modelOptions.value[index].unit;
+		row.specification = modelOptions[index].model;
+		row.unit = modelOptions[index].unit;
 	} else {
 		row.specification = '';
 		row.unit = '';
@@ -616,23 +617,46 @@
   form.paymentMethod = row.paymentMethod || ''
   form.status = row.status || '鑽夌'
   form.remark = row.remark || ''
-  form.products = row.products ? row.products.map(product => {
+  form.products = row.products ? await Promise.all(row.products.map(async (product) => {
     const productName = product.product || product.productName || ''
     // 浼樺厛鐢� productId锛涘鏋滃彧鏈夊悕绉帮紝灏濊瘯鍙嶆煡 id 浠ヤ究鏍戦�夋嫨鍣ㄥ弽鏄�
-    const resolvedId = product.productId
+    const resolvedProductId = product.productId
       ? Number(product.productId)
       : findNodeIdByLabel(productOptions.value, productName) || ''
+    
+    // 濡傛灉鏈変骇鍝両D锛屽姞杞藉搴旂殑瑙勬牸鍨嬪彿鍒楄〃
+    let modelOptions = [];
+    let resolvedSpecificationId = product.specificationId || '';
+    
+    if (resolvedProductId) {
+      try {
+        const res = await modelList({ id: resolvedProductId });
+        modelOptions = res || [];
+        
+        // 濡傛灉杩斿洖鐨勬暟鎹病鏈� specificationId锛屼絾鏈� specification 鍚嶇О锛屾牴鎹悕绉版煡鎵� ID
+        if (!resolvedSpecificationId && product.specification) {
+          const foundModel = modelOptions.find(item => item.model === product.specification);
+          if (foundModel) {
+            resolvedSpecificationId = foundModel.id;
+          }
+        }
+      } catch (error) {
+        console.error('鍔犺浇瑙勬牸鍨嬪彿澶辫触:', error);
+      }
+    }
+    
     return {
-      productId: resolvedId,
+      productId: resolvedProductId,
       product: productName,
-      specificationId: product.specificationId || '',
+      specificationId: resolvedSpecificationId,
       specification: product.specification || '',
       quantity: product.quantity || 0,
       unit: product.unit || '',
       unitPrice: product.unitPrice || 0,
-      amount: product.amount || 0
+      amount: product.amount || 0,
+      modelOptions: modelOptions // 涓烘瘡琛屾坊鍔犵嫭绔嬬殑瑙勬牸鍨嬪彿鍒楄〃
     }
-  }) : []
+  })) : []
   form.subtotal = row.subtotal || 0
   form.freight = row.freight || 0
   form.otherFee = row.otherFee || 0
@@ -714,7 +738,8 @@
     quantity: 1,
     unit: '',
     unitPrice: 0,
-    amount: 0
+    amount: 0,
+    modelOptions: [] // 涓烘瘡琛屾坊鍔犵嫭绔嬬殑瑙勬牸鍨嬪彿鍒楄〃
   })
 }
 

--
Gitblit v1.9.3