From c53aab006b9db28e62381dba4fca4d77ec3566b0 Mon Sep 17 00:00:00 2001
From: 罗广辉 <guanghui.luo@foxmail.com>
Date: Sat, 17 Jan 2026 15:36:07 +0800
Subject: [PATCH] Merge remote-tracking branch 'origin/master'
---
applications/drone-command/src/assets/images/dataCockpit/legend/drone.png | 0
applications/drone-command/src/assets/images/dataCockpit/legend/equipment.png | 0
applications/drone-command/src/utils/cesium/publicCesium.js | 2
applications/drone-command/src/assets/images/dataCockpit/legend/command-post.png | 0
applications/drone-command/src/assets/images/dataCockpit/map/equipment.png | 0
applications/drone-command/src/components/map-container/common-cesium-map.vue | 135 +++++++++++
applications/drone-command/src/views/dataCockpit/index.vue | 10
applications/drone-command/src/views/areaManage/defenseZone/FormDiaLog.vue | 42 ++
applications/drone-command/src/utils/cesium/adminBoundary.js | 88 +++++++
applications/drone-command/src/views/areaManage/partition/FormDiaLog.vue | 42 ++
applications/task-work-order/src/utils/cesium/publicCesium.js | 2
applications/drone-command/src/components/map-container/device-map-container.vue | 150 ++----------
applications/drone-command/src/assets/images/dataCockpit/map/command-post.png | 0
applications/drone-command/src/views/dataCockpit/components/LegendBar.vue | 108 +++++++++
applications/drone-command/src/views/areaManage/precinctInfo/FormDiaLog.vue | 30 +
applications/drone-command/src/views/detectionCountermeasure/detectionRange/DetectionRangeDialog.vue | 26 +
applications/drone-command/src/views/areaManage/sceneConfig/FormDiaLog.vue | 37 +-
applications/mobile-web-view/src/hooks/useAreaBoundary.js | 2
18 files changed, 491 insertions(+), 183 deletions(-)
diff --git a/applications/drone-command/src/assets/images/dataCockpit/legend/command-post.png b/applications/drone-command/src/assets/images/dataCockpit/legend/command-post.png
new file mode 100644
index 0000000..dca43d0
--- /dev/null
+++ b/applications/drone-command/src/assets/images/dataCockpit/legend/command-post.png
Binary files differ
diff --git a/applications/drone-command/src/assets/images/dataCockpit/legend/drone.png b/applications/drone-command/src/assets/images/dataCockpit/legend/drone.png
new file mode 100644
index 0000000..130cf04
--- /dev/null
+++ b/applications/drone-command/src/assets/images/dataCockpit/legend/drone.png
Binary files differ
diff --git a/applications/drone-command/src/assets/images/dataCockpit/legend/equipment.png b/applications/drone-command/src/assets/images/dataCockpit/legend/equipment.png
new file mode 100644
index 0000000..ec33491
--- /dev/null
+++ b/applications/drone-command/src/assets/images/dataCockpit/legend/equipment.png
Binary files differ
diff --git a/applications/drone-command/src/assets/images/dataCockpit/map/command-post.png b/applications/drone-command/src/assets/images/dataCockpit/map/command-post.png
new file mode 100644
index 0000000..1d090e2
--- /dev/null
+++ b/applications/drone-command/src/assets/images/dataCockpit/map/command-post.png
Binary files differ
diff --git a/applications/drone-command/src/assets/images/dataCockpit/map/equipment.png b/applications/drone-command/src/assets/images/dataCockpit/map/equipment.png
index f07291b..99f9bd2 100644
--- a/applications/drone-command/src/assets/images/dataCockpit/map/equipment.png
+++ b/applications/drone-command/src/assets/images/dataCockpit/map/equipment.png
Binary files differ
diff --git a/applications/drone-command/src/components/map-container/common-cesium-map.vue b/applications/drone-command/src/components/map-container/common-cesium-map.vue
new file mode 100644
index 0000000..eec995b
--- /dev/null
+++ b/applications/drone-command/src/components/map-container/common-cesium-map.vue
@@ -0,0 +1,135 @@
+<template>
+ <div :id="mapId" class="common-cesium-map"></div>
+</template>
+
+<script setup>
+import { onBeforeUnmount, onMounted, ref, watch } from 'vue'
+import { PublicCesium } from '@/utils/cesium/publicCesium'
+import { loadJaAdminBoundary, removeJaAdminBoundary } from '@/utils/cesium/adminBoundary'
+
+const props = defineProps({
+ active: {
+ type: Boolean,
+ default: true,
+ },
+ domId: {
+ type: String,
+ default: '',
+ },
+ flatMode: {
+ type: Boolean,
+ default: false,
+ },
+ terrain: {
+ type: Boolean,
+ default: true,
+ },
+ layerMode: {
+ type: Number,
+ default: 4,
+ },
+ boundary: {
+ type: Boolean,
+ default: false,
+ },
+ contour: {
+ type: Boolean,
+ default: false,
+ },
+ showAdminBoundary: {
+ type: Boolean,
+ default: true,
+ },
+ zoomToBoundary: {
+ type: Boolean,
+ default: true,
+ },
+ enableStageEmit: {
+ type: Boolean,
+ default: false,
+ },
+ clusterHeight: {
+ type: Number,
+ default: 100000,
+ },
+ detailHeight: {
+ type: Number,
+ default: 10000,
+ },
+})
+
+const emit = defineEmits(['ready', 'height-change', 'stage-change'])
+const mapId = props.domId || `common-cesium-map-${Math.random().toString(36).slice(2, 10)}`
+const viewInstance = ref(null)
+const viewer = ref(null)
+let adminBoundarySources = null
+let initialized = false
+let removeCameraListener = null
+
+const initMap = async () => {
+ if (initialized) return
+ initialized = true
+ viewInstance.value = new PublicCesium({
+ dom: mapId,
+ flatMode: props.flatMode,
+ terrain: props.terrain,
+ layerMode: props.layerMode,
+ boundary: props.boundary,
+ contour: props.contour,
+ })
+ viewer.value = viewInstance.value.getViewer()
+ if (props.showAdminBoundary) {
+ adminBoundarySources = await loadJaAdminBoundary(viewer.value, {
+ zoomTo: props.zoomToBoundary,
+ })
+ }
+ if (props.enableStageEmit) {
+ let lastStage = ''
+ const onCameraChanged = () => {
+ const height = viewer.value?.camera?.positionCartographic?.height
+ if (height == null) return
+ emit('height-change', height)
+ let stage = 'mid'
+ if (height >= props.clusterHeight) stage = 'cluster'
+ if (height <= props.detailHeight) stage = 'detail'
+ if (stage !== lastStage) {
+ lastStage = stage
+ emit('stage-change', stage)
+ }
+ }
+ viewer.value?.camera?.changed?.addEventListener(onCameraChanged)
+ removeCameraListener = () => viewer.value?.camera?.changed?.removeEventListener(onCameraChanged)
+ }
+ emit('ready', { viewer: viewer.value, publicCesium: viewInstance.value })
+}
+
+watch(
+ () => props.active,
+ active => {
+ if (active) initMap()
+ }
+)
+
+onMounted(() => {
+ if (props.active) initMap()
+})
+
+onBeforeUnmount(() => {
+ if (removeCameraListener) removeCameraListener()
+ removeJaAdminBoundary(viewer.value, adminBoundarySources)
+ viewInstance.value?.viewerDestroy?.()
+})
+
+const getMap = () => ({ viewer: viewer.value, publicCesium: viewInstance.value })
+const getViewer = () => viewer.value
+const getPublicCesium = () => viewInstance.value
+
+defineExpose({ getMap, getViewer, getPublicCesium })
+</script>
+
+<style scoped lang="scss">
+.common-cesium-map {
+ width: 100%;
+ height: 100%;
+}
+</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 704eaf9..938bdfe 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
@@ -1,5 +1,18 @@
<template>
- <div class="command-cesium map-container" :id="props.containerId"></div>
+ <CommonCesiumMap
+ ref="mapRef"
+ class="command-cesium map-container"
+ :dom-id="props.containerId"
+ :active="true"
+ :flat-mode="false"
+ :terrain="false"
+ :layer-mode="4"
+ :contour="false"
+ :boundary="false"
+ :show-admin-boundary="true"
+ :zoom-to-boundary="true"
+ @ready="handleMapReady"
+ />
<div v-if="props.showLayerControl" class="layer-control-root" :class="{ collapsed: props.leftCollapsed }">
<div class="layer-control-wrap" ref="layerWrapRef">
<div class="layer-control" @click="toggleLayerPanel">
@@ -25,11 +38,10 @@
<script setup>
import * as Cesium from 'cesium'
-import { PublicCesium } from '@/utils/cesium/publicCesium'
+import CommonCesiumMap from '@/components/map-container/common-cesium-map.vue'
import { geomAnalysis } from '@ztzf/utils'
import { fwDefenseZonePageApi } from '@/views/areaManage/defenseZone/defenseZoneApi'
import { fwAreaDividePageApi } from '@/views/areaManage/partition/partitionApi'
-import jaGeojsonRaw from '@/assets/geojson/ja.geojson?raw'
import layerControlIcon from '@/assets/images/dataCockpit/layerControl.png'
import equipmentIcon from '@/assets/images/dataCockpit/map/equipment.png'
@@ -54,15 +66,11 @@
const DEFAULT_ZONE_PAGE_SIZE = 999
-let viewInstance = null
+const mapRef = ref(null)
let viewer = null
const deviceEntityIds = new Set()
let defenseZoneSource = null
let partitionSource = null
-let adminBoundarySource = null
-let adminBoundaryLabelSource = null
-let adminBoundaryLineSource = null
-let adminBoundaryFlyDone = false
const showLayerPanel = ref(false)
const layerWrapRef = ref(null)
const layerTreeProps = {
@@ -127,20 +135,6 @@
partitionSource.entities.removeAll()
}
-const clearAdminBoundaryEntities = () => {
- if (!adminBoundarySource) return
- adminBoundarySource.entities.removeAll()
-}
-
-const clearAdminBoundaryLabels = () => {
- if (!adminBoundaryLabelSource) return
- adminBoundaryLabelSource.entities.removeAll()
-}
-
-const clearAdminBoundaryLines = () => {
- if (!adminBoundaryLineSource) return
- adminBoundaryLineSource.entities.removeAll()
-}
const RING_STYLES = [
{ inner: 0, outer: 2000, gradient: ['#FF361C', '#360B00'] }
@@ -263,8 +257,9 @@
position: Cesium.Cartesian3.fromDegrees(position.longitude, position.latitude, 0),
billboard: {
image: equipmentIcon,
- width: 40.34,
- height: 40.34,
+ width: 40,
+ height: 56,
+ verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
},
})
})
@@ -366,83 +361,6 @@
}
}
-const loadAdminBoundary = async () => {
- if (!viewer) return
- try {
- if (adminBoundarySource) {
- viewer.dataSources.remove(adminBoundarySource)
- adminBoundarySource = null
- }
- if (adminBoundaryLabelSource) {
- viewer.dataSources.remove(adminBoundaryLabelSource)
- adminBoundaryLabelSource = null
- }
- if (adminBoundaryLineSource) {
- viewer.dataSources.remove(adminBoundaryLineSource)
- adminBoundaryLineSource = null
- }
- const geojson = JSON.parse(jaGeojsonRaw)
- adminBoundarySource = await Cesium.GeoJsonDataSource.load(geojson, {
- stroke: Cesium.Color.fromCssColorString('#FFFFFF'),
- strokeWidth: 2,
- fill: Cesium.Color.fromCssColorString('#FFFFFF').withAlpha(0.05),
- clampToGround: true,
- })
- viewer.dataSources.add(adminBoundarySource)
- if (!adminBoundaryFlyDone) {
- adminBoundaryFlyDone = true
- viewer.flyTo(adminBoundarySource, {
- duration: 0,
- offset: new Cesium.HeadingPitchRange(0, Cesium.Math.toRadians(-75), 0),
- })
- }
-
- adminBoundaryLineSource = new Cesium.CustomDataSource('adminBoundaryLineSource')
- adminBoundarySource.entities.values.forEach(entity => {
- const polygon = entity.polygon
- if (!polygon) return
- const hierarchy = polygon.hierarchy?.getValue?.(viewer.clock.currentTime)
- const positions = hierarchy?.positions
- if (!positions?.length) return
- adminBoundaryLineSource.entities.add({
- polyline: {
- positions,
- clampToGround: true,
- width: 2,
- material: Cesium.Color.WHITE,
- },
- })
- })
- viewer.dataSources.add(adminBoundaryLineSource)
-
- adminBoundaryLabelSource = new Cesium.CustomDataSource('adminBoundaryLabelSource')
- geojson.features?.forEach(feature => {
- const name = feature?.properties?.name
- const point = feature?.properties?.centroid || feature?.properties?.center
- if (!name || !Array.isArray(point) || point.length < 2) return
- adminBoundaryLabelSource.entities.add({
- position: Cesium.Cartesian3.fromDegrees(point[0], point[1]),
- label: {
- text: name,
- font: '14px Source Han Sans CN',
- fillColor: Cesium.Color.WHITE,
- outlineColor: Cesium.Color.BLACK.withAlpha(0.6),
- outlineWidth: 2,
- style: Cesium.LabelStyle.FILL_AND_OUTLINE,
- heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
- verticalOrigin: Cesium.VerticalOrigin.CENTER,
- horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
- disableDepthTestDistance: Number.POSITIVE_INFINITY,
- },
- })
- })
- viewer.dataSources.add(adminBoundaryLabelSource)
- } catch (error) {
- clearAdminBoundaryEntities()
- clearAdminBoundaryLabels()
- clearAdminBoundaryLines()
- }
-}
watch(
() => props.onlineDevices,
@@ -464,6 +382,13 @@
showLayerPanel.value = !showLayerPanel.value
}
+const handleMapReady = ({ viewer: mapViewer }) => {
+ viewer = mapViewer
+ renderDeviceEntities(props.onlineDevices)
+ loadDefenseZones()
+ loadPartitions()
+}
+
const handleClickOutside = event => {
if (!showLayerPanel.value) return
const target = event.target
@@ -473,19 +398,8 @@
onMounted(() => {
document.addEventListener('click', handleClickOutside)
- viewInstance = new PublicCesium({
- dom: props.containerId,
- flatMode: false,
- terrain: false,
- layerMode: 4,
- contour: false,
- })
-
- viewer = viewInstance.getViewer()
- renderDeviceEntities(props.onlineDevices)
- loadDefenseZones()
- loadPartitions()
- loadAdminBoundary()
+ const map = mapRef.value?.getMap()
+ if (map?.viewer) handleMapReady(map)
})
onBeforeUnmount(() => {
@@ -493,14 +407,6 @@
clearDeviceEntities()
clearDefenseZoneEntities()
clearPartitionEntities()
- clearAdminBoundaryEntities()
- clearAdminBoundaryLabels()
- clearAdminBoundaryLines()
- if (viewInstance) {
- viewInstance?.viewerDestroy()
- viewInstance = null
- }
-
viewer = null
})
</script>
diff --git a/applications/drone-command/src/utils/cesium/adminBoundary.js b/applications/drone-command/src/utils/cesium/adminBoundary.js
new file mode 100644
index 0000000..381dc7d
--- /dev/null
+++ b/applications/drone-command/src/utils/cesium/adminBoundary.js
@@ -0,0 +1,88 @@
+import * as Cesium from 'cesium'
+import jaGeojsonRaw from '@/assets/geojson/ja.geojson?raw'
+
+const DEFAULT_OPTIONS = {
+ strokeColor: '#00F9EC',
+ strokeWidth: 2,
+ fillColor: '#FFFFFF',
+ fillAlpha: 0.05,
+ labelFont: '14px Source Han Sans CN',
+ labelFill: '#FFFFFF',
+ labelOutline: '#18305C',
+ labelOutlineAlpha: 1,
+ zoomTo: true,
+}
+
+export const loadJaAdminBoundary = async (viewer, options = {}) => {
+ if (!viewer) return null
+ const config = { ...DEFAULT_OPTIONS, ...options }
+ const geojson = JSON.parse(jaGeojsonRaw)
+
+ const boundarySource = await Cesium.GeoJsonDataSource.load(geojson, {
+ stroke: Cesium.Color.fromCssColorString(config.strokeColor),
+ strokeWidth: config.strokeWidth,
+ fill: Cesium.Color.fromCssColorString(config.fillColor).withAlpha(config.fillAlpha),
+ clampToGround: true,
+ })
+ viewer.dataSources.add(boundarySource)
+
+ const lineSource = new Cesium.CustomDataSource('jaBoundaryLineSource')
+ boundarySource.entities.values.forEach(entity => {
+ const polygon = entity.polygon
+ if (!polygon) return
+ const hierarchy = polygon.hierarchy?.getValue?.(viewer.clock.currentTime)
+ const positions = hierarchy?.positions
+ if (!positions?.length) return
+ lineSource.entities.add({
+ polyline: {
+ positions,
+ clampToGround: true,
+ width: config.strokeWidth,
+ material: Cesium.Color.fromCssColorString(config.strokeColor),
+ },
+ })
+ })
+ viewer.dataSources.add(lineSource)
+
+ const labelSource = new Cesium.CustomDataSource('jaBoundaryLabelSource')
+ geojson.features?.forEach(feature => {
+ const name = feature?.properties?.name
+ const point = feature?.properties?.centroid || feature?.properties?.center
+ if (!name || !Array.isArray(point) || point.length < 2) return
+ labelSource.entities.add({
+ position: Cesium.Cartesian3.fromDegrees(point[0], point[1]),
+ label: {
+ text: name,
+ font: config.labelFont,
+ fillColor: Cesium.Color.fromCssColorString(config.labelFill),
+ outlineColor: Cesium.Color.fromCssColorString(config.labelOutline).withAlpha(
+ config.labelOutlineAlpha
+ ),
+ outlineWidth: 2,
+ style: Cesium.LabelStyle.FILL_AND_OUTLINE,
+ heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
+ verticalOrigin: Cesium.VerticalOrigin.CENTER,
+ horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
+ disableDepthTestDistance: Number.POSITIVE_INFINITY,
+ },
+ })
+ })
+ viewer.dataSources.add(labelSource)
+
+ if (config.zoomTo) {
+ await viewer.flyTo(boundarySource, {
+ duration: 0,
+ offset: new Cesium.HeadingPitchRange(0, Cesium.Math.toRadians(-75), 0),
+ })
+ }
+
+ return { boundarySource, lineSource, labelSource }
+}
+
+export const removeJaAdminBoundary = (viewer, sources) => {
+ if (!viewer || !sources) return
+ const { boundarySource, lineSource, labelSource } = sources
+ if (boundarySource) viewer.dataSources.remove(boundarySource)
+ if (lineSource) viewer.dataSources.remove(lineSource)
+ if (labelSource) viewer.dataSources.remove(labelSource)
+}
diff --git a/applications/drone-command/src/utils/cesium/publicCesium.js b/applications/drone-command/src/utils/cesium/publicCesium.js
index e0fe177..830c3f0 100644
--- a/applications/drone-command/src/utils/cesium/publicCesium.js
+++ b/applications/drone-command/src/utils/cesium/publicCesium.js
@@ -100,7 +100,7 @@
dockOptions = {},
boundaryChange,
terrainLoadCallback,
- boundaryColor = '#7FFFD4',
+ boundaryColor = '#00F9EC',
dockRangeType = 1,
useDockHeight = false
} = options
diff --git a/applications/drone-command/src/views/areaManage/defenseZone/FormDiaLog.vue b/applications/drone-command/src/views/areaManage/defenseZone/FormDiaLog.vue
index d93446e..31dcb77 100644
--- a/applications/drone-command/src/views/areaManage/defenseZone/FormDiaLog.vue
+++ b/applications/drone-command/src/views/areaManage/defenseZone/FormDiaLog.vue
@@ -2,7 +2,15 @@
<el-dialog class="command-page-map-view-dialog" v-model="visible" :show-close="false" :close-on-click-modal="false">
<div class="dialog-container">
<div class="left-container">
- <div class="leftMap command-cesium" id="mapContainer"></div>
+ <CommonCesiumMap
+ ref="mapRef"
+ class="leftMap command-cesium"
+ :active="visible"
+ :flat-mode="false"
+ :terrain="true"
+ :layer-mode="4"
+ :boundary="false"
+ />
</div>
<div class="right-container">
@@ -92,7 +100,7 @@
import { fwDefenseZoneDetailApi, fwDefenseZoneSubmitApi } from './defenseZoneApi'
import { fwDefenseSceneListApi } from '@/views/areaManage/sceneConfig/sceneConfigApi'
import { fieldRules, geomAnalysis, getDictLabel } from '@ztzf/utils'
-import { PublicCesium } from '@/utils/cesium/publicCesium'
+import CommonCesiumMap from '@/components/map-container/common-cesium-map.vue'
import { DrawPolygon } from '@/utils/cesium/DrawPolygon'
import { cartesian3Convert } from '@/utils/cesium/mapUtil'
import * as turf from '@turf/turf'
@@ -119,6 +127,7 @@
const sceneList = ref([]) // 关联场景列表
const selectedSceneRows = ref([]) // 选中场景
const dictObj = inject('dictObj')
+const mapRef = ref(null)
let viewer
let drawPolygonExample
let pointList = []
@@ -209,14 +218,9 @@
// 初始化地图实例
function initMap () {
- const publicCesiumInstance = new PublicCesium({
- dom: 'mapContainer',
- flatMode: false,
- terrain: true,
- layerMode: 4,
- boundary: false,
- })
- viewer = publicCesiumInstance.getViewer()
+ if (viewer) return
+ const map = mapRef.value?.getMap()
+ viewer = map?.viewer || null
}
// 绘制完成回调
@@ -253,6 +257,22 @@
noClosedList.map(item => ({ lng: item.longitude, lat: item.latitude }))
)
drawPolygonExample.subscribe('getPolygonPositions', drawFinished)
+ if (noClosedList.length) {
+ const result = noClosedList.map(item => [item.longitude, item.latitude]).flat()
+ const tempEntity = viewer.entities?.add({
+ position: Cesium.Cartesian3.fromDegrees(result[0], result[1]),
+ polyline: {
+ positions: Cesium.Cartesian3.fromDegreesArray(result),
+ clampToGround: true,
+ width: 1,
+ material: Cesium.Color.TRANSPARENT,
+ },
+ })
+ if (tempEntity) {
+ viewer.flyTo(tempEntity, { duration: 0 })
+ viewer.entities.remove(tempEntity)
+ }
+ }
}
// 查看面
@@ -270,7 +290,7 @@
material: Cesium.Color.RED,
},
})
- viewer.flyTo(mian)
+ viewer.flyTo(mian, { duration: 0 })
}
// 打开弹框
diff --git a/applications/drone-command/src/views/areaManage/partition/FormDiaLog.vue b/applications/drone-command/src/views/areaManage/partition/FormDiaLog.vue
index 0b11930..e46084d 100644
--- a/applications/drone-command/src/views/areaManage/partition/FormDiaLog.vue
+++ b/applications/drone-command/src/views/areaManage/partition/FormDiaLog.vue
@@ -3,7 +3,15 @@
:close-on-click-modal="false">
<div class="dialog-container">
<div class="left-container">
- <div class="leftMap command-cesium" id="mapContainer"></div>
+ <CommonCesiumMap
+ ref="mapRef"
+ class="leftMap command-cesium"
+ :active="visible"
+ :flat-mode="false"
+ :terrain="true"
+ :layer-mode="4"
+ :boundary="false"
+ />
</div>
<div class="right-container">
@@ -159,7 +167,7 @@
import { ElMessage } from 'element-plus'
import { fwAreaDivideDetailApi, fwAreaDivideSubmitApi } from './partitionApi'
import { fieldRules, geomAnalysis, getDictLabel } from '@ztzf/utils'
-import { PublicCesium } from '@/utils/cesium/publicCesium'
+import CommonCesiumMap from '@/components/map-container/common-cesium-map.vue'
import { DrawPolygon } from '@/utils/cesium/DrawPolygon'
import { cartesian3Convert } from '@/utils/cesium/mapUtil'
import * as turf from '@turf/turf'
@@ -197,6 +205,7 @@
const policeStationOptions = ref([]) // 关联派出所
const deviceOptions = ref([]) // 关联设备
const dictObj = inject('dictObj')
+const mapRef = ref(null)
let viewer
let drawPolygonExample
let pointList = []
@@ -265,14 +274,9 @@
// 初始化地图实例
function initMap () {
- const publicCesiumInstance = new PublicCesium({
- dom: 'mapContainer',
- flatMode: false,
- terrain: true,
- layerMode: 4,
- boundary: false,
- })
- viewer = publicCesiumInstance.getViewer()
+ if (viewer) return
+ const map = mapRef.value?.getMap()
+ viewer = map?.viewer || null
}
// 绘制完成回调
@@ -311,6 +315,22 @@
pointList.map(item => ({ lng: item.longitude, lat: item.latitude }))
)
drawPolygonExample.subscribe('getPolygonPositions', drawFinished)
+ if (pointList1.length) {
+ const result = pointList1.map(item => [item.longitude, item.latitude]).flat()
+ const tempEntity = viewer.entities?.add({
+ position: Cesium.Cartesian3.fromDegrees(result[0], result[1]),
+ polyline: {
+ positions: Cesium.Cartesian3.fromDegreesArray(result),
+ clampToGround: true,
+ width: 1,
+ material: Cesium.Color.TRANSPARENT,
+ },
+ })
+ if (tempEntity) {
+ viewer.flyTo(tempEntity, { duration: 0 })
+ viewer.entities.remove(tempEntity)
+ }
+ }
}
// 查看面
@@ -328,7 +348,7 @@
material: Cesium.Color.RED,
},
})
- viewer.flyTo(mian)
+ viewer.flyTo(mian, { duration: 0 })
}
// 获取派出所列表
diff --git a/applications/drone-command/src/views/areaManage/precinctInfo/FormDiaLog.vue b/applications/drone-command/src/views/areaManage/precinctInfo/FormDiaLog.vue
index 588d0b9..e6ac8dd 100644
--- a/applications/drone-command/src/views/areaManage/precinctInfo/FormDiaLog.vue
+++ b/applications/drone-command/src/views/areaManage/precinctInfo/FormDiaLog.vue
@@ -63,7 +63,15 @@
:close-on-click-modal="false" destroy-on-close @closed="positionClosed">
<div class="dialog-container">
<div class="left-container">
- <div class="leftMap command-cesium" id="mapContainer"></div>
+ <CommonCesiumMap
+ ref="mapRef"
+ class="leftMap command-cesium"
+ :active="visible1"
+ :flat-mode="false"
+ :terrain="true"
+ :layer-mode="4"
+ :boundary="false"
+ />
</div>
</div>
@@ -80,7 +88,7 @@
import { ElMessage } from 'element-plus'
import { fwPoliceStationDetailApi, fwPoliceStationSubmitApi } from './precinctInfoApi'
import { fieldRules } from '@ztzf/utils'
-import { PublicCesium } from '@/utils/cesium/publicCesium'
+import CommonCesiumMap from '@/components/map-container/common-cesium-map.vue'
import * as Cesium from 'cesium'
import axios from 'axios'
@@ -103,6 +111,7 @@
const readonly = computed(() => dialogMode.value === 'view')
const titleEnum = ref({ edit: '编辑', view: '查看', add: '新增' })
const tempLocation = ref({ longitude: null, latitude: null })
+const mapRef = ref(null)
const rules = {
address: fieldRules(true, 50),
@@ -186,6 +195,7 @@
let viewer
let redPointEntity
+let leftClickBound = false
function setMapPoint (longitude, latitude) {
if (!viewer || longitude == null || latitude == null) return
if (!redPointEntity) {
@@ -225,15 +235,12 @@
async function selectLocation () {
visible1.value = true
await nextTick()
- const publicCesiumInstance = new PublicCesium({
- dom: 'mapContainer',
- flatMode: false,
- terrain: true,
- layerMode: 4,
- boundary: false,
- })
- publicCesiumInstance.addLeftClickEvent(null, LeftClickEvent)
- viewer = publicCesiumInstance.getViewer()
+ const map = mapRef.value?.getMap()
+ viewer = map?.viewer || null
+ if (viewer && !leftClickBound) {
+ map.publicCesium?.addLeftClickEvent?.(null, LeftClickEvent)
+ leftClickBound = true
+ }
if (formData.value.longitude != null && formData.value.latitude != null) {
tempLocation.value = { longitude: formData.value.longitude, latitude: formData.value.latitude }
setMapPoint(formData.value.longitude, formData.value.latitude)
@@ -264,6 +271,7 @@
}
visible1.value = false
}
+
// 打开弹框
async function open ({ mode, row } = {}) {
dialogMode.value = mode || 'add'
diff --git a/applications/drone-command/src/views/areaManage/sceneConfig/FormDiaLog.vue b/applications/drone-command/src/views/areaManage/sceneConfig/FormDiaLog.vue
index f61f46d..199e92d 100644
--- a/applications/drone-command/src/views/areaManage/sceneConfig/FormDiaLog.vue
+++ b/applications/drone-command/src/views/areaManage/sceneConfig/FormDiaLog.vue
@@ -2,7 +2,15 @@
<el-dialog class="command-page-map-view-dialog" v-model="visible" :show-close="false" :close-on-click-modal="false">
<div class="dialog-container">
<div class="left-container">
- <div class="leftMap command-cesium" id="mapContainer"></div>
+ <CommonCesiumMap
+ ref="mapRef"
+ class="leftMap command-cesium"
+ :active="visible"
+ :flat-mode="false"
+ :terrain="true"
+ :layer-mode="4"
+ :boundary="false"
+ />
</div>
<div class="right-container">
<div class="header">
@@ -135,7 +143,7 @@
import { ElMessage } from 'element-plus'
import { fwDefenseSceneDetailApi, fwDefenseSceneSubmitApi } from './sceneConfigApi'
import { fieldRules, geomAnalysis, getDictLabel } from '@ztzf/utils'
-import { PublicCesium } from '@/utils/cesium/publicCesium'
+import CommonCesiumMap from '@/components/map-container/common-cesium-map.vue'
import * as Cesium from 'cesium'
import { fwAreaDivideListApi } from '../partition/partitionApi'
import { DrawPolygon } from '@/utils/cesium/DrawPolygon'
@@ -166,8 +174,10 @@
const areaList = ref([]) // 关联区域列表
const selectedAreaRows = ref([]) //选中列表
const dictObj = inject('dictObj')
+const mapRef = ref(null)
let viewer
let redPointEntity
+let leftClickBound = false
const rules = {
sceneName: fieldRules(true, 50),
@@ -285,19 +295,18 @@
let geometricSource
// 初始化地图实例
function initMap () {
- const publicCesiumInstance = new PublicCesium({
- dom: 'mapContainer',
- flatMode: false,
- terrain: true,
- layerMode: 4,
- boundary: false,
- })
- if (!readonly.value) {
- publicCesiumInstance.addLeftClickEvent(null, LeftClickEvent)
+ if (viewer) return
+ const map = mapRef.value?.getMap()
+ if (!map?.viewer) return
+ viewer = map.viewer
+ if (!readonly.value && !leftClickBound) {
+ map.publicCesium?.addLeftClickEvent?.(null, LeftClickEvent)
+ leftClickBound = true
}
- viewer = publicCesiumInstance.getViewer()
- geometricSource = new Cesium.CustomDataSource('geometricSource')
- viewer.dataSources.add(geometricSource)
+ if (!geometricSource) {
+ geometricSource = new Cesium.CustomDataSource('geometricSource')
+ viewer.dataSources.add(geometricSource)
+ }
}
function LeftClickEvent (click) {
diff --git a/applications/drone-command/src/views/dataCockpit/components/LegendBar.vue b/applications/drone-command/src/views/dataCockpit/components/LegendBar.vue
new file mode 100644
index 0000000..d115225
--- /dev/null
+++ b/applications/drone-command/src/views/dataCockpit/components/LegendBar.vue
@@ -0,0 +1,108 @@
+<!--
+ * @Author : yuan
+ * @Date : 2026-01-17 14:51:39
+ * @LastEditors : yuan
+ * @LastEditTime : 2026-01-17 15:13:50
+ * @FilePath : \applications\drone-command\src\views\dataCockpit\components\LegendBar.vue
+ * @Description :
+ * Copyright 2026 OBKoro1, All Rights Reserved.
+ * 2026-01-17 14:51:39
+-->
+<template>
+ <div class="legend-bar">
+ <div class="legend-title" data-text="图例">图例</div>
+ <div class="legend-item">
+ <span class="legend-color defense"></span>
+ <span class="legend-text" data-text="防区">防区</span>
+ </div>
+ <div class="legend-item">
+ <span class="legend-color partition"></span>
+ <span class="legend-text" data-text="区域">区域</span>
+ </div>
+ <div class="legend-item">
+ <img class="legend-icon drone" :src="droneIcon" alt="无人机" />
+ <span class="legend-text" data-text="无人机">无人机</span>
+ </div>
+ <div class="legend-item">
+ <img class="legend-icon" :src="commandPostIcon" alt="指挥点" />
+ <span class="legend-text" data-text="指挥点">指挥点</span>
+ </div>
+ <div class="legend-item">
+ <img class="legend-icon" :src="equipmentIcon" alt="设备" />
+ <span class="legend-text" data-text="设备">设备</span>
+ </div>
+ </div>
+</template>
+
+<script setup>
+import droneIcon from '@/assets/images/dataCockpit/legend/drone.png'
+import commandPostIcon from '@/assets/images/dataCockpit/legend/command-post.png'
+import equipmentIcon from '@/assets/images/dataCockpit/legend/equipment.png'
+</script>
+
+<style scoped lang="scss">
+.legend-bar {
+ display: flex;
+ align-items: center;
+ gap: 20px;
+ padding: 10px 16px;
+
+ font-family: Source Han Sans CN, Source Han Sans CN;
+ font-size: 14px;
+ color: #FFFFFF;
+ text-align: center;
+ font-style: normal;
+ text-transform: none;
+}
+
+.legend-title {
+ font-weight: 800;
+}
+
+.legend-item {
+ display: flex;
+ align-items: center;
+ gap: 8px;
+ font-size: 12px;
+}
+
+.legend-title,
+.legend-text {
+ position: relative;
+ white-space: nowrap;
+
+ text-shadow:
+ -1px -1px 0 black,
+ 1px -1px 0 black,
+ -1px 1px 0 black,
+ 1px 1px 0 black;
+}
+
+.legend-color {
+ width: 30px;
+ height: 30px;
+ border-radius: 0;
+}
+
+.legend-color.defense {
+ background: radial-gradient(50% 50% at 50% 50%, #2aedbf 0%, #012b11 100%);
+ border: 1px solid #19d266;
+}
+
+.legend-color.partition {
+ background: radial-gradient(50% 50% at 50% 50%, #ffc609 0%, #583300 100%);
+ border: 1px solid #ffcd2a;
+}
+
+.legend-icon {
+ width: 30px;
+ height: 42px;
+ display: block;
+}
+
+.legend-icon.drone {
+ width: 30px;
+ height: 30px;
+ display: block;
+}
+</style>
diff --git a/applications/drone-command/src/views/dataCockpit/index.vue b/applications/drone-command/src/views/dataCockpit/index.vue
index 0568cef..7f44448 100644
--- a/applications/drone-command/src/views/dataCockpit/index.vue
+++ b/applications/drone-command/src/views/dataCockpit/index.vue
@@ -18,6 +18,7 @@
<LeftContainer class="left-container" v-model:activeId="leftActiveId" v-model:collapsed="leftCollapsed" />
<RightContainer class="right-container" v-model:collapsed="rightCollapsed" v-model:onlineDevices="onlineDevices" />
<CenterContainer @select-warning="onSelectWarning" @select-equipment="onSelectEquipment" />
+ <LegendBar class="legend-container" />
</div>
</template>
@@ -26,6 +27,7 @@
import LeftContainer from './components/LeftContainer.vue';
import RightContainer from './components/RightContainer.vue';
import CenterContainer from './components/CenterContainer.vue';
+ import LegendBar from './components/LegendBar.vue';
const leftActiveId = ref(1);
const leftCollapsed = ref(false);
@@ -85,4 +87,12 @@
right: 17px;
background: linear-gradient( 270deg, rgba(17,23,34,0.96) 0.16%, rgba(17,23,34,0.56) 57.57%, rgba(4,30,37,0) 100%);
}
+
+ .legend-container {
+ position: absolute;
+ left: 50%;
+ bottom: 22px;
+ transform: translateX(-50%);
+ z-index: 9;
+ }
</style>
diff --git a/applications/drone-command/src/views/detectionCountermeasure/detectionRange/DetectionRangeDialog.vue b/applications/drone-command/src/views/detectionCountermeasure/detectionRange/DetectionRangeDialog.vue
index e3caeb2..e787566 100644
--- a/applications/drone-command/src/views/detectionCountermeasure/detectionRange/DetectionRangeDialog.vue
+++ b/applications/drone-command/src/views/detectionCountermeasure/detectionRange/DetectionRangeDialog.vue
@@ -9,7 +9,15 @@
>
<div class="dialog-container">
<div class="left-container">
- <div class="leftMap command-cesium" id="detectionRangeMap"></div>
+ <CommonCesiumMap
+ ref="mapRef"
+ class="leftMap command-cesium"
+ :active="visible"
+ :flat-mode="false"
+ :terrain="true"
+ :layer-mode="4"
+ :boundary="false"
+ />
</div>
<div class="right-container">
@@ -138,7 +146,7 @@
detectionRangePageApi,
detectionRangeSubmitApi,
} from '@/api/detectionCountermeasure/detectionRange'
-import { PublicCesium } from '@/utils/cesium/publicCesium'
+import CommonCesiumMap from '@/components/map-container/common-cesium-map.vue'
import * as Cesium from 'cesium'
import deviceZcImg from '@/assets/images/dataCockpit/device-zc.svg'
@@ -161,6 +169,7 @@
const submitting = ref(false) // 提交中
const deviceOptions = ref([])
const dialogReadonly = computed(() => dialogMode.value === 'view')
+const mapRef = ref(null)
let viewer
let redPointEntity
let rangeCircleEntity
@@ -338,17 +347,12 @@
function initMap() {
if (viewer) return
- const publicCesiumInstance = new PublicCesium({
- dom: 'detectionRangeMap',
- flatMode: false,
- terrain: true,
- layerMode: 4,
- boundary: false,
- })
+ const map = mapRef.value?.getMap()
+ if (!map?.viewer) return
+ viewer = map.viewer
if (!dialogReadonly.value) {
- publicCesiumInstance.addLeftClickEvent(null, handleMapClick)
+ map.publicCesium?.addLeftClickEvent?.(null, handleMapClick)
}
- viewer = publicCesiumInstance.getViewer()
}
function handleMapClick(click) {
diff --git a/applications/mobile-web-view/src/hooks/useAreaBoundary.js b/applications/mobile-web-view/src/hooks/useAreaBoundary.js
index c62c508..d824c29 100644
--- a/applications/mobile-web-view/src/hooks/useAreaBoundary.js
+++ b/applications/mobile-web-view/src/hooks/useAreaBoundary.js
@@ -71,7 +71,7 @@
geoJsonLayer && map.removeLayer(geoJsonLayer)
geoJsonLayer = L.geoJSON(row.gJson, {
style: feature => ({
- color: '#37D2D5', // 边界线颜色
+ color: '#00F9EC', // 边界线颜色
weight: 2, // 边界线宽度
fillOpacity: 0, // 填充透明度
}),
diff --git a/applications/task-work-order/src/utils/cesium/publicCesium.js b/applications/task-work-order/src/utils/cesium/publicCesium.js
index e0fe177..830c3f0 100644
--- a/applications/task-work-order/src/utils/cesium/publicCesium.js
+++ b/applications/task-work-order/src/utils/cesium/publicCesium.js
@@ -100,7 +100,7 @@
dockOptions = {},
boundaryChange,
terrainLoadCallback,
- boundaryColor = '#7FFFD4',
+ boundaryColor = '#00F9EC',
dockRangeType = 1,
useDockHeight = false
} = options
--
Gitblit v1.9.3