From 75435383608c681cb4158b22c166bc3a3cd33c96 Mon Sep 17 00:00:00 2001
From: huminmin <mac@MacBook-Pro.local>
Date: 星期五, 15 五月 2026 13:26:48 +0800
Subject: [PATCH] Merge branch 'dev_NEW_pro' of http://114.132.189.42:9002/r/product-inventory-management into dev_NEW_pro

---
 src/views/reportAnalysis/PSIDataAnalysis/components/left-top.vue          |    9 
 multiple/config.json                                                      |    2 
 src/views/reportAnalysis/productionAnalysis/index.vue                     |   16 +
 src/views/equipmentManagement/measurementEquipment/components/formDia.vue |   34 --
 src/views/equipmentManagement/upkeep/Form/PlanModal.vue                   |   13 
 src/views/reportAnalysis/dataDashboard/index.vue                          |   16 +
 src/views/equipmentManagement/inspectionManagement/components/formDia.vue |   19 +
 src/views/equipmentManagement/repair/Modal/AcceptanceModal.vue            |  144 ++++++++++
 src/views/reportAnalysis/dataDashboard/components/basic/right-top.vue     |    9 
 src/views/reportAnalysis/productionAnalysis/components/left-top.vue       |    9 
 src/views/reportAnalysis/dataDashboard/components/basic/right-bottom.vue  |    9 
 src/views/personnelManagement/contractManagement/index.vue                |   22 +
 src/views/reportAnalysis/PSIDataAnalysis/index.vue                        |   16 +
 src/views/collaborativeApproval/sealManagement/index.vue                  |   82 +++++
 src/views/reportAnalysis/productionAnalysis/components/center-center.vue  |    9 
 src/views/reportAnalysis/productionAnalysis/components/right-top.vue      |    9 
 src/views/reportAnalysis/productionAnalysis/components/left-bottom.vue    |    9 
 src/views/reportAnalysis/productionAnalysis/components/right-bottom.vue   |    9 
 src/views/equipmentManagement/upkeep/index.vue                            |    5 
 src/views/personnelManagement/employeeRecord/index.vue                    |   59 ++-
 src/views/equipmentManagement/repair/Modal/RepairModal.vue                |   38 ++
 src/views/equipmentManagement/repair/index.vue                            |   36 ++
 src/views/reportAnalysis/dataDashboard/components/basic/center-bottom.vue |    9 
 src/views/equipmentManagement/inspectionManagement/index.vue              |   17 +
 src/views/reportAnalysis/productionAnalysis/components/center-top.vue     |    9 
 src/views/reportAnalysis/PSIDataAnalysis/components/left-bottom.vue       |    9 
 src/views/reportAnalysis/dataDashboard/components/basic/left-bottom.vue   |    9 
 src/views/procurementManagement/procurementLedger/index.vue               |    1 
 src/api/equipmentManagement/repair.js                                     |   13 
 src/views/equipmentManagement/measurementEquipment/index.vue              |   48 ++
 src/views/reportAnalysis/PSIDataAnalysis/components/center-bottom.vue     |    9 
 src/views/reportAnalysis/PSIDataAnalysis/components/center-top.vue        |    9 
 src/views/reportAnalysis/productionAnalysis/components/center-bottom.vue  |   27 +
 src/views/equipmentManagement/upkeep/Form/formDia.vue                     |   22 +
 src/views/reportAnalysis/PSIDataAnalysis/components/center-center.vue     |    9 
 src/views/reportAnalysis/dataDashboard/components/basic/center-top.vue    |   44 ++-
 src/views/reportAnalysis/dataDashboard/components/basic/left-top.vue      |    9 
 37 files changed, 682 insertions(+), 136 deletions(-)

diff --git a/multiple/config.json b/multiple/config.json
index 802ef67..6a0b9e6 100644
--- a/multiple/config.json
+++ b/multiple/config.json
@@ -44,7 +44,7 @@
   },
   "BTYX": {
     "env": {
-      "VITE_APP_TITLE": "娌冲崡甯お浼橀�夎繘鍑哄彛鏈夐檺鍏徃",
+      "VITE_APP_TITLE": "娌冲崡甯お浼橀�夐鍝佹湁闄愬叕鍙�",
       "VITE_BASE_API": "http://1.15.17.182:9056",
       "VITE_JAVA_API": "http://1.15.17.182:9057"
     },
diff --git a/src/api/equipmentManagement/repair.js b/src/api/equipmentManagement/repair.js
index 0233ae6..16bfd28 100644
--- a/src/api/equipmentManagement/repair.js
+++ b/src/api/equipmentManagement/repair.js
@@ -70,3 +70,16 @@
     data,
   });
 };
+
+/**
+ * @desc 楠屾敹瀹℃壒
+ * @param {楠屾敹鍙傛暟} data
+ * @returns
+ */
+export const repairAcceptance = (data) => {
+  return request({
+    url: `/device/repair/acceptance`,
+    method: "post",
+    data,
+  });
+};
diff --git a/src/views/collaborativeApproval/sealManagement/index.vue b/src/views/collaborativeApproval/sealManagement/index.vue
index a6232c2..9d68848 100644
--- a/src/views/collaborativeApproval/sealManagement/index.vue
+++ b/src/views/collaborativeApproval/sealManagement/index.vue
@@ -87,10 +87,18 @@
         </el-form-item>
         <el-form-item label="绱ф�ョ▼搴�" prop="urgency">
           <el-radio-group v-model="sealForm.urgency">
-            <el-radio label="normal">鏅��</el-radio>
-            <el-radio label="urgent">绱ф��</el-radio>
-            <el-radio label="very-urgent">鐗规��</el-radio>
+            <el-radio value="normal">鏅��</el-radio>
+            <el-radio value="urgent">绱ф��</el-radio>
+            <el-radio value="very-urgent">鐗规��</el-radio>
           </el-radio-group>
+        </el-form-item>
+        <el-form-item label="闄勪欢涓婁紶">
+          <AttachmentUploadFile
+            v-model:fileList="sealForm.storageBlobDTOs"
+            :limit="10"
+            :fileSize="50"
+            buttonText="鐐瑰嚮涓婁紶闄勪欢"
+          />
         </el-form-item>
       </el-form>
     </FormDialog>
@@ -119,8 +127,27 @@
           </el-descriptions-item>
           <el-descriptions-item label="鐢宠鍘熷洜" :span="2">{{ currentSealDetail.reason }}</el-descriptions-item>
         </el-descriptions>
+        <!-- 闄勪欢鍒楄〃 -->
+        <div v-if="currentSealDetail.storageBlobVOList?.length || currentSealDetail.storageBlobDTOs?.length" class="attachment-section">
+          <div class="attachment-title">闄勪欢鍒楄〃锛�</div>
+          <el-table :data="currentSealDetail.storageBlobVOList || currentSealDetail.storageBlobDTOs" border class="attachment-table">
+            <el-table-column label="闄勪欢鍚嶇О" show-overflow-tooltip>
+              <template #default="scope">
+                {{ scope.row.originalFilename || scope.row.name || scope.row.fileName || '鏈懡鍚嶆枃浠�' }}
+              </template>
+            </el-table-column>
+            <el-table-column fixed="right" label="鎿嶄綔" width="150" align="center">
+              <template #default="scope">
+                <el-button link type="primary" size="small" @click="previewFile(scope.row)">棰勮</el-button>
+                <el-button link type="primary" size="small" @click="downloadFile(scope.row)">涓嬭浇</el-button>
+              </template>
+            </el-table-column>
+          </el-table>
+        </div>
       </div>
     </FormDialog>
+    <!-- 鏂囦欢棰勮缁勪欢 -->
+    <FilePreview ref="filePreviewRef" />
 
   </div>
 </template>
@@ -134,6 +161,9 @@
 import useUserStore from '@/store/modules/user'
 import FormDialog from '@/components/Dialog/FormDialog.vue'
 import PIMTable from '@/components/PIMTable/PIMTable.vue'
+import AttachmentUploadFile from '@/components/AttachmentUpload/file/index.vue'
+import FilePreview from '@/components/filePreview/index.vue'
+import download from '@/plugins/download.js'
 
 // 鍝嶅簲寮忔暟鎹�
 // 鐢ㄥ嵃鐢宠鐩稿叧
@@ -143,6 +173,7 @@
 const tableLoading = ref(false)
 const showSealDetailDialog = ref(false)
 const currentSealDetail = ref(null)
