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

---
 applications/drone-command/src/store/modules/user.js                                |    2 
 applications/drone-command/src/styles/common.scss                                   |    1 
 applications/drone-command/src/styles/element-ui.scss                               |    8 +
 applications/drone-command/src/styles/sidebar.scss                                  |    2 
 applications/drone-command/src/views/api.txt                                        |    0 
 applications/drone-command/src/views/dataCockpit/components/DeviceHistoryDialog.vue |  285 +++++++++++++++++++++++++++++------------------
 applications/drone-command/src/views/aICrudTemplate/FormDiaLog.vue                  |   55 ++++----
 7 files changed, 211 insertions(+), 142 deletions(-)

diff --git a/applications/drone-command/src/store/modules/user.js b/applications/drone-command/src/store/modules/user.js
index 3950b41..3f6ba06 100644
--- a/applications/drone-command/src/store/modules/user.js
+++ b/applications/drone-command/src/store/modules/user.js
@@ -275,7 +275,7 @@
           const env = import.meta.env.VITE_APP_ENV
           const adminUrl = import.meta.env.VITE_APP_DASHBOARD_URL
           env === 'development'
-            ? window.location.href = "/manage/login"
+            ? window.location.href = "/drone-command/login"
             : window.location.replace(`${adminUrl}#/login`)
         })
       }
diff --git a/applications/drone-command/src/styles/common.scss b/applications/drone-command/src/styles/common.scss
index 6f734ad..7172f8e 100644
--- a/applications/drone-command/src/styles/common.scss
+++ b/applications/drone-command/src/styles/common.scss
@@ -71,6 +71,7 @@
     padding-top: 109px;
     width: 160px;
     height: 100%;
+    box-sizing: border-box;
 
     .avue-sidebar {
 
diff --git a/applications/drone-command/src/styles/element-ui.scss b/applications/drone-command/src/styles/element-ui.scss
index bcea1e1..8dc06ed 100644
--- a/applications/drone-command/src/styles/element-ui.scss
+++ b/applications/drone-command/src/styles/element-ui.scss
@@ -1019,4 +1019,12 @@
             }
         }
     }
+}
+
+.ztzf-data-cockpit-dialog {
+    width: 1222px;
+    height: 835px;
+    background: #1A1A2A;
+    border-radius: 6px 6px 6px 6px;
+    border: 1px solid #2E2E46;
 }
