From bcbcc546577c7c6643e7f0d4ac366f8a013bd306 Mon Sep 17 00:00:00 2001
From: 罗广辉 <guanghui.luo@foxmail.com>
Date: Tue, 20 Jan 2026 13:47:19 +0800
Subject: [PATCH] Merge remote-tracking branch 'origin/master'

---
 applications/drone-command/src/views/basicManage/maintainRecord/MaintenanceDiaLog.vue                   |    2 
 applications/drone-command/src/views/job/jobinfo.vue                                                    |   12 
 applications/task-work-order/src/views/orderView/orderDataManage/supplyAdd/index.vue                    |   16 
 applications/drone-command/src/styles/common/cockpit.scss                                               |   32 +
 applications/task-work-order/src/views/orderView/orderDataManage/supplyAdd/reasonForRejectionDialog.vue |   91 +++++
 applications/drone-command/src/page/index/top/top-full.vue                                              |   13 
 applications/drone-command/src/utils/cesium/DrawPolygon.js                                              |    1 
 applications/drone-command/src/views/dataCockpit/components/RightContainer.vue                          |    4 
 applications/task-work-order/src/views/orderView/orderDataManage/supplyAdd/FormDiaLog.vue               |    6 
 applications/drone-command/src/views/detectionCountermeasure/taskSchedule/FormDiaLog.vue                |    1 
 applications/drone-command/src/views/layerManagement/components/utils.js                                |    1 
 applications/drone-command/src/utils/util.js                                                            |   25 
 applications/drone-command/src/views/basicManage/maintainRecord/FormDiaLog.vue                          |    2 
 applications/drone-command/src/components/map-container/device-map-container.vue                        |   30 +
 applications/drone-command/src/mac/index.vue                                                            |    7 
 applications/drone-command/src/views/detectionCountermeasure/deviceAppConfig/FormDiaLog.vue             |    3 
 applications/drone-command/src/views/permissionManage/permissionDept/FormDiaLog.vue                     |    4 
 applications/drone-command/src/views/layerManagement/index.vue                                          |    8 
 applications/drone-command/src/views/permissionManage/permissionRole/FormDiaLog.vue                     |    4 
 applications/drone-command/src/views/dataCockpit/components/templateComponents/RealTemplate.vue         |    4 
 applications/drone-command/src/views/basicManage/deviceStock/DeviceTrackDiaLog.vue                      |    3 
 applications/drone-command/src/views/dataCockpit/components/CenterContainer.vue                         |    8 
 applications/drone-command/public/fonts/DinAB.TTF                                                       |    0 
 applications/drone-command/src/views/permissionManage/permissionUser/FormDiaLog.vue                     |    3 
 applications/task-work-order/src/views/orderView/orderDataManage/supplyAdd/ApplyViewDialog.vue          |  607 ++++++++++++++++++++---------------
 applications/drone-command/src/views/basicManage/deviceStock/DeviceScrapDiaLog.vue                      |    3 
 applications/drone-command/src/views/recordManage/historyTracks/index.vue                               |   33 +
 applications/drone-command/src/page/login/index.vue                                                     |   10 
 applications/drone-command/src/views/basicManage/deviceStock/FormDiaLog.vue                             |    2 
 applications/drone-command/src/page/lock/index.vue                                                      |   10 
 applications/task-work-order/src/views/orderView/orderDataManage/supplyAdd/supplyAddApi.js              |    9 
 applications/drone-command/src/views/areaManage/precinctInfo/FormDiaLog.vue                             |    4 
 applications/drone-command/src/views/basicManage/deviceScrap/FormDiaLog.vue                             |    2 
 applications/drone-command/src/views/dataCenter/components/dataCenterMap.vue                            |    8 
 applications/drone-command/public/fonts/font.css                                                        |    7 
 35 files changed, 649 insertions(+), 326 deletions(-)

diff --git a/applications/drone-command/public/fonts/DinAB.TTF b/applications/drone-command/public/fonts/DinAB.TTF
new file mode 100644
index 0000000..81f2f7a
--- /dev/null
+++ b/applications/drone-command/public/fonts/DinAB.TTF
Binary files differ
diff --git a/applications/drone-command/public/fonts/font.css b/applications/drone-command/public/fonts/font.css
index 4da8f62..8cd27b0 100644
--- a/applications/drone-command/public/fonts/font.css
+++ b/applications/drone-command/public/fonts/font.css
@@ -52,3 +52,10 @@
   font-display: swap;
 }
 
+@font-face {
+  font-family: "DinAB";
+  src: url("DinAB.TTF") format("truetype");
+  font-weight: normal;
+  font-style: normal;
+  font-display: swap;
+}
\ No newline at end of file
diff --git a/applications/drone-command/src/components/map-container/device-map-container.vue b/applications/drone-command/src/components/map-container/device-map-container.vue
index 8610eaf..46199a1 100644
--- a/applications/drone-command/src/components/map-container/device-map-container.vue
+++ b/applications/drone-command/src/components/map-container/device-map-container.vue
@@ -22,7 +22,15 @@
 
 		<div v-if="popupVisible" class="device-popup" :style="popupStyle" @click.stop>
 			<div class="device-popup__header">
-				<span class="device-popup__title">{{ popupTitle }}</span>
+				<el-tooltip
+					class="device-popup__title-tooltip"
+					:content="popupTitle"
+					placement="top"
+					effect="dark"
+					:show-after="200"
+				>
+					<span class="device-popup__title">{{ popupTitleDisplay }}</span>
+				</el-tooltip>
 
 				<img class="device-popup__close" :src="popupClose" alt="" @click.stop="closePopup">
 			</div>
@@ -579,7 +587,13 @@
 	top: `${popupPosition.value.y}px`,
 }))
 
+const POPUP_TITLE_MAX = 12
 const popupTitle = computed(() => selectedDevice.value?.deviceName || selectedDevice.value?.deviceModel || '-')
+const popupTitleOverflow = computed(() => popupTitle.value.length > POPUP_TITLE_MAX)
+const popupTitleDisplay = computed(() => {
+	if (!popupTitleOverflow.value) return popupTitle.value
+	return `${popupTitle.value.slice(0, POPUP_TITLE_MAX)}……`
+})
 const popupStatusText = computed(() => {
 	const status = selectedDevice.value?.status
 	if (status === 0) return '在线'
@@ -828,6 +842,20 @@
 			border-radius: 0px 0px 5px 5px;
 		}
 
+		.device-popup__title-tooltip {
+			flex: 1;
+			min-width: 0;
+			display: block;
+		}
+
+		.device-popup__title {
+			display: inline-block;
+			max-width: 100%;
+			white-space: nowrap;
+			overflow: hidden;
+			text-overflow: ellipsis;
+		}
+
 		.device-popup__close {
 			cursor: pointer;
 		}
diff --git a/applications/drone-command/src/mac/index.vue b/applications/drone-command/src/mac/index.vue
index 0d7f386..675df91 100644
--- a/applications/drone-command/src/mac/index.vue
+++ b/applications/drone-command/src/mac/index.vue
@@ -69,6 +69,7 @@
     return {
       app: false,
       timeString: '',
+      timeTimer: null,
     }
   },
   computed: {
@@ -116,6 +117,12 @@
     this.startTimer()
     this.$store.dispatch('GetMenu')
   },