+const filePreviewRef = ref(null)
 const sealFormRef = ref()
 const userList = ref([])
 const sealForm = reactive({
@@ -152,7 +183,8 @@
   reason: '',
   approveUserId: '',
   urgency: 'normal',
-  status: 'pending'
+  status: 'pending',
+  storageBlobDTOs: []
 })
 
 const sealRules = {
@@ -281,7 +313,8 @@
         reason: '',
         approveUserId: '',
         urgency: 'normal',
-        status: 'pending'
+        status: 'pending',
+        storageBlobDTOs: []
       })
       }
     }).catch(err => {
@@ -301,7 +334,8 @@
     reason: '',
     approveUserId: '',
     urgency: 'normal',
-    status: 'pending'
+    status: 'pending',
+    storageBlobDTOs: []
   })
   // 娓呴櫎琛ㄥ崟楠岃瘉鐘舵��
   if (sealFormRef.value) {
@@ -318,6 +352,27 @@
 const viewSealDetail = (row) => {
   currentSealDetail.value = row
   showSealDetailDialog.value = true
+}
+
+// 棰勮鏂囦欢
+const previewFile = (row) => {
+  const url = row.previewURL || row.previewUrl || row.url
+  if (url && filePreviewRef.value) {
+    filePreviewRef.value.open(url)
+  } else {
+    ElMessage.warning('鏂囦欢鍦板潃鏃犳晥锛屾棤娉曢瑙�')
+  }
+}
+
+// 涓嬭浇鏂囦欢
+const downloadFile = (row) => {
+  const url = row.downloadURL || row.downloadUrl || row.url
+  if (url) {
+    const filename = row.originalFilename || row.name || row.fileName || 'download'
+    download.byUrl(url, filename)
+  } else {
+    ElMessage.warning('鏂囦欢鍦板潃鏃犳晥锛屾棤娉曚笅杞�')
+  }
 }
 // 瀹℃壒鐢ㄥ嵃鐢宠
 const approveSeal = (row) => {
@@ -421,4 +476,19 @@
 .ml-10 {
   margin-left: 10px;
 }
+
+.attachment-section {
+  margin-top: 20px;
+}
+
+.attachment-title {
+  font-size: 14px;
+  color: #606266;
+  margin-bottom: 10px;
+  font-weight: 500;
+}
+
+.attachment-table {
+  border-radius: 4px;
+}
 </style>
diff --git a/src/views/equipmentManagement/inspectionManagement/components/formDia.vue b/src/views/equipmentManagement/inspectionManagement/components/formDia.vue
index 9f509b1..3e7f1ca 100644
--- a/src/views/equipmentManagement/inspectionManagement/components/formDia.vue
+++ b/src/views/equipmentManagement/inspectionManagement/components/formDia.vue
@@ -26,6 +26,21 @@
         </el-row>
         <el-row>
           <el-col :span="12">
+            <el-form-item label="宸℃椤圭洰" prop="inspectionProject">
+              <el-input v-model="form.inspectionProject" placeholder="璇疯緭鍏ュ贰妫�椤圭洰" />
+            </el-form-item>
+          </el-col>
+          <el-col :span="12">
+            <el-form-item label="鏄惁鍚敤" prop="isEnabled">
+              <el-radio-group v-model="form.isEnabled">
+                <el-radio :value="1">鏄�</el-radio>
+                <el-radio :value="0">鍚�</el-radio>
+              </el-radio-group>
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <el-row>
+          <el-col :span="12">
             <el-form-item label="澶囨敞" prop="remarks">
               <el-input v-model="form.remarks" placeholder="璇疯緭鍏ュ娉�" type="textarea" />
             </el-form-item>
@@ -118,6 +133,8 @@
     taskName: undefined,
     inspector: '',
     inspectorIds: '',
+    inspectionProject: '',
+    isEnabled: 1,
     remarks: '',
     frequencyType: '',
     frequencyDetail: '',
@@ -245,6 +262,8 @@
     taskName: undefined,
     inspector: '',
     inspectorIds: '',
+    inspectionProject: '',
+    isEnabled: 1,
     remarks: '',
     frequencyType: '',
     frequencyDetail: '',
diff --git a/src/views/equipmentManagement/inspectionManagement/index.vue b/src/views/equipmentManagement/inspectionManagement/index.vue
index 35f82d5..44103ac 100644
--- a/src/views/equipmentManagement/inspectionManagement/index.vue
+++ b/src/views/equipmentManagement/inspectionManagement/index.vue
@@ -70,6 +70,11 @@
                     class="no-data">--</span>
             </div>
           </template>
+          <template #isEnabled="{ row }">
+            <el-tag :type="row.isEnabled === 1 ? 'success' : 'danger'" size="small">
+              {{ row.isEnabled == 1 ? '鏄�' : '鍚�' }}
+            </el-tag>
+          </template>
         </PIMTable>
       </div>
     </el-card>
@@ -126,8 +131,16 @@
   // 鍒楅厤缃�
   const columns = ref([
     { prop: "taskName", label: "宸℃浠诲姟鍚嶇О", minWidth: 160 },
+    { prop: "inspectionProject", label: "宸℃椤圭洰", minWidth: 150 },
     { prop: "remarks", label: "澶囨敞", minWidth: 150 },
     { prop: "inspector", label: "鎵ц宸℃浜�", minWidth: 150, slot: "inspector" },
+    {
+      prop: "isEnabled",
+      label: "鏄惁鍚敤",
+      minWidth: 100,
+      dataType: "slot",
+      slot: "isEnabled"
+    },
     {
       prop: "frequencyType",
       label: "棰戞",
@@ -227,8 +240,10 @@
       operationsArr.value = ["edit"];
     } else if (value === "task") {
       const operationColumn = getOperationColumn(["viewFile"]);
+      // 瀹氭椂浠诲姟璁板綍涓嶅睍绀�"鏄惁鍚敤"鍒�
+      const taskColumns = columns.value.filter(col => col.prop !== "isEnabled");
       tableColumns.value = [
-        ...columns.value,
+        ...taskColumns,
         ...(operationColumn ? [operationColumn] : []),
       ];
       operationsArr.value = ["viewFile"];
diff --git a/src/views/equipmentManagement/measurementEquipment/components/formDia.vue b/src/views/equipmentManagement/measurementEquipment/components/formDia.vue
index 6b7feec..16ac41f 100644
--- a/src/views/equipmentManagement/measurementEquipment/components/formDia.vue
+++ b/src/views/equipmentManagement/measurementEquipment/components/formDia.vue
@@ -36,15 +36,6 @@
 				</el-row>
 				<el-row :gutter="30">
 					<el-col :span="12">
-						<el-form-item label="瀹夎浣嶇疆锛�" prop="instationLocation">
-							<el-input
-								v-model="form.instationLocation"
-								placeholder="璇疯緭鍏�"
-								clearable
-							/>
-						</el-form-item>
-					</el-col>
-					<el-col :span="12">
 						<el-form-item label="妫�瀹氬崟浣嶏細" prop="unit">
               <el-input
                   v-model="form.unit"
@@ -53,17 +44,17 @@
               />
 						</el-form-item>
 					</el-col>
-				</el-row>
-        <el-row :gutter="30">
-          <el-col :span="12">
-            <el-form-item label="璇佷功缂栧彿锛�" prop="model">
+					<el-col :span="12">
+						<el-form-item label="璇佷功缂栧彿锛�" prop="model">
               <el-input
                   v-model="form.model"
                   placeholder="璇疯緭鍏�"
                   clearable
               />
             </el-form-item>
-          </el-col>
+					</el-col>
+				</el-row>
+        <el-row :gutter="30">
           <el-col :span="12">
             <el-form-item label="鏈�鏂伴壌瀹氭棩鏈燂細" prop="mostDate">
               <el-date-picker
@@ -77,8 +68,6 @@
               />
             </el-form-item>
           </el-col>
-        </el-row>
-        <el-row :gutter="30">
           <el-col :span="12">
             <el-form-item label="鏈夋晥鏃ユ湡(澶�)锛�" prop="valid">
               <el-input
@@ -91,15 +80,6 @@
               >
               <template #append>鏃�</template>
               </el-input>
-            </el-form-item>
-          </el-col>
-          <el-col :span="12">
-            <el-form-item label="妫�瀹氬懆鏈燂細" prop="cycle">
-              <el-input
-                  v-model="form.cycle"
-                  placeholder="璇疯緭鍏ユ瀹氬懆鏈�"
-                  clearable
-              />
             </el-form-item>
           </el-col>
         </el-row>
@@ -184,10 +164,8 @@
 	form: {
 		code: "",
     name: "",
-    instationLocation: "",
     mostDate:"",
 		model: "",
-    cycle:"",
 		validDate: "",
 		nextDate: "",
 		userId: "",
@@ -203,9 +181,7 @@
 		nextDate: [{required: true, message: "璇烽�夋嫨", trigger: "change"}],
 		userId: [{required: true, message: "璇烽�夋嫨", trigger: "change"}],
 		recordDate: [{required: true, message: "璇烽�夋嫨", trigger: "change"}],
-    instationLocation: [{required: true, message: "璇疯緭鍏�", trigger: "blur"}],
     mostDate: [{required: true, message: "璇烽�夋嫨", trigger: "change"}],
-    cycle: [{required: true, message: "璇烽�夋嫨", trigger: "blur"}],
     valid: [
       {required: true, message: "璇疯緭鍏�", trigger: "blur"},
       {
diff --git a/src/views/equipmentManagement/measurementEquipment/index.vue b/src/views/equipmentManagement/measurementEquipment/index.vue
index c1d5379..d2ec2d7 100644
--- a/src/views/equipmentManagement/measurementEquipment/index.vue
+++ b/src/views/equipmentManagement/measurementEquipment/index.vue
@@ -42,6 +42,7 @@
 				:tableLoading="tableLoading"
 				@pagination="pagination"
         :dbRowClick="dbRowClick"
+        :rowClassName="rowClassName"
 			></PIMTable>
 		</div>
 		<form-dia ref="formDia" @close="handleQuery"></form-dia>
@@ -89,12 +90,6 @@
     align: "center",
   },
 	{
-		label: "瀹夎浣嶇疆",
-		prop: "instationLocation",
-		width: 150,
-    align:"center"
-	},
-	{
 		label: "妫�瀹氬崟浣�",
 		prop: "unit",
 		width: 200,
@@ -130,12 +125,6 @@
 		width: 130,
     align:"center"
 	},
-  {
-    label: "妫�瀹氬懆鏈�(澶�)",
-    prop: "cycle",
-    width: 130,
-    align:"center"
-  },
   {
     label: "鐘舵��",
     prop: "status",
@@ -193,6 +182,31 @@
 
 const dbRowClick = (row)=>{
   rowClickData.value?.openDialog(row)
+}
+
+// 琛屾牱寮忥細蹇埌鏈燂紙7澶╁唴锛夋垨閫炬湡鏍囩孩
+const rowClassName = ({ row }) => {
+  console.log('rowClassName called:', row);
+  // valid 鏄湁鏁堝ぉ鏁帮紝mostDate 鏄渶鏂版瀹氭棩鏈�
+  if (row.valid && row.mostDate) {
+    const mostDate = new Date(row.mostDate);
+    // 璁$畻鍒版湡鏃ユ湡 = 妫�瀹氭棩鏈� + 鏈夋晥澶╂暟
+    const validDays = parseInt(row.valid) || 0;
+    const expireDate = new Date(mostDate);
+    expireDate.setDate(expireDate.getDate() + validDays);
+    
+    const now = new Date();
+    const diffDays = Math.ceil((expireDate - now) / (1000 * 60 * 60 * 24));
+    console.log('row:', row.code, 'validDays:', validDays, 'expireDate:', expireDate, 'diffDays:', diffDays);
+    // 7澶╁唴鍒版湡鎴栧凡閫炬湡閮芥爣绾�
+    if (diffDays <= 7) {
+      console.log('return warning-row');
+      return 'warning-row';
+    }
+  } else {
+    console.log('row missing valid or mostDate:', row.valid, row.mostDate);
+  }
+  return '';
 }
 
 // 琛ㄦ牸閫夋嫨鏁版嵁
@@ -294,5 +308,13 @@
 </script>
 
 <style scoped>
-
+:deep(.el-table .warning-row) {
+  background-color: #fef0f0 !important;
+}
+:deep(.el-table .warning-row:hover > td) {
+  background-color: #f9d5d5 !important;
+}
+:deep(.el-table .el-table__body tr.warning-row td) {
+  background-color: #fef0f0 !important;
+}
 </style>
\ No newline at end of file
diff --git a/src/views/equipmentManagement/repair/Modal/AcceptanceModal.vue b/src/views/equipmentManagement/repair/Modal/AcceptanceModal.vue
new file mode 100644
index 0000000..6d61a9f
--- /dev/null
+++ b/src/views/equipmentManagement/repair/Modal/AcceptanceModal.vue
@@ -0,0 +1,144 @@
+<template>
+  <FormDialog
+    v-model="visible"
+    title="楠屾敹瀹℃壒"
+    width="500px"
+    @confirm="submitForm"
+    @cancel="handleCancel"
+    @close="handleCancel"
+  >
+    <el-form :model="form" :rules="rules" label-width="100px">
+      <el-form-item label="楠屾敹浜�" prop="acceptanceName">
+        <el-select
+          v-model="form.acceptanceName"
+          placeholder="璇烽�夋嫨楠屾敹浜�"
+          filterable
+          style="width: 100%"
+        >
+          <el-option
+            v-for="item in userList"
+            :key="item.userId"
+            :label="item.nickName"
+            :value="item.nickName"
+          />
+        </el-select>
+      </el-form-item>
+      <el-form-item label="楠屾敹鏃堕棿" prop="acceptanceTime">
+        <el-date-picker
+          v-model="form.acceptanceTime"
+          type="datetime"
+          placeholder="璇烽�夋嫨楠屾敹鏃堕棿"
+          format="YYYY-MM-DD HH:mm:ss"
+          value-format="YYYY-MM-DD HH:mm:ss"
+          style="width: 100%"
+        />
+      </el-form-item>
+      <el-form-item label="楠屾敹澶囨敞" prop="acceptanceRemark">
+        <el-input
+          v-model="form.acceptanceRemark"
+          type="textarea"
+          :rows="3"
+          placeholder="璇疯緭鍏ラ獙鏀跺娉�"
+        />
+      </el-form-item>
+    </el-form>
+  </FormDialog>
+</template>
+
+<script setup>
+import FormDialog from "@/components/Dialog/FormDialog.vue";
+import { ref, reactive } from "vue";
+import { ElMessage } from "element-plus";
+import { userListNoPageByTenantId } from "@/api/system/user.js";
+import { repairAcceptance } from "@/api/equipmentManagement/repair";
+import dayjs from "dayjs";
+
+defineOptions({
+  name: "楠屾敹瀹℃壒寮圭獥",
+});
+
+const emits = defineEmits(["ok"]);
+
+const visible = ref(false);
+const loading = ref(false);
+const repairId = ref(null);
+const userList = ref([]);
+
+const form = reactive({
+  acceptanceName: undefined,
+  acceptanceTime: dayjs().format("YYYY-MM-DD HH:mm:ss"),
+  acceptanceRemark: undefined,
+});
+
+const rules = {
+  acceptanceName: [
+    { required: true, message: "璇烽�夋嫨楠屾敹浜�", trigger: "change" },
+  ],
+  acceptanceTime: [
+    { required: true, message: "璇烽�夋嫨楠屾敹鏃堕棿", trigger: "change" },
+  ],
+  acceptanceRemark: [
+    { required: true, message: "璇疯緭鍏ラ獙鏀跺娉�", trigger: "blur" },
+  ],
+};
+
+// 鍔犺浇鐢ㄦ埛鍒楄〃
+const loadUserList = async () => {
+  const { data } = await userListNoPageByTenantId();
+  userList.value = data;
+};
+
+// 鎵撳紑寮圭獥
+const open = async (row) => {
+  repairId.value = row.id;
+  visible.value = true;
+  // 閲嶇疆琛ㄥ崟
+  form.acceptanceName = undefined;
+  form.acceptanceTime = dayjs().format("YYYY-MM-DD HH:mm:ss");
+  form.acceptanceRemark = undefined;
+  await loadUserList();
+};
+
+// 鎻愪氦琛ㄥ崟
+const submitForm = async () => {
+  if (!form.acceptanceName) {
+    ElMessage.warning("璇烽�夋嫨楠屾敹浜�");
+    return;
+  }
+  if (!form.acceptanceTime) {
+    ElMessage.warning("璇烽�夋嫨楠屾敹鏃堕棿");
+    return;
+  }
+  if (!form.acceptanceRemark) {
+    ElMessage.warning("璇疯緭鍏ラ獙鏀跺娉�");
+    return;
+  }
+
+  loading.value = true;
+  try {
+    const { code } = await repairAcceptance({
+      id: repairId.value,
+      acceptanceName: form.acceptanceName,
+      acceptanceTime: form.acceptanceTime,
+      acceptanceRemark: form.acceptanceRemark,
+    });
+    if (code === 200) {
+      ElMessage.success("楠屾敹閫氳繃");
+      visible.value = false;
+      emits("ok");
+    }
+  } finally {
+    loading.value = false;
+  }
+};
+
+const handleCancel = () => {
+  visible.value = false;
+};
+
+defineExpose({
+  open,
+});
+</script>
+
+<style lang="scss" scoped></style>
diff --git a/src/views/equipmentManagement/repair/Modal/RepairModal.vue b/src/views/equipmentManagement/repair/Modal/RepairModal.vue
index 5e31943..4e73833 100644
--- a/src/views/equipmentManagement/repair/Modal/RepairModal.vue
+++ b/src/views/equipmentManagement/repair/Modal/RepairModal.vue
@@ -49,19 +49,44 @@
           </el-form-item>
         </el-col>
         <el-col :span="12">
-          <el-form-item label="椤圭洰">
-            <el-input v-model="form.machineryCategory" placeholder="璇疯緭鍏ラ」鐩�" />
+          <el-form-item label="鎶ヤ慨鎶ヤ慨椤圭洰">
+            <el-input v-model="form.machineryCategory" placeholder="璇疯緭鍏ユ姤淇姤淇」鐩�" />
+          </el-form-item>
+        </el-col>
+      </el-row>
+      <el-row>
+        <el-col :span="12">
+          <el-form-item label="缁翠慨浜�">
+            <el-input v-model="form.maintenanceName" placeholder="璇疯緭鍏ョ淮淇汉濮撳悕" />
           </el-form-item>
         </el-col>
       </el-row>
       <el-row v-if="id">
         <el-col :span="12">
           <el-form-item label="鎶ヤ慨鐘舵��">
-            <el-select v-model="form.status">
+            <el-select v-model="form.status" disabled>
               <el-option label="寰呯淮淇�" :value="0"></el-option>
-              <el-option label="瀹岀粨" :value="1"></el-option>
+              <el-option label="宸查獙鏀�" :value="1"></el-option>
               <el-option label="澶辫触" :value="2"></el-option>
             </el-select>
+          </el-form-item>
+        </el-col>
+      </el-row>
+      <!-- 楠屾敹淇℃伅灞曠ず -->
+      <el-row v-if="id && form.status === 1">
+        <el-col :span="12">
+          <el-form-item label="楠屾敹浜�">
+            <el-input v-model="form.acceptanceName" disabled />
+          </el-form-item>
+        </el-col>
+        <el-col :span="12">
+          <el-form-item label="楠屾敹鏃堕棿">
+            <el-input v-model="form.acceptanceTime" disabled />
+          </el-form-item>
+        </el-col>
+        <el-col :span="24">
+          <el-form-item label="楠屾敹澶囨敞">
+            <el-input v-model="form.acceptanceRemark" type="textarea" :rows="2" disabled />
           </el-form-item>
         </el-col>
       </el-row>
@@ -131,6 +156,7 @@
   status: 0, // 鎶ヤ慨鐘舵��
   machineryCategory: undefined,
   storageBlobDTOs: [],
+  maintenanceName: undefined, // 缁翠慨浜�
 });
 
 const setDeviceModel = (deviceId) => {
@@ -148,6 +174,10 @@
   form.status = data.status;
   form.machineryCategory = data.machineryCategory;
   form.storageBlobDTOs = data.storageBlobVOs || [];
+  form.maintenanceName = data.maintenanceName;
+  form.acceptanceName = data.acceptanceName;
+  form.acceptanceTime = data.acceptanceTime;
+  form.acceptanceRemark = data.acceptanceRemark;
 };
 
 const sendForm = async () => {
diff --git a/src/views/equipmentManagement/repair/index.vue b/src/views/equipmentManagement/repair/index.vue
index f3a4330..2835356 100644
--- a/src/views/equipmentManagement/repair/index.vue
+++ b/src/views/equipmentManagement/repair/index.vue
@@ -100,13 +100,14 @@
         <template #statusRef="{ row }">
           <el-tag v-if="row.status === 2" type="danger">澶辫触</el-tag>
           <el-tag v-if="row.status === 1" type="success">瀹岀粨</el-tag>
+          <el-tag v-if="row.status === 3" type="info">寰呴獙鏀�</el-tag>
           <el-tag v-if="row.status === 0" type="warning">寰呯淮淇�</el-tag>
         </template>
         <template #operation="{ row }">
           <el-button
             type="primary"
             link
-            :disabled="row.status === 1"
+            :disabled="row.status === 1 || row.status === 3"
             @click="editRepair(row.id)"
           >
             缂栬緫
@@ -114,15 +115,23 @@
           <el-button
             type="success"
             link
-            :disabled="row.status === 1"
+            :disabled="row.status !== 0"
             @click="addMaintain(row)"
           >
             缁翠慨
           </el-button>
           <el-button
+            type="warning"
+            link
+            :disabled="row.status !== 3"
+            @click="openAcceptance(row)"
+          >
+            楠屾敹
+          </el-button>
+          <el-button
             type="danger"
             link
-            :disabled="row.status === 1"
+            :disabled="row.status === 1 || row.status === 3"
             @click="delRepairByIds(row.id)"
           >
             鍒犻櫎
@@ -139,6 +148,7 @@
     </div>
     <RepairModal ref="repairModalRef" @ok="getTableData"/>
     <MaintainModal ref="maintainModalRef" @ok="getTableData"/>
+    <AcceptanceModal ref="acceptanceModalRef" @ok="getTableData"/>
     <FileList v-if="fileDialogVisible"  v-model:visible="fileDialogVisible" :record-type="'device_repair'" :record-id="recordId"  />
   </div>
 </template>
@@ -151,6 +161,7 @@
 import {ElMessageBox, ElMessage} from "element-plus";
 import dayjs from "dayjs";
 import MaintainModal from "./Modal/MaintainModal.vue";
+import AcceptanceModal from "./Modal/AcceptanceModal.vue";
 const FileList = defineAsyncComponent(() => import("@/components/Dialog/FileList.vue"));
 
 defineOptions({
@@ -162,6 +173,7 @@
 // 妯℃�佹瀹炰緥
 const repairModalRef = ref();
 const maintainModalRef = ref();
+const acceptanceModalRef = ref();
 
 // 琛ㄦ牸澶氶�夋閫変腑椤�
 const multipleList = ref([]);
@@ -197,7 +209,7 @@
         prop: "deviceModel",
       },
       {
-        label: "椤圭洰",
+        label: "鎶ヤ慨椤圭洰",
         align: "center",
         prop: "machineryCategory",
       },
@@ -232,6 +244,17 @@
         align: "center",
         prop: "maintenanceTime",
         formatData: (cell) => (cell ? dayjs(cell).format("YYYY-MM-DD") : ""),
+      },
+      {
+        label: "楠屾敹浜�",
+        align: "center",
+        prop: "acceptanceName",
+      },
+      {
+        label: "楠屾敹鏃堕棿",
+        align: "center",
+        prop: "acceptanceTime",
+        formatData: (cell) => (cell ? dayjs(cell).format("YYYY-MM-DD HH:mm:ss") : ""),
       },
       {
         label: "鐘舵��",
@@ -301,6 +324,11 @@
   maintainModalRef.value.open(row.id, row);
 };
 
+// 鎵撳紑楠屾敹寮圭獥
+const openAcceptance = (row) => {
+  acceptanceModalRef.value.open(row);
+};
+
 const changePage = ({page, limit}) => {
   pagination.currentPage = page;
   pagination.pageSize = limit;
diff --git a/src/views/equipmentManagement/upkeep/Form/PlanModal.vue b/src/views/equipmentManagement/upkeep/Form/PlanModal.vue
index ee59ce2..8a9cd98 100644
--- a/src/views/equipmentManagement/upkeep/Form/PlanModal.vue
+++ b/src/views/equipmentManagement/upkeep/Form/PlanModal.vue
@@ -32,10 +32,10 @@
           disabled
         />
       </el-form-item>
-      <el-form-item label="椤圭洰">
+      <el-form-item label="淇濆吇椤圭洰">
         <el-input
             v-model="form.machineryCategory"
-            placeholder="璇疯緭鍏ラ」鐩�"
+            placeholder="璇疯緭鍏ヤ繚鍏婚」鐩�"
         />
       </el-form-item>
       <el-form-item label="褰曞叆浜�">
@@ -61,6 +61,13 @@
           <el-option label="瀹岀粨" :value="1"></el-option>
           <el-option label="澶辫触" :value="2"></el-option>
         </el-select>
+      </el-form-item>
+      <el-form-item label="淇濆吇浜�">
+        <el-input
+          v-model="form.maintenancePerson"
+          placeholder="璇疯緭鍏ヤ繚鍏讳汉濮撳悕"
+          clearable
+        />
       </el-form-item>
       <el-form-item label="璁″垝淇濆吇鏃ユ湡">
         <el-date-picker
@@ -124,6 +131,7 @@
   status: 0, //淇濅慨鐘舵��
   machineryCategory: undefined,
   storageBlobDTOs: [],
+  maintenancePerson: undefined, // 淇濆吇浜�
 });
 
 const setDeviceModel = (deviceId) => {
@@ -142,6 +150,7 @@
   form.createUser = Number(data.createUser);
   form.status = data.status;
   form.machineryCategory = data.machineryCategory;
+  form.maintenancePerson = data.maintenancePerson;
   if (data.maintenancePlanTime) {
     form.maintenancePlanTime = dayjs(data.maintenancePlanTime).format(
       "YYYY-MM-DD HH:mm:ss"
diff --git a/src/views/equipmentManagement/upkeep/Form/formDia.vue b/src/views/equipmentManagement/upkeep/Form/formDia.vue
index 9550b08..6856ae1 100644
--- a/src/views/equipmentManagement/upkeep/Form/formDia.vue
+++ b/src/views/equipmentManagement/upkeep/Form/formDia.vue
@@ -67,10 +67,20 @@
 			</el-row>
 			<el-row>
 				<el-col :span="12">
-					<el-form-item label="璁惧椤圭洰" prop="machineryCategory">
+					<el-form-item label="淇濆吇椤圭洰" prop="machineryCategory">
 						<el-input
 							v-model.trim="form.machineryCategory"
-							placeholder="璇疯緭鍏ヨ澶囬」鐩�"
+							placeholder="璇疯緭鍏ヤ繚鍏婚」鐩�"
+							maxlength="100"
+							clearable
+						/>
+					</el-form-item>
+				</el-col>
+				<el-col :span="12">
+					<el-form-item label="淇濆吇浜�" prop="maintenancePerson">
+						<el-input
+							v-model.trim="form.maintenancePerson"
+							placeholder="璇疯緭鍏ヤ繚鍏讳汉濮撳悕"
 							maxlength="100"
 							clearable
 						/>
@@ -173,13 +183,14 @@
 		week: '',
 		time: '',
 		deviceModel: undefined, // 瑙勬牸鍨嬪彿
-		registrationDate: ''
+		registrationDate: '',
+		maintenancePerson: '' // 淇濆吇浜�
 	},
 	rules: {
 		taskId: [{ required: true, message: "璇烽�夋嫨璁惧", trigger: "change" },],
 		inspector: [{ required: true, message: "璇烽�夋嫨褰曞叆浜�", trigger: "blur" },],
 		registrationDate: [{ required: true, message: "璇烽�夋嫨鐧昏鏃堕棿", trigger: "change" }],
-		machineryCategory: [{ required: true, message: "璇疯緭鍏ヨ澶囬」鐩�", trigger: "blur" }]
+		machineryCategory: [{ required: true, message: "璇疯緭鍏ヤ繚鍏婚」鐩�", trigger: "blur" }]
 	}
 })
 const { form, rules } = toRefs(data)
@@ -259,7 +270,8 @@
 		week: '',
 		time: '',
 		deviceModel: undefined,
-		registrationDate: ''
+		registrationDate: '',
+		maintenancePerson: ''
 	}
 }
 
diff --git a/src/views/equipmentManagement/upkeep/index.vue b/src/views/equipmentManagement/upkeep/index.vue
index 2fc3eae..6bdbc8f 100644
--- a/src/views/equipmentManagement/upkeep/index.vue
+++ b/src/views/equipmentManagement/upkeep/index.vue
@@ -300,7 +300,7 @@
       prop: "deviceModel",
     },
     {
-      label: "璁惧椤圭洰",
+      label: "淇濆吇椤圭洰",
       prop: "machineryCategory",
       minWidth: 120,
       formatData: cell => cell || "--",
@@ -342,6 +342,7 @@
         );
       },
     },
+    { prop: "maintenancePerson", label: "淇濆吇浜�", minWidth: 100 },
     { prop: "registrant", label: "鐧昏浜�", minWidth: 100 },
     { prop: "registrationDate", label: "鐧昏鏃ユ湡", minWidth: 100 },
     {
@@ -378,7 +379,7 @@
       prop: "createUserName",
     },
     {
-      label: "璁惧椤圭洰",
+      label: "淇濆吇椤圭洰",
       align: "center",
       prop: "machineryCategory",
       formatData: cell => cell || "--",
diff --git a/src/views/personnelManagement/contractManagement/index.vue b/src/views/personnelManagement/contractManagement/index.vue
index a55a502..074b9ac 100644
--- a/src/views/personnelManagement/contractManagement/index.vue
+++ b/src/views/personnelManagement/contractManagement/index.vue
@@ -23,6 +23,12 @@
         :total="page.total"></PIMTable>
     </div>
     <form-dia ref="formDia" @close="handleQuery"></form-dia>
+    <renew-contract
+        v-if="isShowRenewContractModal"
+        v-model:visible="isShowRenewContractModal"
+        :id="id"
+        @completed="handleQuery"
+    />
 
     <!-- 鍚堝悓瀵煎叆瀵硅瘽妗� -->
     <el-dialog
@@ -71,8 +77,9 @@
 
 <script setup>
 import { Search } from "@element-plus/icons-vue";
-import { onMounted, ref } from "vue";
+import { onMounted, ref, defineAsyncComponent } from "vue";
 import FormDia from "@/views/personnelManagement/contractManagement/components/formDia.vue";
+const RenewContract = defineAsyncComponent(() => import("@/views/personnelManagement/employeeRecord/components/RenewContract.vue"));
 import { ElMessageBox } from "element-plus";
 import { staffOnJobListPage } from "@/api/personnelManagement/staffOnJob.js";
 import dayjs from "dayjs";
@@ -183,7 +190,7 @@
     label: "鎿嶄綔",
     align: "center",
     fixed: 'right',
-    width: 120,
+    width: 160,
     operation: [
       {
         name: "璇︽儏",
@@ -191,11 +198,22 @@
         clickFun: (row) => {
           openForm("edit", row);
         },
+      },
+      {
+        name: "缁鍚堝悓",
+        type: "text",
+        showHide: row => row.staffState === 1,
+        clickFun: (row) => {
+          isShowRenewContractModal.value = true;
+          id.value = row.id;
+        },
       }
     ],
   },
 ]);
 const filesDia = ref()