\ No newline at end of file
diff --git a/applications/drone-command/src/styles/sidebar.scss b/applications/drone-command/src/styles/sidebar.scss
index 2b39cc4..7732087 100644
--- a/applications/drone-command/src/styles/sidebar.scss
+++ b/applications/drone-command/src/styles/sidebar.scss
@@ -17,7 +17,7 @@
   }
 
   .avue-menu {
-    height: calc(100% - #{$top_height});
+    height: calc(100% - 42px);
   }
 
   &--tip {
diff --git a/applications/drone-command/src/views/aICrudTemplate/FormDiaLog.vue b/applications/drone-command/src/views/aICrudTemplate/FormDiaLog.vue
index a323631..0190b96 100644
--- a/applications/drone-command/src/views/aICrudTemplate/FormDiaLog.vue
+++ b/applications/drone-command/src/views/aICrudTemplate/FormDiaLog.vue
@@ -1,6 +1,31 @@
 <template>
 	<el-dialog v-model="visible" :title="dialogTitle" @closed="handleClosed" destroy-on-close>
-		<el-form ref="formRef" :model="formData" :rules="rules" :disabled="dialogReadonly" label-width="100px">
+		<div v-if="dialogReadonly">
+			<el-row>
+				<el-col :span="12">
+					<div>设备信息: {{ formData.deviceName }}</div>
+				</el-col>
+				<el-col :span="12">
+					<div>设备类型: {{ formData.deviceType }}</div>
+				</el-col>
+				<el-col :span="12">
+					<div>设备属性: {{ formData.deviceAtt }}</div>
+				</el-col>
+				<el-col :span="12">
+					<div>型号: {{ formData.deviceModel }}</div>
+				</el-col>
+				<el-col :span="12">
+					<div>所属部门: {{ formData.belongDept }}</div>
+				</el-col>
+				<el-col :span="12">
+					<div>负责人: {{ formData.charger }}</div>
+				</el-col>
+				<el-col :span="12">
+					<div>联系电话: {{ formData.contactPhone }}</div>
+				</el-col>
+			</el-row>
+		</div>
+		<el-form v-else ref="formRef" :model="formData" :rules="rules" :disabled="dialogReadonly" label-width="100px">
 			<el-row>
 				<el-col :span="12">
 					<el-form-item label="设备名称" prop="deviceName">
@@ -34,26 +59,6 @@
 				<el-col :span="12">
 					<el-form-item label="型号" prop="deviceModel">
 						<el-input v-model="formData.deviceModel" maxlength="50" placeholder="请输入" clearable />
-					</el-form-item>
-				</el-col>
-				<el-col :span="12">
-					<el-form-item label="规格" prop="deviceSpecification">
-						<el-input v-model="formData.deviceSpecification" maxlength="50" placeholder="请输入" clearable />
-					</el-form-item>
-				</el-col>
-				<el-col :span="12">
-					<el-form-item label="生产厂商" prop="manufacturer">
-						<el-input v-model="formData.manufacturer" maxlength="50" placeholder="请输入" clearable />
-					</el-form-item>
-				</el-col>
-				<el-col :span="12">
-					<el-form-item label="来源" prop="source">
-						<el-input v-model="formData.source" maxlength="50" placeholder="请输入" clearable />
-					</el-form-item>
-				</el-col>
-				<el-col :span="12">
-					<el-form-item label="用途" prop="purpose">
-						<el-input v-model="formData.purpose" maxlength="50" placeholder="请输入" clearable />
 					</el-form-item>
 				</el-col>
 				<el-col :span="12">
@@ -112,11 +117,7 @@
 	deviceAtt: '', // 设备属性
 	deviceType: '', // 设备类型
 	deviceModel: '', // 型号
-	deviceSpecification: '', // 规格
 	deviceName: '', // 设备名称
-	manufacturer: '', // 生产厂商
-	purpose: '', // 用途
-	source: '', // 来源
 })
 const treeProps = {
 	label: 'name',
@@ -149,10 +150,6 @@
 	deviceType: fieldRules(true, 0),
 	deviceAtt: fieldRules(true, 0),
 	deviceModel: fieldRules(true, 50),
-	deviceSpecification: fieldRules(true, 50),
-	manufacturer: fieldRules(true, 50),
-	source: fieldRules(true, 50),
-	purpose: fieldRules(true, 50),
 	belongDept: fieldRules(true, 50),
 	contactPhone: fieldRules(true, 50),
 	charger: fieldRules(true, 0),
diff --git a/applications/drone-command/src/views/api.txt b/applications/drone-command/src/views/api.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/applications/drone-command/src/views/api.txt
diff --git a/applications/drone-command/src/views/dataCockpit/components/DeviceHistoryDialog.vue b/applications/drone-command/src/views/dataCockpit/components/DeviceHistoryDialog.vue
index 828427c..c9b0954 100644
--- a/applications/drone-command/src/views/dataCockpit/components/DeviceHistoryDialog.vue
+++ b/applications/drone-command/src/views/dataCockpit/components/DeviceHistoryDialog.vue
@@ -1,67 +1,94 @@
 <template>
 	<el-dialog
-		class="ztzf-dialog-mange data-cockpit-history-dialog"
+		class="ztzf-data-cockpit-dialog"
 		append-to-body
 		v-model="visibleModel"
 		:title="dialogTitle"
-		width="1100px"
 		:close-on-click-modal="false"
 		:destroy-on-close="true"
 	>
 		<div class="dialog-body">
-			<div class="device-summary">
-				<div class="item">
-					<span class="label">设备名称</span>
-					<span class="value">{{ device?.name || '反制设备名称' }}</span>
-				</div>
-				<div class="item">
-					<span class="label">类型</span>
-					<span class="value">{{ device?.type || '-' }}</span>
-				</div>
-				<div class="item">
-					<span class="label">厂商</span>
-					<span class="value">{{ device?.vendor || '-' }}</span>
-				</div>
-				<div class="item">
-					<span class="label">状态</span>
-					<span class="value">{{ device?.statusText || '-' }}</span>
-				</div>
-			</div>
+			<el-form ref="queryParamsRef" :model="searchParams" class="history-search">
+				<el-row :gutter="12">
+					<el-col :span="5">
+						<el-form-item label="关键字" prop="keyword">
+							<el-input v-model="searchParams.keyword" placeholder="名称/序列号" clearable @clear="handleSearch" />
+						</el-form-item>
+					</el-col>
+					<el-col :span="5">
+						<el-form-item label="日期" prop="dateRange">
+							<el-date-picker
+								v-model="searchParams.dateRange"
+								type="daterange"
+								range-separator="至"
+								start-placeholder="开始日期"
+								end-placeholder="结束日期"
+								value-format="YYYY/MM/DD"
+								@change="handleSearch"
+							/>
+						</el-form-item>
+					</el-col>
+					<el-col :span="5">
+						<el-form-item label="区域" prop="area">
+							<el-tree-select
+								v-model="searchParams.area"
+								:data="areaTree"
+								:props="areaTreeProps"
+								node-key="value"
+								check-strictly
+								clearable
+								placeholder="请选择"
+								@change="handleSearch"
+							/>
+						</el-form-item>
+					</el-col>
+					<el-col :span="5">
+						<el-form-item label="无人机类型" prop="droneType">
+							<el-select
+								v-model="searchParams.droneType"
+								placeholder="请选择"
+								clearable
+								@change="handleSearch"
+							>
+								<el-option v-for="item in droneTypeOptions" :key="item" :label="item" :value="item" />
+							</el-select>
+						</el-form-item>
+					</el-col>
+					<el-col :span="4" class="history-search-actions">
+						<el-form-item>
+							<el-button @click="resetForm">重置</el-button>
+							<el-button type="primary" @click="handleSearch">查询</el-button>
+						</el-form-item>
+					</el-col>
+				</el-row>
+			</el-form>
 
-			<div class="table">
-				<div class="thead">
-					<div class="cell index">序号</div>
-					<div class="cell">无人机名称</div>
-					<div class="cell">无人机序列号</div>
-					<div class="cell">无人机类型</div>
-					<div class="cell">区域</div>
-					<div class="cell">数据来源</div>
-					<div class="cell">信号频段</div>
-					<div class="cell">发现时间</div>
-					<div class="cell">停留时间</div>
-					<div class="cell">反制方式</div>
-				</div>
-				<div class="tbody">
-					<div class="tr" v-for="(row, index) in historyList" :key="row.id">
-						<div class="cell index">{{ index + 1 }}</div>
-						<div class="cell">{{ row.droneName }}</div>
-						<div class="cell">{{ row.serialNumber }}</div>
-						<div class="cell">{{ row.droneType }}</div>
-						<div class="cell">{{ row.area }}</div>
-						<div class="cell">{{ row.dataSource }}</div>
-						<div class="cell">{{ row.frequency }}</div>
-						<div class="cell">{{ row.discoveredAt }}</div>
-						<div class="cell">{{ row.stayTime }}</div>
-						<div class="cell">{{ row.counterMethod }}</div>
-					</div>
-				</div>
+			<el-table v-loading="loading" :data="pagedList" height="360" class="history-table">
+				<el-table-column type="index" width="60" label="序号" />
+				<el-table-column prop="droneName" label="无人机名称" min-width="120" />
+				<el-table-column prop="serialNumber" label="无人机序列号" min-width="140" />
+				<el-table-column prop="droneType" label="无人机类型" min-width="110" />
+				<el-table-column prop="area" label="区域" min-width="90" />
+				<el-table-column prop="dataSource" label="数据来源" min-width="110" />
+				<el-table-column prop="frequency" label="信号频段" min-width="100" />
+				<el-table-column prop="discoveredAt" label="发现时间" min-width="150" />
+				<el-table-column prop="stayTime" label="停留时间" min-width="110" />
+				<el-table-column prop="counterMethod" label="反制方式" min-width="110" />
+			</el-table>
+
+			<div class="history-pagination">
+				<el-pagination
+					v-model:current-page="searchParams.current"
+					v-model:page-size="searchParams.size"
+					:total="total"
+				/>
 			</div>
 		</div>
 	</el-dialog>
 </template>
 
 <script setup>
-import { computed } from 'vue'
+import { computed, ref } from 'vue'
 
 const props = defineProps({
 	modelValue: {
@@ -84,6 +111,36 @@
 const dialogTitle = computed(() => {
 	return `反制设备名称 ${props.device?.name || ''}`.trim()
 })
+
+const initSearchParams = () => ({
+	keyword: '',
+	dateRange: [],
+	area: '',
+	droneType: '',
+	current: 1,
+	size: 6
+})
+const searchParams = ref(initSearchParams())
+const queryParamsRef = ref(null)
+const loading = ref(false)
+const areaTree = ref([
+	{
+		label: '古村区',
+		value: '古村区'
+	},
+	{
+		label: '新区',
+		value: '新区'
+	},
+	{
+		label: '产业园',
+		value: '产业园'
+	}
+])
+const areaTreeProps = {
+	label: 'label',
+	children: 'children'
+}
 
 const historyList = computed(() => {
 	const dataSource = props.device?.name || '侦测反制设备名称'
@@ -162,6 +219,50 @@
 		}
 	]
 })
+
+const droneTypeOptions = computed(() => {
+	const types = historyList.value.map((item) => item.droneType).filter(Boolean)
+	return Array.from(new Set(types))
+})
+
+const filteredList = computed(() => {
+	const { keyword, dateRange, area, droneType } = searchParams.value
+	const [startDate, endDate] = dateRange || []
+	return historyList.value.filter((item) => {
+		const keywordMatch =
+			!keyword || item.droneName.includes(keyword) || item.serialNumber.includes(keyword)
+		const typeMatch = !droneType || item.droneType === droneType
+		const areaMatch = !area || item.area.includes(area)
+		const dateMatch =
+			!startDate || !endDate || isWithinDateRange(item.discoveredAt, startDate, endDate)
+		return keywordMatch && typeMatch && areaMatch && dateMatch
+	})
+})
+
+const total = computed(() => filteredList.value.length)
+
+const pagedList = computed(() => {
+	const { current, size } = searchParams.value
+	const start = (current - 1) * size
+	return filteredList.value.slice(start, start + size)
+})
+
+function handleSearch() {
+	searchParams.value.current = 1
+}
+
+function resetForm() {
+	queryParamsRef.value?.resetFields()
+	searchParams.value.current = 1
+}
+
+function isWithinDateRange(value, start, end) {
+	const dateValue = new Date(value)
+	const startDate = new Date(`${start} 00:00:00`)
+	const endDate = new Date(`${end} 23:59:59`)
+	return dateValue >= startDate && dateValue <= endDate
+}
+
 </script>
 
 <style lang="scss" scoped>
@@ -172,74 +273,36 @@
 	color: #C3C3DD;
 }
 
-.device-summary {
-	display: flex;
-	flex-wrap: wrap;
-	gap: 16px 24px;
-
-	.item {
-		display: flex;
-		align-items: center;
-		gap: 8px;
-		font-size: 14px;
-
-		.label {
-			color: #8B8BA7;
-		}
-
-		.value {
-			color: #FFFFFF;
-		}
-	}
-}
-
-.table {
-	border: 1px solid rgba(255, 255, 255, 0.1);
-	border-radius: 6px;
-	overflow: hidden;
-}
-
-.thead,
-.tr {
-	display: grid;
-	grid-template-columns: 60px 1.1fr 1.1fr 0.9fr 0.8fr 1.2fr 0.9fr 1.3fr 0.9fr 0.9fr;
-	align-items: center;
-}
-
-.thead {
-	background: rgba(20, 24, 48, 0.9);
-	color: #FFFFFF;
-	font-size: 13px;
-	height: 42px;
-	border-bottom: 1px solid rgba(255, 255, 255, 0.08);
-}
-
-.tbody {
-	max-height: 360px;
-	overflow-y: auto;
+.history-search {
+	padding: 8px 12px 4px;
 	background: rgba(10, 14, 34, 0.6);
+	border: 1px solid rgba(255, 255, 255, 0.08);
+	border-radius: 6px;
 }
 
-.tr {
-	font-size: 12px;
-	color: #C3C3DD;
-	height: 40px;
-	border-bottom: 1px solid rgba(255, 255, 255, 0.05);
-
-	&:nth-child(2n) {
-		background: rgba(255, 255, 255, 0.02);
-	}
+.history-search :deep(.el-date-editor),
+.history-search :deep(.el-select),
+.history-search :deep(.el-tree-select) {
+	width: 100%;
 }
 
-.cell {
-	padding: 0 10px;
-	white-space: nowrap;
-	overflow: hidden;
-	text-overflow: ellipsis;
+.history-search-actions :deep(.el-form-item__content) {
+	justify-content: flex-end;
+	gap: 8px;
+}
 
-	&.index {
-		text-align: center;
-		color: #86909C;
-	}
+.history-table {
+	margin-top: 8px;
+	--el-table-border-color: rgba(255, 255, 255, 0.08);
+	--el-table-header-bg-color: rgba(20, 24, 48, 0.9);
+	--el-table-row-hover-bg-color: rgba(255, 255, 255, 0.03);
+	--el-table-text-color: #C3C3DD;
+	--el-table-header-text-color: #FFFFFF;
+}
+
+.history-pagination {
+	display: flex;
+	justify-content: flex-end;
+	padding-top: 8px;
 }
 </style>

--
Gitblit v1.9.3