From cabb1279e9370edfebdef62f6eba272eeae8fe67 Mon Sep 17 00:00:00 2001
From: 张含笑 <zhx18749296735@163.com>
Date: Fri, 23 Jan 2026 18:10:36 +0800
Subject: [PATCH] Merge remote-tracking branch 'origin/master'

---
 applications/drone-command/src/views/basicManage/maintainRecord/MaintenanceDiaLog.vue                |    2 
 applications/task-work-order/src/views/orderView/orderDataManage/supplyAdd/index.vue                 |   26 
 applications/task-work-order/src/views/orderView/orderManage/inspectionReport/index.vue              |  253 +++---
 applications/drone-command/src/views/areaManage/areaStatistics/FormDiaLog.vue                        |    2 
 applications/task-work-order/src/views/orderView/orderDataManage/appInnovation/index.vue             |   20 
 applications/drone-command/src/views/detectionCountermeasure/countermeasureEvaluation/FormDiaLog.vue |    2 
 applications/drone-command/src/views/areaManage/defenseZone/FormDiaLog.vue                           |    2 
 applications/drone-command/src/assets/images/dataCockpit/favorite-y.png                              |    0 
 applications/drone-command/src/views/detectionCountermeasure/taskSchedule/FormDiaLog.vue             |    2 
 applications/drone-command/src/views/areaManage/partition/FormDiaLog.vue                             |    2 
 applications/task-work-order/src/views/orderView/orderManage/clueEvents/index.vue                    |    6 
 applications/drone-command/src/views/basicManage/maintainRecord/FormDiaLog.vue                       |    2 
 applications/drone-command/src/components/map-container/device-map-container.vue                     |  565 +++-----------
 applications/drone-command/src/views/detectionCountermeasure/deviceAppConfig/FormDiaLog.vue          |    2 
 applications/drone-command/src/views/permissionManage/permissionDept/FormDiaLog.vue                  |    2 
 applications/task-work-order/src/views/orderView/orderManage/operatingIncome/index.vue               |   10 
 applications/drone-command/src/views/permissionManage/permissionRole/FormDiaLog.vue                  |    2 
 applications/drone-command/src/views/recordManage/historyTracks/TrajectoryDiaLog.vue                 |    2 
 applications/task-work-order/src/styles/common/cockpit.scss                                          |  352 ++++----
 applications/drone-command/src/views/dataCockpit/components/templateComponents/RealTemplate.vue      |   20 
 applications/task-work-order/src/views/orderView/orderManage/inspectionRequest/ViewDiaLog.vue        |   38 
 applications/drone-command/src/views/basicManage/deviceStock/DeviceTrackDiaLog.vue                   |    2 
 applications/drone-command/src/assets/images/dataCockpit/favorite-n.png                              |    0 
 applications/task-work-order/src/views/orderView/orderDataManage/evaluate/index.vue                  |   10 
 applications/task-work-order/src/views/orderView/orderDataManage/dataObjection/index.vue             |   24 
 applications/task-work-order/src/views/orderView/orderManage/orderManage/index.vue                   |    8 
 applications/drone-command/src/views/permissionManage/permissionUser/FormDiaLog.vue                  |    2 
 applications/drone-command/src/components/map-container/components/DronePopup.vue                    |  323 ++++++++
 applications/drone-command/src/views/basicManage/deviceStock/DeviceScrapDiaLog.vue                   |    2 
 applications/task-work-order/src/views/orderView/orderManage/orderManage/FormDiaLog.vue              |   22 
 applications/drone-command/src/views/basicManage/deviceStock/FormDiaLog.vue                          |    2 
 applications/task-work-order/src/views/orderView/orderManage/inspectionRequest/FormDiaLog.vue        |    2 
 applications/drone-command/src/components/map-container/components/DevicePopup.vue                   |  325 ++++++++
 applications/task-work-order/src/views/orderView/orderManage/inspectionRequest/index.vue             |   20 
 applications/drone-command/env/.env.development                                                      |    4 
 applications/drone-command/src/views/areaManage/precinctInfo/FormDiaLog.vue                          |    2 
 applications/drone-command/src/views/basicManage/deviceScrap/FormDiaLog.vue                          |    2 
 applications/drone-command/src/views/detectionCountermeasure/detectionRange/DetectionRangeDialog.vue |    2 
 applications/drone-command/src/components/map-container/device-map-materials.js                      |  188 ++++
 applications/drone-command/src/views/areaManage/sceneConfig/FormDiaLog.vue                           |    2 
 40 files changed, 1,414 insertions(+), 840 deletions(-)

diff --git a/applications/drone-command/env/.env.development b/applications/drone-command/env/.env.development
index 368f458..585cd95 100644
--- a/applications/drone-command/env/.env.development
+++ b/applications/drone-command/env/.env.development
@@ -2,7 +2,7 @@
  # @Author       : yuan
  # @Date         : 2026-01-07 14:58:30
  # @LastEditors  : yuan
- # @LastEditTime : 2026-01-22 15:51:00
+ # @LastEditTime : 2026-01-23 17:51:43
  # @FilePath     : \applications\drone-command\env\.env.development
  # @Description  : 
  # Copyright 2026 OBKoro1, All Rights Reserved. 
@@ -16,7 +16,7 @@
 
 #开发环境代理地址(推荐本地新建文件 .env.development.local 来进行覆盖)
 # VITE_APP_URL = https://wrj.shuixiongit.com/api
-VITE_APP_URL= http://192.168.1.204
+VITE_APP_URL= http://192.168.1.33
 
 #新大屏地址
 VITE_APP_DASHBOARD_URL = 'https://wrj.shuixiongit.com/command-center-dashboard/'