+const isShowRenewContractModal = ref(false);
+const id = ref(0);
 const tableData = ref([]);
 const selectedRows = ref([]);
 const tableLoading = ref(false);
diff --git a/src/views/personnelManagement/employeeRecord/index.vue b/src/views/personnelManagement/employeeRecord/index.vue
index cd4ecf5..5dda8c7 100644
--- a/src/views/personnelManagement/employeeRecord/index.vue
+++ b/src/views/personnelManagement/employeeRecord/index.vue
@@ -52,16 +52,14 @@
           :tableLoading="tableLoading"
           @pagination="pagination"
           :total="page.total"
-      ></PIMTable>
+      >
+        <template #positiveDate="{ row }">
+          <span :class="getPositiveDateClass(row.positiveDate)">{{ row.positiveDate }}</span>
+        </template>
+      </PIMTable>
     </div>
     <show-form-dia ref="formDia" @close="handleQuery"></show-form-dia>
     <new-or-edit-form-dia ref="formDiaNewOrEditFormDia" @close="handleQuery"></new-or-edit-form-dia>
-    <renew-contract
-        v-if="isShowRenewContractModal"
-        v-model:visible="isShowRenewContractModal"
-        :id="id"
-        @completed="handleQuery"
-    />
     
     <!-- 瀵煎叆瀵硅瘽妗� -->
     <el-dialog :title="upload.title" v-model="upload.open" width="400px" append-to-body>