+  beforeDestroy () {
+    if (this.timeTimer) {
+      clearInterval(this.timeTimer)
+      this.timeTimer = null
+    }
+  },
   methods: {
     switchTheme () {
       this.$store.commit('SET_THEME_NAME', '')
diff --git a/applications/drone-command/src/page/index/top/top-full.vue b/applications/drone-command/src/page/index/top/top-full.vue
index 099d698..cec6ea3 100644
--- a/applications/drone-command/src/page/index/top/top-full.vue
+++ b/applications/drone-command/src/page/index/top/top-full.vue
@@ -6,11 +6,22 @@
 import { fullscreenToggel, listenfullscreen } from 'utils/util';
 
 export default {
+  data() {
+    return {
+      fullscreenCleanup: null,
+    };
+  },
   computed: {
     ...mapGetters(['isFullScren']),
   },
   mounted() {
-    listenfullscreen(this.setScreen);
+    this.fullscreenCleanup = listenfullscreen(this.setScreen);
+  },
+  beforeDestroy() {
+    if (this.fullscreenCleanup) {
+      this.fullscreenCleanup();
+      this.fullscreenCleanup = null;
+    }
   },
   methods: {
     setScreen() {
diff --git a/applications/drone-command/src/page/lock/index.vue b/applications/drone-command/src/page/lock/index.vue
index 2215769..9b65ab3 100644
--- a/applications/drone-command/src/page/lock/index.vue
+++ b/applications/drone-command/src/page/lock/index.vue
@@ -45,6 +45,7 @@
   data() {
     return {
       time: '',
+      timeTimer: null,
       passwd: '',
       passwdError: false,
       pass: false,
@@ -52,10 +53,17 @@
   },
   created() {
     this.getTime();
-    setInterval(() => {
+    if (this.timeTimer) clearInterval(this.timeTimer);
+    this.timeTimer = setInterval(() => {
       this.getTime();
     }, 1000);
   },
+  beforeDestroy() {
+    if (this.timeTimer) {
+      clearInterval(this.timeTimer);
+      this.timeTimer = null;
+    }
+  },
   mounted() {},
   computed: {
     ...mapGetters(['userInfo', 'tag', 'lockPasswd']),
diff --git a/applications/drone-command/src/page/login/index.vue b/applications/drone-command/src/page/login/index.vue
index 4453760..ad005da 100644
--- a/applications/drone-command/src/page/login/index.vue
+++ b/applications/drone-command/src/page/login/index.vue
@@ -56,6 +56,7 @@
       },
       website: website,
       time: '',
+      timeTimer: null,
       activeName: 'user',
       socialForm: {
         tenantId: '000000',
@@ -82,6 +83,12 @@
   computed: {
     ...mapGetters(['tagWel']),
   },
+  beforeDestroy() {
+    if (this.timeTimer) {
+      clearInterval(this.timeTimer);
+      this.timeTimer = null;
+    }
+  },
   props: [],
   methods: {
     // 动态获取系统名称
@@ -93,7 +100,8 @@
       })
     },
     getTime() {
-      setInterval(() => {
+      if (this.timeTimer) clearInterval(this.timeTimer);
+      this.timeTimer = setInterval(() => {
         this.time = this.$dayjs().format('YYYY-MM-DD HH:mm:ss');
       }, 1000);
     },
diff --git a/applications/drone-command/src/styles/common/cockpit.scss b/applications/drone-command/src/styles/common/cockpit.scss
index e9ae2cb..e2468bc 100644
--- a/applications/drone-command/src/styles/common/cockpit.scss
+++ b/applications/drone-command/src/styles/common/cockpit.scss
@@ -1065,24 +1065,37 @@
 }
 
 .command-page-view-dialog {
-    padding: 30px;
+    margin: 0;
+    padding: 20px;
     display: flex;
     flex-direction: column;
     width: 770px;
     background: #1A1A2A;
     border-radius: 6px 6px 6px 6px;
     border: 1px solid #2E2E46;
+    position: absolute;
+    top: 50%;
+    left: 50%;
+    transform: translate(-50%, -50%);
 
     .el-dialog__header {
+        position: relative;
+
         span {
             font-family: Source Han Sans CN, Source Han Sans CN;
             font-weight: bold;
             font-size: 18px;
             color: #FFFFFF;
-            line-height: 40px;
             text-align: left;
             font-style: normal;
             text-transform: none;
+        }
+
+        .el-button {
+            width: auto;
+            height: auto;
+            display: flex;
+            align-items: center;
         }
 
         .el-icon {
@@ -1145,6 +1158,7 @@
                 height: 360px;
 
                 .command-table-pagination {
+                    padding-bottom: 20px;
                     justify-content: center;
                 }
             }
@@ -1165,6 +1179,10 @@
             .el-row {
                 .el-col {
                     margin-bottom: 0;
+
+                    .el-form-item {
+                        margin-bottom: 20px;
+                    }
                 }
             }
 
@@ -1288,6 +1306,7 @@
     }
 
     .el-dialog__footer {
+        padding-top: 0;
         display: flex;
         justify-content: center;
 
@@ -1353,7 +1372,9 @@
 }
 
 .command-page-map-view-dialog {
-    padding: 30px;
+    margin: 0;
+
+    padding: 20px;
     display: flex;
     flex-direction: column;
     width: 80%;
@@ -1362,6 +1383,11 @@
     border-radius: 6px 6px 6px 6px;
     border: 1px solid #2E2E46;
 
+    position: absolute;
+    top: 50%;
+    left: 50%;
+    transform: translate(-50%, -50%);
+
     .el-dialog__header,
     .el-dialog__footer {
         margin: 0;
diff --git a/applications/drone-command/src/utils/cesium/DrawPolygon.js b/applications/drone-command/src/utils/cesium/DrawPolygon.js
index 6c37a35..4a4f10c 100644
--- a/applications/drone-command/src/utils/cesium/DrawPolygon.js
+++ b/applications/drone-command/src/utils/cesium/DrawPolygon.js
@@ -785,6 +785,7 @@
 				this.handler.removeInputAction(type)
 			})
 
+			this.handler.destroy()
 			this.handler = null
 		}
 	}
diff --git a/applications/drone-command/src/utils/util.js b/applications/drone-command/src/utils/util.js
index 57c3536..c149ad4 100644
--- a/applications/drone-command/src/utils/util.js
+++ b/applications/drone-command/src/utils/util.js
@@ -102,22 +102,21 @@
  * esc监听全屏
  */
 export const listenfullscreen = callback => {
-  function listen () {
+  const handler = () => {
     callback()
   }
 
-  document.addEventListener('fullscreenchange', function () {
-    listen()
-  })
-  document.addEventListener('mozfullscreenchange', function () {
-    listen()
-  })
-  document.addEventListener('webkitfullscreenchange', function () {
-    listen()
-  })
-  document.addEventListener('msfullscreenchange', function () {
-    listen()
-  })
+  document.addEventListener('fullscreenchange', handler)
+  document.addEventListener('mozfullscreenchange', handler)
+  document.addEventListener('webkitfullscreenchange', handler)
+  document.addEventListener('msfullscreenchange', handler)
+
+  return () => {
+    document.removeEventListener('fullscreenchange', handler)
+    document.removeEventListener('mozfullscreenchange', handler)
+    document.removeEventListener('webkitfullscreenchange', handler)
+    document.removeEventListener('msfullscreenchange', handler)
+  }
 }
 /**
  * 获取缩略图路径
diff --git a/applications/drone-command/src/views/areaManage/precinctInfo/FormDiaLog.vue b/applications/drone-command/src/views/areaManage/precinctInfo/FormDiaLog.vue
index a6fb72d..d98a363 100644
--- a/applications/drone-command/src/views/areaManage/precinctInfo/FormDiaLog.vue
+++ b/applications/drone-command/src/views/areaManage/precinctInfo/FormDiaLog.vue
@@ -1,7 +1,7 @@
 <template>
-	<el-dialog class="command-page-view-dialog" v-model="visible" :title="titleEnum[dialogMode]">
+	<el-dialog class="command-page-view-dialog" v-model="visible" :title="titleEnum[dialogMode]"
+		:close-on-click-modal="false">
 		<div class="detail-container" v-if="readonly">
-			<div class="detail-title">派出所详情</div>
 			<el-row>
 				<el-col :span="12">
 					<div class="label">派出所名称</div>
diff --git a/applications/drone-command/src/views/basicManage/deviceScrap/FormDiaLog.vue b/applications/drone-command/src/views/basicManage/deviceScrap/FormDiaLog.vue
index 4361786..b97ca68 100644
--- a/applications/drone-command/src/views/basicManage/deviceScrap/FormDiaLog.vue
+++ b/applications/drone-command/src/views/basicManage/deviceScrap/FormDiaLog.vue
@@ -1,6 +1,6 @@
 <template>
 	<el-dialog class="command-page-view-dialog" v-model="visible" :title="titleEnum[dialogMode]" @closed="handleClosed"
-		destroy-on-close>
+		destroy-on-close :close-on-click-modal="false">
 		<div class="detail-container" v-if="dialogReadonly">
 			<el-row>
 				<el-col :span="12">
diff --git a/applications/drone-command/src/views/basicManage/deviceStock/DeviceScrapDiaLog.vue b/applications/drone-command/src/views/basicManage/deviceStock/DeviceScrapDiaLog.vue
index 456a8a0..caea697 100644
--- a/applications/drone-command/src/views/basicManage/deviceStock/DeviceScrapDiaLog.vue
+++ b/applications/drone-command/src/views/basicManage/deviceStock/DeviceScrapDiaLog.vue
@@ -1,5 +1,6 @@
 <template>
-	<el-dialog class="command-page-view-dialog" v-model="visible" :title="dialogTitle" @closed="handleClosed" destroy-on-close>
+	<el-dialog class="command-page-view-dialog" v-model="visible" :title="dialogTitle" @closed="handleClosed" destroy-on-close
+		:close-on-click-modal="false">
 		<el-form class="dialog-form" ref="formRef" :model="formData" :rules="rules" label-width="100px">
 			<el-row>
 				<el-col :span="24">
diff --git a/applications/drone-command/src/views/basicManage/deviceStock/DeviceTrackDiaLog.vue b/applications/drone-command/src/views/basicManage/deviceStock/DeviceTrackDiaLog.vue
index bb77694..4e05934 100644
--- a/applications/drone-command/src/views/basicManage/deviceStock/DeviceTrackDiaLog.vue
+++ b/applications/drone-command/src/views/basicManage/deviceStock/DeviceTrackDiaLog.vue
@@ -1,5 +1,6 @@
 <template>
-	<el-dialog class="command-page-view-dialog" v-model="visible" :title="dialogTitle" @closed="handleClosed" destroy-on-close>
+	<el-dialog class="command-page-view-dialog" v-model="visible" :title="dialogTitle" @closed="handleClosed" destroy-on-close
+		:close-on-click-modal="false">
 		<el-form class="dialog-form" ref="formRef" :model="formData" :rules="rules" label-width="100px">
 			<el-row>
 				<el-col :span="12">
diff --git a/applications/drone-command/src/views/basicManage/deviceStock/FormDiaLog.vue b/applications/drone-command/src/views/basicManage/deviceStock/FormDiaLog.vue
index 9c4c2e3..ea94ffa 100644
--- a/applications/drone-command/src/views/basicManage/deviceStock/FormDiaLog.vue
+++ b/applications/drone-command/src/views/basicManage/deviceStock/FormDiaLog.vue
@@ -1,6 +1,6 @@
 <template>
 	<el-dialog class="command-page-view-dialog" v-model="visible" :title="dialogTitle" @closed="handleClosed"
-		destroy-on-close>
+		destroy-on-close :close-on-click-modal="false">
 		<div class="detail-container" v-if="dialogReadonly">
 			<div class="detail-title">设备详情</div>
 			<el-row>
diff --git a/applications/drone-command/src/views/basicManage/maintainRecord/FormDiaLog.vue b/applications/drone-command/src/views/basicManage/maintainRecord/FormDiaLog.vue
index 71171cf..1696a0d 100644
--- a/applications/drone-command/src/views/basicManage/maintainRecord/FormDiaLog.vue
+++ b/applications/drone-command/src/views/basicManage/maintainRecord/FormDiaLog.vue
@@ -1,6 +1,6 @@
 <template>
 	<el-dialog class="command-page-view-dialog" v-model="visible" :title="titleEnum[dialogMode]" @closed="handleClosed"
-		destroy-on-close>
+		destroy-on-close :close-on-click-modal="false">
 		<div class="detail-container" v-if="dialogReadonly">
 			<div class="detail-title">设备详情</div>
 			<el-row>
diff --git a/applications/drone-command/src/views/basicManage/maintainRecord/MaintenanceDiaLog.vue b/applications/drone-command/src/views/basicManage/maintainRecord/MaintenanceDiaLog.vue
index 70f5b9f..72ac79a 100644
--- a/applications/drone-command/src/views/basicManage/maintainRecord/MaintenanceDiaLog.vue
+++ b/applications/drone-command/src/views/basicManage/maintainRecord/MaintenanceDiaLog.vue
@@ -5,9 +5,9 @@
 		:title="titleEnum[dialogMode]"
 		@closed="handleClosed"
 		destroy-on-close
+		:close-on-click-modal="false"
 	>
 		<div class="detail-container" v-if="dialogReadonly">
-			<div class="detail-title">设备详情</div>
 			<el-row>
 				<el-col :span="12">
 					<div class="label">设备名称</div>
diff --git a/applications/drone-command/src/views/dataCenter/components/dataCenterMap.vue b/applications/drone-command/src/views/dataCenter/components/dataCenterMap.vue
index 5271f02..dbe87c4 100644
--- a/applications/drone-command/src/views/dataCenter/components/dataCenterMap.vue
+++ b/applications/drone-command/src/views/dataCenter/components/dataCenterMap.vue
@@ -72,8 +72,11 @@
 
 const removeDom = () => {
   const dom = document.querySelector('#mapPopUpBox');
-  if (dom && dom.parentNode) {
-    dom.parentNode.removeChild(dom);
+  if (dom) {
+    render(null, dom);
+    if (dom.parentNode) {
+      dom.parentNode.removeChild(dom);
+    }
   }
 };
 // 移除弹框标签
@@ -290,6 +293,7 @@
 
 onMounted(() => {});
 onBeforeUnmount(() => {
+  removeLabel();
   if (viewer) {
     viewer.destroy();
   }
diff --git a/applications/drone-command/src/views/dataCockpit/components/CenterContainer.vue b/applications/drone-command/src/views/dataCockpit/components/CenterContainer.vue
index 170826c..9e43ad3 100644
--- a/applications/drone-command/src/views/dataCockpit/components/CenterContainer.vue
+++ b/applications/drone-command/src/views/dataCockpit/components/CenterContainer.vue
@@ -25,7 +25,7 @@
 
 			<div class="list">
 				<div class="item" v-for="(item, ind) in equipmentList" :key="ind">
-					<div class="val" :class="{highlight: item.isHighlight}" @click="equipmentClick(item.isHighlight)">
+					<div class="val" :class="{ highlight: item.isHighlight }" @click="equipmentClick(item.isHighlight)">
 						{{ item.value }}
 					</div>
 
@@ -158,7 +158,7 @@
 		display: flex;
 		align-items: center;
 		height: 100px;
-		background: rgba(0,0,0,0.3);
+		background: rgba(0, 0, 0, 0.3);
 		box-sizing: border-box;
 		border-radius: 16px 16px 16px 16px;
 		pointer-events: auto;
@@ -172,7 +172,7 @@
 			height: 100%;
 			z-index: -1;
 			background: rgba(17, 23, 34, 0.56);
-      		backdrop-filter: blur(2px);
+			backdrop-filter: blur(2px);
 			border-radius: 16px 16px 16px 16px;
 		}
 
@@ -208,7 +208,7 @@
 				}
 
 				.val {
-					font-family: Source Han Sans CN, Source Han Sans CN;
+					font-family: DinAB;
 					font-weight: bold;
 					font-size: 30px;
 					text-align: left;
diff --git a/applications/drone-command/src/views/dataCockpit/components/RightContainer.vue b/applications/drone-command/src/views/dataCockpit/components/RightContainer.vue
index fb146b5..5cd84d9 100644
--- a/applications/drone-command/src/views/dataCockpit/components/RightContainer.vue
+++ b/applications/drone-command/src/views/dataCockpit/components/RightContainer.vue
@@ -2,7 +2,7 @@
  * @Author       : yuan
  * @Date         : 2026-01-07 15:17:54
  * @LastEditors  : yuan
- * @LastEditTime : 2026-01-19 14:05:35
+ * @LastEditTime : 2026-01-20 09:19:16
  * @FilePath     : \applications\drone-command\src\views\dataCockpit\components\RightContainer.vue
  * @Description  : 
  * Copyright 2026 OBKoro1, All Rights Reserved. 
@@ -233,7 +233,7 @@
 
 			.val {
 				margin-top: 10px;
-				font-family: DIN, DIN;
+				font-family: DinAB;
 				font-weight: bold;
 				font-size: 22px;
 				color: #FFFFFF;
diff --git a/applications/drone-command/src/views/dataCockpit/components/templateComponents/RealTemplate.vue b/applications/drone-command/src/views/dataCockpit/components/templateComponents/RealTemplate.vue
index 74036d9..2019774 100644
--- a/applications/drone-command/src/views/dataCockpit/components/templateComponents/RealTemplate.vue
+++ b/applications/drone-command/src/views/dataCockpit/components/templateComponents/RealTemplate.vue
@@ -65,8 +65,8 @@
 		</div>
 
 		<div class="footer">
-			<el-button v-if="showSignalBtn(data)" class="general" color="#2B2B4C" @click="emit('signal')">信号干扰</el-button>
-			<el-button v-if="showCounterBtn(data)" color="#284FE3" type="primary" @click="emit('counter')">诱导驱离</el-button>
+			<el-button class="general" color="#2B2B4C" @click="emit('signal')">信号干扰</el-button>
+			<el-button color="#284FE3" type="primary" @click="emit('counter')">诱导驱离</el-button>
 		</div>
 	</div>
 </template>
diff --git a/applications/drone-command/src/views/detectionCountermeasure/deviceAppConfig/FormDiaLog.vue b/applications/drone-command/src/views/detectionCountermeasure/deviceAppConfig/FormDiaLog.vue
index 7c6c675..d371ba6 100644
--- a/applications/drone-command/src/views/detectionCountermeasure/deviceAppConfig/FormDiaLog.vue
+++ b/applications/drone-command/src/views/detectionCountermeasure/deviceAppConfig/FormDiaLog.vue
@@ -8,7 +8,6 @@
 		destroy-on-close
 	>
 		<div v-if="readonly" class="detail-container">
-			<div class="detail-title">配置详情</div>
 			<el-row>
 				<el-col :span="12">
 					<div class="label">起始扇区</div>
@@ -94,7 +93,7 @@
 						/>
 					</el-form-item>
 				</el-col>
-				<el-col :span="24"><h3 style="color: #ffffff">工作模式</h3></el-col>
+				<el-col :span="24"><h3 style="color: #ffffff">设备参数</h3></el-col>
 				<el-col :span="12">
 					<el-form-item label="伺服模式" prop="servoMode">
 						<el-select
diff --git a/applications/drone-command/src/views/detectionCountermeasure/taskSchedule/FormDiaLog.vue b/applications/drone-command/src/views/detectionCountermeasure/taskSchedule/FormDiaLog.vue
index 5cb95e6..b411642 100644
--- a/applications/drone-command/src/views/detectionCountermeasure/taskSchedule/FormDiaLog.vue
+++ b/applications/drone-command/src/views/detectionCountermeasure/taskSchedule/FormDiaLog.vue
@@ -8,7 +8,6 @@
 		@closed="handleClosed"
 	>
 		<div v-if="readonly" class="detail-container">
-			<div class="detail-title">调度详情</div>
 			<el-row>
 				<el-col :span="12">
 					<div class="label">设备名称</div>
diff --git a/applications/drone-command/src/views/job/jobinfo.vue b/applications/drone-command/src/views/job/jobinfo.vue
index 2fa7b2b..240c22f 100644
--- a/applications/drone-command/src/views/job/jobinfo.vue
+++ b/applications/drone-command/src/views/job/jobinfo.vue
@@ -45,13 +45,21 @@
       selectionList: [],
       option: option,
       data: [],
+      searchChangeHandler: null,
     }
   },
   created() {
-       this.$bus?.on('triggerSearchChange', (params) => {
+       this.searchChangeHandler = (params) => {
          this.searchChange(params, () => {});
-       });
+       };
+       this.$bus?.on('triggerSearchChange', this.searchChangeHandler);
      },
+  beforeDestroy() {
+    if (this.searchChangeHandler) {
+      this.$bus?.off('triggerSearchChange', this.searchChangeHandler);
+      this.searchChangeHandler = null;
+    }
+  },
   computed: {
     ...mapGetters(['permission']),
     permissionList () {
diff --git a/applications/drone-command/src/views/layerManagement/components/utils.js b/applications/drone-command/src/views/layerManagement/components/utils.js
index 7001570..458b5a7 100644
--- a/applications/drone-command/src/views/layerManagement/components/utils.js
+++ b/applications/drone-command/src/views/layerManagement/components/utils.js
@@ -600,6 +600,7 @@
 				this.handler.removeInputAction(type)
 			})
 
+			this.handler.destroy()
 			this.handler = null
 		}
 	}
diff --git a/applications/drone-command/src/views/layerManagement/index.vue b/applications/drone-command/src/views/layerManagement/index.vue
index 67ee11a..f1bcf7a 100644
--- a/applications/drone-command/src/views/layerManagement/index.vue
+++ b/applications/drone-command/src/views/layerManagement/index.vue
@@ -488,14 +488,15 @@
   isPageLoading.value = status;
 };
 provide('layerParams', layerParams);
+const focusOnNodeHandler = nodeData => {
+  focusOnNode(nodeData);
+};
 onMounted(() => {
   initMap();
   cesiumContextMenu();
   getdataFolderApi();
   // 监听定位事件
-  EventBus.on('focusOnNode', (nodeData) => {
-    focusOnNode(nodeData);
-  });
+  EventBus.on('focusOnNode', focusOnNodeHandler);
   EventBus.on('deleteMapEntityById', deleteMapEntityById);
   EventBus.on('deleteMapEntitiesByFolderId', deleteMapEntitiesByFolderId);
 });
@@ -523,6 +524,7 @@
 onBeforeUnmount(() => {
   destroyMap();
   cesiumContextMenu(false);
+  EventBus.off('focusOnNode', focusOnNodeHandler);
   EventBus.off('deleteMapEntityById', deleteMapEntityById);
   EventBus.off('deleteMapEntitiesByFolderId', deleteMapEntitiesByFolderId);
 });
diff --git a/applications/drone-command/src/views/permissionManage/permissionDept/FormDiaLog.vue b/applications/drone-command/src/views/permissionManage/permissionDept/FormDiaLog.vue
index 829062d..c171ead 100644
--- a/applications/drone-command/src/views/permissionManage/permissionDept/FormDiaLog.vue
+++ b/applications/drone-command/src/views/permissionManage/permissionDept/FormDiaLog.vue
@@ -1,7 +1,7 @@
 <template>
-	<el-dialog class="command-page-view-dialog" v-model="visible" :title="dialogTitle" @closed="handleClosed" destroy-on-close>
+	<el-dialog class="command-page-view-dialog" v-model="visible" :title="dialogTitle" @closed="handleClosed" destroy-on-close
+		:close-on-click-modal="false">
 		<div class="detail-container" v-if="dialogReadonly">
-			<div class="detail-title">机构详情</div>
 			<el-row>
 				<el-col :span="12">
 					<div class="label">部门名称</div>
diff --git a/applications/drone-command/src/views/permissionManage/permissionRole/FormDiaLog.vue b/applications/drone-command/src/views/permissionManage/permissionRole/FormDiaLog.vue
index 5b008e9..9e39032 100644
--- a/applications/drone-command/src/views/permissionManage/permissionRole/FormDiaLog.vue
+++ b/applications/drone-command/src/views/permissionManage/permissionRole/FormDiaLog.vue
@@ -1,7 +1,7 @@
 <template>
-	<el-dialog class="command-page-view-dialog" v-model="visible" :title="dialogTitle" @closed="handleClosed" destroy-on-close>
+	<el-dialog class="command-page-view-dialog" v-model="visible" :title="dialogTitle" @closed="handleClosed" destroy-on-close
+		:close-on-click-modal="false">
 		<div class="detail-container" v-if="dialogReadonly">
-			<div class="detail-title">角色详情</div>
 			<el-row>
 				<el-col :span="12">
 					<div class="label">角色名称</div>
diff --git a/applications/drone-command/src/views/permissionManage/permissionUser/FormDiaLog.vue b/applications/drone-command/src/views/permissionManage/permissionUser/FormDiaLog.vue
index fec23bc..62957b1 100644
--- a/applications/drone-command/src/views/permissionManage/permissionUser/FormDiaLog.vue
+++ b/applications/drone-command/src/views/permissionManage/permissionUser/FormDiaLog.vue
@@ -1,5 +1,6 @@
 <template>
-	<el-dialog class="command-page-view-dialog" v-model="visible" :title="dialogTitle" @closed="handleClosed" destroy-on-close>
+	<el-dialog class="command-page-view-dialog" v-model="visible" :title="dialogTitle" @closed="handleClosed" destroy-on-close
+		:close-on-click-modal="false">
 		<div class="detail-container" v-if="dialogReadonly">
 			<div class="detail-title">用户详情</div>
 			<el-row>
diff --git a/applications/drone-command/src/views/recordManage/historyTracks/index.vue b/applications/drone-command/src/views/recordManage/historyTracks/index.vue
index ec936f8..69b6ad5 100644
--- a/applications/drone-command/src/views/recordManage/historyTracks/index.vue
+++ b/applications/drone-command/src/views/recordManage/historyTracks/index.vue
@@ -39,12 +39,22 @@
 		</el-form>
 
 		<div class="command-table-toolbar">
-			<el-button :icon="Download" color="#1A2652" type="primary" @click="exportFile" :loading="exportLoading">导出</el-button>
+			<el-button
+				:icon="Download"
+				color="#1A2652"
+				type="primary"
+				@click="exportFile"
+				:loading="exportLoading"
+				:disabled="!selectionList.length"
+			>
+				导出
+			</el-button>
 		</div>
 
 		<div class="command-table-container" v-loading="loading" element-loading-background="rgba(5, 5, 15, 0.6)">
 			<div class="command-table-content command-table-content-bg">
-				<el-table class="command-table" :data="list">
+				<el-table class="command-table" :data="list" ref="tableRef" @selection-change="handleSelectionChange">
+					<el-table-column type="selection" width="48" />
 					<el-table-column type="index" show-overflow-tooltip width="64" label="序号" />
 					<el-table-column prop="droneName" show-overflow-tooltip width="140" label="无人机名称" />
 					<el-table-column prop="serialNo" show-overflow-tooltip label="无人机序列号" />
@@ -82,7 +92,7 @@
 
 <script setup>
 import { Search, RefreshRight, Download } from '@element-plus/icons-vue'
-import { onMounted, ref } from 'vue'
+import { onMounted, ref, nextTick } from 'vue'
 import { exportFwDroneFlightRecordApi, fwDroneFlightRecordPageApi } from './fwDroneFlightRecord'
 import { blobDownload, dateRangeFormat } from '@ztzf/utils'
 import TrajectoryDiaLog from '@/views/recordManage/historyTracks/TrajectoryDiaLog.vue'
@@ -97,6 +107,8 @@
 const total = ref(0) // 总条数
 const loading = ref(true) // 列表加载中
 const list = ref([]) // 列表数据
+const tableRef = ref(null)
+const selectionList = ref([])
 const queryParamsRef = ref(null) // 查询表单实例
 const dateRange = ref([])
 const exportLoading = ref(false)
@@ -111,6 +123,9 @@
 		const res = await fwDroneFlightRecordPageApi(params)
 		list.value = res?.data?.data?.records ?? []
 		total.value = res?.data?.data?.total ?? 0
+		selectionList.value = []
+		await nextTick()
+		tableRef.value?.clearSelection()
 	} finally {
 		loading.value = false
 	}
@@ -141,8 +156,14 @@
 
 function exportFile() {
 	const range = dateRangeFormat(dateRange.value)
+	const ids = selectionList.value.map(item => item.id).filter(Boolean)
 	exportLoading.value = true
-	exportFwDroneFlightRecordApi({ ...searchParams.value, start_time: range[0], end_time: range[1] })
+	exportFwDroneFlightRecordApi({
+		...searchParams.value,
+		start_time: range?.[0],
+		end_time: range?.[1],
+		id: ids.join(','),
+	})
 		.then(res => {
 			blobDownload(res)
 		})
@@ -151,6 +172,10 @@
 		})
 }
 
+function handleSelectionChange(selection) {
+	selectionList.value = selection || []
+}
+
 function handleView(row) {
 	dialogRef.value?.open({ mode: 'view', row: { ...row } })
 }
diff --git a/applications/task-work-order/src/views/orderView/orderDataManage/supplyAdd/ApplyViewDialog.vue b/applications/task-work-order/src/views/orderView/orderDataManage/supplyAdd/ApplyViewDialog.vue
index e30d064..c054e4a 100644
--- a/applications/task-work-order/src/views/orderView/orderDataManage/supplyAdd/ApplyViewDialog.vue
+++ b/applications/task-work-order/src/views/orderView/orderDataManage/supplyAdd/ApplyViewDialog.vue
@@ -1,164 +1,154 @@
 <template>
-	<el-dialog
-		class="gd-dialog"
-		v-model="visible"
-		:title="'查看申请'"
-		@closed="visible = false"
-		destroy-on-close
-	>
-	<div class="detail-container">
-		<!-- 左侧步骤条 -->
-		<div class="detail-left">
-			<el-steps :active="activeStep" direction="vertical" align-center>
-				<el-step v-for="(step, index) in steps" :key="index" :title="step.title">
-					<template #description>
-						<div class="step-person">{{ step.person }}</div>
-						<div class="step-time">{{ step.time }}</div>
-					</template>
-				</el-step>
-			</el-steps>
-		</div>
-		<!-- 右侧表单数据 -->
-		<div class="detail-right">
-		<div>
-			<div class="label">需求详情</div>
-			<div class="requirementsDetailsBox">
-				<div class="detail-table">
-					<div class="detail-row">
-						<div class="detail-cell">
-							<span class="cell-label">需求名称</span>
-							<span class="cell-value">{{ formData.demandName }}</span>
-						</div>
-						<div class="detail-cell">
-							<span class="cell-label">需求类型</span>
-							<span class="cell-value">{{ getDictLabel(formData.demandType, dictObj.requirementType) }}</span>
+	<el-dialog class="gd-dialog" v-model="visible" :title="'查看申请'" @closed="visible = false" destroy-on-close>
+		<div class="detail-container">
+			<!-- 左侧审批记录 -->
+			<div class="detail-left">
+				<div class="label">审批记录</div>
+				<el-steps :active="activeStep" direction="vertical" align-center>
+					<el-step v-for="(step, index) in steps" :key="index" :title="step.title">
+						<template #description>
+							<div class="step-person">{{ step.person }}</div>
+							<div class="step-time">{{ step.time }}</div>
+						</template>
+					</el-step>
+				</el-steps>
+			</div>
+			<!-- 右侧表单数据 -->
+			<div class="detail-right">
+				<div>
+					<div class="label">需求详情</div>
+					<div class="requirementsDetailsBox">
+						<div class="detail-table">
+							<div class="detail-row">
+								<div class="detail-cell">
+									<span class="cell-label">需求名称</span>
+									<span class="cell-value">{{ formData.demandName }}</span>
+								</div>
+								<div class="detail-cell">
+									<span class="cell-label">需求类型</span>
+									<span class="cell-value">{{ getDictLabel(formData.demandType, dictObj.requirementType) }}</span>
+								</div>
+							</div>
+							<div class="detail-row">
+								<div class="detail-cell">
+									<span class="cell-label">需求联系人</span>
+									<span class="cell-value">{{ formData.contactPerson }}</span>
+								</div>
+								<div class="detail-cell">
+									<span class="cell-label">需求联系人电话</span>
+									<span class="cell-value">{{ formData.contactPhone }}</span>
+								</div>
+							</div>
+							<div class="detail-row">
+								<div class="detail-cell">
+									<span class="cell-label">需求邮箱</span>
+									<span class="cell-value">{{ formData.contactEmail }}</span>
+								</div>
+								<div class="detail-cell">
+									<span class="cell-label">更新周期</span>
+									<span class="cell-value">{{ formData.updateCycle }}</span>
+								</div>
+							</div>
+							<div class="detail-row">
+								<div class="detail-cell">
+									<span class="cell-label">申请依据</span>
+									<span class="cell-value">{{ formData.applyBasis }}</span>
+								</div>
+								<div class="detail-cell">
+									<span class="cell-label">共享类型</span>
+									<span class="cell-value">{{ getDictLabel(formData.shareType, dictObj.sharedType) }}</span>
+								</div>
+							</div>
+							<div class="detail-row">
+								<div class="detail-cell">
+									<span class="cell-label">应用场景类型</span>
+									<span class="cell-value">{{ getDictLabel(formData.applicationScene, dictObj.appSceneType) }}</span>
+								</div>
+								<div class="detail-cell">
+									<span class="cell-label">责任部门</span>
+									<span class="cell-value">{{ formData.responsibleDeptName }}</span>
+								</div>
+							</div>
+							<div class="detail-row">
+								<div class="detail-cell">
+									<span class="cell-label">数据来源依据</span>
+									<span class="cell-value">{{ formData.dataSource }}</span>
+								</div>
+								<div class="detail-cell">
+									<span class="cell-label">需求信息项</span>
+									<span class="cell-value">{{ formData.demandInfo }}</span>
+								</div>
+							</div>
 						</div>
 					</div>
-					<div class="detail-row">
-						<div class="detail-cell">
-							<span class="cell-label">需求联系人</span>
-							<span class="cell-value">{{ formData.contactPerson }}</span>
-						</div>
-						<div class="detail-cell">
-							<span class="cell-label">需求联系人电话</span>
-							<span class="cell-value">{{ formData.contactPhone }}</span>
-						</div>
-					</div>
-					<div class="detail-row">
-						<div class="detail-cell">
-							<span class="cell-label">需求邮箱</span>
-							<span class="cell-value">{{ formData.contactEmail }}</span>
-						</div>
-						<div class="detail-cell">
-							<span class="cell-label">更新周期</span>
-							<span class="cell-value">{{ formData.updateCycle }}</span>
-						</div>
-					</div>
-					<div class="detail-row">
-						<div class="detail-cell">
-							<span class="cell-label">申请依据</span>
-							<span class="cell-value">{{ formData.applyBasis }}</span>
-						</div>
-						<div class="detail-cell">
-							<span class="cell-label">共享类型</span>
-							<span class="cell-value">{{ getDictLabel(formData.shareType, dictObj.sharedType) }}</span>
-						</div>
-					</div>
-					<div class="detail-row">
-						<div class="detail-cell">
-							<span class="cell-label">应用场景类型</span>
-							<span class="cell-value">{{ getDictLabel(formData.applicationScene, dictObj.appSceneType) }}</span>
-						</div>
-						<div class="detail-cell">
-							<span class="cell-label">责任部门</span>
-							<span class="cell-value">{{ formData.responsibleDeptName }}</span>
-						</div>
-					</div>
-					<div class="detail-row">
-						<div class="detail-cell">
-							<span class="cell-label">数据来源依据</span>
-							<span class="cell-value">{{ formData.dataSource }}</span>
-						</div>
-						<div class="detail-cell">
-							<span class="cell-label">需求信息项</span>
-							<span class="cell-value">{{ formData.demandInfo }}</span>
+				</div>
+				<div>
+					<div class="label">数据上传</div>
+					<div class="upload-container">
+						<el-upload
+							ref="uploadRef"
+							:auto-upload="false"
+							:limit="1"
+							:on-change="handleFileChange"
+							:on-remove="handleFileRemove"
+							:before-upload="beforeFileUpload"
+							:file-list="fileList"
+							accept=".zip,.rar,.7z,.tar,.gz"
+							class="upload-demo"
+						>
+							<template #trigger>
+								<el-button type="primary">选择文件</el-button>
+							</template>
+							<template #tip>
+								<div class="el-upload__tip">请上传压缩文件 (.zip/.rar/.7z/.tar/.gz)</div>
+							</template>
+						</el-upload>
+						<el-button type="success" :disabled="!selectedFile" @click="handleUpload" style="margin-top: 10px">
+							上传文件
+						</el-button>
+
+						<!-- 已上传文件列表 -->
+						<div v-if="uploadedFiles.length > 0" class="uploaded-files">
+							<h4>已上传文件:</h4>
+							<div v-for="(file, index) in uploadedFiles" :key="index" class="file-item">
+								<span>{{ file.originalName }}</span>
+								<el-button type="text" @click="viewFile(file)" style="margin-left: 10px">查看</el-button>
+								<el-button type="text" @click="downloadFile(file)" style="margin-left: 5px">下载</el-button>
+							</div>
 						</div>
 					</div>
 				</div>
 			</div>
 		</div>
-			<div>
-				<div class="label">数据上传</div>
-				<div class="upload-container">
-				   <el-upload
-					ref="uploadRef"
-					:auto-upload="false"
-					:limit="1"
-					:on-change="handleFileChange"
-					:on-remove="handleFileRemove"
-					:before-upload="beforeFileUpload"
-					:file-list="fileList"
-					accept=".zip,.rar,.7z,.tar,.gz"
-					class="upload-demo"
-				  >
-					<template #trigger>
-					  <el-button type="primary">选择文件</el-button>
-					</template>
-					<template #tip>
-					  <div class="el-upload__tip">
-						请上传压缩文件 (.zip/.rar/.7z/.tar/.gz)
-					  </div>
-					</template>
-				  </el-upload>
-				  <el-button 
-					type="success" 
-					:disabled="!selectedFile" 
-					@click="handleUpload"
-					style="margin-top: 10px;"
-				  >
-					上传文件
-				  </el-button>
-				  
-				  <!-- 已上传文件列表 -->
-				  <div v-if="uploadedFiles.length > 0" class="uploaded-files">
-					<h4>已上传文件:</h4>
-					<div v-for="(file, index) in uploadedFiles" :key="index" class="file-item">
-					  <span>{{ file.originalName }}</span>
-					  <el-button type="text" @click="viewFile(file)" style="margin-left: 10px;">查看</el-button>
-					  <el-button type="text" @click="downloadFile(file)" style="margin-left: 5px;">下载</el-button>
-					</div>
-				  </div>
-				</div>
-			</div>
-
-		</div>
-
-	</div>
 		<template #footer>
-			<el-button
-				class="save-btn"
-				color="#4C34FF"
-				
-				
-				@click="rejectTheApplication"
-			>
-				拒绝申请
-			</el-button>
-			<el-button color="#F2F3F5"  @click="approvedByTheReview">审核通过</el-button>
-
+			<el-button class="save-btn" color="#4C34FF" @click="rejectTheApplication">拒绝申请</el-button>
+			<el-button color="#F2F3F5" @click="approvedByTheReview">审核通过</el-button>
 		</template>
 	</el-dialog>
+
+	<!-- 拒绝申请弹框 -->
+	<reasonForRejectionDialog
+		v-if="rejectionDialogVisible"
+		v-model="rejectionDialogVisible"
+		@confirm="handleRejectionConfirm"
+	/>
 </template>
 
 <script setup>
-import { ref, inject } from 'vue'
 import { getDictLabel } from '@ztzf/utils'
-import { gdSupplyDemandDetailApi, putFileAttachApi,gdSupplyDemandAuditPassApi,gdSupplyDemandAuditRejectApi } from '@/views/orderView/orderDataManage/supplyAdd/supplyAddApi'
-import { ElMessage, ElMessageBox } from 'element-plus'
-
+import {
+	gdSupplyDemandDetailApi,
+	putFileAttachApi,
+	gdSupplyDemandAuditPassApi,
+	gdSupplyDemandAuditRejectApi,
+	gdSupplyDemandAuditListApi
+} from '@/views/orderView/orderDataManage/supplyAdd/supplyAddApi'
+import { ElMessage } from 'element-plus'
+import reasonForRejectionDialog from './reasonForRejectionDialog.vue'
+const emit = defineEmits(['success'])
 const dictObj = inject('dictObj')
 const deptTree = inject('deptTree')
-
+const demandId = ref('')
 const visible = defineModel() // 弹框显隐
 const formData = ref({}) // 表单数据
 const uploadRef = ref() // 上传组件引用
@@ -167,131 +157,132 @@
 const uploadedFiles = ref([]) // 已上传文件列表
 const uploadLoading = ref(false) // 上传加载状态
 const responseData = ref([])
+// 拒绝申请弹框控制
+const rejectionDialogVisible = ref(false) // 拒绝申请弹框显隐
 // 步骤条数据
 const steps = ref([
-	{ title: '需求申请', person: '张三', time: '2025-03-31 12:23:30' },
-	{ title: '审核通过', person: '', time: '' },
+	{ title: '需求申请', person: '', time: '' },
+	{ title: '审核通过', person: '', time: '' }
 ])
 // 当前激活步骤
-const activeStep = ref(0) 
+const activeStep = ref(0)
 
 // 文件选择变化
 const handleFileChange = (file, fileList) => {
-  if (fileList.length > 0) {
-    selectedFile.value = file.raw
-  } else {
-    selectedFile.value = null
-  }
+	if (fileList.length > 0) {
+		selectedFile.value = file.raw
+	} else {
+		selectedFile.value = null
+	}
 }
 
 // 文件移除
 const handleFileRemove = () => {
-  selectedFile.value = null
+	selectedFile.value = null
 }
 
 // 上传前验证
-const beforeFileUpload = (file) => {
-  const allowedExtensions = ['.zip', '.rar', '.7z', '.tar', '.gz']
-  const fileExtension = '.' + file.name.split('.').pop().toLowerCase()
-  
-  if (!allowedExtensions.includes(fileExtension)) {
-    ElMessage.error('只能上传压缩文件格式:.zip/.rar/.7z/.tar/.gz')
-    return false
-  }
-  
-  // 文件大小限制,这里限制为100MB
-  const maxSize = 100 * 1024 * 1024 // 100MB
-  if (file.size > maxSize) {
-    ElMessage.error('文件大小不能超过100MB')
-    return false
-  }
-  
-  return true
+const beforeFileUpload = file => {
+	const allowedExtensions = ['.zip', '.rar', '.7z', '.tar', '.gz']
+	const fileExtension = '.' + file.name.split('.').pop().toLowerCase()
+
+	if (!allowedExtensions.includes(fileExtension)) {
+		ElMessage.error('只能上传压缩文件格式:.zip/.rar/.7z/.tar/.gz')
+		return false
+	}
+
+	// 文件大小限制,这里限制为100MB
+	const maxSize = 100 * 1024 * 1024 // 100MB
+	if (file.size > maxSize) {
+		ElMessage.error('文件大小不能超过100MB')
+		return false
+	}
+
+	return true
 }
 
 // 处理文件上传
 const handleUpload = async () => {
-  if (!selectedFile.value) {
-    ElMessage.warning('请先选择文件')
-    return
-  }
+	if (!selectedFile.value) {
+		ElMessage.warning('请先选择文件')
+		return
+	}
 
-  // 再次验证文件类型
-  if (!beforeFileUpload(selectedFile.value)) {
-    return
-  }
+	// 再次验证文件类型
+	if (!beforeFileUpload(selectedFile.value)) {
+		return
+	}
 
-  try {
-    uploadLoading.value = true
-    
-    // 创建FormData对象
-    const formData = new FormData()
-    formData.append('file', selectedFile.value)
-    
-    // 调用上传接口
-    const response = await putFileAttachApi(formData)
-    
-    if (response.data && response.data.success) {
-      const fileData = response.data.data
-      console.log('成功数据',fileData);
-	  responseData.value = fileData
-      // 添加到已上传文件列表
-      uploadedFiles.value.push({
-        name: fileData.name,
-        originalName: fileData.originalName,
-        link: fileData.link,
-        attachId: fileData.attachId
-      })
-      
-      ElMessage.success('文件上传成功!')
-      
-      // 清空上传列表
-      uploadRef.value.clearFiles()
-      selectedFile.value = null
-      
-      // 这里可以将附件ID保存到表单数据中,供后续提交使用
-      // formData.value.attachmentId = fileData.attachId
-      
-    } else {
-      ElMessage.error(response.data?.msg || '文件上传失败')
-    }
-  } catch (error) {
-    console.error('文件上传失败:', error)
-    ElMessage.error('文件上传失败,请重试')
-  } finally {
-    uploadLoading.value = false
-  }
+	try {
+		uploadLoading.value = true
+
+		// 创建FormData对象
+		const formData = new FormData()
+		formData.append('file', selectedFile.value)
+
+		// 调用上传接口
+		const response = await putFileAttachApi(formData)
+
+		if (response.data && response.data.success) {
+			const fileData = response.data.data
+			console.log('成功数据', fileData)
+			responseData.value = fileData
+			// 添加到已上传文件列表
+			uploadedFiles.value.push({
+				name: fileData.name,
+				originalName: fileData.originalName,
+				link: fileData.link,
+				attachId: fileData.attachId,
+			})
+
+			ElMessage.success('文件上传成功!')
+
+			// 清空上传列表
+			uploadRef.value.clearFiles()
+			selectedFile.value = null
+
+			// 这里可以将附件ID保存到表单数据中,供后续提交使用
+			// formData.value.attachmentId = fileData.attachId
+		} else {
+			ElMessage.error(response.data?.msg || '文件上传失败')
+		}
+	} catch (error) {
+		console.error('文件上传失败:', error)
+		ElMessage.error('文件上传失败,请重试')
+	} finally {
+		uploadLoading.value = false
+	}
 }
 
 // 查看文件
-const viewFile = (file) => {
-  if (file.link) {
-    window.open(file.link, '_blank')
-  } else {
-    ElMessage.warning('文件链接无效')
-  }
+const viewFile = file => {
+	if (file.link) {
+		window.open(file.link, '_blank')
+	} else {
+		ElMessage.warning('文件链接无效')
+	}
 }
 
 // 下载文件
-const downloadFile = (file) => {
-  if (file.link) {
-    // 创建一个隐藏的a标签来触发下载
-    const a = document.createElement('a')
-    a.href = file.link
-    a.download = file.originalName || file.name
-    document.body.appendChild(a)
-    a.click()
-    document.body.removeChild(a)
-  } else {
-    ElMessage.warning('文件链接无效')
-  }
+const downloadFile = file => {
+	if (file.link) {
+		// 创建一个隐藏的a标签来触发下载
+		const a = document.createElement('a')
+		a.href = file.link
+		a.download = file.originalName || file.name
+		document.body.appendChild(a)
+		a.click()
+		document.body.removeChild(a)
+	} else {
+		ElMessage.warning('文件链接无效')
+	}
 }
 
 // 根据部门ID获取部门名称
 function getDeptNameById(deptId, deptList) {
 	// 处理类型转换,确保比较的是相同类型
 	const targetId = String(deptId)
-	
+
 	// 递归遍历部门树
 	function findDept(deptList) {
 		for (const dept of deptList) {
@@ -305,11 +296,11 @@
 		}
 		return ''
 	}
-	
+
 	if (!targetId || !Array.isArray(deptList) || deptList.length === 0) {
 		return ''
 	}
-	
+
 	return findDept(deptList)
 }
 
@@ -317,8 +308,8 @@
 async function open({ row }) {
 	if (row?.id) {
 		await loadDetail(row.id)
-		// 可以在这里加载已上传的文件列表
-		// loadUploadedFiles(row.id)
+		demandId.value = row.id
+		console.log('row.id', demandId.value)
 	}
 	visible.value = true
 }
@@ -332,36 +323,132 @@
 		data.responsibleDeptName = getDeptNameById(data.responsibleDeptId, deptTree.value)
 	}
 	formData.value = data
+	
+	// 加载审核记录
+	await loadAuditRecords(id)
 }
 
-// 如果需要加载已上传的文件列表
-const loadUploadedFiles = async (id) => {
-  try {
-    // 这里根据实际情况调用接口获取已上传的文件列表
-    // const response = await getFileListApi({ id })
-    // if (response.data?.success) {
-    //   uploadedFiles.value = response.data.data || []
-    // }
-  } catch (error) {
-    console.error('加载已上传文件失败:', error)
-  }
+// 加载审核记录
+async function loadAuditRecords(demandId) {
+	try {
+		const res = await gdSupplyDemandAuditListApi({ demandId })
+		const auditRecords = res?.data?.data ?? []
+		
+		// 处理审核记录为步骤格式
+		processAuditRecords(auditRecords)
+	} catch (error) {
+		console.error('加载审核记录失败:', error)
+		ElMessage.error('加载审核记录失败,请重试')
+		// 保持默认步骤,不做清空
+		activeStep.value = 0
+	}
 }
+
+// 处理审核记录为步骤格式
+function processAuditRecords(records) {
+	// 重置为默认步骤结构
+	steps.value = [
+		{ title: '需求申请', person: '', time: '' },
+		{ title: '审核通过', person: '', time: '' }
+	]
+	
+	if (!records || records.length === 0) {
+		// 没有审核记录,保持默认步骤
+		activeStep.value = 0
+		return
+	}
+	
+	// 按创建时间排序(最新的在最后)
+	const sortedRecords = [...records].sort((a, b) => new Date(a.createTime) - new Date(b.createTime))
+	
+	// 处理需求申请步骤(第一个步骤)
+	const demandRecord = sortedRecords.find(record => record.auditStatus === '0') || sortedRecords[0]
+	if (demandRecord) {
+		steps.value[0] = {
+			title: '需求申请',
+			person: demandRecord.createUser ? `${demandRecord.createUser}` : '',
+			time: demandRecord.createTime ? demandRecord.createTime : ''
+		}
+	}
+	
+	// 处理审核步骤(第二个步骤)
+	const latestRecord = sortedRecords[sortedRecords.length - 1]
+	if (latestRecord) {
+		// 根据最新审核结果设置标题
+		let auditTitle = '审核通过'
+		if (latestRecord.auditStatus === '2') {
+			auditTitle = '审核驳回'
+			// 更新第二个步骤的标题为审核驳回
+			steps.value[1].title = auditTitle
+		}
+		
+		// 添加审核意见(如果有)
+		if (latestRecord.auditOpinion) {
+			steps.value[1].title += ` - ${latestRecord.auditOpinion}`
+		}
+		
+		// 更新审核步骤的信息
+		steps.value[1].person = latestRecord.createUser ? `${latestRecord.createUser}` : ''
+		steps.value[1].time = latestRecord.createTime ? latestRecord.createTime : ''
+		
+		// 根据最新审核结果设置activeStep
+		switch (latestRecord.auditStatus) {
+			case '0':
+				// 审核中,高亮第一个步骤
+				activeStep.value = 0
+				break
+			case '1':
+				// 审核通过,高亮第二个步骤
+				activeStep.value = 1
+				break
+			case '2':
+				// 审核驳回,高亮第二个步骤
+				activeStep.value = 1
+				break
+			default:
+				// 默认高亮第一个步骤
+				activeStep.value = 0
+		}
+	}
+}
+
+
 // 拒绝申请
 const rejectTheApplication = () => {
-	// const id = ['2013182736046530562']
+	if (responseData.value.length === 0) {
+		return ElMessage.warning('请上传数据')
+	}
+	// 打开拒绝申请弹框
+	rejectionDialogVisible.value = true
+}
+
+// 处理拒绝申请确认
+const handleRejectionConfirm = reason => {
 	const id = [responseData.value.attachId]
-	console.log('responseData.value',responseData.value)
-	gdSupplyDemandAuditRejectApi({ attachIds:id }).then(() => {
-		ElMessage.success('拒绝申请成功')
-		visible.value = false
-	})
+	console.log('demandId.value', demandId.value)
+
+	gdSupplyDemandAuditRejectApi({ attachIds: id, auditOpinion: reason, demandId: demandId.value })
+		.then(() => {
+			ElMessage.success('拒绝申请成功')
+			visible.value = false
+			emit('success')
+		})
+		.catch(error => {
+			console.error('拒绝申请失败:', error)
+			ElMessage.error('拒绝申请失败,请重试')
+			emit('success')
+		})
 }
 // 审核通过
 const approvedByTheReview = () => {
+	if (responseData.value.length === 0) {
+		return ElMessage.warning('请上传数据')
+	}
 	const id = [responseData.value.attachId]
-	gdSupplyDemandAuditPassApi({ id }).then(() => {
+	gdSupplyDemandAuditPassApi({ attachIds: id, demandId: demandId.value }).then(() => {
 		ElMessage.success('审核通过成功')
 		visible.value = false
+		emit('success')
 	})
 }
 
@@ -436,7 +523,7 @@
 }
 
 :deep(.el-step) {
-	margin-bottom: 20px;
+	margin-bottom: 90px;
 }
 
 :deep(.el-step__title) {
diff --git a/applications/task-work-order/src/views/orderView/orderDataManage/supplyAdd/FormDiaLog.vue b/applications/task-work-order/src/views/orderView/orderDataManage/supplyAdd/FormDiaLog.vue
index 1086a59..53a659f 100644
--- a/applications/task-work-order/src/views/orderView/orderDataManage/supplyAdd/FormDiaLog.vue
+++ b/applications/task-work-order/src/views/orderView/orderDataManage/supplyAdd/FormDiaLog.vue
@@ -66,7 +66,7 @@
 			:model="formData"
 			:rules="rules"
 			:disabled="dialogReadonly"
-			label-width="120px"
+			label-width="130px"
 		>
 			<el-row>
 				<el-col :span="12">
@@ -172,13 +172,11 @@
 						<el-input class="gd-input" v-model="formData.dataSource" placeholder="请输入" clearable />
 					</el-form-item>
 				</el-col>
-				<el-col :span="24">
+				<el-col :span="12">
 					<el-form-item label="需求信息项" prop="demandInfo">
 						<el-input
 							class="gd-input"
 							v-model="formData.demandInfo"
-							type="textarea"
-							:rows="4"
 							placeholder="请输入"
 							clearable
 						/>
diff --git a/applications/task-work-order/src/views/orderView/orderDataManage/supplyAdd/index.vue b/applications/task-work-order/src/views/orderView/orderDataManage/supplyAdd/index.vue
index 43e7c61..fc5a434 100644
--- a/applications/task-work-order/src/views/orderView/orderDataManage/supplyAdd/index.vue
+++ b/applications/task-work-order/src/views/orderView/orderDataManage/supplyAdd/index.vue
@@ -75,10 +75,11 @@
 					<el-table-column prop="demandInfo" show-overflow-tooltip label="需求信息项" />
 					<el-table-column label="操作" class-name="operation-btns">
 						<template v-slot="{ row }">
-							<el-link @click="openForm('view', row)">查看</el-link>
-							<el-link @click="openForm('edit', row)" v-if="row.demandStatus !== '1'">编辑</el-link>
-							<el-link @click="handleDelete(row)" v-if="row.demandStatus !== '1'">删除</el-link>
-						</template>
+					<el-link @click="openForm('view', row)">查看</el-link>
+					<!-- 只对非审批状态显示编辑和删除按钮 -->
+					<el-link @click="openForm('edit', row)" v-if="!['1', '2', '3'].includes(row.demandStatus)">编辑</el-link>
+					<el-link @click="handleDelete(row)" v-if="!['1', '2', '3'].includes(row.demandStatus)">删除</el-link>
+				</template>
 					</el-table-column>
 				</el-table>
 			</div>
@@ -96,7 +97,7 @@
 		</div>
 
 		<FormDiaLog ref="dialogRef" @success="getList" v-if="dialogVisible" v-model="dialogVisible" />
-		<ApplyViewDialog ref="applyDialogRef" v-if="applyDialogVisible" v-model="applyDialogVisible" />
+		<ApplyViewDialog ref="applyDialogRef" @success="getList" v-if="applyDialogVisible" v-model="applyDialogVisible" />
 	</basic-container>
 </template>
 <script setup>
@@ -192,8 +193,9 @@
 
 // 新增/编辑/查看 弹框
 function openForm(mode, row) {
-	if (mode === 'view' && row?.demandStatus === '1') {
-		// 如果是查看申请中的记录,使用申请详情弹框
+	// 对于所有审批相关状态(申请中、审核通过、审核拒绝)都使用申请详情弹框
+	if (mode === 'view' && ['1', '2', '3'].includes(row?.demandStatus)) {
+		// 使用申请详情弹框
 		openApplyViewDialog(row)
 	} else {
 		// 其他情况使用原有弹框
diff --git a/applications/task-work-order/src/views/orderView/orderDataManage/supplyAdd/reasonForRejectionDialog.vue b/applications/task-work-order/src/views/orderView/orderDataManage/supplyAdd/reasonForRejectionDialog.vue
new file mode 100644
index 0000000..40f5eed
--- /dev/null
+++ b/applications/task-work-order/src/views/orderView/orderDataManage/supplyAdd/reasonForRejectionDialog.vue
@@ -0,0 +1,91 @@
+<template>
+	<el-dialog
+		class="gd-dialog"
+		v-model="visible"
+		:title="'拒绝申请'"
+		@closed="visible = false"
+		destroy-on-close
+		width="550px"
+		align-center
+	>
+		<div class="detail-container">
+			<div class="detail-cell">
+				<span class="cell-label">拒绝原因:</span>
+				<el-input v-model="reasonForRejection" style="width: 380px" type="textarea" placeholder="请输入" />
+			</div>
+		</div>
+		<template #footer>
+			<!-- <el-button @click="handleCancel">取消</el-button> -->
+			<el-button class="save-btn" color="#4C34FF" @click="handleConfirm">确认</el-button>
+		</template>
+	</el-dialog>
+</template>
+
+<script setup>
+import { ref, watch } from 'vue'
+import { ElMessage } from 'element-plus'
+
+const props = defineProps({
+	modelValue: {
+		type: Boolean,
+		default: false,
+	},
+})
+
+const emit = defineEmits(['update:modelValue', 'confirm'])
+
+const visible = ref(props.modelValue)
+const reasonForRejection = ref('')
+
+// 监听visible变化,同步到父组件
+watch(
+	() => visible.value,
+	newVal => {
+		emit('update:modelValue', newVal)
+	}
+)
+
+// 监听父组件modelValue变化
+watch(
+	() => props.modelValue,
+	newVal => {
+		visible.value = newVal
+	}
+)
+
+// 取消按钮点击事件
+const handleCancel = () => {
+	visible.value = false
+	reasonForRejection.value = ''
+}
+
+// 确认按钮点击事件
+const handleConfirm = () => {
+	if (!reasonForRejection.value.trim()) {
+		return ElMessage.warning('请输入拒绝原因')
+	}
+	emit('confirm', reasonForRejection.value)
+	visible.value = false
+	reasonForRejection.value = ''
+}
+</script>
+
+<style scoped lang="scss">
+.detail-container {
+	padding: 20px;
+	display: flex;
+	align-items: flex-start;
+	gap: 30px;
+	.detail-cell {
+		display: flex;
+		justify-content: center;
+		.cell-label {
+			min-width: 80px;
+			flex-shrink: 0;
+		}
+        :deep(.el-textarea__inner) {
+            height: 100px !important;
+        }
+	}
+}
+</style>
diff --git a/applications/task-work-order/src/views/orderView/orderDataManage/supplyAdd/supplyAddApi.js b/applications/task-work-order/src/views/orderView/orderDataManage/supplyAdd/supplyAddApi.js
index 6085530..27d7e58 100644
--- a/applications/task-work-order/src/views/orderView/orderDataManage/supplyAdd/supplyAddApi.js
+++ b/applications/task-work-order/src/views/orderView/orderDataManage/supplyAdd/supplyAddApi.js
@@ -63,3 +63,12 @@
 	
 	})
 }
+
+// 获取供需需求审核记录
+export const gdSupplyDemandAuditListApi = params => {
+	return request({
+		url: `/drone-gd/orderdata/gdSupplyDemandAudit/list`,
+		method: 'get',
+		params,
+	})
+}

--
Gitblit v1.9.3