diff --git a/applications/drone-command/src/assets/images/dataCockpit/favorite-n.png b/applications/drone-command/src/assets/images/dataCockpit/favorite-n.png
new file mode 100644
index 0000000..c4b4cf3
--- /dev/null
+++ b/applications/drone-command/src/assets/images/dataCockpit/favorite-n.png
Binary files differ
diff --git a/applications/drone-command/src/assets/images/dataCockpit/favorite-y.png b/applications/drone-command/src/assets/images/dataCockpit/favorite-y.png
new file mode 100644
index 0000000..7815723
--- /dev/null
+++ b/applications/drone-command/src/assets/images/dataCockpit/favorite-y.png
Binary files differ
diff --git a/applications/drone-command/src/components/map-container/components/DevicePopup.vue b/applications/drone-command/src/components/map-container/components/DevicePopup.vue
new file mode 100644
index 0000000..e1f24f5
--- /dev/null
+++ b/applications/drone-command/src/components/map-container/components/DevicePopup.vue
@@ -0,0 +1,325 @@
+<template>
+	<div v-if="visible" class="device-popup" :style="popupStyle" @click.stop>
+		<div class="device-popup__header">
+			<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="emit('close')" />
+		</div>
+		<div class="device-popup__type">
+			<span class="value">{{ popupTypeText }}</span>
+		</div>
+
+		<div class="device-popup__subtitle">
+			<span class="device-popup__dot" :class="popupActionClass"></span>
+			<span class="device-popup__action">{{ popupActionText }}</span>
+		</div>
+
+		<div class="device-popup__rows">
+			<div class="device-popup__row">
+				<div class="device-popup__col">
+					<span class="label">状态</span>
+					<span class="value" :class="popupStatusClass">{{ popupStatusText }}</span>
+				</div>
+
+				<span class="divider">|</span>
+
+				<div class="device-popup__col">
+					<span class="label">电量</span>
+					<span class="value">{{ popupBatteryText }}</span>
+				</div>
+			</div>
+			<div class="device-popup__row">
+				<div class="device-popup__col">
+					<span class="label">方位角</span>
+					<span class="value">{{ popupAzimuthText }}</span>
+				</div>
+
+				<span class="divider">|</span>
+
+				<div class="device-popup__col">
+					<span class="label">俯仰角</span>
+					<span class="value">{{ popupElevationText }}</span>
+				</div>
+			</div>
+			<div class="device-popup__row">
+				<span class="label">侦测目标</span>
+				<span class="value">{{ popupDetectCountText }}</span>
+			</div>
+			<div class="device-popup__row">
+				<span class="label">有效范围</span>
+				<span class="value">{{ popupRangeText }}</span>
+			</div>
+		</div>
+	</div>
+</template>
+
+<script setup>
+import { computed } from 'vue'
+import popupClose from '@/assets/images/dataCockpit/map/popup-close.png'
+
+const props = defineProps({
+	visible: {
+		type: Boolean,
+		default: false,
+	},
+	position: {
+		type: Object,
+		default: () => ({ x: 0, y: 0 }),
+	},
+	device: {
+		type: Object,
+		default: () => ({}),
+	},
+	titleMax: {
+		type: Number,
+		default: 12,
+	},
+})
+
+const emit = defineEmits(['close'])
+
+const popupStyle = computed(() => ({
+	left: `${props.position?.x ?? 0}px`,
+	top: `${props.position?.y ?? 0}px`,
+}))
+
+const popupTitle = computed(() => props.device?.deviceName || props.device?.deviceModel || '-')
+const popupTitleOverflow = computed(() => popupTitle.value.length > props.titleMax)
+const popupTitleDisplay = computed(() => {
+	if (!popupTitleOverflow.value) return popupTitle.value
+	return `${popupTitle.value.slice(0, props.titleMax)}……`
+})
+
+const popupStatusText = computed(() => {
+	const status = props.device?.status
+	if (status === 0) return '在线'
+	if (status === 1) return '离线'
+	if (status === 2) return '故障'
+	if (status === 3) return '报废'
+	return '-'
+})
+const popupStatusClass = computed(() => (props.device?.status === 0 ? 'online' : ''))
+const popupActionText = computed(() => {
+	const workMode = props.device?.workMode
+	if (workMode === 1 || workMode === '1') return '侦测中'
+	if (workMode === 2 || workMode === '2') return '信号干扰中'
+	if (workMode === 3 || workMode === '3') return '诱导驱离中'
+	if (workMode === 4 || workMode === '4') return '待机'
+	return workMode || '-'
+})
+const popupActionClass = computed(() => {
+	const workMode = props.device?.workMode
+	if (workMode === 1 || workMode === '1') return 'is-detecting'
+	if (workMode === 2 || workMode === '2') return 'is-jamming'
+	if (workMode === 3 || workMode === '3') return 'is-driving'
+	if (workMode === 4 || workMode === '4') return 'is-standby'
+	return 'is-standby'
+})
+const popupTypeText = computed(() => {
+	const type = props.device?.deviceType
+	if (type === 1 || type === '1') return '便捷侦测箱'
+	if (type === 2 || type === '2') return '反制枪'
+	if (type === 3 || type === '3') return '察打一体'
+	return type || '-'
+})
+const popupBatteryText = computed(() => {
+	const val = props.device?.batteryPct
+	if (val == null) return '-'
+	return `${val}%`
+})
+const popupAzimuthText = computed(() => {
+	const val = props.device?.azimuth
+	if (val == null) return '-'
+	return `${val}°`
+})
+const popupElevationText = computed(() => {
+	const val = props.device?.elevation
+	if (val == null) return '-'
+	return `${val}°`
+})
+const popupDetectCountText = computed(() => {
+	const val = props.device?.detectTargetCnt
+	if (val == null) return '-'
+	return `${val}台`
+})
+const popupRangeText = computed(() => {
+	const val = props.device?.effectiveRangeKm
+	if (val == null) return '-'
+	return `${val}KM`
+})
+</script>
+
+<style lang="scss" scoped>
+.device-popup {
+	position: absolute;
+	transform: translate(-50%, calc(-100% - 72px));
+	width: 202px;
+	padding: 0 16px 20px;
+	border-radius: 16px;
+	background: rgba(5, 5, 15, 0.7);
+	backdrop-filter: blur(16px);
+	color: #C3C3DD;
+	font-family: Source Han Sans CN, Source Han Sans CN;
+	font-size: 12px;
+	pointer-events: auto;
+	z-index: 11;
+	box-sizing: border-box;
+
+	&::after {
+		content: "";
+		position: absolute;
+		left: 50%;
+		bottom: -8px;
+		transform: translateX(-50%);
+		width: 0;
+		height: 0;
+		border-left: 8px solid transparent;
+		border-right: 8px solid transparent;
+		border-top: 8px solid rgba(5, 5, 15, 0.7);
+	}
+
+	.device-popup__header {
+		height: 40px;
+		display: flex;
+		align-items: center;
+		justify-content: space-between;
+		position: relative;
+
+		font-weight: bold;
+		font-size: 14px;
+		color: #FFFFFF;
+
+		&::after {
+			content: "";
+			position: absolute;
+			left: 0;
+			bottom: 0;
+			width: 50px;
+			height: 2px;
+			background: #284FE3;
+			box-shadow: 0px 3px 2px 0px rgba(15, 89, 255, 0.1), 0px 7px 5px 0px rgba(15, 89, 255, 0.15), 0px 13px 10px 0px rgba(15, 89, 255, 0.18), 0px 22px 18px 0px rgba(15, 89, 255, 0.21), 0px 42px 33px 0px rgba(15, 89, 255, 0.26), 0px 100px 80px 0px rgba(15, 89, 255, 0.36);
+			border-radius: 5px 5px 0px 0px;
+		}
+
+		&::before {
+			content: "";
+			position: absolute;
+			left: 55px;
+			right: 0;
+			bottom: 0;
+			height: 2px;
+			background: #323245;
+			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;
+		}
+	}
+
+	.device-popup__type {
+		display: flex;
+		align-items: center;
+		gap: 6px;
+		font-size: 12px;
+		margin-top: 8px;
+		margin-bottom: 10px;
+		color: #d2d7df;
+
+		.label {
+			color: #9aa4b2;
+		}
+	}
+
+	.device-popup__subtitle {
+		display: inline-flex;
+		align-items: center;
+		gap: 6px;
+		padding: 2px 10px;
+		border-radius: 999px;
+		background: rgba(255, 255, 255, 0.06);
+		font-size: 12px;
+		margin-bottom: 10px;
+
+		.device-popup__dot {
+			width: 6px;
+			height: 6px;
+			border-radius: 50%;
+			background: #6b7685;
+
+			&.is-detecting {
+				background: #35f08c;
+				box-shadow: 0 0 6px rgba(53, 240, 140, 0.8);
+			}
+
+			&.is-jamming {
+				background: #ff4444;
+				box-shadow: 0 0 6px rgba(255, 68, 68, 0.7);
+			}
+
+			&.is-driving {
+				background: #ffb020;
+				box-shadow: 0 0 6px rgba(255, 176, 32, 0.7);
+			}
+
+			&.is-standby {
+				background: #9aa4b2;
+			}
+		}
+	}
+
+	.device-popup__rows {
+		display: flex;
+		flex-direction: column;
+		gap: 6px;
+		font-size: 12px;
+		color: #d2d7df;
+
+		.device-popup__row {
+			display: flex;
+			align-items: center;
+			margin-bottom: 10px;
+
+			.device-popup__col {
+				flex: 1;
+				display: flex;
+				align-items: center;
+
+				&:last-child {
+					justify-content: flex-end;
+				}
+			}
+		}
+
+		.value {
+			margin-left: 10px;
+		}
+
+		.value.online {
+			color: #35f08c;
+		}
+	}
+}
+</style>
diff --git a/applications/drone-command/src/components/map-container/components/DronePopup.vue b/applications/drone-command/src/components/map-container/components/DronePopup.vue
new file mode 100644
index 0000000..759e748
--- /dev/null
+++ b/applications/drone-command/src/components/map-container/components/DronePopup.vue
@@ -0,0 +1,323 @@
+<template>
+	<div v-if="visible" class="drone-popup" :style="popupStyle" @click.stop>
+		<div class="drone-popup__header">
+			<el-tooltip
+				class="drone-popup__title-tooltip"
+				:content="popupTitle"
+				placement="top"
+				effect="dark"
+				:show-after="200"
+			>
+				<span class="drone-popup__title">{{ titleDisplay }}</span>
+			</el-tooltip>
+
+			<div class="drone-popup__header-actions">
+				<img
+					class="drone-popup__favorite"
+					:src="favoriteIcon"
+					alt="收藏"
+					@click.stop="emit('toggle-favorite')"
+				/>
+				<img class="drone-popup__close" :src="popupClose" alt="" @click.stop="emit('close')" />
+			</div>
+		</div>
+
+		<div class="drone-popup__serial">{{ serial }}</div>
+
+		<div class="drone-popup__status">
+			<span class="drone-popup__status-dot" :class="statusClass"></span>
+			<span class="drone-popup__status-text">{{ statusText }}</span>
+		</div>
+
+		<div class="drone-popup__row">
+			<span class="label">数据源</span>
+			<span class="value">{{ dataSource }}</span>
+		</div>
+
+		<div class="drone-popup__row drone-popup__row-split">
+			<div class="drone-popup__col">
+				<span class="label">高度</span>
+				<span class="value">{{ height }}</span>
+			</div>
+			<span class="divider">|</span>
+			<div class="drone-popup__col">
+				<span class="label">速度</span>
+				<span class="value">{{ speed }}</span>
+			</div>
+		</div>
+
+		<div class="drone-popup__row drone-popup__row-coord">
+			<span class="label">经纬度</span>
+			<div class="drone-popup__coord">
+				<div>{{ longitude }}</div>
+				<div>{{ latitude }}</div>
+			</div>
+		</div>
+
+		<div class="drone-popup__footer">
+			<button class="drone-popup__btn ghost" @click.stop="emit('signal')">信号干扰</button>
+			<button class="drone-popup__btn primary" @click.stop="emit('counter')">诱导驱离</button>
+		</div>
+	</div>
+</template>
+
+<script setup>
+import { computed } from 'vue'
+import popupClose from '@/assets/images/dataCockpit/map/popup-close.png'
+import favoriteNo from '@/assets/images/dataCockpit/favorite-n.png'
+import favoriteYes from '@/assets/images/dataCockpit/favorite-y.png'
+
+const props = defineProps({
+	visible: {
+		type: Boolean,
+		default: false,
+	},
+	position: {
+		type: Object,
+		default: () => ({ x: 0, y: 0 }),
+	},
+	drone: {
+		type: Object,
+		default: () => ({}),
+	},
+	titleMax: {
+		type: Number,
+		default: 12,
+	},
+	favorite: {
+		type: Boolean,
+		default: false,
+	},
+})
+
+const emit = defineEmits(['close', 'toggle-favorite', 'signal', 'counter'])
+
+const popupStyle = computed(() => ({
+	left: `${props.position?.x ?? 0}px`,
+	top: `${props.position?.y ?? 0}px`,
+}))
+const favoriteIcon = computed(() => (props.favorite ? favoriteYes : favoriteNo))
+
+const title = computed(() => props.drone?.droneName || '无人机名称')
+const titleOverflow = computed(() => title.value.length > props.titleMax)
+const titleDisplay = computed(() => {
+	if (!titleOverflow.value) return title.value
+	return `${title.value.slice(0, props.titleMax)}……`
+})
+
+const serial = computed(() => props.drone?.droneSerialNo || '-')
+const statusText = computed(() => {
+	const status = props.drone?.flightStatus
+	if (status === 1 || status === '1') return '侦测中'
+	if (status === 2 || status === '2') return '反制中'
+	return status || '侦测中'
+})
+const statusClass = computed(() => (statusText.value.includes('反制') ? 'is-driving' : 'is-detecting'))
+
+const dataSource = computed(() => props.drone?.dataSource || props.drone?.deviceName || props.drone?.areaName || '-')
+const counterDevice = computed(() => props.drone?.counterDeviceName || props.drone?.deviceName || '-')
+
+const formatNumber = (value, unit = '', digits = 0) => {
+	if (value == null || value === '') return '-'
+	const num = Number(value)
+	if (!Number.isFinite(num)) return '-'
+	return `${num.toFixed(digits)}${unit}`
+}
+const formatCoord = (value, type) => {
+	const num = Number(value)
+	if (!Number.isFinite(num)) return '-'
+	const absVal = Math.abs(num).toFixed(6)
+	const dir = type === 'lng' ? (num >= 0 ? 'E' : 'W') : num >= 0 ? 'N' : 'S'
+	return `${absVal} ${dir}`
+}
+
+const height = computed(() => formatNumber(props.drone?.flightHeightM, 'm', 0))
+const speed = computed(() => formatNumber(props.drone?.flightSpeedMs, 'm/s', 1))
+const longitude = computed(() => formatCoord(props.drone?.longitude, 'lng'))
+const latitude = computed(() => formatCoord(props.drone?.latitude, 'lat'))
+</script>
+
+<style lang="scss" scoped>
+.drone-popup {
+	position: absolute;
+	transform: translate(-50%, calc(-100% - 42px));
+	width: 202px;
+	padding: 0 16px 20px;
+	border-radius: 16px;
+	background: rgba(5, 5, 15, 0.7);
+	backdrop-filter: blur(16px);
+	color: #C3C3DD;
+	font-family: Source Han Sans CN, Source Han Sans CN;
+	font-size: 12px;
+	pointer-events: auto;
+	z-index: 12;
+	box-sizing: border-box;
+
+	&::after {
+		content: "";
+		position: absolute;
+		left: 50%;
+		bottom: -8px;
+		transform: translateX(-50%);
+		width: 0;
+		height: 0;
+		border-left: 8px solid transparent;
+		border-right: 8px solid transparent;
+		border-top: 8px solid rgba(5, 5, 15, 0.7);
+	}
+
+	.drone-popup__header {
+		height: 40px;
+		display: flex;
+		align-items: center;
+		justify-content: space-between;
+		position: relative;
+
+		font-weight: bold;
+		font-size: 14px;
+		color: #FFFFFF;
+
+		&::after {
+			content: "";
+			position: absolute;
+			left: 0;
+			bottom: 0;
+			width: 50px;
+			height: 2px;
+			background: #284FE3;
+			box-shadow: 0px 3px 2px 0px rgba(15, 89, 255, 0.1), 0px 7px 5px 0px rgba(15, 89, 255, 0.15), 0px 13px 10px 0px rgba(15, 89, 255, 0.18), 0px 22px 18px 0px rgba(15, 89, 255, 0.21), 0px 42px 33px 0px rgba(15, 89, 255, 0.26), 0px 100px 80px 0px rgba(15, 89, 255, 0.36);
+			border-radius: 5px 5px 0px 0px;
+		}
+
+		&::before {
+			content: "";
+			position: absolute;
+			left: 55px;
+			right: 0;
+			bottom: 0;
+			height: 2px;
+			background: #323245;
+			border-radius: 0px 0px 5px 5px;
+		}
+
+		.drone-popup__title-tooltip {
+			flex: 1;
+			min-width: 0;
+			display: block;
+		}
+
+		.drone-popup__title {
+			display: inline-block;
+			max-width: 100%;
+			white-space: nowrap;
+			overflow: hidden;
+			text-overflow: ellipsis;
+		}
+
+		.drone-popup__header-actions {
+			display: inline-flex;
+			align-items: center;
+			gap: 6px;
+			color: #C9CBE6;
+			font-size: 11px;
+		}
+
+		.drone-popup__favorite,
+		.drone-popup__close {
+			width: 16px;
+			height: 16px;
+			display: inline-flex;
+			align-items: flex-start;
+			vertical-align: middle;
+			cursor: pointer;
+		}
+
+		.drone-popup__favorite {
+			width: 12px;
+			height: 12px;
+		}
+	}
+}
+
+.drone-popup__serial {
+	margin-top: 8px;
+	color: #B7BACF;
+	font-size: 12px;
+	letter-spacing: 0.3px;
+}
+
+.drone-popup__status {
+	margin-top: 10px;
+	display: inline-flex;
+	align-items: center;
+	gap: 6px;
+	padding: 3px 10px;
+	border-radius: 999px;
+	background: #303041;
+}
+
+.drone-popup__status-dot {
+	width: 4px;
+	height: 4px;
+	border-radius: 50%;
+	background: #4CC3FF;
+}
+
+.drone-popup__status-dot.is-driving {
+	background: #FF7A4A;
+}
+
+.drone-popup__row {
+	margin-top: 10px;
+	display: flex;
+	align-items: center;
+	gap: 10px;
+}
+
+.drone-popup__row-split {
+	justify-content: flex-start;
+	gap: 12px;
+}
+
+.drone-popup__col {
+	display: inline-flex;
+	align-items: center;
+	gap: 6px;
+}
+
+.drone-popup__row-coord {
+	align-items: flex-start;
+}
+
+.drone-popup__coord {
+	display: flex;
+	flex-direction: column;
+	gap: 4px;
+}
+
+.drone-popup__footer {
+	margin-top: 14px;
+	display: flex;
+	gap: 12px;
+}
+
+.drone-popup__btn {
+	flex: 1;
+	height: 34px;
+	border-radius: 8px;
+	border: none;
+	font-size: 13px;
+	cursor: pointer;
+	color: #FFFFFF;
+	background: #3B3E55;
+}
+
+.drone-popup__btn.primary {
+	background: #2F5BFF;
+}
+
+.drone-popup__btn.ghost {
+	background: rgba(59, 62, 85, 0.9);
+	border: 1px solid rgba(111, 118, 150, 0.6);
+}
+</style>
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 6e584a0..723c82f 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
@@ -20,66 +20,23 @@
 			</div>
 		</div>
 
-		<div v-if="popupVisible" class="device-popup" :style="popupStyle" @click.stop>
-			<div class="device-popup__header">
-				<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>
+		<DevicePopup
+			:visible="popupVisible && !isDronePopup"
+			:position="popupPosition"
+			:device="selectedDevice"
+			@close="closePopup"
+		/>
 
-				<img class="device-popup__close" :src="popupClose" alt="" @click.stop="closePopup">
-			</div>
-			<div class="device-popup__type">
-				<span class="value">{{ popupTypeText }}</span>
-			</div>
-
-			<div class="device-popup__subtitle">
-				<span class="device-popup__dot" :class="popupActionClass"></span>
-				<span class="device-popup__action">{{ popupActionText }}</span>
-			</div>
-
-			<div class="device-popup__rows">
-				<div class="device-popup__row">
-					<div class="device-popup__col">
-						<span class="label">状态</span>
-						<span class="value" :class="popupStatusClass">{{ popupStatusText }}</span>
-					</div>
-
-					<span class="divider">|</span>
-
-					<div class="device-popup__col">
-						<span class="label">电量</span>
-						<span class="value">{{ popupBatteryText }}</span>
-					</div>
-				</div>
-				<div class="device-popup__row">
-					<div class="device-popup__col">
-						<span class="label">方位角</span>
-						<span class="value">{{ popupAzimuthText }}</span>
-					</div>
-
-					<span class="divider">|</span>
-
-					<div class="device-popup__col">
-						<span class="label">俯仰角</span>
-						<span class="value">{{ popupElevationText }}</span>
-					</div>
-				</div>
-				<div class="device-popup__row">
-					<span class="label">侦测目标</span>
-					<span class="value">{{ popupDetectCountText }}</span>
-				</div>
-				<div class="device-popup__row">
-					<span class="label">有效范围</span>
-					<span class="value">{{ popupRangeText }}</span>
-				</div>
-			</div>
-		</div>
+		<DronePopup
+			:visible="popupVisible && isDronePopup"
+			:position="popupPosition"
+			:drone="selectedDevice"
+			:favorite="Boolean(selectedDevice?.isFavorite)"
+			@close="closePopup"
+			@toggle-favorite="toggleDroneFavorite"
+			@signal="handleDroneSignal"
+			@counter="handleDroneCounter"
+		/>
 	</div>
 </template>
 
@@ -96,8 +53,16 @@
 import droneIcon from '@/assets/images/dataCockpit/map/drone.png'
 import aggregationIcon from '@/assets/images/dataCockpit/map/aggregation.png'
 import commandPostIcon from '@/assets/images/dataCockpit/map/command-post.png'
-import popupClose from '@/assets/images/dataCockpit/map/popup-close.png'
 import jaGeojsonRaw from '@/assets/geojson/ja.geojson?raw'
+import DevicePopup from './components/DevicePopup.vue'
+import DronePopup from './components/DronePopup.vue'
+import {
+	RING_STYLES,
+	addDeviceRings,
+	createDroneTrackMaterial,
+	createRadialGradientMaterial,
+	getTexturedVertexFormat,
+} from './device-map-materials'
 
 const props = defineProps({
 	onlineDevices: {
@@ -117,6 +82,7 @@
 		default: true,
 	},
 })
+const emit = defineEmits(['droneSignal', 'droneCounter'])
 
 const DEFAULT_ZONE_PAGE_SIZE = 999
 
@@ -124,6 +90,7 @@
 let viewer = null
 let cockpitPrimitiveLayer = null
 const devicePickMap = new Map()
+const dronePickMap = new Map()
 let deviceBillboardCollection = null
 let deviceRingOutlinePrimitives = []
 let deviceRingFillPrimitives = []
@@ -144,6 +111,7 @@
 const showLayerPanel = ref(false)
 const layerWrapRef = ref(null)
 const selectedDevice = ref(null)
+const selectedTargetType = ref('device')
 let selectedDeviceBillboard = null
 let deviceClickHandler = null
 let popupRenderHandler = null