@@ -107,7 +105,6 @@
 
 const NewOrEditFormDia = defineAsyncComponent(() => import("@/views/personnelManagement/employeeRecord/components/NewOrEditFormDia.vue"));
 const ShowFormDia = defineAsyncComponent(() => import( "@/views/personnelManagement/employeeRecord/components/Show.vue"));
-const RenewContract = defineAsyncComponent(() => import( "@/views/personnelManagement/employeeRecord/components/RenewContract.vue"));
 
 const data = reactive({
   searchForm: {
@@ -119,8 +116,6 @@
   deptOptions: [],
 });
 const { searchForm, deptOptions } = toRefs(data);
-const isShowRenewContractModal = ref(false);
-const id = ref(0);
 const tableColumn = ref([
   {
     label: "鐘舵��",
@@ -177,6 +172,13 @@
     width: 120,
   },
   {
+    label: "杞鏃ユ湡",
+    prop: "positiveDate",
+    width: 120,
+    dataType: "slot",
+    slot: "positiveDate",
+  },
+  {
     label: "骞撮緞",
     prop: "age",
   },
@@ -208,22 +210,6 @@
           openFormNewOrEditFormDia("edit", row);
         },
       },
-      {
-        name: "缁鍚堝悓",
-        type: "text",
-        showHide: row => row.staffState === 1,
-        clickFun: (row) => {
-          isShowRenewContractModal.value = true;
-          id.value = row.id;
-        },
-      },
-      // {
-      //   name: "璇︽儏",
-      //   type: "text",
-      //   clickFun: (row) => {
-      //     openForm("edit", row);
-      //   },
-      // },
     ],
   },
 ]);
@@ -253,6 +239,22 @@
   // 涓婁紶鐨勫湴鍧�
   url: import.meta.env.VITE_APP_BASE_API + "/staff/staffOnJob/import"
 })
+
+// 鍒ゆ柇杞鏃ユ湡鏄惁鍦�7澶╁唴
+const getPositiveDateClass = (positiveDate) => {
+  if (!positiveDate) return '';
+  const today = new Date();
+  today.setHours(0, 0, 0, 0);
+  const positive = new Date(positiveDate);
+  positive.setHours(0, 0, 0, 0);
+  const diffTime = positive - today;
+  const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24));
+  // 7澶╁唴杞锛堝寘鎷粖澶╋級鏄剧ず璀﹀憡鑹�
+  if (diffDays >= 0 && diffDays <= 7) {
+    return 'positive-date-warning';
+  }
+  return '';
+};
 
 const fetchDeptOptions = () => {
     deptTreeSelect().then(response => {
@@ -402,4 +404,9 @@
 .search_title2 {
   margin-left: 10px;
 }
+
+.positive-date-warning {
+  color: #f56c6c;
+  font-weight: bold;
+}
 </style>
diff --git a/src/views/procurementManagement/procurementLedger/index.vue b/src/views/procurementManagement/procurementLedger/index.vue
index cffdcc6..adf7b6e 100644
--- a/src/views/procurementManagement/procurementLedger/index.vue
+++ b/src/views/procurementManagement/procurementLedger/index.vue
@@ -693,6 +693,7 @@
   const salesContractList = ref([]);
   const supplierList = ref([]);
   const tableLoading = ref(false);
+  const recordId = ref();
   const fileListDialogVisible = ref(false);
   const page = reactive({
     current: 1,
diff --git a/src/views/reportAnalysis/PSIDataAnalysis/components/center-bottom.vue b/src/views/reportAnalysis/PSIDataAnalysis/components/center-bottom.vue
index ccd7504..f4e49b6 100644
--- a/src/views/reportAnalysis/PSIDataAnalysis/components/center-bottom.vue
+++ b/src/views/reportAnalysis/PSIDataAnalysis/components/center-bottom.vue
@@ -23,7 +23,7 @@
 </template>
 
 <script setup>
-import { ref, onMounted } from 'vue'
+import { ref, onMounted, inject, watch } from 'vue'
 import * as echarts from 'echarts'
 import Echarts from '@/components/Echarts/echarts.vue'
 import PanelHeader from './PanelHeader.vue'
@@ -151,6 +151,13 @@
   fetchData()
 }
 
+const dataDashboardRefreshTick = inject('dataDashboardRefreshTick', null)
+if (dataDashboardRefreshTick) {
+  watch(dataDashboardRefreshTick, () => {
+    fetchData()
+  })
+}
+
 onMounted(() => {
   fetchData()
 })
diff --git a/src/views/reportAnalysis/PSIDataAnalysis/components/center-center.vue b/src/views/reportAnalysis/PSIDataAnalysis/components/center-center.vue
index 0f3ec84..6e39eb1 100644
--- a/src/views/reportAnalysis/PSIDataAnalysis/components/center-center.vue
+++ b/src/views/reportAnalysis/PSIDataAnalysis/components/center-center.vue
@@ -27,7 +27,7 @@
 </template>
 
 <script setup>
-import { ref, onMounted } from 'vue'
+import { ref, onMounted, inject, watch } from 'vue'
 import Echarts from '@/components/Echarts/echarts.vue'
 import { productTurnoverDays } from '@/api/viewIndex.js'
 
@@ -82,6 +82,13 @@
     })
 }
 
+const dataDashboardRefreshTick = inject('dataDashboardRefreshTick', null)
+if (dataDashboardRefreshTick) {
+  watch(dataDashboardRefreshTick, () => {
+    fetchData()
+  })
+}
+
 onMounted(() => {
   fetchData()
 })
diff --git a/src/views/reportAnalysis/PSIDataAnalysis/components/center-top.vue b/src/views/reportAnalysis/PSIDataAnalysis/components/center-top.vue
index 0937b32..055fb66 100644
--- a/src/views/reportAnalysis/PSIDataAnalysis/components/center-top.vue
+++ b/src/views/reportAnalysis/PSIDataAnalysis/components/center-top.vue
@@ -24,7 +24,7 @@
 </template>
 
 <script setup>
-import { ref, onMounted } from 'vue'
+import { ref, onMounted, inject, watch } from 'vue'
 import { salesPurchaseStorageProductCount } from '@/api/viewIndex.js'
 
 const statItems = ref([])
@@ -52,6 +52,13 @@
     })
 }
 