@@ -371,24 +339,36 @@
 
 const clearDroneTrackEntities = () => {
 	if (!viewer) return
+	stopDroneTrackAnimation()
 	if (droneTrackBillboardCollection) {
-		droneTrackBillboardCollection.removeAll()
-		removeCockpitPrimitive(droneTrackBillboardCollection)
+		if (!droneTrackBillboardCollection.isDestroyed?.()) {
+			removeCockpitPrimitive(droneTrackBillboardCollection)
+		}
 		droneTrackBillboardCollection = null
 	}
 	if (droneTrackPolylineCollection) {
-		droneTrackPolylineCollection.removeAll()
-		removeCockpitPrimitive(droneTrackPolylineCollection)
+		if (!droneTrackPolylineCollection.isDestroyed?.()) {
+			removeCockpitPrimitive(droneTrackPolylineCollection)
+		}
 		droneTrackPolylineCollection = null
 	}
 	droneTrackRuntime = []
-	stopDroneTrackAnimation()
+	dronePickMap.clear()
+	if (selectedTargetType.value === 'drone') {
+		closePopup()
+	}
 }
 
 
 const ensureDroneTrackCollections = () => {
 	if (!viewer) return
 	ensureCockpitPrimitiveLayer()
+	if (droneTrackBillboardCollection?.isDestroyed?.()) {
+		droneTrackBillboardCollection = null
+	}
+	if (droneTrackPolylineCollection?.isDestroyed?.()) {
+		droneTrackPolylineCollection = null
+	}
 	if (!droneTrackBillboardCollection) {
 		droneTrackBillboardCollection = new Cesium.BillboardCollection()
 		addCockpitPrimitive(droneTrackBillboardCollection)
@@ -404,10 +384,17 @@
 	stopDroneTrackAnimation()
 	droneTrackStartTime = Cesium.JulianDate.now()
 	droneTrackTickHandler = clock => {
+		if (!viewer || viewer.isDestroyed?.() || !viewer.scene) {
+			stopDroneTrackAnimation()
+			return
+		}
 		if (!droneTrackRuntime.length) return
 		const current = clock.currentTime
 		const elapsed = Cesium.JulianDate.secondsDifference(current, droneTrackStartTime)
 		droneTrackRuntime.forEach(track => {
+			if (!track?.billboard || track.billboard.isDestroyed?.()) return
+			if (!track.billboard._scene) return
+			if (!track.positions || track.positions.length < 2) return
 			const duration = track.duration
 			if (duration <= 0) return
 			const t = ((elapsed % duration) + duration) % duration
@@ -434,33 +421,62 @@
 
 const renderSimulatedDroneTrack = () => {
 	if (!viewer) return
+	clearDroneTrackEntities()
 	ensureCountyCenterMap()
 	ensureDroneTrackCollections()
-	droneTrackBillboardCollection.removeAll()
-	droneTrackPolylineCollection.removeAll()
 	droneTrackRuntime = []
-	const centers = Array.from(countyCenterMap.values())
-	const baseCenters = centers.length ? centers.slice(0, 4) : [{ longitude: 116.397, latitude: 39.908 }]
+	const centers = Array.from(countyCenterMap.entries())
+	const baseCenters = centers.length
+		? centers.slice(0, 4)
+		: [['默认区域', { longitude: 116.397, latitude: 39.908 }]]
 	const segmentDuration = 6
-	baseCenters.forEach((center, trackIndex) => {
+	const baseTrackColor = Cesium.Color.fromCssColorString('red')
+	baseCenters.forEach(([centerName, center], trackIndex) => {
 		const points = buildSimulatedTrackPoints(center)
 		if (points.length < 2) return
 		const positions = points.map(point =>
 			Cesium.Cartesian3.fromDegrees(point.longitude, point.latitude, point.height)
 		)
+		let trackMaterial = createDroneTrackMaterial({
+			color: baseTrackColor,
+			speed: 4.5,
+			headWidth: 0.2,
+			glowPower: 1.8,
+			backgroundAlpha: 0.34,
+		})
+		if (!trackMaterial) {
+			trackMaterial = Cesium.Material.fromType('Color', { color: baseTrackColor })
+		}
 		droneTrackPolylineCollection.add({
 			positions,
-			width: 2,
-			material: Cesium.Material.fromType('Color', {
-				color: Cesium.Color.fromCssColorString('#2AEDBF'),
-			}),
+			width: 3,
+			material: trackMaterial,
 		})
+		const droneId = `drone-track-${trackIndex}`
 		const billboard = droneTrackBillboardCollection.add({
 			position: positions[0],
 			image: droneIcon,
 			width: 36,
 			height: 36,
 			verticalOrigin: Cesium.VerticalOrigin.CENTER,
+			disableDepthTestDistance: Number.POSITIVE_INFINITY,
+		})
+		billboard.id = droneId
+		const speedMs = Math.round(Cesium.Cartesian3.distance(positions[0], positions[1]) / segmentDuration)
+		dronePickMap.set(droneId, {
+			data: {
+				droneName: `无人机-${trackIndex + 1}`,
+				droneSerialNo: `UAV-${trackIndex + 1}`,
+				flightHeightM: points[0].height,
+				flightSpeedMs: speedMs,
+				longitude: points[0].longitude,
+				latitude: points[0].latitude,
+				flightStatus: 1,
+				deviceName: centerName,
+				dataSource: centerName,
+				counterDeviceName: centerName,
+			},
+			billboard,
 		})
 		droneTrackRuntime.push({
 			positions,
@@ -472,128 +488,6 @@
 	viewer.clock.multiplier = 1
 	startDroneTrackAnimation()
 	reorderCockpitPrimitives()
-}
-
-const RING_STYLES = [
-	{ inner: 0, outer: 2000, gradient: ['#FF361C', '#360B00'] }
-]
-
-const MATERIAL_TYPE = 'RadialGradientMaterial'
-const TEXTURED_VERTEX_FORMAT =
-	Cesium.MaterialAppearance?.MaterialSupport?.TEXTURED?.vertexFormat || Cesium.VertexFormat.POSITION_AND_ST
-let materialRegistered = false
-
-const registerRadialGradientMaterial = () => {
-	if (materialRegistered || !Cesium?.Material) return
-	materialRegistered = true
-	Cesium.Material._materialCache.addMaterial(MATERIAL_TYPE, {
-		fabric: {
-			type: MATERIAL_TYPE,
-			uniforms: {
-				color1: new Cesium.Color(1.0, 1.0, 1.0, 1.0),
-				color2: new Cesium.Color(0.0, 0.0, 0.0, 1.0),
-			},
-			source: `
-				czm_material czm_getMaterial(czm_materialInput materialInput) {
-					czm_material material = czm_getDefaultMaterial(materialInput);
-					vec2 st = materialInput.st - vec2(0.5);
-					float t = clamp(length(st) * 2.0, 0.0, 1.0);
-					vec4 color = mix(color1, color2, t);
-					material.diffuse = color.rgb;
-					material.alpha = color.a;
-					return material;
-				}
-			`,
-		},
-		translucent: () => true,
-	})
-}
-
-const buildCirclePositions = (center, radiusMeters, steps = 64) => {
-	const positions = []
-	const latRad = Cesium.Math.toRadians(center.latitude)
-	const metersToLat = 1 / 111320
-	const metersToLon = 1 / (111320 * Math.cos(latRad))
-	for (let i = 0; i <= steps; i += 1) {
-		const angle = Cesium.Math.toRadians((i / steps) * 360)
-		const dx = radiusMeters * Math.cos(angle)
-		const dy = radiusMeters * Math.sin(angle)
-		const lon = center.longitude + dx * metersToLon
-		const lat = center.latitude + dy * metersToLat
-		positions.push(Cesium.Cartesian3.fromDegrees(lon, lat))
-	}
-	return positions
-}
-
-const addDeviceRings = (center, ringFillInstancesByStyle, ringOutlineInstancesByStyle) => {
-	if (!ringFillInstancesByStyle) return
-	const centerPosition = Cesium.Cartesian3.fromDegrees(center.longitude, center.latitude, 0)
-	RING_STYLES.forEach((ring, index) => {
-		if (!ringFillInstancesByStyle[index]) return
-		ringFillInstancesByStyle[index].push(
-			new Cesium.GeometryInstance({
-				geometry: new Cesium.EllipseGeometry({
-					center: centerPosition,
-					semiMajorAxis: ring.outer,
-					semiMinorAxis: ring.outer,
-					vertexFormat: TEXTURED_VERTEX_FORMAT,
-				}),
-			})
-		)
-	})
-	if (!ringOutlineInstancesByStyle) return
-	RING_STYLES.forEach((ring, index) => {
-		if (!ringOutlineInstancesByStyle[index]) return
-		const positions = buildCirclePositions(center, ring.outer)
-		ringOutlineInstancesByStyle[index].push(
-			new Cesium.GeometryInstance({
-				geometry: new Cesium.GroundPolylineGeometry({
-					positions,
-					width: 2,
-				}),
-				attributes: {
-					color: Cesium.ColorGeometryInstanceAttribute.fromColor(
-						Cesium.Color.fromCssColorString(ring.gradient[0]).withAlpha(0.8)
-					),
-				},
-			})
-		)
-	})
-}
-
-class RadialGradientMaterialProperty {
-	constructor(color1, color2) {
-		this._definitionChanged = new Cesium.Event()
-		this.color1 = color1
-		this.color2 = color2
-	}
-
-	get isConstant () {
-		return true
-	}
-
-	get definitionChanged () {
-		return this._definitionChanged
-	}
-
-	getType () {
-		return MATERIAL_TYPE
-	}
-
-	getValue (time, result) {
-		const target = result || {}
-		target.color1 = this.color1
-		target.color2 = this.color2
-		return target
-	}
-
-	equals (other) {
-		return (
-			other instanceof RadialGradientMaterialProperty &&
-			Cesium.Color.equals(this.color1, other.color1) &&
-			Cesium.Color.equals(this.color2, other.color2)
-		)
-	}
 }
 
 const renderDeviceEntities = devices => {
@@ -628,17 +522,16 @@
 		billboard.id = entityId
 		devicePickMap.set(entityId, { data: item, billboard })
 	})
-	if (selectedDeviceBillboard && !devicePickMap.has(selectedDeviceBillboard.id)) {
+	if (selectedTargetType.value === 'device' && selectedDeviceBillboard && !devicePickMap.has(selectedDeviceBillboard.id)) {
 		closePopup()
 	}
-	registerRadialGradientMaterial()
 	ringFillInstancesByStyle.forEach((instances, index) => {
 		if (!instances.length) return
 		const ring = RING_STYLES[index]
-		const material = Cesium.Material.fromType(MATERIAL_TYPE, {
-			color1: Cesium.Color.fromCssColorString(ring.gradient[0]).withAlpha(0.64),
-			color2: Cesium.Color.fromCssColorString(ring.gradient[1]).withAlpha(0.64),
-		})
+		const material = createRadialGradientMaterial(
+			Cesium.Color.fromCssColorString(ring.gradient[0]).withAlpha(0.64),
+			Cesium.Color.fromCssColorString(ring.gradient[1]).withAlpha(0.64)
+		)
 		const primitive = new Cesium.GroundPrimitive({
 			geometryInstances: instances,
 			appearance: new Cesium.MaterialAppearance({
@@ -679,14 +572,14 @@
 	if (!viewer) return { primitive: null, outlinePrimitive: null }
 	const polygonInstances = []
 	const lineInstances = []
-	registerRadialGradientMaterial()
+	const texturedVertexFormat = getTexturedVertexFormat()
 	; (zones || []).forEach((zone, index) => {
 		if (!zone?.geom) return
 		const positions = getDefenseZonePositions(zone.geom)
 		if (!positions.length) return
 		const polygon = new Cesium.PolygonGeometry({
 			polygonHierarchy: new Cesium.PolygonHierarchy(positions),
-			vertexFormat: TEXTURED_VERTEX_FORMAT,
+			vertexFormat: texturedVertexFormat,
 		})
 		polygonInstances.push(
 			new Cesium.GeometryInstance({
@@ -712,10 +605,7 @@
 	if (polygonInstances.length) {
 		const baseColor1 = Cesium.Color.fromCssColorString(fillColor1)
 		const baseColor2 = Cesium.Color.fromCssColorString(fillColor2)
-		const material = Cesium.Material.fromType(MATERIAL_TYPE, {
-			color1: baseColor1.withAlpha(0.64),
-			color2: baseColor2.withAlpha(0.64),
-		})
+		const material = createRadialGradientMaterial(baseColor1.withAlpha(0.64), baseColor2.withAlpha(0.64))
 		primitive = new Cesium.GroundPrimitive({
 			geometryInstances: polygonInstances,
 			appearance: new Cesium.MaterialAppearance({
@@ -822,12 +712,15 @@
 	})
 }
 
-const getPickedDevice = picks => {
+const getPickedTarget = picks => {
 	for (const pick of picks) {
 		const pickId = pick?.id
 		const resolvedId = typeof pickId === 'string' ? pickId : pickId?.id
 		if (resolvedId && devicePickMap.has(resolvedId)) {
-			return devicePickMap.get(resolvedId)
+			return { type: 'device', ...devicePickMap.get(resolvedId) }
+		}
+		if (resolvedId && dronePickMap.has(resolvedId)) {
+			return { type: 'drone', ...dronePickMap.get(resolvedId) }
 		}
 	}
 	return null
@@ -858,13 +751,14 @@
 const handleDeviceClick = movement => {
 	if (!viewer) return
 	const picks = viewer.scene.drillPick(movement.position) || []
-	const pickedDevice = getPickedDevice(picks)
-	if (!pickedDevice) {
+	const pickedTarget = getPickedTarget(picks)
+	if (!pickedTarget) {
 		closePopup()
 		return
 	}
-	selectedDevice.value = pickedDevice.data
-	selectedDeviceBillboard = pickedDevice.billboard
+	selectedTargetType.value = pickedTarget.type
+	selectedDevice.value = pickedTarget.data
+	selectedDeviceBillboard = pickedTarget.billboard
 	startPopupRender()
 }
 
@@ -883,80 +777,19 @@
 function closePopup () {
 	selectedDevice.value = null
 	selectedDeviceBillboard = null
+	selectedTargetType.value = 'device'
 	stopPopupRender()
 }
 
 const popupPosition = ref({ x: 0, y: 0 })
 const popupVisible = computed(() => Boolean(selectedDevice.value))
-const popupStyle = computed(() => ({
-	left: `${popupPosition.value.x}px`,
-	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 '在线'
-	if (status === 1) return '离线'
-	if (status === 2) return '故障'
-	if (status === 3) return '报废'
-	return '-'
-})
-const popupStatusClass = computed(() => (selectedDevice.value?.status === 0 ? 'online' : ''))
-const popupActionText = computed(() => {
-	const workMode = selectedDevice.value?.workMode
-	if (workMode === 1 || workMode === '1') return '侦测中'
-	if (workMode === 2 || workMode === '2') return '信号干扰中'
-	if (workMode === 3 || workMode === '3') return '诱导驱离中'
-	if (workMode === 4 || workMode === '4') return '待机'
-	return workMode || '-'
-})
-const popupActionClass = computed(() => {
-	const workMode = selectedDevice.value?.workMode
-	if (workMode === 1 || workMode === '1') return 'is-detecting'
-	if (workMode === 2 || workMode === '2') return 'is-jamming'
-	if (workMode === 3 || workMode === '3') return 'is-driving'
-	if (workMode === 4 || workMode === '4') return 'is-standby'
-	return 'is-standby'
-})
-const popupTypeText = computed(() => {
-	const type = selectedDevice.value?.deviceType
-	if (type === 1 || type === '1') return '便捷侦测箱'
-	if (type === 2 || type === '2') return '反制枪'
-	if (type === 3 || type === '3') return '察打一体'
-	return type || '-'
-})
-const popupBatteryText = computed(() => {
-	const val = selectedDevice.value?.batteryPct
-	if (val == null) return '-'
-	return `${val}%`
-})
-const popupAzimuthText = computed(() => {
-	const val = selectedDevice.value?.azimuth
-	if (val == null) return '-'
-	return `${val}°`
-})
-const popupElevationText = computed(() => {
-	const val = selectedDevice.value?.elevation
-	if (val == null) return '-'
-	return `${val}°`
-})
-const popupDetectCountText = computed(() => {
-	const val = selectedDevice.value?.detectTargetCnt
-	if (val == null) return '-'
-	return `${val}台`
-})
-const popupRangeText = computed(() => {
-	const val = selectedDevice.value?.effectiveRangeKm
-	if (val == null) return '-'
-	return `${val}KM`
-})
+const isDronePopup = computed(() => selectedTargetType.value === 'drone')
+const toggleDroneFavorite = () => {
+	if (!selectedDevice.value) return
+	selectedDevice.value.isFavorite = !selectedDevice.value.isFavorite
+}
+const handleDroneSignal = () => emit('droneSignal', selectedDevice.value)
+const handleDroneCounter = () => emit('droneCounter', selectedDevice.value)
 
 const renderCommandPosts = list => {
 	if (!viewer) return
@@ -1085,172 +918,6 @@
 	left: 0;
 	width: 100%;
 	height: 100%;
-}
-
-.device-popup {
-	position: absolute;
-	transform: translate(-50%, calc(-100% - 72px));
-	width: 202px;
-	padding: 0 16px 20px;
-	border-radius: 16px;
-	background: rgba(5, 5, 15, 0.7);
-	backdrop-filter: blur(16px);
-	color: #C3C3DD;
-	font-family: Source Han Sans CN, Source Han Sans CN;
-	font-size: 12px;
-	pointer-events: auto;
-	z-index: 11;
-	box-sizing: border-box;
-
-	&::after {
-		content: "";
-		position: absolute;
-		left: 50%;
-		bottom: -8px;
-		transform: translateX(-50%);
-		width: 0;
-		height: 0;
-		border-left: 8px solid transparent;
-		border-right: 8px solid transparent;
-		border-top: 8px solid rgba(5, 5, 15, 0.7);
-	}
-
-	.device-popup__header {
-		height: 40px;
-		display: flex;
-		align-items: center;
-		justify-content: space-between;
-		position: relative;
-
-		font-weight: bold;
-		font-size: 14px;
-		color: #FFFFFF;
-
-		&::after {
-			content: "";
-			position: absolute;
-			left: 0;
-			bottom: 0;
-			width: 50px;
-			height: 2px;
-			background: #284FE3;
-			box-shadow: 0px 3px 2px 0px rgba(15, 89, 255, 0.1), 0px 7px 5px 0px rgba(15, 89, 255, 0.15), 0px 13px 10px 0px rgba(15, 89, 255, 0.18), 0px 22px 18px 0px rgba(15, 89, 255, 0.21), 0px 42px 33px 0px rgba(15, 89, 255, 0.26), 0px 100px 80px 0px rgba(15, 89, 255, 0.36);
-			border-radius: 5px 5px 0px 0px;
-		}
-
-		&::before {
-			content: "";
-			position: absolute;
-			left: 55px;
-			right: 0;
-			bottom: 0;
-			height: 2px;
-			background: #323245;
-			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;
-		}
-	}
-
-	.device-popup__type {
-		display: flex;
-		align-items: center;
-		gap: 6px;
-		font-size: 12px;
-		margin-top: 8px;
-		margin-bottom: 10px;
-		color: #d2d7df;
-
-		.label {
-			color: #9aa4b2;
-		}
-	}
-
-	.device-popup__subtitle {
-		display: inline-flex;
-		align-items: center;
-		gap: 6px;
-		padding: 2px 10px;
-		border-radius: 999px;
-		background: rgba(255, 255, 255, 0.06);
-		font-size: 12px;
-		margin-bottom: 10px;
-
-		.device-popup__dot {
-			width: 6px;
-			height: 6px;
-			border-radius: 50%;
-			background: #6b7685;
-
-			&.is-detecting {
-				background: #35f08c;
-				box-shadow: 0 0 6px rgba(53, 240, 140, 0.8);
-			}
-
-			&.is-jamming {
-				background: #ff4444;
-				box-shadow: 0 0 6px rgba(255, 68, 68, 0.7);
-			}
-
-			&.is-driving {
-				background: #ffb020;
-				box-shadow: 0 0 6px rgba(255, 176, 32, 0.7);
-			}
-
-			&.is-standby {
-				background: #9aa4b2;
-			}
-		}
-	}
-
-	.device-popup__rows {
-		display: flex;
-		flex-direction: column;
-		gap: 6px;
-		font-size: 12px;
-		color: #d2d7df;
-
-		.device-popup__row {
-			display: flex;
-			align-items: center;
-			margin-bottom: 10px;
-
-			.device-popup__col {
-				flex: 1;
-				display: flex;
-				align-items: center;
-
-				&:last-child {
-					justify-content: flex-end;
-				}
-			}
-		}
-
-		.value {
-			margin-left: 10px;
-		}
-
-		.value.online {
-			color: #35f08c;
-		}
-	}
-
 }
 
 .layer-control-root {
diff --git a/applications/drone-command/src/components/map-container/device-map-materials.js b/applications/drone-command/src/components/map-container/device-map-materials.js
new file mode 100644
index 0000000..bf2edc8
--- /dev/null
+++ b/applications/drone-command/src/components/map-container/device-map-materials.js
@@ -0,0 +1,188 @@
+import * as Cesium from 'cesium'
+
+export const RING_STYLES = [{ inner: 0, outer: 2000, gradient: ['#FF361C', '#360B00'] }]
+
+export const MATERIAL_TYPE = 'RadialGradientMaterial'
+export const DRONE_TRACK_MATERIAL_TYPE = 'DroneTrackFlowMaterial'
+
+let materialRegistered = false
+let droneTrackMaterialRegistered = false
+let texturedVertexFormat = null
+
+export const getTexturedVertexFormat = () => {
+	if (!texturedVertexFormat) {
+		texturedVertexFormat =
+			Cesium.MaterialAppearance?.MaterialSupport?.TEXTURED?.vertexFormat || Cesium.VertexFormat.POSITION_AND_ST
+	}
+	return texturedVertexFormat
+}
+
+export const registerRadialGradientMaterial = () => {
+	if (materialRegistered || !Cesium?.Material) return
+	materialRegistered = true
+	Cesium.Material._materialCache.addMaterial(MATERIAL_TYPE, {
+		fabric: {
+			type: MATERIAL_TYPE,
+			uniforms: {
+				color1: new Cesium.Color(1.0, 1.0, 1.0, 1.0),
+				color2: new Cesium.Color(0.0, 0.0, 0.0, 1.0),
+			},
+			source: `
+				czm_material czm_getMaterial(czm_materialInput materialInput) {
+					czm_material material = czm_getDefaultMaterial(materialInput);
+					vec2 st = materialInput.st - vec2(0.5);
+					float t = clamp(length(st) * 2.0, 0.0, 1.0);
+					vec4 color = mix(color1, color2, t);
+					material.diffuse = color.rgb;
+					material.alpha = color.a;
+					return material;
+				}
+			`,
+		},
+		translucent: () => true,
+	})
+}
+
+export const registerDroneTrackMaterial = () => {
+	if (droneTrackMaterialRegistered || !Cesium?.Material) return
+	droneTrackMaterialRegistered = true
+	Cesium.Material._materialCache.addMaterial(DRONE_TRACK_MATERIAL_TYPE, {
+		fabric: {
+			type: DRONE_TRACK_MATERIAL_TYPE,
+			uniforms: {
+				color: new Cesium.Color(1.0, 0.28, 0.18, 1.0),
+				speed: 4.0,
+				headWidth: 0.18,
+				glowPower: 1.6,
+				backgroundAlpha: 0.22,
+			},
+			source: `
+				uniform vec4 color;
+				uniform float speed;
+				uniform float headWidth;
+				uniform float glowPower;
+				uniform float backgroundAlpha;
+
+				czm_material czm_getMaterial(czm_materialInput materialInput) {
+					czm_material material = czm_getDefaultMaterial(materialInput);
+					vec2 st = materialInput.st;
+					float time = fract(czm_frameNumber * speed / 1000.0);
+					float flow = fract(st.s - time);
+					float head = smoothstep(headWidth, 0.0, flow) * smoothstep(0.0, headWidth, flow);
+					float alpha = mix(backgroundAlpha, 1.0, head);
+					vec3 rgb = color.rgb;
+					material.diffuse = rgb;
+					material.emission = rgb * alpha * glowPower;
+					material.alpha = color.a * alpha;
+					return material;
+				}
+			`,
+		},
+		translucent: () => true,
+	})
+}
+
+export const createRadialGradientMaterial = (color1, color2) => {
+	registerRadialGradientMaterial()
+	return Cesium.Material.fromType(MATERIAL_TYPE, { color1, color2 })
+}
+
+export const createDroneTrackMaterial = options => {
+	registerDroneTrackMaterial()
+	return Cesium.Material.fromType(DRONE_TRACK_MATERIAL_TYPE, {
+		color: new Cesium.Color(1.0, 0.28, 0.18, 1.0),
+		speed: 4.0,
+		headWidth: 0.18,
+		glowPower: 1.6,
+		backgroundAlpha: 0.22,
+		...(options || {}),
+	})
+}
+
+export const buildCirclePositions = (center, radiusMeters, steps = 64) => {
+	const positions = []
+	const latRad = Cesium.Math.toRadians(center.latitude)
+	const metersToLat = 1 / 111320
+	const metersToLon = 1 / (111320 * Math.cos(latRad))
+	for (let i = 0; i <= steps; i += 1) {
+		const angle = Cesium.Math.toRadians((i / steps) * 360)
+		const dx = radiusMeters * Math.cos(angle)
+		const dy = radiusMeters * Math.sin(angle)
+		const lon = center.longitude + dx * metersToLon
+		const lat = center.latitude + dy * metersToLat
+		positions.push(Cesium.Cartesian3.fromDegrees(lon, lat))
+	}
+	return positions
+}
+
+export const addDeviceRings = (center, ringFillInstancesByStyle, ringOutlineInstancesByStyle) => {
+	if (!ringFillInstancesByStyle) return
+	const centerPosition = Cesium.Cartesian3.fromDegrees(center.longitude, center.latitude, 0)
+	const vertexFormat = getTexturedVertexFormat()
+	RING_STYLES.forEach((ring, index) => {
+		if (!ringFillInstancesByStyle[index]) return
+		ringFillInstancesByStyle[index].push(
+			new Cesium.GeometryInstance({
+				geometry: new Cesium.EllipseGeometry({
+					center: centerPosition,
+					semiMajorAxis: ring.outer,
+					semiMinorAxis: ring.outer,
+					vertexFormat,
+				}),
+			})
+		)
+	})
+	if (!ringOutlineInstancesByStyle) return
+	RING_STYLES.forEach((ring, index) => {
+		if (!ringOutlineInstancesByStyle[index]) return
+		const positions = buildCirclePositions(center, ring.outer)
+		ringOutlineInstancesByStyle[index].push(
+			new Cesium.GeometryInstance({
+				geometry: new Cesium.GroundPolylineGeometry({
+					positions,
+					width: 2,
+				}),
+				attributes: {
+					color: Cesium.ColorGeometryInstanceAttribute.fromColor(
+						Cesium.Color.fromCssColorString(ring.gradient[0]).withAlpha(0.8)
+					),
+				},
+			})
+		)
+	})
+}
+
+export class RadialGradientMaterialProperty {
+	constructor(color1, color2) {
+		this._definitionChanged = new Cesium.Event()
+		this.color1 = color1
+		this.color2 = color2
+	}
+
+	get isConstant () {
+		return true
+	}
+
+	get definitionChanged () {
+		return this._definitionChanged
+	}
+
+	getType () {
+		return MATERIAL_TYPE
+	}
+
+	getValue (time, result) {
+		const target = result || {}
+		target.color1 = this.color1
+		target.color2 = this.color2
+		return target
+	}
+
+	equals (other) {
+		return (
+			other instanceof RadialGradientMaterialProperty &&
+			Cesium.Color.equals(this.color1, other.color1) &&
+			Cesium.Color.equals(this.color2, other.color2)
+		)
+	}
+}
diff --git a/applications/drone-command/src/views/areaManage/areaStatistics/FormDiaLog.vue b/applications/drone-command/src/views/areaManage/areaStatistics/FormDiaLog.vue
index c3ec2e5..5ad124e 100644
--- a/applications/drone-command/src/views/areaManage/areaStatistics/FormDiaLog.vue
+++ b/applications/drone-command/src/views/areaManage/areaStatistics/FormDiaLog.vue
@@ -42,7 +42,7 @@
 			</el-row>
 		</div>
 		<template #footer>
-			<el-button color="#2B2B4C" @click="handleCancel">关闭</el-button>
+			<el-button v-if="dialogMode != 'view'" color="#2B2B4C" @click="handleCancel">关闭</el-button>
 		</template>
 	</el-dialog>
 </template>
diff --git a/applications/drone-command/src/views/areaManage/defenseZone/FormDiaLog.vue b/applications/drone-command/src/views/areaManage/defenseZone/FormDiaLog.vue
index 763d8d7..6b799c1 100644
--- a/applications/drone-command/src/views/areaManage/defenseZone/FormDiaLog.vue
+++ b/applications/drone-command/src/views/areaManage/defenseZone/FormDiaLog.vue
@@ -85,7 +85,7 @@
 				</el-form>
 
 				<div class="footer">
-					<el-button color="#2B2B4C" @click="handleCancel">{{ readonly ? '关闭' : '取消' }}</el-button>
+					<el-button v-if="dialogMode != 'view'" color="#2B2B4C" @click="handleCancel">{{ readonly ? '关闭' : '取消' }}</el-button>
 					<el-button color="#284FE3" v-if="!readonly" type="primary" :loading="submitting"
 						:disabled="submitting" @click="handleSubmit">
 						确定
diff --git a/applications/drone-command/src/views/areaManage/partition/FormDiaLog.vue b/applications/drone-command/src/views/areaManage/partition/FormDiaLog.vue
index 00e1113..0b2786e 100644
--- a/applications/drone-command/src/views/areaManage/partition/FormDiaLog.vue
+++ b/applications/drone-command/src/views/areaManage/partition/FormDiaLog.vue
@@ -154,7 +154,7 @@
 				</el-form>
 
 				<div class="footer">
-					<el-button color="#2B2B4C" @click="handleCancel">{{ readonly ? '关闭' : '取消' }}</el-button>
+					<el-button v-if="dialogMode != 'view'" color="#2B2B4C" @click="handleCancel">{{ readonly ? '关闭' : '取消' }}</el-button>
 					<el-button color="#284FE3" v-if="!readonly" type="primary" :loading="submitting"
 						:disabled="submitting" @click="handleSubmit">
 						确定
diff --git a/applications/drone-command/src/views/areaManage/precinctInfo/FormDiaLog.vue b/applications/drone-command/src/views/areaManage/precinctInfo/FormDiaLog.vue
index de089a8..d76eae9 100644
--- a/applications/drone-command/src/views/areaManage/precinctInfo/FormDiaLog.vue
+++ b/applications/drone-command/src/views/areaManage/precinctInfo/FormDiaLog.vue
@@ -52,7 +52,7 @@
 			</el-row>
 		</el-form>
 		<template #footer>
-			<el-button color="#2B2B4C" @click="handleCancel">{{ readonly ? '关闭' : '取消' }}</el-button>
+			<el-button v-if="dialogMode != 'view'" color="#2B2B4C" @click="handleCancel">{{ readonly ? '关闭' : '取消' }}</el-button>
 			<el-button color="#284FE3" v-if="!readonly" type="primary" :loading="submitting" :disabled="submitting"
 				@click="handleSubmit">
 				确定
diff --git a/applications/drone-command/src/views/areaManage/sceneConfig/FormDiaLog.vue b/applications/drone-command/src/views/areaManage/sceneConfig/FormDiaLog.vue
index b6558c9..e546c27 100644
--- a/applications/drone-command/src/views/areaManage/sceneConfig/FormDiaLog.vue
+++ b/applications/drone-command/src/views/areaManage/sceneConfig/FormDiaLog.vue
@@ -129,7 +129,7 @@
 				</el-form>
 
 				<div class="footer">
-					<el-button color="#2B2B4C" @click="handleCancel">{{ readonly ? '关闭' : '取消' }}</el-button>
+					<el-button v-if="dialogMode != 'view'" color="#2B2B4C" @click="handleCancel">{{ readonly ? '关闭' : '取消' }}</el-button>
 					<el-button color="#284FE3" v-if="!readonly" type="primary" :loading="submitting"
 						:disabled="submitting" @click="handleSubmit">
 						确定
diff --git a/applications/drone-command/src/views/basicManage/deviceScrap/FormDiaLog.vue b/applications/drone-command/src/views/basicManage/deviceScrap/FormDiaLog.vue
index cb60414..7e3ef76 100644
--- a/applications/drone-command/src/views/basicManage/deviceScrap/FormDiaLog.vue
+++ b/applications/drone-command/src/views/basicManage/deviceScrap/FormDiaLog.vue
@@ -50,7 +50,7 @@
 			</el-row>
 		</div>
 		<template #footer>
-			<el-button color="#2B2B4C" @click="handleCancel">{{ dialogReadonly ? '关闭' : '取消' }}</el-button>
+			<el-button v-if="dialogMode != 'view'" color="#2B2B4C" @click="handleCancel">{{ dialogReadonly ? '关闭' : '取消' }}</el-button>
 		</template>
 	</el-dialog>
 </template>
diff --git a/applications/drone-command/src/views/basicManage/deviceStock/DeviceScrapDiaLog.vue b/applications/drone-command/src/views/basicManage/deviceStock/DeviceScrapDiaLog.vue
index 38e194f..ad4958c 100644
--- a/applications/drone-command/src/views/basicManage/deviceStock/DeviceScrapDiaLog.vue
+++ b/applications/drone-command/src/views/basicManage/deviceStock/DeviceScrapDiaLog.vue
@@ -16,7 +16,7 @@
 			</el-row>
 		</el-form>
 		<template #footer>
-			<el-button color="#2B2B4C" @click="handleCancel">{{ dialogReadonly ? '关闭' : '取消' }}</el-button>
+			<el-button v-if="dialogMode != 'view'" color="#2B2B4C" @click="handleCancel">{{ dialogReadonly ? '关闭' : '取消' }}</el-button>
 			<el-button
 				v-if="!dialogReadonly"
 				type="primary"
diff --git a/applications/drone-command/src/views/basicManage/deviceStock/DeviceTrackDiaLog.vue b/applications/drone-command/src/views/basicManage/deviceStock/DeviceTrackDiaLog.vue
index dac459c..1f905b1 100644
--- a/applications/drone-command/src/views/basicManage/deviceStock/DeviceTrackDiaLog.vue
+++ b/applications/drone-command/src/views/basicManage/deviceStock/DeviceTrackDiaLog.vue
@@ -47,7 +47,7 @@
 			</el-row>
 		</el-form>
 		<template #footer>
-			<el-button color="#2B2B4C" @click="handleCancel">{{ dialogReadonly ? '关闭' : '取消' }}</el-button>
+			<el-button v-if="dialogMode != 'view'" color="#2B2B4C" @click="handleCancel">{{ dialogReadonly ? '关闭' : '取消' }}</el-button>
 			<el-button
 				v-if="!dialogReadonly"
 				type="primary"
diff --git a/applications/drone-command/src/views/basicManage/deviceStock/FormDiaLog.vue b/applications/drone-command/src/views/basicManage/deviceStock/FormDiaLog.vue
index c115e2e..b570b0f 100644
--- a/applications/drone-command/src/views/basicManage/deviceStock/FormDiaLog.vue
+++ b/applications/drone-command/src/views/basicManage/deviceStock/FormDiaLog.vue
@@ -162,7 +162,7 @@
 			</el-row>
 		</el-form>
 		<template #footer>
-			<el-button color="#2B2B4C" @click="handleCancel">{{ dialogReadonly ? '关闭' : '取消' }}</el-button>
+			<el-button v-if="dialogMode != 'view'" color="#2B2B4C" @click="handleCancel">{{ dialogReadonly ? '关闭' : '取消' }}</el-button>
 			<el-button color="#284FE3" v-if="!dialogReadonly" type="primary" :loading="submitting"
 				:disabled="submitting" @click="handleSubmit">
 				保存
diff --git a/applications/drone-command/src/views/basicManage/maintainRecord/FormDiaLog.vue b/applications/drone-command/src/views/basicManage/maintainRecord/FormDiaLog.vue
index e9ffb94..adc1346 100644
--- a/applications/drone-command/src/views/basicManage/maintainRecord/FormDiaLog.vue
+++ b/applications/drone-command/src/views/basicManage/maintainRecord/FormDiaLog.vue
@@ -112,7 +112,7 @@
 			</el-row>
 		</el-form>
 		<template #footer>
-			<el-button color="#2B2B4C" @click="handleCancel">{{ dialogReadonly ? '关闭' : '取消' }}</el-button>
+			<el-button v-if="dialogMode != 'view'" color="#2B2B4C" @click="handleCancel">{{ dialogReadonly ? '关闭' : '取消' }}</el-button>
 			<el-button color="#284FE3" v-if="!dialogReadonly" type="primary" :loading="submitting"
 				:disabled="submitting" @click="handleSubmit">
 				保存
diff --git a/applications/drone-command/src/views/basicManage/maintainRecord/MaintenanceDiaLog.vue b/applications/drone-command/src/views/basicManage/maintainRecord/MaintenanceDiaLog.vue
index db0e3fd..5d7d61f 100644
--- a/applications/drone-command/src/views/basicManage/maintainRecord/MaintenanceDiaLog.vue
+++ b/applications/drone-command/src/views/basicManage/maintainRecord/MaintenanceDiaLog.vue
@@ -56,7 +56,7 @@
 </el-row>
 		</el-form>
 		<template #footer>
-			<el-button color="#2B2B4C" @click="handleCancel">{{ dialogReadonly ? '关闭' : '取消' }}</el-button>
+			<el-button v-if="dialogMode != 'view'" color="#2B2B4C" @click="handleCancel">{{ dialogReadonly ? '关闭' : '取消' }}</el-button>
 			<el-button
 				v-if="!dialogReadonly"
 				type="primary"
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 79119bf..e834cff 100644
--- a/applications/drone-command/src/views/dataCockpit/components/templateComponents/RealTemplate.vue
+++ b/applications/drone-command/src/views/dataCockpit/components/templateComponents/RealTemplate.vue
@@ -18,9 +18,12 @@
 			</div>
 
 			<div class="actions">
-				<span class="star" @click="emit('favorite')">
-					{{ data.isFavorite ? '★' : '☆' }}
-				</span>
+				<img
+					class="favorite-icon"
+					:src="favoriteIcon"
+					alt="收藏"
+					@click="emit('favorite')"
+				/>
 			</div>
 		</div>
 
@@ -67,8 +70,11 @@
 </template>
 
 <script setup>
+import { computed } from 'vue'
 import { saveOperationLog } from '@ztzf/apis'
 import { useRoute } from 'vue-router'
+import favoriteNo from '@/assets/images/dataCockpit/favorite-n.png'
+import favoriteYes from '@/assets/images/dataCockpit/favorite-y.png'
 
 const props = defineProps({
 	data: {
@@ -80,6 +86,7 @@
 
 const route = useRoute()
 const emit = defineEmits(['signal', 'counter', 'favorite'])
+const favoriteIcon = computed(() => (props.data?.isFavorite ? favoriteYes : favoriteNo))
 
 // 信号干扰操作
 const handleSignal = () => {
@@ -250,6 +257,11 @@
 			gap: 8px;
 			font-size: 16px;
 			cursor: pointer;
+
+			.favorite-icon {
+				width: 16px;
+				height: 16px;
+			}
 		}
 	}
 
@@ -296,4 +308,4 @@
 		}
 	}
 }
-</style>
\ No newline at end of file
+</style>
diff --git a/applications/drone-command/src/views/detectionCountermeasure/countermeasureEvaluation/FormDiaLog.vue b/applications/drone-command/src/views/detectionCountermeasure/countermeasureEvaluation/FormDiaLog.vue
index 28dafb2..edd2ae5 100644
--- a/applications/drone-command/src/views/detectionCountermeasure/countermeasureEvaluation/FormDiaLog.vue
+++ b/applications/drone-command/src/views/detectionCountermeasure/countermeasureEvaluation/FormDiaLog.vue
@@ -67,7 +67,7 @@
 			</el-row>
 		</div>
 		<template #footer>
-			<el-button color="#2B2B4C" @click="handleCancel">关闭</el-button>
+			<el-button v-if="dialogMode != 'view'" color="#2B2B4C" @click="handleCancel">关闭</el-button>
 		</template>
 	</el-dialog>
 </template>
diff --git a/applications/drone-command/src/views/detectionCountermeasure/detectionRange/DetectionRangeDialog.vue b/applications/drone-command/src/views/detectionCountermeasure/detectionRange/DetectionRangeDialog.vue
index 176171b..79a1287 100644
--- a/applications/drone-command/src/views/detectionCountermeasure/detectionRange/DetectionRangeDialog.vue
+++ b/applications/drone-command/src/views/detectionCountermeasure/detectionRange/DetectionRangeDialog.vue
@@ -129,7 +129,7 @@
 					</el-form-item>
 				</el-form>
 				<div class="footer">
-					<el-button color="#2B2B4C" @click="handleCancel">{{ dialogReadonly ? '关闭' : '取消' }}</el-button>
+					<el-button v-if="dialogMode != 'view'" color="#2B2B4C" @click="handleCancel">{{ dialogReadonly ? '关闭' : '取消' }}</el-button>
 					<el-button
 						color="#284FE3"
 						v-if="!dialogReadonly"
diff --git a/applications/drone-command/src/views/detectionCountermeasure/deviceAppConfig/FormDiaLog.vue b/applications/drone-command/src/views/detectionCountermeasure/deviceAppConfig/FormDiaLog.vue
index 9cde3af..eeab733 100644
--- a/applications/drone-command/src/views/detectionCountermeasure/deviceAppConfig/FormDiaLog.vue
+++ b/applications/drone-command/src/views/detectionCountermeasure/deviceAppConfig/FormDiaLog.vue
@@ -152,7 +152,7 @@
 			</el-row>
 		</el-form>
 		<template #footer>
-			<el-button color="#2B2B4C" @click="handleCancel">{{ readonly ? '关闭' : '取消' }}</el-button>
+			<el-button v-if="dialogMode != 'view'" color="#2B2B4C" @click="handleCancel">{{ readonly ? '关闭' : '取消' }}</el-button>
 			<el-button
 				color="#284FE3"
 				v-if="!readonly"
diff --git a/applications/drone-command/src/views/detectionCountermeasure/taskSchedule/FormDiaLog.vue b/applications/drone-command/src/views/detectionCountermeasure/taskSchedule/FormDiaLog.vue
index c9f1591..a217adb 100644
--- a/applications/drone-command/src/views/detectionCountermeasure/taskSchedule/FormDiaLog.vue
+++ b/applications/drone-command/src/views/detectionCountermeasure/taskSchedule/FormDiaLog.vue
@@ -142,7 +142,7 @@
 		</el-form>
 
 		<template #footer>
-			<el-button color="#2B2B4C" @click="handleCancel">{{ readonly ? '关闭' : '取消' }}</el-button>
+			<el-button v-if="dialogMode != 'view'" color="#2B2B4C" @click="handleCancel">{{ readonly ? '关闭' : '取消' }}</el-button>
 			<el-button color="#284FE3" v-if="!readonly" type="primary" :loading="submitting" :disabled="submitting"
 				@click="handleSubmit">
 				保存
diff --git a/applications/drone-command/src/views/permissionManage/permissionDept/FormDiaLog.vue b/applications/drone-command/src/views/permissionManage/permissionDept/FormDiaLog.vue
index 74c37cd..95955ad 100644
--- a/applications/drone-command/src/views/permissionManage/permissionDept/FormDiaLog.vue
+++ b/applications/drone-command/src/views/permissionManage/permissionDept/FormDiaLog.vue
@@ -115,7 +115,7 @@
 		</el-form>
 
 		<template #footer>
-			<el-button color="#2B2B4C" @click="handleCancel">{{ dialogReadonly ? '关闭' : '取消' }}</el-button>
+			<el-button v-if="dialogMode != 'view'" color="#2B2B4C" @click="handleCancel">{{ dialogReadonly ? '关闭' : '取消' }}</el-button>
 			<el-button color="#284FE3" v-if="!dialogReadonly" type="primary" :loading="submitting" :disabled="submitting" @click="handleSubmit">
 				保存
 			</el-button>
diff --git a/applications/drone-command/src/views/permissionManage/permissionRole/FormDiaLog.vue b/applications/drone-command/src/views/permissionManage/permissionRole/FormDiaLog.vue
index 66d2840..0622c6f 100644
--- a/applications/drone-command/src/views/permissionManage/permissionRole/FormDiaLog.vue
+++ b/applications/drone-command/src/views/permissionManage/permissionRole/FormDiaLog.vue
@@ -57,7 +57,7 @@
 		</el-form>
 
 		<template #footer>
-			<el-button color="#2B2B4C" @click="handleCancel">{{ dialogReadonly ? '关闭' : '取消' }}</el-button>
+			<el-button v-if="dialogMode != 'view'" color="#2B2B4C" @click="handleCancel">{{ dialogReadonly ? '关闭' : '取消' }}</el-button>
 			<el-button color="#284FE3" v-if="!dialogReadonly" type="primary" :loading="submitting" :disabled="submitting" @click="handleSubmit">
 				保存
 			</el-button>
diff --git a/applications/drone-command/src/views/permissionManage/permissionUser/FormDiaLog.vue b/applications/drone-command/src/views/permissionManage/permissionUser/FormDiaLog.vue
index 4cea05b..0aca836 100644
--- a/applications/drone-command/src/views/permissionManage/permissionUser/FormDiaLog.vue
+++ b/applications/drone-command/src/views/permissionManage/permissionUser/FormDiaLog.vue
@@ -231,7 +231,7 @@
 		</el-form>
 
 		<template #footer>
-			<el-button color="#2B2B4C" @click="handleCancel">{{ dialogReadonly ? '关闭' : '取消' }}</el-button>
+			<el-button v-if="dialogMode != 'view'" color="#2B2B4C" @click="handleCancel">{{ dialogReadonly ? '关闭' : '取消' }}</el-button>
 			<el-button color="#284FE3" v-if="!dialogReadonly" type="primary" :loading="submitting" :disabled="submitting" @click="handleSubmit">
 				保存
 			</el-button>
diff --git a/applications/drone-command/src/views/recordManage/historyTracks/TrajectoryDiaLog.vue b/applications/drone-command/src/views/recordManage/historyTracks/TrajectoryDiaLog.vue
index 4c18aaa..869bdae 100644
--- a/applications/drone-command/src/views/recordManage/historyTracks/TrajectoryDiaLog.vue
+++ b/applications/drone-command/src/views/recordManage/historyTracks/TrajectoryDiaLog.vue
@@ -56,7 +56,7 @@
 					</div>
 				</div>
 				<div class="footer">
-					<el-button color="#2B2B4C" @click="handleCancel">{{ dialogReadonly ? '关闭' : '取消' }}</el-button>
+					<el-button v-if="dialogMode != 'view'" color="#2B2B4C" @click="handleCancel">{{ dialogReadonly ? '关闭' : '取消' }}</el-button>
 				</div>
 			</div>
 		</div>
diff --git a/applications/task-work-order/src/styles/common/cockpit.scss b/applications/task-work-order/src/styles/common/cockpit.scss
index aa7ee39..bdd93cd 100644
--- a/applications/task-work-order/src/styles/common/cockpit.scss
+++ b/applications/task-work-order/src/styles/common/cockpit.scss
@@ -1,142 +1,95 @@
-//变量
-$gd-placeholder: #86909C;
 $form-bg: #F2F3F5;
-
-.gd-table {
-  height: 0;
-  flex: 1;
-  background: transparent !important;
-
-  .el-table--border .el-table__inner-wrapper:after,
-  .el-table--border:after,
-  .el-table--border:before,
-  .el-table__inner-wrapper:before {
-    height: 0;
-  }
-
-  tr {
-    background: transparent !important;
-  }
-
-  th.el-table__cell {
-    height: 40px;
-    border-bottom: 1px solid #DBDFF1 !important;
-
-    .cell {
-      padding: 0 0 0 16px;
-      font-family: Source Han Sans CN, Source Han Sans CN;
-      font-weight: 400;
-      font-size: 14px;
-      color: #9292C1;
-      text-align: left;
-      font-style: normal;
-      text-transform: none;
-    }
-  }
-
-  td.el-table__cell {
-    padding: 9px 0;
-    height: 56px;
-
-    .cell {
-      padding: 0 0 0 16px;
-      font-family: Source Han Sans CN, Source Han Sans CN;
-      font-weight: 400;
-      font-size: 14px;
-      color: #383874;
-      text-align: left;
-      font-style: normal;
-      text-transform: none;
-    }
-  }
-
-  td.operation-btns .cell {
-    display: flex;
-    flex-wrap: nowrap;
-    gap: 12px;
-    /* 按钮间距(推荐) */
-    white-space: nowrap;
-    /* 双保险 */
-
-    a {
-      min-width: 28px;
-      color: #0075FF;
-
-      &:last-child {
-        margin-right: 0;
-      }
-    }
-  }
-
-  th.el-table__cell:not(.fixed-column),
-  td.el-table__cell:not(.fixed-column) {
-    background: transparent !important;
-  }
-
-  .fixed-column {
-    background-color: #1A1A2A !important;
-  }
-}
+$form-tips: #86909C;
+//灰色变量
+$form-bg-gray: #DDE2ED;
+$form-tips-gray: #A1A3D4;
 
 .gd-input {
+  --bg: #{$form-bg};
+  --tips: #{$form-tips};
+
+  &.gray {
+    --bg: #{$form-bg-gray};
+    --tips: #{$form-tips-gray};
+  }
+
   .el-input__wrapper, .el-textarea__inner {
-    padding: 0 8px !important;
-    background: $form-bg;
     box-shadow: none !important;
+    background: var(--bg);
     border: none;
   }
-
   .el-input__inner, .el-textarea__inner {
     &::placeholder {
-      color: $gd-placeholder;
+      color: var(--tips);
     }
   }
-
 
   &.is-disabled {
     .el-input__wrapper {
-      background: #DDE2ED;
+      background: var(--bg);
     }
   }
 }
 
-.gd-select {
-  .el-select__input {
-    color: #8ac3fd !important;
+.gd-select, {
+  --bg: #{$form-bg};
+  --tips: #{$form-tips};
+
+  &.gray {
+    --bg: #{$form-bg-gray};
+    --tips: #{$form-tips-gray};
   }
 
   .el-select__wrapper {
     padding: 0 8px;
-    background: $form-bg;
+    background: var(--bg);
     box-shadow: none !important;
     border: none;
-    width: 100%;
   }
 
   .el-select__placeholder {
     &.is-transparent {
-      color: $gd-placeholder !important;
+      color: var(--tips) !important;
     }
 
     &.el-select__selected-item {
       color: #383874;
     }
   }
+}
 
-  .el-select {
-    --el-select-border-color-hover: rgb(0, 162, 255) !important;
+.gd-date-picker {
+  --bg: #{$form-bg};
+  --tips: #{$form-tips};
+
+  &.gray {
+    --bg: #{$form-bg-gray};
+    --tips: #{$form-tips-gray};
   }
 
-  .el-input {
-    --el-border-color: rgb(0, 162, 255);
-  }
-
-  .el-select .el-input__wrapper {
-    background-color: #DDE2ED !important;
-  }
+  box-shadow: none !important;
+  background: var(--bg);
+  border: none;
+  border-radius: 5px;
+  box-sizing: border-box !important;
 
   .el-input__wrapper {
-    --el-input-text-color: #DDE2ED !important;
+    box-shadow: none !important;
+    background-color: transparent !important;
+
+    &.is-focus {
+      box-shadow: none !important;
+    }
+  }
+
+  .el-range-input {
+    &::placeholder {
+      color: var(--tips);
+    }
+  }
+
+  .el-range-separator {
+    color: #ffffff;
   }
 }
 
@@ -215,35 +168,6 @@
       background: #012a50 !important;
       border: 1px solid #012a50 !important;
     }
-  }
-}
-
-.gd-date-picker {
-  box-shadow: none !important;
-  background: $form-bg;
-  border: none;
-  border-radius: 5px;
-  box-sizing: border-box !important;
-
-  .el-input__wrapper {
-    box-shadow: none !important;
-    background-color: transparent !important;
-
-    &.is-focus {
-      box-shadow: none !important;
-    }
-  }
-
-  .el-range-input {
-    color: #fff;
-
-    &::placeholder {
-      color: $gd-placeholder;
-    }
-  }
-
-  .el-range-separator {
-    color: #ffffff;
   }
 }
 
@@ -454,10 +378,10 @@
   }
 }
 
-.el-overlay-dialog{
+.el-overlay-dialog {
   display: flex;
   justify-content: center; /* 水平居中 */
-  align-items: center;     /* 垂直居中 */
+  align-items: center; /* 垂直居中 */
 }
 
 .gd-dialog {
@@ -489,6 +413,7 @@
   .el-dialog__body {
     overflow: auto;
     min-height: 5vh;
+
     .detail-title {
       margin-bottom: 10px;
       font-family: Source Han Sans CN, Source Han Sans CN;
@@ -510,6 +435,7 @@
         margin-bottom: 0;
 
         .label {
+          display: inline-block;
           width: 88px;
           font-family: Source Han Sans CN, Source Han Sans CN;
           font-weight: 500;
@@ -554,6 +480,82 @@
     .save-btn {
       color: #FFFFFF;
     }
+  }
+}
+
+.gd-table {
+  height: 0;
+  flex: 1;
+  background: transparent !important;
+
+  .el-table--border .el-table__inner-wrapper:after,
+  .el-table--border:after,
+  .el-table--border:before,
+  .el-table__inner-wrapper:before {
+    height: 0;
+  }
+
+  tr {
+    background: transparent !important;
+  }
+
+  th.el-table__cell {
+    height: 40px;
+    border-bottom: 1px solid #DBDFF1 !important;
+
+    .cell {
+      padding: 0 0 0 16px;
+      font-family: Source Han Sans CN, Source Han Sans CN;
+      font-weight: 400;
+      font-size: 14px;
+      color: #9292C1;
+      text-align: left;
+      font-style: normal;
+      text-transform: none;
+    }
+  }
+
+  td.el-table__cell {
+    padding: 9px 0;
+    height: 56px;
+
+    .cell {
+      padding: 0 0 0 16px;
+      font-family: Source Han Sans CN, Source Han Sans CN;
+      font-weight: 400;
+      font-size: 14px;
+      color: #383874;
+      text-align: left;
+      font-style: normal;
+      text-transform: none;
+    }
+  }
+
+  td.operation-btns .cell {
+    display: flex;
+    flex-wrap: nowrap;
+    gap: 12px;
+    /* 按钮间距(推荐) */
+    white-space: nowrap;
+    /* 双保险 */
+
+    a {
+      min-width: 28px;
+      color: #0075FF;
+
+      &:last-child {
+        margin-right: 0;
+      }
+    }
+  }
+
+  th.el-table__cell:not(.fixed-column),
+  td.el-table__cell:not(.fixed-column) {
+    background: transparent !important;
+  }
+
+  .fixed-column {
+    background-color: #1A1A2A !important;
   }
 }
 
@@ -618,7 +620,7 @@
         text-transform: none;
       }
 
-      background: #F2F3F5;
+      background: $form-bg;
       border: none;
       box-shadow: none;
     }
@@ -701,47 +703,6 @@
   .gd-input {
     width: 200px;
     height: 36px;
-
-    .el-input__wrapper {
-    }
-
-    &.is-disabled {
-      .el-input__wrapper {
-      }
-    }
-  }
-
-  .gd-date-picker {
-  }
-
-  .gd-date-picker-popper {
-
-    .el-picker-panel {
-      .el-picker-panel__body-wrapper {
-        .el-picker-panel__body {
-
-          .el-date-picker__time-header {
-
-            .el-date-picker__editor-wrap {
-              .el-time-panel {
-
-                // 将 time-picker-popper 的样式移到这里
-                .el-time-panel__header {
-                }
-              }
-            }
-          }
-        }
-      }
-    }
-
-    .el-popper__arrow {
-      &::before {
-        background: #DDE2ED !important;
-        border: 1px solid #DDE2ED !important;
-        box-sizing: border-box;
-      }
-    }
   }
 
   .gd-search-actions {
@@ -829,7 +790,7 @@
 
 .gd-select-popper {
   border: none;
-  background: #F2F3F5 !important;
+  background: $form-bg !important;
 
   .el-select-dropdown {
     .el-scrollbar {
@@ -853,16 +814,55 @@
     }
 
     .el-select-dropdown__empty {
-      background: #F2F3F5;
+      background: $form-bg;
       border-radius: 0px 0px 8px 8px;
     }
   }
 
   .el-popper__arrow::before {
-    background: #F2F3F5 !important;
+    background: $form-bg !important;
     border: 1px solid #F2F3F5 !important;
   }
 }
 
+.gd-timeline {
+  padding-left: 120px;
 
+  .el-timeline-item {
+    height: 120px;
 
+    &:nth-last-child(1) {
+      height: auto;
+    }
+
+    .el-timeline-item__tail {
+      left: 15px;
+      transform: translate(-15px);
+      border-left-color: #4c34ff;
+    }
+
+    .el-timeline-item__node {
+      width: 32px;
+      height: 32px;
+      background-color: #161b2c;
+      transform: translate(-15px);
+
+      &.el-timeline-item__node--success {
+        background-color: #4c34ff;
+      }
+
+      .el-timeline-item__icon {
+        font-size: 22px;
+      }
+    }
+
+    .el-timeline-item__wrapper {
+      top: 5px;
+      font-size: 16px;
+
+      .el-timeline-item__timestamp {
+        margin-top: 20px;
+      }
+    }
+  }
+}
diff --git a/applications/task-work-order/src/views/orderView/orderDataManage/appInnovation/index.vue b/applications/task-work-order/src/views/orderView/orderDataManage/appInnovation/index.vue
index be52dca..f01cb6e 100644
--- a/applications/task-work-order/src/views/orderView/orderDataManage/appInnovation/index.vue
+++ b/applications/task-work-order/src/views/orderView/orderDataManage/appInnovation/index.vue
@@ -2,21 +2,30 @@
 	<basic-container>
 		<el-form ref="queryParamsRef" :model="searchParams" class="gd-search-form">
 			<el-form-item label="案例名称" prop="caseName">
-				<el-input class="gd-input" v-model="searchParams.caseName" placeholder="请输入" clearable @clear="handleSearch" />
+				<el-input
+					class="gd-input gray"
+					v-model="searchParams.caseName"
+					placeholder="请输入"
+					clearable
+					@clear="handleSearch"
+				/>
 			</el-form-item>
 
 			<el-form-item label="应用创新状态" prop="innovationStatus">
 				<el-select
-					class="gd-select"
+					class="gd-select gray"
 					popper-class="gd-select-popper"
 					v-model="searchParams.innovationStatus"
 					placeholder="请选择"
 					clearable
 					@change="handleSearch"
 				>
-					<el-option v-for="item in dictObj.appInnovationStatus" :key="item.dictKey"
+					<el-option
+						v-for="item in dictObj.appInnovationStatus"
+						:key="item.dictKey"
 						:label="item.dictValue"
-						:value="item.dictKey"/>
+						:value="item.dictKey"
+					/>
 				</el-select>
 			</el-form-item>
 
@@ -111,10 +120,8 @@
 function getDictList() {
 	return getDictionaryByCode('appInnovationStatus').then(res => {
 		dictObj.value = res.data.data
-		
 	})
 }
-
 
 // 获取列表
 async function getList() {
@@ -182,4 +189,3 @@
 })
 </script>
 <style scoped lang="scss"></style>
-
diff --git a/applications/task-work-order/src/views/orderView/orderDataManage/dataObjection/index.vue b/applications/task-work-order/src/views/orderView/orderDataManage/dataObjection/index.vue
index ab4a763..e32abdf 100644
--- a/applications/task-work-order/src/views/orderView/orderDataManage/dataObjection/index.vue
+++ b/applications/task-work-order/src/views/orderView/orderDataManage/dataObjection/index.vue
@@ -2,12 +2,18 @@
 	<basic-container>
 		<el-form ref="queryParamsRef" :model="searchParams" class="gd-search-form">
 			<el-form-item label="异议标题" prop="title">
-				<el-input class="gd-input" v-model="searchParams.title" placeholder="请输入" clearable @clear="handleSearch" />
+				<el-input
+					class="gd-input gray"
+					v-model="searchParams.title"
+					placeholder="请输入"
+					clearable
+					@clear="handleSearch"
+				/>
 			</el-form-item>
 
 			<el-form-item label="异议状态" prop="objectionStatus">
 				<el-select
-					class="gd-select"
+					class="gd-select gray"
 					popper-class="gd-select-popper"
 					v-model="searchParams.objectionStatus"
 					placeholder="请选择"
@@ -31,17 +37,17 @@
 
 		<div class="gd-table-toolbar">
 			<el-button :icon="Plus" color="#4C34FF" type="primary" @click="openForm('add')">数据异议申请</el-button>
-<!--			-->
+			<!--			-->
 		</div>
 
 		<div class="gd-table-container" v-loading="loading">
 			<div class="gd-table-content gd-table-content-bg">
 				<el-table class="gd-table" :data="list">
-				<el-table-column label="序号" width="60">
-					<template v-slot="{ $index }">
-						{{ String($index + 1).padStart(2, '0') }}
-					</template>
-				</el-table-column>
+					<el-table-column label="序号" width="60">
+						<template v-slot="{ $index }">
+							{{ String($index + 1).padStart(2, '0') }}
+						</template>
+					</el-table-column>
 					<el-table-column prop="title" show-overflow-tooltip label="标题" />
 					<el-table-column prop="objectionType" show-overflow-tooltip label="异议类别">
 						<template v-slot="{ row }">
@@ -174,8 +180,6 @@
 	ElMessage.success('删除成功')
 	getList()
 }
-
-
 
 // 获取部门树
 function getDeptTreeFun() {
diff --git a/applications/task-work-order/src/views/orderView/orderDataManage/evaluate/index.vue b/applications/task-work-order/src/views/orderView/orderDataManage/evaluate/index.vue
index f5913f0..de01bab 100644
--- a/applications/task-work-order/src/views/orderView/orderDataManage/evaluate/index.vue
+++ b/applications/task-work-order/src/views/orderView/orderDataManage/evaluate/index.vue
@@ -2,12 +2,18 @@
 	<basic-container>
 		<el-form ref="queryParamsRef" :model="searchParams" class="gd-search-form">
 			<el-form-item label="标题" prop="title">
-				<el-input class="gd-input" v-model="searchParams.title" placeholder="请输入" clearable @clear="handleSearch" />
+				<el-input
+					class="gd-input gray"
+					v-model="searchParams.title"
+					placeholder="请输入"
+					clearable
+					@clear="handleSearch"
+				/>
 			</el-form-item>
 
 			<el-form-item label="是否解决" prop="isResolved">
 				<el-select
-					class="gd-select"
+					class="gd-select gray"
 					popper-class="gd-select-popper"
 					v-model="searchParams.isResolved"
 					placeholder="请选择"
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 ebf589c..cc0df97 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
@@ -3,7 +3,7 @@
 		<el-form ref="queryParamsRef" :model="searchParams" class="gd-search-form">
 			<el-form-item label="需求名称" prop="demandName">
 				<el-input
-					class="gd-input"
+					class="gd-input gray"
 					v-model="searchParams.demandName"
 					placeholder="请输入"
 					clearable
@@ -13,7 +13,7 @@
 
 			<el-form-item label="需求状态" prop="demandStatus">
 				<el-select
-					class="gd-select"
+					class="gd-select gray"
 					popper-class="gd-select-popper"
 					v-model="searchParams.demandStatus"
 					placeholder="请选择"
@@ -43,10 +43,10 @@
 			<div class="gd-table-content gd-table-content-bg">
 				<el-table class="gd-table" :data="list">
 					<el-table-column label="序号" width="60" align="center">
-				<template #default="scope">
-					{{ ((searchParams.current - 1) * searchParams.size + scope.$index + 1).toString().padStart(2, '0') }}
-				</template>
-			</el-table-column>
+						<template #default="scope">
+							{{ ((searchParams.current - 1) * searchParams.size + scope.$index + 1).toString().padStart(2, '0') }}
+						</template>
+					</el-table-column>
 					<el-table-column prop="demandName" show-overflow-tooltip label="需求名称" />
 					<el-table-column prop="demandType" show-overflow-tooltip label="需求类型">
 						<template v-slot="{ row }">
@@ -78,11 +78,11 @@
 					<el-table-column prop="demandInfo" show-overflow-tooltip label="需求信息项" />
 					<el-table-column label="操作" class-name="operation-btns" width="180">
 						<template v-slot="{ row }">
-					<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-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>
@@ -175,7 +175,7 @@
 		// 为每条记录添加部门名称
 		list.value = records.map(item => ({
 			...item,
-			responsibleDeptName: item.responsibleDeptName || getDeptNameById(item.responsibleDeptId, deptTree.value)
+			responsibleDeptName: item.responsibleDeptName || getDeptNameById(item.responsibleDeptId, deptTree.value),
 		}))
 		total.value = res?.data?.data?.total ?? 0
 	} finally {
@@ -234,8 +234,6 @@
 	ElMessage.success('删除成功')
 	getList()
 }
-
-
 
 // 获取字典
 function getDictList() {
diff --git a/applications/task-work-order/src/views/orderView/orderManage/clueEvents/index.vue b/applications/task-work-order/src/views/orderView/orderManage/clueEvents/index.vue
index 3d4e94a..8402090 100644
--- a/applications/task-work-order/src/views/orderView/orderManage/clueEvents/index.vue
+++ b/applications/task-work-order/src/views/orderView/orderManage/clueEvents/index.vue
@@ -4,7 +4,7 @@
 		<el-form ref="queryParamsRef" :model="searchParams" class="gd-search-form">
 			<el-form-item label="模糊搜索" prop="patrolTaskName">
 				<el-input
-					class="gd-input"
+					class="gd-input gray"
 					v-model="searchParams.patrolTaskName"
 					placeholder="请输入"
 					clearable
@@ -14,7 +14,7 @@
 
 			<el-form-item label="巡查任务类型" prop="patrolTaskType">
 				<el-select
-					class="gd-select"
+					class="gd-select gray"
 					popper-class="gd-select-popper"
 					v-model="searchParams.patrolTaskType"
 					placeholder="请选择"
@@ -50,7 +50,7 @@
 
 			<el-form-item label="执行时间" prop="executeTime">
 				<el-date-picker
-					class="gd-date-picker"
+					class="gd-date-picker gray"
 					popper-class="gd-date-picker-popper"
 					v-model="dateRange"
 					type="daterange"
diff --git a/applications/task-work-order/src/views/orderView/orderManage/inspectionReport/index.vue b/applications/task-work-order/src/views/orderView/orderManage/inspectionReport/index.vue
index 49d5005..3e3cfb9 100644
--- a/applications/task-work-order/src/views/orderView/orderManage/inspectionReport/index.vue
+++ b/applications/task-work-order/src/views/orderView/orderManage/inspectionReport/index.vue
@@ -1,10 +1,10 @@
 <!-- 巡查报告管理 -->
 <template>
-  <basic-container>
-    <el-form ref="queryParamsRef" :model="searchParams" class="gd-search-form">
+	<basic-container>
+		<el-form ref="queryParamsRef" :model="searchParams" class="gd-search-form">
 			<el-form-item label="模糊搜索" prop="nickName">
 				<el-input
-					class="gd-input"
+					class="gd-input gray"
 					v-model="searchParams.nickName"
 					placeholder="请输入"
 					clearable
@@ -14,7 +14,7 @@
 
 			<el-form-item label="文档类型" prop="resultType">
 				<el-select
-					class="gd-select"
+					class="gd-select gray"
 					popper-class="gd-select-popper"
 					v-model="searchParams.resultType"
 					placeholder="请选择"
@@ -37,11 +37,11 @@
 		</el-form>
 
 		<div class="gd-table-toolbar">
-      <el-button :icon="Download" color="#4C34FF" type="primary" @click="handleDownload">文档下载</el-button>
+			<el-button :icon="Download" color="#4C34FF" type="primary" @click="handleDownload">文档下载</el-button>
 			<el-button :icon="Upload" color="#4C34FF" type="primary" @click="handleUpload">文档上传</el-button>
 		</div>
 
-    <div class="gd-table-container" v-loading="loading">
+		<div class="gd-table-container" v-loading="loading">
 			<div class="gd-table-content gd-table-content-bg">
 				<el-table class="gd-table" :data="list" @selection-change="handleSelectionChange">
 					<el-table-column type="selection" width="46" />
@@ -50,7 +50,7 @@
 					<el-table-column prop="attachSize" show-overflow-tooltip label="文档大小" />
 					<el-table-column prop="deptName" show-overflow-tooltip label="文档归属" />
 					<!-- <el-table-column prop="resultType" show-overflow-tooltip label="文档类型" /> -->
-					 <el-table-column prop="resultType" show-overflow-tooltip label="文档类型">
+					<el-table-column prop="resultType" show-overflow-tooltip label="文档类型">
 						<template v-slot="{ row }">
 							{{ getDictLabel(row.resultType, dictObj.patrolTaskType) }}
 						</template>
@@ -76,71 +76,80 @@
 				/>
 			</div>
 		</div>
-    <el-dialog class="gd-dialog" append-to-body v-model="isShowEditView" :title="titleTxt"
-		:width="pxToRem(800)" :close-on-click-modal="false" :destroy-on-close="true" @close="handleClose">
-      <el-form class="gd-dialog-form" ref="ruleFormRef" :model="editParams" :rules="rules" label-width="140px">
-        <el-form-item label="文档名称" prop="nickName">
-          <el-input v-model="editParams.nickName" />
-        </el-form-item>
-        <el-form-item label="文档类型" prop="resultType" v-if="titleTxt === '上传巡查报告'">
-          <el-select
-					class="gd-select"
-					popper-class="gd-select-popper"
-					v-model="editParams.resultType"
-					placeholder="请选择"
-					clearable
+		<el-dialog
+			class="gd-dialog"
+			append-to-body
+			v-model="isShowEditView"
+			:title="titleTxt"
+			:width="pxToRem(800)"
+			:close-on-click-modal="false"
+			:destroy-on-close="true"
+			@close="handleClose"
+		>
+			<el-form class="gd-dialog-form" ref="ruleFormRef" :model="editParams" :rules="rules" label-width="140px">
+				<el-form-item label="文档名称" prop="nickName">
+					<el-input v-model="editParams.nickName" class="gd-input" placeholder="请输入" />
+				</el-form-item>
+				<el-form-item label="文档类型" prop="resultType" v-if="titleTxt === '上传巡查报告'">
+					<el-select
+						class="gd-select"
+						popper-class="gd-select-popper"
+						v-model="editParams.resultType"
+						placeholder="请选择"
+						clearable
+					>
+						<el-option
+							v-for="item in dictObj.patrolTaskType"
+							:key="item.dictKey"
+							:label="item.dictValue"
+							:value="item.dictKey"
+						/>
+					</el-select>
+				</el-form-item>
+				<el-form-item label="上传文件" prop="link" v-if="titleTxt === '上传巡查报告'">
+					{{ uploadName }}
+					<el-upload class="avatar-uploader" action="" :show-file-list="false" :before-upload="onUploadFileBefore">
+						<el-button size="small" type="primary">点击上传</el-button>
+					</el-upload>
+				</el-form-item>
+			</el-form>
+			<!-- </div> -->
+			<template #footer>
+				<el-button color="#F2F3F5" @click="isShowEditView = false">取消</el-button>
+				<el-button
+					class="save-btn"
+					color="#4C34FF"
+					:loading="submitting"
+					:disabled="submitting"
+					@click="submit(ruleFormRef)"
 				>
-					<el-option
-						v-for="item in dictObj.patrolTaskType"
-						:key="item.dictKey"
-						:label="item.dictValue"
-						:value="item.dictKey"
-					/>
-				</el-select>
-        </el-form-item>
-        <el-form-item label="上传文件" prop="link" v-if="titleTxt === '上传巡查报告'">
-			{{ uploadName }}
-          <el-upload
-            class="avatar-uploader"
-            action=""
-            :show-file-list="false"
-            :before-upload="onUploadFileBefore"
-          >
-            <el-button size="small" type="primary">点击上传</el-button>
-          </el-upload>
-        </el-form-item>
-      </el-form>
-    <!-- </div> -->
-     <template #footer>
-			<el-button color="#F2F3F5" @click="isShowEditView = false">取消</el-button>
-			<el-button class="save-btn" color="#4C34FF" :loading="submitting" :disabled="submitting" @click="submit(ruleFormRef)">
-				保存
-			</el-button>
-		</template>
-	</el-dialog>
-	<PreviewFiles v-model="previewVisible" :src="searchUrl" type="docx"/>
-	<!-- <el-image v-if="previewVisibleImg" :src="searchUrl" fit="contain" style="height: 100%;width: 100%" /> -->
-	 <el-image-viewer
-      v-if="previewVisibleImg"
-      :url-list="[searchUrl]"
-      @close="previewVisibleImg = false"
-    ></el-image-viewer>
-  </basic-container>
+					保存
+				</el-button>
+			</template>
+		</el-dialog>
+		<PreviewFiles v-model="previewVisible" :src="searchUrl" type="docx" />
+		<!-- <el-image v-if="previewVisibleImg" :src="searchUrl" fit="contain" style="height: 100%;width: 100%" /> -->
+		<el-image-viewer
+			v-if="previewVisibleImg"
+			:url-list="[searchUrl]"
+			@close="previewVisibleImg = false"
+		></el-image-viewer>
+	</basic-container>
 </template>
 <script setup>
-  import { Search, RefreshRight, Download, Upload, Delete } from '@element-plus/icons-vue'
-  import { fjPageApi, fjSubmitApi, fjRemoveApi, fjDetailApi, fjUploadApi } from './inspectionRequestApi'
-  import { useStore } from 'vuex'
-  import { ref, computed, inject, onMounted } from 'vue'
-  import { ElMessage, ElMessageBox } from 'element-plus'
-  import { getDictLabel } from '@ztzf/utils'
-  import PreviewFiles from '@/components/PreviewFiles/PreviewFiles.vue'
-  import { getDictionaryByCode } from '@/api/system/dictbiz'
+import { Search, RefreshRight, Download, Upload, Delete } from '@element-plus/icons-vue'
+import { fjPageApi, fjSubmitApi, fjRemoveApi, fjDetailApi, fjUploadApi } from './inspectionRequestApi'
+import { useStore } from 'vuex'
+import { ref, computed, inject, onMounted } from 'vue'
+import { ElMessage, ElMessageBox } from 'element-plus'
+import { getDictLabel } from '@ztzf/utils'
+import PreviewFiles from '@/components/PreviewFiles/PreviewFiles.vue'
+import { getDictionaryByCode } from '@/api/system/dictbiz'
 
-  const store = useStore()
-  const userInfo = computed(() => store.getters.userInfo);
+const store = useStore()
+const userInfo = computed(() => store.getters.userInfo)
 
-  // 初始化查询参数
+// 初始化查询参数
 const initSearchParams = () => ({
 	nickName: '',
 	resultType: '',
@@ -171,17 +180,17 @@
 const isShowEditView = ref(false)
 const titleTxt = ref('上传巡查报告')
 const editParams = ref({
-  id:'',
-  nickName: '',
-  resultType: '',
-  link: '',
+	id: '',
+	nickName: '',
+	resultType: '',
+	link: '',
 })
 const ruleFormRef = ref()
 const submitting = ref(false)
 const rules = ref({
-  nickName: [{ required: true, message: '请输入文档名称', trigger: ['blur'] }],
-  resultType: [{ required: true, message: '请选择文档类型', trigger: ['change'] }],
-  link: [{ required: true, message: '请上传文件', trigger: ['change'] }],
+	nickName: [{ required: true, message: '请输入文档名称', trigger: ['blur'] }],
+	resultType: [{ required: true, message: '请选择文档类型', trigger: ['change'] }],
+	link: [{ required: true, message: '请上传文件', trigger: ['change'] }],
 })
 
 // 获取字典
@@ -191,7 +200,7 @@
 	})
 }
 
-  // 获取列表
+// 获取列表
 async function getList() {
 	loading.value = true
 	try {
@@ -219,7 +228,7 @@
 // 新增/编辑/查看 弹框
 function openForm(row) {
 	isShowEditView.value = true
-  	titleTxt.value = '编辑'
+	titleTxt.value = '编辑'
 	editParams.value.id = row.id
 	editParams.value.nickName = row.nickName
 	editParams.value.resultType = row.resultType
@@ -233,7 +242,12 @@
 	if (!row.link) {
 		ElMessage.warning('文件链接不存在')
 		return
-	} else if (!row.link.includes('docx') && !row.link.includes('pdf') && !row.link.includes('png') && !row.link.includes('jpg')) {
+	} else if (
+		!row.link.includes('docx') &&
+		!row.link.includes('pdf') &&
+		!row.link.includes('png') &&
+		!row.link.includes('jpg')
+	) {
 		ElMessage.warning(`${fileType}文件格式,可以下载再查看`)
 		return
 	} else if (row.link.includes('png') || row.link.includes('jpg')) {
@@ -266,7 +280,7 @@
 // 勾选值设置
 function handleSelectionChange(rows) {
 	selectedFiles.value = rows
-	selectedIds.value = rows.map((item) => item.id)
+	selectedIds.value = rows.map(item => item.id)
 }
 
 // 文档下载
@@ -289,69 +303,66 @@
 			}
 		}, index * 300) // 300ms delay between downloads
 	})
-
 }
 
 // 文档上传
 async function handleUpload() {
 	isShowEditView.value = true
-  	titleTxt.value = '上传巡查报告'
+	titleTxt.value = '上传巡查报告'
 }
 
 // 上传文件前处理
 function onUploadFileBefore(file) {
-  // 执行文件上传
-  let data = new FormData();
-  data.append('file', file);
-  
-  fjUploadApi(data).then(res => {
-    if (res.data.code === 200) {
-      ElMessage.success('上传成功')
-      // 保存文件URL到表单
-	  uploadName.value = res.data.data.originalName
-      editParams.value.link = res.data.data.link
-    } else {
-      ElMessage.error(res.msg || '上传失败')
-    }
-  })
-  
-  return false // 阻止组件的默认上传行为
+	// 执行文件上传
+	let data = new FormData()
+	data.append('file', file)
+
+	fjUploadApi(data).then(res => {
+		if (res.data.code === 200) {
+			ElMessage.success('上传成功')
+			// 保存文件URL到表单
+			uploadName.value = res.data.data.originalName
+			editParams.value.link = res.data.data.link
+		} else {
+			ElMessage.error(res.msg || '上传失败')
+		}
+	})
+
+	return false // 阻止组件的默认上传行为
 }
 
 // 保存上传文件数据
 async function submit(formValidate) {
-  if (!formValidate) return
-  await formValidate.validate(async (valid, fields) => {
-    if (valid) {
-      submitting.value = true
-      try {
-         await fjSubmitApi({ ...editParams.value })
-          ElMessage.success('保存成功')
-          isShowEditView.value = false
-		  getList()
-      } finally {
-        submitting.value = false
-      }
-    }
-  })
+	if (!formValidate) return
+	await formValidate.validate(async (valid, fields) => {
+		if (valid) {
+			submitting.value = true
+			try {
+				await fjSubmitApi({ ...editParams.value })
+				ElMessage.success('保存成功')
+				isShowEditView.value = false
+				getList()
+			} finally {
+				submitting.value = false
+			}
+		}
+	})
 }
 
 function handleClose() {
-  // 清除表单内容
-  uploadName.value = ''
-  editParams.value = {
-    id: '',
-    nickName: '',
-    resultType: '',
-    uploadFile: '',
-  }
+	// 清除表单内容
+	uploadName.value = ''
+	editParams.value = {
+		id: '',
+		nickName: '',
+		resultType: '',
+		uploadFile: '',
+	}
 }
 
 onMounted(() => {
 	getDictList()
 	getList()
 })
-
 </script>
-<style scoped lang="scss">
-</style>
+<style scoped lang="scss"></style>
diff --git a/applications/task-work-order/src/views/orderView/orderManage/inspectionRequest/FormDiaLog.vue b/applications/task-work-order/src/views/orderView/orderManage/inspectionRequest/FormDiaLog.vue
index d19aed6..98916f3 100644
--- a/applications/task-work-order/src/views/orderView/orderManage/inspectionRequest/FormDiaLog.vue
+++ b/applications/task-work-order/src/views/orderView/orderManage/inspectionRequest/FormDiaLog.vue
@@ -212,7 +212,7 @@
 	deviceId: null,
 	taskDesc: '',
 })
-
+// todo 时间线
 const dictObj = inject('dictObj')
 
 const emit = defineEmits(['success'])
diff --git a/applications/task-work-order/src/views/orderView/orderManage/inspectionRequest/ViewDiaLog.vue b/applications/task-work-order/src/views/orderView/orderManage/inspectionRequest/ViewDiaLog.vue
index 459e42c..f9d1d67 100644
--- a/applications/task-work-order/src/views/orderView/orderManage/inspectionRequest/ViewDiaLog.vue
+++ b/applications/task-work-order/src/views/orderView/orderManage/inspectionRequest/ViewDiaLog.vue
@@ -4,7 +4,6 @@
 		v-model="visible"
 		:title="titleEnum[dialogMode]"
 		@closed="visible = false"
-		:style="{ width: pxToRem(1216) }"
 		destroy-on-close
 		:close-on-click-modal="false"
 	>
@@ -12,6 +11,7 @@
 			<div class="leftBox">
 				<!-- 查看模式 -->
 				<div class="detail-container" v-if="dialogReadonly">
+					<div class="detail-title">工单详情</div>
 					<el-row class="detail-row-view">
 						<el-col :span="12">
 							<div class="label">巡查任务名称</div>
@@ -47,15 +47,14 @@
 						</el-col>
 					</el-row>
 					<template v-if="['6', '7', '8'].includes(taskStatus)">
-						<div>任务成功({{ list.length || 0 }}条)</div>
-						<div style="display: flex">
+						<div class="detail-title" :style="{ marginTop: pxToRem(10) }">任务成功({{ list.length || 0 }}条)</div>
+						<div class="imgBox">
 							<div v-for="item in list">
 								<el-image
 									v-if="item.resultUrl"
 									:src="item.resultUrl"
 									:preview-src-list="[item.resultUrl]"
 									fit="cover"
-									style="width: 80px; height: 60px"
 									preview-teleported
 								/>
 							</div>
@@ -149,7 +148,14 @@
 						</el-col>
 						<el-col :span="24">
 							<el-form-item label="巡查任务描述" prop="taskDesc">
-								<el-input class="gd-input" type="textarea" :rows="4" v-model="formData.taskDesc" placeholder="请输入" clearable />
+								<el-input
+									class="gd-input"
+									type="textarea"
+									:rows="4"
+									v-model="formData.taskDesc"
+									placeholder="请输入"
+									clearable
+								/>
 							</el-form-item>
 						</el-col>
 					</el-row>
@@ -158,13 +164,14 @@
 				<!-- 地图组件 -->
 				<CommonCesiumMap
 					ref="mapRef"
-					class="leftMap gd-cesium"
+					class="gd-cesium"
 					:active="visible"
 					:flat-mode="false"
 					:terrain="true"
 					:layer-mode="4"
 					:boundary="false"
 					:zoomToBoundary="false"
+					@ready="() => mapRef.flyBoundary()"
 				/>
 			</div>
 		</div>
@@ -414,12 +421,27 @@
 	display: flex;
 	gap: 0 20px;
 	.leftBox {
-		width: 0;
-		flex: 1;
+		width: 920px;
 		.gd-cesium {
+			padding-top: 10px;
 			width: 100%;
 			height: 423px;
 		}
 	}
+
+	.imgBox {
+		display: flex;
+		flex-wrap: wrap;
+		gap: 10px;
+		> div {
+			width: calc((100% - 40px) / 5); /* 5列布局,减去4个10px间隙 */
+			height: 110px;
+			flex-shrink: 0;
+		}
+		.el-image {
+			width: 100%;
+			height: 100%;
+		}
+	}
 }
 </style>
diff --git a/applications/task-work-order/src/views/orderView/orderManage/inspectionRequest/index.vue b/applications/task-work-order/src/views/orderView/orderManage/inspectionRequest/index.vue
index b3eaa32..6d64be5 100644
--- a/applications/task-work-order/src/views/orderView/orderManage/inspectionRequest/index.vue
+++ b/applications/task-work-order/src/views/orderView/orderManage/inspectionRequest/index.vue
@@ -2,12 +2,12 @@
 	<basic-container>
 		<el-tabs class="gd-tabs" v-model="activeName" @tab-click="tabsClick">
 			<el-tab-pane label="全部 " name="all"></el-tab-pane>
-			<el-tab-pane label="我的任务工单" name="my"></el-tab-pane>
+			<el-tab-pane label="我的巡查任务" name="my"></el-tab-pane>
 		</el-tabs>
 		<el-form ref="queryParamsRef" :model="searchParams" class="gd-search-form">
 			<el-form-item label="任务名称" prop="patrolTaskName">
 				<el-input
-					class="gd-input"
+					class="gd-input gray"
 					v-model="searchParams.patrolTaskName"
 					placeholder="请输入"
 					clearable
@@ -17,7 +17,7 @@
 
 			<el-form-item label="任务类型" prop="patrolTaskType">
 				<el-select
-					class="gd-select"
+					class="gd-select gray"
 					popper-class="gd-select-popper"
 					v-model="searchParams.patrolTaskType"
 					placeholder="请选择"
@@ -35,7 +35,7 @@
 
 			<el-form-item label="任务状态" prop="taskStatus">
 				<el-select
-					class="gd-select"
+					class="gd-select gray"
 					popper-class="gd-select-popper"
 					v-model="searchParams.taskStatus"
 					placeholder="请选择"
@@ -53,7 +53,7 @@
 
 			<el-form-item label="执行时间" prop="executeTime">
 				<el-date-picker
-					class="gd-date-picker"
+					class="gd-date-picker gray"
 					popper-class="gd-date-picker-popper"
 					v-model="dateRange"
 					type="daterange"
@@ -118,7 +118,13 @@
 		</div>
 
 		<FormDiaLog ref="dialogRef" @success="getList" v-if="dialogVisible" v-model="dialogVisible" />
-		<ViewDiaLog ref="viewDiaLogRef" @success="getList" @refusalAccept="refusalAccept" v-if="viewDiaLogVisible" v-model="viewDiaLogVisible" />
+		<ViewDiaLog
+			ref="viewDiaLogRef"
+			@success="getList"
+			@refusalAccept="refusalAccept"
+			v-if="viewDiaLogVisible"
+			v-model="viewDiaLogVisible"
+		/>
 	</basic-container>
 </template>
 <script setup>
@@ -236,7 +242,7 @@
 function refusalAccept(row) {
 	dialogVisible.value = true
 	nextTick(() => {
-		dialogRef.value?.open({ mode:'edit', row })
+		dialogRef.value?.open({ mode: 'edit', row })
 	})
 }
 
diff --git a/applications/task-work-order/src/views/orderView/orderManage/operatingIncome/index.vue b/applications/task-work-order/src/views/orderView/orderManage/operatingIncome/index.vue
index a616d31..52abda1 100644
--- a/applications/task-work-order/src/views/orderView/orderManage/operatingIncome/index.vue
+++ b/applications/task-work-order/src/views/orderView/orderManage/operatingIncome/index.vue
@@ -41,19 +41,19 @@
 		:width="pxToRem(800)" :close-on-click-modal="false" :destroy-on-close="true" @close="handleClose">
       <el-form class="gd-dialog-form" ref="ruleFormRef" :model="editParams" :rules="rules" label-width="140px">
         <el-form-item label="营业收入" prop="operatingIncome">
-          <el-input v-model="editParams.operatingIncome" />
+          <el-input class="gd-input" v-model="editParams.operatingIncome" />
         </el-form-item>
         <el-form-item label="综合总成本费用" prop="totalCost">
-          <el-input v-model="editParams.totalCost" />
+          <el-input class="gd-input" v-model="editParams.totalCost" />
         </el-form-item>
         <el-form-item label="净利润" prop="netProfit">
-          <el-input v-model="editParams.netProfit" />
+          <el-input class="gd-input" v-model="editParams.netProfit" />
         </el-form-item>
         <el-form-item label="财务内部收益率" prop="financialIrr">
-          <el-input v-model="editParams.financialIrr" />
+          <el-input class="gd-input" v-model="editParams.financialIrr" />
         </el-form-item>
         <el-form-item label="市场空间" prop="marketSpace">
-          <el-input v-model="editParams.marketSpace"  />
+          <el-input class="gd-input" v-model="editParams.marketSpace"  />
         </el-form-item>
       </el-form>
     <!-- </div> -->
diff --git a/applications/task-work-order/src/views/orderView/orderManage/orderManage/FormDiaLog.vue b/applications/task-work-order/src/views/orderView/orderManage/orderManage/FormDiaLog.vue
index 2b5ba57..47b6124 100644
--- a/applications/task-work-order/src/views/orderView/orderManage/orderManage/FormDiaLog.vue
+++ b/applications/task-work-order/src/views/orderView/orderManage/orderManage/FormDiaLog.vue
@@ -10,7 +10,7 @@
 	>
 		<div class="content" style="display: flex">
 			<div class="processBox" v-if="dialogMode !== 'add' && processList.length">
-				<el-timeline>
+				<el-timeline class="gd-timeline">
 					<el-timeline-item
 						v-for="(activity, index) in processList"
 						:key="index"
@@ -149,7 +149,14 @@
 						</el-col>
 						<el-col :span="24">
 							<el-form-item label="工单备注" prop="remark">
-								<el-input class="gd-input" type="textarea" :rows="4" v-model="formData.remark" placeholder="请输入" clearable />
+								<el-input
+									class="gd-input"
+									type="textarea"
+									:rows="4"
+									v-model="formData.remark"
+									placeholder="请输入"
+									clearable
+								/>
 							</el-form-item>
 						</el-col>
 					</el-row>
@@ -559,6 +566,7 @@
 	// setMapDevice()
 	await nextTick()
 	syncSelection()
+	getDeviceList()
 }
 
 // 初始化地图实例
@@ -603,21 +611,19 @@
 
 	.processBox {
 		width: 312px;
-		.el-timeline {
-			padding-left: 100px;
-		}
 		.item-content {
 			position: relative;
 			.flowName {
+				width: 80px;
 				position: absolute;
-				left: -100px;
-				top: 0;
+				left: -120px;
+				top: 0px;
 			}
 		}
 	}
 }
 
-.tipSelect{
+.tipSelect {
 	text-align: center;
 	height: 200px;
 	line-height: 200px;
diff --git a/applications/task-work-order/src/views/orderView/orderManage/orderManage/index.vue b/applications/task-work-order/src/views/orderView/orderManage/orderManage/index.vue
index df3b2c3..b7df2ad 100644
--- a/applications/task-work-order/src/views/orderView/orderManage/orderManage/index.vue
+++ b/applications/task-work-order/src/views/orderView/orderManage/orderManage/index.vue
@@ -7,7 +7,7 @@
 		<el-form ref="queryParamsRef" :model="searchParams" class="gd-search-form">
 			<el-form-item label="工单名称" prop="workOrderName">
 				<el-input
-					class="gd-input"
+					class="gd-input gray"
 					v-model="searchParams.workOrderName"
 					placeholder="请输入"
 					clearable
@@ -17,7 +17,7 @@
 
 			<el-form-item label="工单类型" prop="workOrderType">
 				<el-select
-					class="gd-select"
+					class="gd-select gray"
 					popper-class="gd-select-popper"
 					v-model="searchParams.workOrderType"
 					placeholder="请选择"
@@ -35,7 +35,7 @@
 
 			<el-form-item label="工单状态" prop="workOrderStatus">
 				<el-select
-					class="gd-select"
+					class="gd-select gray"
 					popper-class="gd-select-popper"
 					v-model="searchParams.workOrderStatus"
 					placeholder="请选择"
@@ -53,7 +53,7 @@
 
 			<el-form-item label="执行时间" prop="executeTime">
 				<el-date-picker
-					class="gd-date-picker"
+					class="gd-date-picker gray"
 					popper-class="gd-date-picker-popper"
 					v-model="dateRange"
 					type="daterange"

--
Gitblit v1.9.3