+const dataDashboardRefreshTick = inject('dataDashboardRefreshTick', null)
+if (dataDashboardRefreshTick) {
+  watch(dataDashboardRefreshTick, () => {
+    fetchData()
+  })
+}
+
 onMounted(() => {
   fetchData()
 })
diff --git a/src/views/reportAnalysis/PSIDataAnalysis/components/left-bottom.vue b/src/views/reportAnalysis/PSIDataAnalysis/components/left-bottom.vue
index 669c826..65a72fe 100644
--- a/src/views/reportAnalysis/PSIDataAnalysis/components/left-bottom.vue
+++ b/src/views/reportAnalysis/PSIDataAnalysis/components/left-bottom.vue
@@ -22,7 +22,7 @@
 </template>
 
 <script setup>
-import { ref, onMounted, onBeforeUnmount, computed } from 'vue'
+import { ref, onMounted, onBeforeUnmount, computed, inject, watch } from 'vue'
 import Echarts from '@/components/Echarts/echarts.vue'
 import PanelHeader from './PanelHeader.vue'
 import CarouselCards from './CarouselCards.vue'
@@ -205,6 +205,13 @@
     })
 }
 
+const dataDashboardRefreshTick = inject('dataDashboardRefreshTick', null)
+if (dataDashboardRefreshTick) {
+  watch(dataDashboardRefreshTick, () => {
+    fetchData()
+  })
+}
+
 onMounted(() => {
   fetchData()
   initBackground()
diff --git a/src/views/reportAnalysis/PSIDataAnalysis/components/left-top.vue b/src/views/reportAnalysis/PSIDataAnalysis/components/left-top.vue
index 8fcaa42..f5dac31 100644
--- a/src/views/reportAnalysis/PSIDataAnalysis/components/left-top.vue
+++ b/src/views/reportAnalysis/PSIDataAnalysis/components/left-top.vue
@@ -21,7 +21,7 @@
 </template>
 
 <script setup>
-import { ref, onMounted, onBeforeUnmount, computed } from 'vue'
+import { ref, onMounted, onBeforeUnmount, computed, inject, watch } from 'vue'
 import { productSalesAnalysis } from '@/api/viewIndex.js'
 import PanelHeader from './PanelHeader.vue'
 import CarouselCards from './CarouselCards.vue'
@@ -175,6 +175,13 @@
     })
 }
 
+const dataDashboardRefreshTick = inject('dataDashboardRefreshTick', null)
+if (dataDashboardRefreshTick) {
+  watch(dataDashboardRefreshTick, () => {
+    fetchData()
+  })
+}
+
 onMounted(() => {
   fetchData()
   initBackground()
diff --git a/src/views/reportAnalysis/PSIDataAnalysis/index.vue b/src/views/reportAnalysis/PSIDataAnalysis/index.vue
index 065b59d..f81e482 100644
--- a/src/views/reportAnalysis/PSIDataAnalysis/index.vue
+++ b/src/views/reportAnalysis/PSIDataAnalysis/index.vue
@@ -43,7 +43,7 @@
 </template>
 
 <script setup>
-import { ref, onMounted, onBeforeUnmount, nextTick } from 'vue'
+import { ref, onMounted, onBeforeUnmount, nextTick, provide } from 'vue'
 import autofit from 'autofit.js'
 import LeftBottom from './components/left-bottom.vue'
 import CenterCenter from './components/center-center.vue'
@@ -65,6 +65,12 @@
 
 // 鐢ㄦ埛store
 const userStore = useUserStore()
+
+/** 涓� dataDashboard 鍏辩敤娉ㄥ叆鍚嶏紝瀛愮粍浠讹紙鍚鐢ㄧ殑 right-top/right-bottom锛夋瘡鍒嗛挓鍒锋柊 */
+const DASHBOARD_REFRESH_MS = 60 * 1000
+const dataDashboardRefreshTick = ref(0)
+provide('dataDashboardRefreshTick', dataDashboardRefreshTick)
+let dashboardPollTimer = null
 
 // 璁$畻缂╂斁姣斾緥
 const calculateScale = () => {
@@ -140,9 +146,17 @@
   window.addEventListener('fullscreenchange', handleFullscreenChange)
   window.addEventListener('webkitfullscreenchange', handleFullscreenChange)
   window.addEventListener('MSFullscreenChange', handleFullscreenChange)
+
+  dashboardPollTimer = setInterval(() => {
+    dataDashboardRefreshTick.value++
+  }, DASHBOARD_REFRESH_MS)
 })
 
 onBeforeUnmount(() => {
+  if (dashboardPollTimer) {
+    clearInterval(dashboardPollTimer)
+    dashboardPollTimer = null
+  }
   window.removeEventListener('resize', handleResize)
   window.removeEventListener('fullscreenchange', handleFullscreenChange)
   window.removeEventListener('webkitfullscreenchange', handleFullscreenChange)
diff --git a/src/views/reportAnalysis/dataDashboard/components/basic/center-bottom.vue b/src/views/reportAnalysis/dataDashboard/components/basic/center-bottom.vue
index a4824a2..c28c2fa 100644
--- a/src/views/reportAnalysis/dataDashboard/components/basic/center-bottom.vue
+++ b/src/views/reportAnalysis/dataDashboard/components/basic/center-bottom.vue
@@ -20,7 +20,7 @@
 </template>
 
 <script setup>
-import { ref, onMounted, computed } from 'vue'
+import { ref, onMounted, computed, inject, watch } from 'vue'
 import { deptStaffDistribution } from '@/api/viewIndex.js'
 import PanelHeader from '../PanelHeader.vue'
 import Echarts from '@/components/Echarts/echarts.vue'
@@ -148,6 +148,13 @@
   })
 }
 
+const dataDashboardRefreshTick = inject('dataDashboardRefreshTick', null)
+if (dataDashboardRefreshTick) {
+  watch(dataDashboardRefreshTick, () => {
+    getDeptStaffDistribution()
+  })
+}
+
 onMounted(() => {
   getDeptStaffDistribution()
 })
diff --git a/src/views/reportAnalysis/dataDashboard/components/basic/center-top.vue b/src/views/reportAnalysis/dataDashboard/components/basic/center-top.vue
index 950038e..a7d0174 100644
--- a/src/views/reportAnalysis/dataDashboard/components/basic/center-top.vue
+++ b/src/views/reportAnalysis/dataDashboard/components/basic/center-top.vue
@@ -110,7 +110,7 @@
 </template>
 
 <script setup>
-import { ref, onMounted, onBeforeUnmount, nextTick } from 'vue'
+import { ref, onMounted, onBeforeUnmount, nextTick, inject, watch } from 'vue'
 import { homeTodos, summaryStatistics } from '@/api/viewIndex.js'
 import { getLedgerPage } from '@/api/equipmentManagement/ledger.js'
 import { getRepairPage } from '@/api/equipmentManagement/repair.js'
@@ -175,8 +175,23 @@
   })
 }
 
+const destroyTodoListScroll = () => {
+  const todoListEl = refTodoList.value
+  if (todoListEl) {
+    if (todoListEl._animationFrame) {
+      cancelAnimationFrame(todoListEl._animationFrame)
+      todoListEl._animationFrame = null
+    }
+    if (todoListEl._pauseTimer) {
+      clearInterval(todoListEl._pauseTimer)
+      todoListEl._pauseTimer = null
+    }
+  }
+}
+
 // 鍒濆鍖栧緟鍔炰簨椤瑰垪琛ㄦ粴鍔ㄥ姛鑳�
 const initTodoListScroll = () => {
+  destroyTodoListScroll()
   const todoListEl = refTodoList.value
   // 寮哄埗鍚敤婊氬姩锛屼笉妫�鏌ヤ换浣曟潯浠�
   if (todoListEl) {
@@ -259,6 +274,7 @@
 
 // 寰呭姙浜嬮」
 const todoInfoS = () => {
+  destroyTodoListScroll()
   homeTodos().then((res) => {
     todoList.value = res.data
     // 鍦ㄨ幏鍙栧埌寰呭姙浜嬮」鏁版嵁鍚庯紝鍒濆鍖栨粴鍔ㄥ姛鑳�
@@ -268,25 +284,25 @@
   })
 }
 
-onMounted(() => {
+const refreshCenterTopData = () => {
   getNum()
   getLedgerNum()
   todoInfoS()
+}
+
+const dataDashboardRefreshTick = inject('dataDashboardRefreshTick', null)
+if (dataDashboardRefreshTick) {
+  watch(dataDashboardRefreshTick, () => {
+    refreshCenterTopData()
+  })
+}
+
+onMounted(() => {
+  refreshCenterTopData()
 })
 
 onBeforeUnmount(() => {
-  // 娓呯悊寰呭姙浜嬮」鍒楄〃鐨勫姩鐢诲拰瀹氭椂鍣�
-  const todoListEl = refTodoList.value
-  if (todoListEl) {
-    if (todoListEl._animationFrame) {
-      cancelAnimationFrame(todoListEl._animationFrame)
-      todoListEl._animationFrame = null
-    }
-    if (todoListEl._pauseTimer) {
-      clearInterval(todoListEl._pauseTimer)
-      todoListEl._pauseTimer = null
-    }
-  }
+  destroyTodoListScroll()
 })
 </script>
 
diff --git a/src/views/reportAnalysis/dataDashboard/components/basic/left-bottom.vue b/src/views/reportAnalysis/dataDashboard/components/basic/left-bottom.vue
index 58c83d8..bab6024 100644
--- a/src/views/reportAnalysis/dataDashboard/components/basic/left-bottom.vue
+++ b/src/views/reportAnalysis/dataDashboard/components/basic/left-bottom.vue
@@ -40,7 +40,7 @@
 </template>
 
 <script setup>
-import { ref, onMounted } from 'vue'
+import { ref, onMounted, inject, watch } from 'vue'
 import Echarts from '@/components/Echarts/echarts.vue'
 import PanelHeader from '../PanelHeader.vue'
 import DateTypeSwitch from '../DateTypeSwitch.vue'
@@ -192,6 +192,13 @@
   getCustomerRevenueAnalysis()
 }
 
+const dataDashboardRefreshTick = inject('dataDashboardRefreshTick', null)
+if (dataDashboardRefreshTick) {
+  watch(dataDashboardRefreshTick, () => {
+    getCustomerRevenueAnalysis()
+  })
+}
+
 onMounted(() => {
   fetchCustomerOptions()
 })
diff --git a/src/views/reportAnalysis/dataDashboard/components/basic/left-top.vue b/src/views/reportAnalysis/dataDashboard/components/basic/left-top.vue
index 5b7e29e..16791de 100644
--- a/src/views/reportAnalysis/dataDashboard/components/basic/left-top.vue
+++ b/src/views/reportAnalysis/dataDashboard/components/basic/left-top.vue
@@ -21,7 +21,7 @@
 </template>
 
 <script setup>
-import { ref, onMounted, onBeforeUnmount } from 'vue'
+import { ref, onMounted, onBeforeUnmount, inject, watch } from 'vue'
 import Echarts from '@/components/Echarts/echarts.vue'
 import PanelHeader from '../PanelHeader.vue'
 import { productCategoryDistribution } from '@/api/viewIndex.js'
@@ -207,6 +207,13 @@
 }
 
 
+const dataDashboardRefreshTick = inject('dataDashboardRefreshTick', null)
+if (dataDashboardRefreshTick) {
+  watch(dataDashboardRefreshTick, () => {
+    loadData()
+  })
+}
+
 onMounted(() => {
   loadData()
   initBackground()
diff --git a/src/views/reportAnalysis/dataDashboard/components/basic/right-bottom.vue b/src/views/reportAnalysis/dataDashboard/components/basic/right-bottom.vue
index bbcd5f0..6fcd80f 100644
--- a/src/views/reportAnalysis/dataDashboard/components/basic/right-bottom.vue
+++ b/src/views/reportAnalysis/dataDashboard/components/basic/right-bottom.vue
@@ -22,7 +22,7 @@
 </template>
 
 <script setup>
-import { ref, onMounted, computed } from 'vue'
+import { ref, onMounted, computed, inject, watch } from 'vue'
 import Echarts from '@/components/Echarts/echarts.vue'
 import PanelHeader from '../PanelHeader.vue'
 import DateTypeSwitch from '../DateTypeSwitch.vue'
@@ -308,6 +308,13 @@
   fetchCustomerRanking()
 }
 
+const dataDashboardRefreshTick = inject('dataDashboardRefreshTick', null)
+if (dataDashboardRefreshTick) {
+  watch(dataDashboardRefreshTick, () => {
+    fetchCustomerRanking()
+  })
+}
+
 onMounted(() => {
   fetchCustomerRanking()
 })
diff --git a/src/views/reportAnalysis/dataDashboard/components/basic/right-top.vue b/src/views/reportAnalysis/dataDashboard/components/basic/right-top.vue
index 21696fa..96e4548 100644
--- a/src/views/reportAnalysis/dataDashboard/components/basic/right-top.vue
+++ b/src/views/reportAnalysis/dataDashboard/components/basic/right-top.vue
@@ -21,7 +21,7 @@
 </template>
 
 <script setup>
-import { ref, onMounted, computed } from 'vue'
+import { ref, onMounted, computed, inject, watch } from 'vue'
 import Echarts from '@/components/Echarts/echarts.vue'
 import PanelHeader from '../PanelHeader.vue'
 import DateTypeSwitch from '../DateTypeSwitch.vue'
@@ -331,6 +331,13 @@
   fetchSupplierRanking()
 }
 
+const dataDashboardRefreshTick = inject('dataDashboardRefreshTick', null)
+if (dataDashboardRefreshTick) {
+  watch(dataDashboardRefreshTick, () => {
+    fetchSupplierRanking()
+  })
+}
+
 onMounted(() => {
   fetchSupplierRanking()
 })
diff --git a/src/views/reportAnalysis/dataDashboard/index.vue b/src/views/reportAnalysis/dataDashboard/index.vue
index 67a700f..ff53a7b 100644
--- a/src/views/reportAnalysis/dataDashboard/index.vue
+++ b/src/views/reportAnalysis/dataDashboard/index.vue
@@ -44,7 +44,7 @@
 </template>
 
 <script setup>
-import { ref, onMounted, onBeforeUnmount, nextTick } from 'vue'
+import { ref, onMounted, onBeforeUnmount, nextTick, provide } from 'vue'
 import autofit from 'autofit.js'
 import LeftTop from './components/basic/left-top.vue'
 import LeftBottom from './components/basic/left-bottom.vue'
@@ -65,6 +65,12 @@
 
 // 鐢ㄦ埛store
 const userStore = useUserStore()
+
+// 澶у睆鎺ュ彛杞闂撮殧
+const DASHBOARD_REFRESH_MS = 60 * 1000
+const dataDashboardRefreshTick = ref(0)
+provide('dataDashboardRefreshTick', dataDashboardRefreshTick)
+let dashboardPollTimer = null
 
 // 璁$畻缂╂斁姣斾緥
 const calculateScale = () => {
@@ -140,9 +146,17 @@
   window.addEventListener('fullscreenchange', handleFullscreenChange)
   window.addEventListener('webkitfullscreenchange', handleFullscreenChange)
   window.addEventListener('MSFullscreenChange', handleFullscreenChange)
+
+  dashboardPollTimer = setInterval(() => {
+    dataDashboardRefreshTick.value++
+  }, DASHBOARD_REFRESH_MS)
 })
 
 onBeforeUnmount(() => {
+  if (dashboardPollTimer) {
+    clearInterval(dashboardPollTimer)
+    dashboardPollTimer = null
+  }
   window.removeEventListener('resize', handleResize)
   window.removeEventListener('fullscreenchange', handleFullscreenChange)
   window.removeEventListener('webkitfullscreenchange', handleFullscreenChange)
diff --git a/src/views/reportAnalysis/productionAnalysis/components/center-bottom.vue b/src/views/reportAnalysis/productionAnalysis/components/center-bottom.vue
index 46a870a..f4f4024 100644
--- a/src/views/reportAnalysis/productionAnalysis/components/center-bottom.vue
+++ b/src/views/reportAnalysis/productionAnalysis/components/center-bottom.vue
@@ -51,7 +51,7 @@
 </template>
 
 <script setup>
-import { ref, onMounted, onBeforeUnmount, nextTick } from 'vue'
+import { ref, onMounted, onBeforeUnmount, nextTick, inject, watch } from 'vue'
 import { getProgressStatistics } from '@/api/viewIndex.js'
 import PanelHeader from './PanelHeader.vue'
 import CarouselCards from './CarouselCards.vue'
@@ -132,17 +132,22 @@
   }, 150)
 }
 
-const initProgressTableScroll = () => {
-  const tableContainer = progressTableRef.value
-  if (!tableContainer) return
+const stopProgressTableScroll = () => {
   if (progressTableScrollTimer.value) {
     cancelAnimationFrame(progressTableScrollTimer.value)
     progressTableScrollTimer.value = null
   }
-  if (tableContainer._pauseTimer) {
+  const tableContainer = progressTableRef.value
+  if (tableContainer?._pauseTimer) {
     clearInterval(tableContainer._pauseTimer)
     tableContainer._pauseTimer = null
   }
+}
+
+const initProgressTableScroll = () => {
+  const tableContainer = progressTableRef.value
+  if (!tableContainer) return
+  stopProgressTableScroll()
   const tbody = tableContainer.querySelector('tbody')
   if (!tbody) return
   const originalCount = progressTableData.value.length
@@ -198,6 +203,7 @@
 const progressStatisticsInfo = () => {
   getProgressStatistics()
     .then((res) => {
+      stopProgressTableScroll()
       if (!res || !res.data) return
       const obj = {
         totalOrderCount: res.data.totalOrderCount || 0,
@@ -224,14 +230,19 @@
     })
 }
 
+const dataDashboardRefreshTick = inject('dataDashboardRefreshTick', null)
+if (dataDashboardRefreshTick) {
+  watch(dataDashboardRefreshTick, () => {
+    progressStatisticsInfo()
+  })
+}
+
 onMounted(() => {
   progressStatisticsInfo()
 })
 
 onBeforeUnmount(() => {
-  if (progressTableScrollTimer.value) {
-    cancelAnimationFrame(progressTableScrollTimer.value)
-  }
+  stopProgressTableScroll()
   if (tableScrollTimeout.value) clearTimeout(tableScrollTimeout.value)
   const tableContainer = progressTableRef.value
   if (tableContainer?._pauseTimer) {
diff --git a/src/views/reportAnalysis/productionAnalysis/components/center-center.vue b/src/views/reportAnalysis/productionAnalysis/components/center-center.vue
index 96bcada..a65f4f8 100644
--- a/src/views/reportAnalysis/productionAnalysis/components/center-center.vue
+++ b/src/views/reportAnalysis/productionAnalysis/components/center-center.vue
@@ -27,7 +27,7 @@
 </template>
 
 <script setup>
-import { ref, onMounted } from 'vue'
+import { ref, onMounted, inject, watch } from 'vue'
 import * as echarts from 'echarts'
 import Echarts from '@/components/Echarts/echarts.vue'
 import { inputOutputAnalysis } from '@/api/viewIndex.js'
@@ -146,6 +146,13 @@
     })
 }
 
+const dataDashboardRefreshTick = inject('dataDashboardRefreshTick', null)
+if (dataDashboardRefreshTick) {
+  watch(dataDashboardRefreshTick, () => {
+    fetchData()
+  })
+}
+
 onMounted(() => {
   fetchData()
 })
diff --git a/src/views/reportAnalysis/productionAnalysis/components/center-top.vue b/src/views/reportAnalysis/productionAnalysis/components/center-top.vue
index 7201828..a806150 100644
--- a/src/views/reportAnalysis/productionAnalysis/components/center-top.vue
+++ b/src/views/reportAnalysis/productionAnalysis/components/center-top.vue
@@ -24,7 +24,7 @@
 </template>
 
 <script setup>
-import { ref, onMounted } from 'vue'
+import { ref, onMounted, inject, watch } from 'vue'
 import { orderCount } from '@/api/viewIndex.js'
 
 const statItems = ref([])
@@ -52,6 +52,13 @@
     })
 }
 
+const dataDashboardRefreshTick = inject('dataDashboardRefreshTick', null)
+if (dataDashboardRefreshTick) {
+  watch(dataDashboardRefreshTick, () => {
+    fetchData()
+  })
+}
+
 onMounted(() => {
   fetchData()
 })
diff --git a/src/views/reportAnalysis/productionAnalysis/components/left-bottom.vue b/src/views/reportAnalysis/productionAnalysis/components/left-bottom.vue
index 9f6a8c1..b7c7358 100644
--- a/src/views/reportAnalysis/productionAnalysis/components/left-bottom.vue
+++ b/src/views/reportAnalysis/productionAnalysis/components/left-bottom.vue
@@ -22,7 +22,7 @@
 </template>
 
 <script setup>
-import { ref, onMounted } from 'vue'
+import { ref, onMounted, inject, watch } from 'vue'
 import Echarts from '@/components/Echarts/echarts.vue'
 import PanelHeader from './PanelHeader.vue'
 import CarouselCards from './CarouselCards.vue'
@@ -143,6 +143,13 @@
     })
 }
 
+const dataDashboardRefreshTick = inject('dataDashboardRefreshTick', null)
+if (dataDashboardRefreshTick) {
+  watch(dataDashboardRefreshTick, () => {
+    workInProcessTurnoverInfo()
+  })
+}
+
 onMounted(() => {
   workInProcessTurnoverInfo()
 })
diff --git a/src/views/reportAnalysis/productionAnalysis/components/left-top.vue b/src/views/reportAnalysis/productionAnalysis/components/left-top.vue
index fd52b1b..37c82f0 100644
--- a/src/views/reportAnalysis/productionAnalysis/components/left-top.vue
+++ b/src/views/reportAnalysis/productionAnalysis/components/left-top.vue
@@ -23,7 +23,7 @@
 </template>
 
 <script setup>
-import { ref, onMounted, onBeforeUnmount, computed } from 'vue'
+import { ref, onMounted, onBeforeUnmount, computed, inject, watch } from 'vue'
 import { processOutputAnalysis } from '@/api/viewIndex.js'
 import PanelHeader from './PanelHeader.vue'
 import Echarts from '@/components/Echarts/echarts.vue'
@@ -170,6 +170,13 @@
   fetchData()
 }
 
+const dataDashboardRefreshTick = inject('dataDashboardRefreshTick', null)
+if (dataDashboardRefreshTick) {
+  watch(dataDashboardRefreshTick, () => {
+    fetchData()
+  })
+}
+
 onMounted(() => {
   fetchData()
   initBackground()
diff --git a/src/views/reportAnalysis/productionAnalysis/components/right-bottom.vue b/src/views/reportAnalysis/productionAnalysis/components/right-bottom.vue
index 28de03b..62356e7 100644
--- a/src/views/reportAnalysis/productionAnalysis/components/right-bottom.vue
+++ b/src/views/reportAnalysis/productionAnalysis/components/right-bottom.vue
@@ -22,7 +22,7 @@
 </template>
 
 <script setup>
-import { ref, onMounted } from 'vue'
+import { ref, onMounted, inject, watch } from 'vue'
 import { productionAccountingAnalysis } from '@/api/viewIndex.js'
 import PanelHeader from './PanelHeader.vue'
 import DateTypeSwitch from './DateTypeSwitch.vue'
@@ -157,6 +157,13 @@
     })
 }
 
+const dataDashboardRefreshTick = inject('dataDashboardRefreshTick', null)
+if (dataDashboardRefreshTick) {
+  watch(dataDashboardRefreshTick, () => {
+    fetchData()
+  })
+}
+
 onMounted(() => {
   fetchData()
 })
diff --git a/src/views/reportAnalysis/productionAnalysis/components/right-top.vue b/src/views/reportAnalysis/productionAnalysis/components/right-top.vue
index d3a9eb9..5ec836f 100644
--- a/src/views/reportAnalysis/productionAnalysis/components/right-top.vue
+++ b/src/views/reportAnalysis/productionAnalysis/components/right-top.vue
@@ -22,7 +22,7 @@
 </template>
 
 <script setup>
-import { ref, onMounted } from 'vue'
+import { ref, onMounted, inject, watch } from 'vue'
 import { workOrderEfficiencyAnalysis } from '@/api/viewIndex.js'
 import PanelHeader from './PanelHeader.vue'
 import Echarts from '@/components/Echarts/echarts.vue'
@@ -152,6 +152,13 @@
     })
 }
 
+const dataDashboardRefreshTick = inject('dataDashboardRefreshTick', null)
+if (dataDashboardRefreshTick) {
+  watch(dataDashboardRefreshTick, () => {
+    fetchData()
+  })
+}
+
 onMounted(() => {
   fetchData()
 })
diff --git a/src/views/reportAnalysis/productionAnalysis/index.vue b/src/views/reportAnalysis/productionAnalysis/index.vue
index e179150..7e03bbd 100644
--- a/src/views/reportAnalysis/productionAnalysis/index.vue
+++ b/src/views/reportAnalysis/productionAnalysis/index.vue
@@ -44,7 +44,7 @@
 </template>
 
 <script setup>
-import { ref, onMounted, onBeforeUnmount, nextTick } from 'vue'
+import { ref, onMounted, onBeforeUnmount, nextTick, provide } from 'vue'
 import autofit from 'autofit.js'
 import LeftBottom from './components/left-bottom.vue'
 import CenterCenter from './components/center-center.vue'
@@ -66,6 +66,12 @@
 
 // 鐢ㄦ埛store
 const userStore = useUserStore()
+
+/** 涓庡叾瀹冮┚椹惰埍鍏辩敤娉ㄥ叆鍚嶏紝瀛愮粍浠舵瘡鍒嗛挓鍒锋柊鎺ュ彛鏁版嵁 */
+const DASHBOARD_REFRESH_MS = 60 * 1000
+const dataDashboardRefreshTick = ref(0)
+provide('dataDashboardRefreshTick', dataDashboardRefreshTick)
+let dashboardPollTimer = null
 
 // 璁$畻缂╂斁姣斾緥
 const calculateScale = () => {
@@ -141,9 +147,17 @@
   window.addEventListener('fullscreenchange', handleFullscreenChange)
   window.addEventListener('webkitfullscreenchange', handleFullscreenChange)
   window.addEventListener('MSFullscreenChange', handleFullscreenChange)
+
+  dashboardPollTimer = setInterval(() => {
+    dataDashboardRefreshTick.value++
+  }, DASHBOARD_REFRESH_MS)
 })
 
 onBeforeUnmount(() => {
+  if (dashboardPollTimer) {
+    clearInterval(dashboardPollTimer)
+    dashboardPollTimer = null
+  }
   window.removeEventListener('resize', handleResize)
   window.removeEventListener('fullscreenchange', handleFullscreenChange)
   window.removeEventListener('webkitfullscreenchange', handleFullscreenChange)

--
Gitblit v1.9.3