吉安感知网项目-前端
罗广辉
2026-01-19 566317f859765cab003351602a35a90e93c557e8
Merge remote-tracking branch 'origin/master'
57 files modified
4 files added
2754 ■■■■■ changed files
applications/drone-command/src/api/dataCockpit/index.js 8 ●●●●● patch | view | raw | blame | history
applications/drone-command/src/assets/images/common/checkbox.png patch | view | raw | blame | history
applications/drone-command/src/assets/images/dataCockpit/left-btn.png patch | view | raw | blame | history
applications/drone-command/src/assets/images/dataCockpit/legend/command-post.png patch | view | raw | blame | history
applications/drone-command/src/assets/images/dataCockpit/legend/equipment.png patch | view | raw | blame | history
applications/drone-command/src/assets/images/dataCockpit/map/aggregation.png patch | view | raw | blame | history
applications/drone-command/src/assets/images/dataCockpit/map/command-post.png patch | view | raw | blame | history
applications/drone-command/src/assets/images/dataCockpit/map/equipment.png patch | view | raw | blame | history
applications/drone-command/src/assets/images/dataCockpit/map/popup-close.png patch | view | raw | blame | history
applications/drone-command/src/assets/images/dataCockpit/right-btn.png patch | view | raw | blame | history
applications/drone-command/src/components/map-container/common-cesium-map.vue 2 ●●● patch | view | raw | blame | history
applications/drone-command/src/components/map-container/device-map-container.vue 575 ●●●●● patch | view | raw | blame | history
applications/drone-command/src/styles/common/cockpit.scss 127 ●●●● patch | view | raw | blame | history
applications/drone-command/src/styles/element-ui.scss 658 ●●●●● patch | view | raw | blame | history
applications/drone-command/src/utils/cesium/publicCesium.js 35 ●●●●● patch | view | raw | blame | history
applications/drone-command/src/views/api.txt 86 ●●●● patch | view | raw | blame | history
applications/drone-command/src/views/areaManage/areaStatistics/index.vue 10 ●●●● patch | view | raw | blame | history
applications/drone-command/src/views/areaManage/defenseZone/FormDiaLog.vue 8 ●●●● patch | view | raw | blame | history
applications/drone-command/src/views/areaManage/defenseZone/index.vue 6 ●●●● patch | view | raw | blame | history
applications/drone-command/src/views/areaManage/partition/FormDiaLog.vue 22 ●●●● patch | view | raw | blame | history
applications/drone-command/src/views/areaManage/partition/index.vue 8 ●●●● patch | view | raw | blame | history
applications/drone-command/src/views/areaManage/precinctInfo/FormDiaLog.vue 6 ●●●● patch | view | raw | blame | history
applications/drone-command/src/views/areaManage/precinctInfo/index.vue 6 ●●●● patch | view | raw | blame | history
applications/drone-command/src/views/areaManage/sceneConfig/FormDiaLog.vue 16 ●●●● patch | view | raw | blame | history
applications/drone-command/src/views/areaManage/sceneConfig/index.vue 14 ●●●● patch | view | raw | blame | history
applications/drone-command/src/views/basicManage/deviceScrap/index.vue 14 ●●●● patch | view | raw | blame | history
applications/drone-command/src/views/basicManage/deviceStock/DeviceScrapDiaLog.vue 6 ●●●● patch | view | raw | blame | history
applications/drone-command/src/views/basicManage/deviceStock/DeviceTrackDiaLog.vue 12 ●●●● patch | view | raw | blame | history
applications/drone-command/src/views/basicManage/deviceStock/FormDiaLog.vue 28 ●●●● patch | view | raw | blame | history
applications/drone-command/src/views/basicManage/deviceStock/index.vue 14 ●●●● patch | view | raw | blame | history
applications/drone-command/src/views/basicManage/maintainRecord/FormDiaLog.vue 10 ●●●● patch | view | raw | blame | history
applications/drone-command/src/views/basicManage/maintainRecord/MaintenanceDiaLog.vue 8 ●●●● patch | view | raw | blame | history
applications/drone-command/src/views/basicManage/maintainRecord/index.vue 10 ●●●● patch | view | raw | blame | history
applications/drone-command/src/views/dataCockpit/components/DeviceHistoryDialog.vue 18 ●●●● patch | view | raw | blame | history
applications/drone-command/src/views/dataCockpit/components/EquipmentWarning.vue 27 ●●●● patch | view | raw | blame | history
applications/drone-command/src/views/dataCockpit/components/HistoryWarning.vue 10 ●●●●● patch | view | raw | blame | history
applications/drone-command/src/views/dataCockpit/components/LeftContainer.vue 11 ●●●● patch | view | raw | blame | history
applications/drone-command/src/views/dataCockpit/components/RealWarning.vue 36 ●●●●● patch | view | raw | blame | history
applications/drone-command/src/views/dataCockpit/components/RightContainer.vue 11 ●●●● patch | view | raw | blame | history
applications/drone-command/src/views/dataCockpit/components/templateComponents/RealEquipmentTemplate.vue 32 ●●●● patch | view | raw | blame | history
applications/drone-command/src/views/dataCockpit/components/templateComponents/RealTemplate.vue 19 ●●●● patch | view | raw | blame | history
applications/drone-command/src/views/detectionCountermeasure/countermeasureEvaluation/index.vue 14 ●●●● patch | view | raw | blame | history
applications/drone-command/src/views/detectionCountermeasure/detectionRange/DetectionRangeDialog.vue 29 ●●●● patch | view | raw | blame | history
applications/drone-command/src/views/detectionCountermeasure/detectionRange/index.vue 10 ●●●● patch | view | raw | blame | history
applications/drone-command/src/views/detectionCountermeasure/deviceAppConfig/FormDiaLog.vue 24 ●●●● patch | view | raw | blame | history
applications/drone-command/src/views/detectionCountermeasure/deviceAppConfig/index.vue 14 ●●●● patch | view | raw | blame | history
applications/drone-command/src/views/detectionCountermeasure/taskSchedule/FormDiaLog.vue 26 ●●●● patch | view | raw | blame | history
applications/drone-command/src/views/detectionCountermeasure/taskSchedule/index.vue 14 ●●●● patch | view | raw | blame | history
applications/drone-command/src/views/permissionManage/permissionDept/FormDiaLog.vue 20 ●●●● patch | view | raw | blame | history
applications/drone-command/src/views/permissionManage/permissionDept/index.vue 8 ●●●● patch | view | raw | blame | history
applications/drone-command/src/views/permissionManage/permissionRole/FormDiaLog.vue 8 ●●●● patch | view | raw | blame | history
applications/drone-command/src/views/permissionManage/permissionRole/index.vue 8 ●●●● patch | view | raw | blame | history
applications/drone-command/src/views/permissionManage/permissionUser/FormDiaLog.vue 42 ●●●● patch | view | raw | blame | history
applications/drone-command/src/views/permissionManage/permissionUser/index.vue 12 ●●●● patch | view | raw | blame | history
applications/drone-command/src/views/recordManage/alarmRecords/index.vue 16 ●●●● patch | view | raw | blame | history
applications/drone-command/src/views/recordManage/historyTracks/TrajectoryDiaLog.vue 2 ●●● patch | view | raw | blame | history
applications/drone-command/src/views/recordManage/historyTracks/index.vue 12 ●●●● patch | view | raw | blame | history
applications/mobile-web-view/src/appComponents/LeafletMap/indexWX.vue 607 ●●●●● patch | view | raw | blame | history
applications/task-work-order/src/views/orderView/orderDataManage/supplyAdd/FormDiaLog.vue 21 ●●●●● patch | view | raw | blame | history
applications/task-work-order/src/views/orderView/orderDataManage/supplyAdd/index.vue 6 ●●●● patch | view | raw | blame | history
uniapps/work-wx/src/subPackages/deviceRegistration/add.vue 8 ●●●●● patch | view | raw | blame | history
applications/drone-command/src/api/dataCockpit/index.js
@@ -53,6 +53,14 @@
    })
}
// 数据驾驶舱地图聚合
export const cockpitAggregationApi = () => {
    return request({
        url: '/drone-fw/device/fwDevice/statisticalDeviceOut',
        method: 'get'
    })
}
// 区域列表
export const areaDivideListApi = (params) => {
    return request({
applications/drone-command/src/assets/images/common/checkbox.png
applications/drone-command/src/assets/images/dataCockpit/left-btn.png

applications/drone-command/src/assets/images/dataCockpit/legend/command-post.png

applications/drone-command/src/assets/images/dataCockpit/legend/equipment.png

applications/drone-command/src/assets/images/dataCockpit/map/aggregation.png
applications/drone-command/src/assets/images/dataCockpit/map/command-post.png

applications/drone-command/src/assets/images/dataCockpit/map/equipment.png

applications/drone-command/src/assets/images/dataCockpit/map/popup-close.png
applications/drone-command/src/assets/images/dataCockpit/right-btn.png

applications/drone-command/src/components/map-container/common-cesium-map.vue
@@ -42,7 +42,7 @@
    },
    zoomToBoundary: {
        type: Boolean,
        default: true,
        default: false,
    },
    enableStageEmit: {
        type: Boolean,
applications/drone-command/src/components/map-container/device-map-container.vue
@@ -1,35 +1,74 @@
<template>
    <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">
                <img :src="layerControlIcon" alt="图层控制" />
            </div>
            <div v-if="showLayerPanel" class="layer-panel">
                <div class="panel-title">图层管理</div>
    <div class="map-shell">
        <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" :enable-stage-emit="true" :cluster-height="100000"
            @ready="handleMapReady" @stage-change="handleStageChange" />
        <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">
                    <img :src="layerControlIcon" alt="图层控制" />
                </div>
                <div v-if="showLayerPanel" class="layer-panel">
                    <div class="panel-title">图层管理</div>
                <div class="panel-content">
                    <el-tree
                        :data="layerTree"
                        show-checkbox
                        default-expand-all
                        node-key="key"
                        :props="layerTreeProps"
                        :default-checked-keys="defaultCheckedKeys"
                    />
                    <div class="panel-content">
                        <el-tree :data="layerTree" show-checkbox default-expand-all node-key="key"
                            :props="layerTreeProps" :default-checked-keys="defaultCheckedKeys" />
                    </div>
                </div>
            </div>
        </div>
        <div v-if="popupVisible" class="device-popup" :style="popupStyle" @click.stop>
            <div class="device-popup__header">
                <span class="device-popup__title">{{ popupTitle }}</span>
                <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>
@@ -42,8 +81,14 @@
import { geomAnalysis } from '@ztzf/utils'
import { fwDefenseZonePageApi } from '@/views/areaManage/defenseZone/defenseZoneApi'
import { fwAreaDividePageApi } from '@/views/areaManage/partition/partitionApi'
import { fwDefenseSceneListApi } from '@/views/areaManage/sceneConfig/sceneConfigApi'
import { cockpitAggregationApi } from '@/api/dataCockpit'
import layerControlIcon from '@/assets/images/dataCockpit/layerControl.png'
import equipmentIcon from '@/assets/images/dataCockpit/map/equipment.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'
const props = defineProps({
    onlineDevices: {
@@ -69,10 +114,20 @@
const mapRef = ref(null)
let viewer = null
const deviceEntityIds = new Set()
const deviceEntityMap = new Map()
let defenseZoneSource = null
let partitionSource = null
let aggregationSource = null
let commandPostSource = null
const detailVisible = ref(true)
const clusterVisible = ref(false)
const countyCenterMap = new Map()
const showLayerPanel = ref(false)
const layerWrapRef = ref(null)
const selectedDevice = ref(null)
let selectedDeviceEntity = null
let deviceClickHandler = null
let popupRenderHandler = null
const layerTreeProps = {
    label: 'label',
    children: 'children',
@@ -123,6 +178,7 @@
        viewer.entities.removeById(id)
    })
    deviceEntityIds.clear()
    deviceEntityMap.clear()
}
const clearDefenseZoneEntities = () => {
@@ -133,6 +189,44 @@
const clearPartitionEntities = () => {
    if (!partitionSource) return
    partitionSource.entities.removeAll()
}
const clearAggregationEntities = () => {
    if (!aggregationSource) return
    aggregationSource.entities.removeAll()
}
const clearCommandPostEntities = () => {
    if (!commandPostSource) return
    commandPostSource.entities.removeAll()
}
const setDetailVisibility = visible => {
    detailVisible.value = visible
    if (defenseZoneSource) defenseZoneSource.show = visible
    if (partitionSource) partitionSource.show = visible
    if (commandPostSource) commandPostSource.show = visible
    if (!visible) closePopup()
    deviceEntityIds.forEach(id => {
        const entity = viewer?.entities?.getById(id)
        if (entity) entity.show = visible
    })
}
const setClusterVisibility = visible => {
    clusterVisible.value = visible
    if (aggregationSource) aggregationSource.show = visible
}
const ensureCountyCenterMap = () => {
    if (countyCenterMap.size) return
    const geojson = JSON.parse(jaGeojsonRaw)
    geojson.features?.forEach(feature => {
        const name = feature?.properties?.name
        const center = feature?.properties?.centroid || feature?.properties?.center
        if (!name || !Array.isArray(center) || center.length < 2) return
        countyCenterMap.set(name, { longitude: center[0], latitude: center[1] })
    })
}
@@ -185,7 +279,7 @@
    return positions
}
const addDeviceRings = (center, baseId) => {
const addDeviceRings = (center, baseId, visible) => {
    RING_STYLES.forEach((ring, index) => {
        const outerPositions = buildCirclePositions(center, ring.outer)
        const holes = ring.inner
@@ -200,6 +294,7 @@
        const material = new RadialGradientMaterialProperty(color1, color2)
        viewer.entities.add({
            id: entityId,
            show: visible,
            polygon: {
                hierarchy: new Cesium.PolygonHierarchy(outerPositions, holes),
                material,
@@ -215,26 +310,26 @@
        this.color2 = color2
    }
    get isConstant() {
    get isConstant () {
        return true
    }
    get definitionChanged() {
    get definitionChanged () {
        return this._definitionChanged
    }
    getType() {
    getType () {
        return MATERIAL_TYPE
    }
    getValue(time, result) {
    getValue (time, result) {
        const target = result || {}
        target.color1 = this.color1
        target.color2 = this.color2
        return target
    }
    equals(other) {
    equals (other) {
        return (
            other instanceof RadialGradientMaterialProperty &&
            Cesium.Color.equals(this.color1, other.color1) &&
@@ -251,9 +346,10 @@
        if (!position) return
        const entityId = `online-device-${item.id ?? index}`
        deviceEntityIds.add(entityId)
        addDeviceRings(position, entityId)
        viewer.entities.add({
        addDeviceRings(position, entityId, detailVisible.value)
        const entity = viewer.entities.add({
            id: entityId,
            show: detailVisible.value,
            position: Cesium.Cartesian3.fromDegrees(position.longitude, position.latitude, 0),
            billboard: {
                image: equipmentIcon,
@@ -262,7 +358,11 @@
                verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
            },
        })
        deviceEntityMap.set(entityId, { data: item, entity })
    })
    if (selectedDeviceEntity && !deviceEntityMap.has(selectedDeviceEntity.id)) {
        closePopup()
    }
}
const getDefenseZonePositions = geom => {
@@ -316,6 +416,7 @@
        viewer.dataSources.add(defenseZoneSource)
    }
    clearDefenseZoneEntities()
    defenseZoneSource.show = detailVisible.value
    renderZonePolygons({
        zones,
        source: defenseZoneSource,
@@ -332,6 +433,7 @@
        viewer.dataSources.add(partitionSource)
    }
    clearPartitionEntities()
    partitionSource.show = detailVisible.value
    renderZonePolygons({
        zones,
        source: partitionSource,
@@ -361,6 +463,225 @@
    }
}
const renderAggregation = list => {
    if (!viewer) return
    ensureCountyCenterMap()
    if (!aggregationSource) {
        aggregationSource = new Cesium.CustomDataSource('aggregationSource')
        viewer.dataSources.add(aggregationSource)
    }
    clearAggregationEntities()
    aggregationSource.show = clusterVisible.value
    const countMap = new Map()
        ; (list || []).forEach(item => {
            if (!item?.type) return
            countMap.set(item.type, Number(item.count ?? 0))
        })
    Array.from(countyCenterMap.entries()).forEach(([name, center], index) => {
        const position = Cesium.Cartesian3.fromDegrees(center.longitude, center.latitude, 0)
        const count = countMap.get(name) ?? 0
        aggregationSource.entities.add({
            id: `aggregation-${name}-${index}`,
            position,
            billboard: {
                image: aggregationIcon,
                width: 82.5,
                height: 59.25,
                verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
                heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
            },
            label: {
                text: `${count}`,
                fillColor: Cesium.Color.WHITE,
                style: Cesium.LabelStyle.FILL_AND_OUTLINE,
                verticalOrigin: Cesium.VerticalOrigin.CENTER,
                horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
                font: '12pt Source Han Sans CN',
                eyeOffset: new Cesium.Cartesian3(0, 0, -20), // 让label "浮" 在广告牌前面
                pixelOffset: new Cesium.Cartesian2(2, -11),
                pixelOffset: new Cesium.Cartesian2(0, -48),
                disableDepthTestDistance: Number.POSITIVE_INFINITY,
                heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
            },
        })
    })
}
const getPickedDevice = picks => {
    for (const pick of picks) {
        const entityId = typeof pick?.id === 'string' ? pick.id : pick?.id?.id
        if (entityId && deviceEntityMap.has(entityId)) {
            return deviceEntityMap.get(entityId)
        }
    }
    return null
}
const updatePopupPosition = () => {
    if (!viewer || !selectedDeviceEntity) return
    const cartesian =
        selectedDeviceEntity.position?.getValue?.(Cesium.JulianDate.now()) ||
        selectedDeviceEntity.position?._value
    if (!cartesian) return
    const screenPosition = viewer.scene.cartesianToCanvasCoordinates(cartesian)
    if (!screenPosition) return
    popupPosition.value = { x: screenPosition.x, y: screenPosition.y }
}
const startPopupRender = () => {
    if (!viewer || popupRenderHandler) return
    popupRenderHandler = () => updatePopupPosition()
    viewer.scene.postRender.addEventListener(popupRenderHandler)
    updatePopupPosition()
}
const stopPopupRender = () => {
    if (!viewer || !popupRenderHandler) return
    viewer.scene.postRender.removeEventListener(popupRenderHandler)
    popupRenderHandler = null
}
const handleDeviceClick = movement => {
    if (!viewer) return
    const picks = viewer.scene.drillPick(movement.position) || []
    const pickedDevice = getPickedDevice(picks)
    if (!pickedDevice) {
        closePopup()
        return
    }
    selectedDevice.value = pickedDevice.data
    selectedDeviceEntity = pickedDevice.entity
    startPopupRender()
}
const initDeviceClickHandler = () => {
    if (deviceClickHandler || !viewer) return
    deviceClickHandler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas)
    deviceClickHandler.setInputAction(handleDeviceClick, Cesium.ScreenSpaceEventType.LEFT_CLICK)
}
const destroyDeviceClickHandler = () => {
    deviceClickHandler?.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK)
    deviceClickHandler?.destroy()
    deviceClickHandler = null
}
function closePopup () {
    selectedDevice.value = null
    selectedDeviceEntity = null
    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 popupTitle = computed(() => selectedDevice.value?.deviceName || selectedDevice.value?.deviceModel || '-')
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 renderCommandPosts = list => {
    if (!viewer) return
    if (!commandPostSource) {
        commandPostSource = new Cesium.CustomDataSource('commandPostSource')
        viewer.dataSources.add(commandPostSource)
    }
    clearCommandPostEntities()
    commandPostSource.show = detailVisible.value
        ; (list || []).forEach((item, index) => {
            const position = getDevicePosition(item)
            if (!position) return
            commandPostSource.entities.add({
                id: `command-post-${item.id ?? index}`,
                position: Cesium.Cartesian3.fromDegrees(position.longitude, position.latitude, 0),
                billboard: {
                    image: commandPostIcon,
                    width: 40,
                    height: 56,
                    verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
                    heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
                },
            })
        })
}
const loadAggregation = async () => {
    try {
        const res = await cockpitAggregationApi()
        renderAggregation(res?.data?.data ?? [])
    } catch (error) {
        renderAggregation([])
    }
}
const loadCommandPosts = async () => {
    try {
        const res = await fwDefenseSceneListApi()
        renderCommandPosts(res?.data?.data ?? [])
    } catch (error) {
        renderCommandPosts([])
    }
}
watch(
    () => props.onlineDevices,
@@ -382,11 +703,27 @@
    showLayerPanel.value = !showLayerPanel.value
}
const updateStageDisplay = stage => {
    const showCluster = stage === 'cluster'
    setClusterVisibility(showCluster)
    setDetailVisibility(!showCluster)
}
const handleMapReady = ({ viewer: mapViewer }) => {
    viewer = mapViewer
    const height = viewer?.camera?.positionCartographic?.height
    const stage = height != null && height >= 100000 ? 'cluster' : 'detail'
    updateStageDisplay(stage)
    renderDeviceEntities(props.onlineDevices)
    loadDefenseZones()
    loadPartitions()
    loadAggregation()
    loadCommandPosts()
    initDeviceClickHandler()
}
const handleStageChange = stage => {
    updateStageDisplay(stage)
}
const handleClickOutside = event => {
@@ -407,11 +744,21 @@
    clearDeviceEntities()
    clearDefenseZoneEntities()
    clearPartitionEntities()
    clearAggregationEntities()
    clearCommandPostEntities()
    closePopup()
    destroyDeviceClickHandler()
    viewer = null
})
</script>
<style lang="scss" scoped>
.map-shell {
    position: relative;
    width: 100%;
    height: 100%;
}
.map-container {
    position: absolute;
    top: 0;
@@ -420,6 +767,158 @@
    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__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 {
    position: absolute;
    left: 337px;
applications/drone-command/src/styles/common/cockpit.scss
@@ -37,8 +37,47 @@
    }
}
.command-radio-group {
    .el-radio {
        .el-radio__input {
            width: 16px;
            height: 16px;
            border: none;
            .el-radio__inner {
                width: 16px;
                height: 16px;
                border: 2px solid #A1A3D4;
                border-radius: 50%;
                background: transparent !important;
                box-sizing: border-box;
            }
        }
        .el-radio__label {
            color: #FFFFFF;
        }
        &.is-checked {
            .el-radio__inner {
                background: #023AFF !important;
                border: none;
                &::after {
                    width: 8px;
                    height: 8px;
                }
            }
            .el-radio__label {
                color: #FFFFFF;
            }
        }
    }
}
// 数据驾驶舱专属
.command-data-cockpit-search-input {
.command-search-input {
    .el-input__wrapper {
        padding: 0 8px !important;
        background: #161B2C;
@@ -61,7 +100,7 @@
    }
}
.command-data-cockpit-date-picker {
.command-date-picker {
    box-shadow: none !important;
    background: #161B2C;
    border: none;
@@ -90,7 +129,7 @@
    }
}
.command-data-cockpit-date-picker-popper {
.command-date-picker-popper {
    background: #161B2C !important;
    border: none !important;
    border-radius: 0px 0px 8px 8px;
@@ -297,7 +336,7 @@
    }
}
.command-data-cockpit-select {
.command-select {
    .el-select__input {
        color: #ffffff !important;
    }
@@ -337,7 +376,7 @@
    }
}
.command-data-cockpit-select-popper.el-select__popper {
.command-select-popper.el-select__popper {
    border: none;
    background: #2E2E48 !important;
@@ -383,13 +422,13 @@
    }
}
.command-data-cockpit-cascader {
.command-cascader {
    .el-input__wrapper {
        --el-input-text-color: #161B2C !important;
    }
}
.command-data-cockpit-cascader-popper.el-cascader__dropdown {
.command-cascader-popper.el-cascader__dropdown {
    border: none;
    background: #2E2E48 !important;
@@ -417,7 +456,7 @@
}
// 树形选择
.command-data-cockpit-tree-select-popper {
.command-tree-select-popper {
    background: #2E2E48 !important;
    border: none !important;
@@ -495,7 +534,7 @@
    }
}
.command-data-cockpit-dialog {
.command-dialog {
    padding: 20px;
    display: flex;
    flex-direction: column;
@@ -550,7 +589,7 @@
        text-transform: none;
    }
    .command-data-cockpit-search-input {
    .command-search-input {
        .el-input__wrapper {
            background: #2E2E48;
        }
@@ -562,11 +601,11 @@
        }
    }
    .command-data-cockpit-date-picker {
    .command-date-picker {
        background: #2E2E48;
    }
    .command-data-cockpit-date-picker-popper {
    .command-date-picker-popper {
        background: #2E2E48 !important;
        .el-picker-panel {
@@ -639,13 +678,13 @@
        text-transform: none;
    }
    .command-data-cockpit-select {
    .command-select {
        .el-select__wrapper {
            background: #1C1C31;
        }
    }
    .command-data-cockpit-search-input {
    .command-search-input {
        .el-input__wrapper {
            background: #1C1C31;
        }
@@ -657,11 +696,11 @@
        }
    }
    .command-data-cockpit-date-picker {
    .command-date-picker {
        background: #1C1C31;
    }
    .command-data-cockpit-date-picker-popper {
    .command-date-picker-popper {
        background: #1C1C31 !important;
        .el-picker-panel {
@@ -799,6 +838,36 @@
        flex: 1;
        display: flex;
        flex-direction: column;
        .el-checkbox {
            width: 16px;
            height: 16px;
            .el-checkbox__input {
                width: 16px;
                height: 16px;
                .el-checkbox__inner {
                    width: 16px;
                    height: 16px;
                    background: transparent !important;
                    border-radius: 2px 2px 2px 2px;
                    border: 2px solid #A1A3D4;
                    box-shadow: none;
                    box-sizing: border-box;
                }
            }
            &.is-checked {
                .el-checkbox__input {
                    .el-checkbox__inner {
                        border: none;
                        background: url("@/assets/images/common/checkbox.png") no-repeat center / 100% 100% !important;
                    }
                }
            }
        }
    }
    .command-table-content-bg {
@@ -806,7 +875,7 @@
    }
}
.command-data-cockpit-table {
.command-table {
    height: 0;
    flex: 1;
    background: transparent !important;
@@ -1066,6 +1135,14 @@
                    .el-input-number {
                        width: 0;
                        flex: 1;
                        .el-input__inner {
                            text-align: left;
                            &::placeholder {
                                text-align: left;
                            }
                        }
                    }
                    .el-cascader {
@@ -1097,11 +1174,11 @@
                        box-shadow: none;
                    }
                    .command-data-cockpit-date-picker {
                    .command-date-picker {
                        background: #2E2E48;
                    }
                    .command-data-cockpit-date-picker-popper {
                    .command-date-picker-popper {
                        background: #2E2E48 !important;
                        .el-picker-panel {
@@ -1371,6 +1448,14 @@
                            .el-input-number {
                                width: 0;
                                flex: 1;
                                .el-input__inner {
                                    text-align: left;
                                    &::placeholder {
                                        text-align: left;
                                    }
                                }
                            }
                            .el-textarea {
@@ -1394,11 +1479,11 @@
                                color: #fff;
                            }
                            .command-data-cockpit-date-picker {
                            .command-date-picker {
                                background: #2E2E48;
                            }
                            .command-data-cockpit-date-picker-popper {
                            .command-date-picker-popper {
                                background: #2E2E48 !important;
                                .el-picker-panel {
applications/drone-command/src/styles/element-ui.scss
@@ -108,662 +108,4 @@
            }
        }
    }
}
.command-drawer-body-basic-container {
    .el-drawer__header {
        margin-bottom: 0;
    }
    .el-drawer__body {
        display: flex;
        flex-direction: column;
    }
}
.command-el-card__body {
    .el-card__body {
        .avue-form {
            padding: 0;
        }
    }
}
.command-public-general-avue-crud {
    .el-table {
        tr {
            min-height: 30px !important;
            line-height: 30px !important;
            box-sizing: border-box !important;
        }
        tr th,
        tr td {
            padding: 6px 0 !important;
            min-height: 30px !important;
            line-height: 30px !important;
            box-sizing: border-box !important;
            div.cell {
                min-height: 30px !important;
                line-height: 30px !important;
            }
        }
    }
}
.command-layer-input {
    .el-input__wrapper {
        padding: 0 8px !important;
        // background: #2D2D2D;
        background-color: transparent !important;
        box-shadow: none !important;
        border: 1px solid #fff;
        .el-input__inner {
            color: #ffffff;
            &::placeholder {
                color: rgba(255, 255, 255, 0.37);
            }
        }
    }
    &.is-disabled {
        .el-input__wrapper {
            background-color: #012a50;
        }
    }
}
.command-button {
    background-color: transparent !important;
    color: #fff !important;
}
.command-el-tree {
    background-color: transparent !important;
    --el-tree-node-hover-bg-color: transparent !important;
    color: #fff !important;
}
.command-layer-search {
    color: #fff !important;
    background-color: transparent !important;
    .el-select__wrapper {
        background-color: transparent !important;
    }
    .el-select__popper.el-popper {
        background-color: transparent !important;
    }
    .el-popper.is-light {
        background-color: transparent !important;
    }
    .el-select__placeholder {
        &.is-transparent {
            color: rgba(255, 255, 255, 0.37) !important;
        }
        &.is-disabled {
            color: rgba(255, 255, 255, 0.37) !important;
        }
    }
    .el-select__selected-item {
        color: #ffffff !important;
        &.is-disabled {
            color: rgba(255, 255, 255, 0.37) !important;
            z-index: 99;
        }
    }
}
.command-select-popper.el-select__popper {
    border: #2D2D2D !important;
    .el-select-dropdown {
        overflow-x: hidden !important;
        .el-scrollbar {
            .el-select-dropdown__wrap {
                background: linear-gradient(180deg, rgba(13, 53, 86, 0.85) 0%, rgba(1, 35, 80, 0.85) 100%);
                border-radius: 0px 0px 8px 8px;
                border: 1px solid;
                border-image: linear-gradient(180deg, #fff, #fff) 1 1;
                overflow-x: hidden !important;
                margin-right: 0 !important;
                .el-select-dropdown__list {
                    padding: 0 !important;
                    .el-select-dropdown__item {
                        background: #2D2D2D !important;
                        color: white;
                        &.hover {
                            background-color: #2D2D2D !important;
                            color: white;
                        }
                        &.selected {
                            color: #fff !important;
                            font-weight: 700;
                        }
                    }
                }
            }
        }
        .el-select-dropdown__empty {
            background: #2D2D2D;
            border-radius: 0px 0px 8px 8px;
            border: 1px solid;
            border-image: linear-gradient(180deg, #fff, #fff) 1 1;
        }
    }
    .el-popper__arrow::before {
        background: #2D2D2D !important;
        border: 1px solid #fff !important;
    }
}
//时间日期选择器
.command-layer-date-picker {
    box-shadow: none !important;
    background: transparent;
    border: 1px solid #fff;
    border-radius: 5px;
    .el-range-editor.is-disabled input {
        background-color: transparent !important;
    }
    .el-range-editor.is-disabled {
        background-color: transparent !important;
    }
    .el-input__wrapper {
        box-shadow: none !important;
        background-color: transparent !important;
        width: 300px;
        &.is-focus {
            box-shadow: none !important;
        }
    }
    .el-range-input {
        color: #fff;
        &::placeholder {
            color: rgba(255, 255, 255, 0.37);
        }
    }
    .el-range-separator {
        color: #ffffff;
    }
}
// 日期下拉框
.command-layer-date-picker-popper {
    background: #012350 !important;
    border: 1px solid !important;
    border-radius: 0px 0px 8px 8px;
    border-image: linear-gradient(180deg, rgba(255, 255, 255, 0), rgba(115, 192, 255, 1)) 1 1 !important;
    .el-picker-panel .el-time-panel {
        background: #012350 !important;
    }
    .el-time-spinner__item {
        color: #fff !important;
    }
    .el-time-spinner__item:hover:not(.is-disabled):not(.is-active) {
        background: transparent !important;
    }
    .el-picker-panel {
        .el-picker-panel__body-wrapper {
            .el-picker-panel__body {
                background: #012350 !important;
                color: #fff !important;
                .el-date-picker__time-header {
                    border: none;
                    .el-date-picker__editor-wrap {
                        .el-time-panel {
                            background: #012350 !important;
                            border-radius: 0px 0px 8px 8px;
                            border: 1px solid !important;
                            border-image: linear-gradient(180deg, rgba(255, 255, 255, 0), rgba(115, 192, 255, 1)) 1 1 !important;
                            // 将 time-picker-popper 的样式移到这里
                            .el-time-panel__header {
                                background: #012350 !important;
                                color: #ffffff !important;
                                border-bottom: 1px solid rgba(255, 255, 255, 0.37) !important;
                            }
                            .el-time-panel__content {
                                .el-time-spinner__item {
                                    color: #e6e6e6 !important;
                                    &:hover {
                                        background: #012350 !important;
                                    }
                                    &.active {
                                        color: #479dff !important;
                                        font-weight: bold;
                                    }
                                }
                            }
                            .el-time-panel__footer {
                                background: #012350 !important;
                                border-top: 1px solid rgba(71, 157, 255, 0.3) !important;
                                .el-button {
                                    color: #fff !important;
                                    &:hover {
                                        color: #479dff !important;
                                    }
                                }
                                .el-time-panel__btn.cancel {
                                    color: #fff !important;
                                    &:hover {
                                        color: #fff !important;
                                    }
                                }
                            }
                        }
                    }
                }
                .el-picker-panel__content {
                    .el-date-range-picker__header {
                        .el-picker-panel__icon-btn {
                            color: #fff !important;
                            &:hover {
                                color: var(--el-color-primary) !important;
                            }
                            .el-icon {
                                &::before {
                                    color: inherit !important;
                                }
                            }
                        }
                        &>div {
                            span {
                                color: #fff !important;
                            }
                        }
                    }
                    .el-date-table {
                        th {
                            color: #fff !important;
                        }
                        td.disabled div {
                            background-color: #00193b !important;
                            color: #505050 !important;
                            cursor: not-allowed;
                        }
                        // td:hover,
                        // td.current:not(.disabled) {
                        //     background: rgba(60, 121, 202) !important;
                        //     color: white !important;
                        // }
                        td.start-date span,
                        td.start-date span,
                        td.end-date span {
                            background-color: #012350 !important;
                        }
                        td.in-range div,
                        td.in-range div:hover,
                        &.is-week-mode .el-date-table__row.current div,
                        &.is-week-mode .el-date-table__row:hover div {
                            background-color: rgba(60, 121, 202) !important;
                        }
                    }
                }
            }
        }
    }
    .el-popper__arrow {
        &::before {
            background: #0d3556 !important;
            border: 1px solid #0d3556 !important;
            box-sizing: border-box;
        }
    }
    .el-picker-panel__sidebar {
        background: #012350;
        color: #fff;
        .el-picker-panel__shortcut {
            color: #ffffff;
        }
    }
    .el-picker-panel__body {
        .el-input.is-disabled .el-input__wrapper {
            background: #012350;
            box-shadow: 0 0 0 0.1rem#409eff;
            color: #fff;
            .el-input__inner {
                color: #fff !important;
            }
        }
        .el-button.is-disabled,
        .el-button.is-disabled:hover {
            background: #012350;
        }
        .el-input__wrapper {
            background: #012350;
            box-shadow: 0 0 0 0.1rem#409eff;
            color: #fff;
            .el-input__inner {
                color: #fff !important;
            }
        }
    }
    .el-picker-panel__footer {
        background: #012350;
        color: #fff;
        border-top: none;
        .el-button--small {
            box-shadow: 0 0 0 0.1rem#409eff;
            background-color: #012350;
            color: #fff;
            border: none;
            &:hover {
                background-color: #012350;
                color: #fff;
                border-color: #409eff;
            }
        }
    }
}
.command-layer-time-picker-popper {
    background: rgba(0, 0, 0, 0.8) !important;
    border-radius: 0px 0px 8px 8px;
    border: 1px solid !important;
    border-image: linear-gradient(180deg, rgba(255, 255, 255, 0), rgba(115, 192, 255, 1)) 1 1 !important;
    .el-popper__arrow::before {
        background: rgba(0, 0, 0, 0.8) !important;
        border: 1px solid #479dff !important;
    }
    .el-time-panel__header {
        background: rgba(0, 0, 0, 0.8) !important;
        color: #ffffff !important;
        border-bottom: 1px solid rgba(71, 157, 255, 0.3) !important;
    }
    .el-time-panel__content {
        // background: #012350 !important;
        .el-time-spinner__item {
            color: #e6e6e6 !important;
            &:hover {
                background: rgba(71, 157, 255, 0.3) !important;
            }
            &.active {
                color: #479dff !important;
                font-weight: bold;
            }
        }
    }
    .el-time-panel__footer {
        background: rgba(0, 0, 0, 0.8) !important;
        border-top: 1px solid rgba(71, 157, 255, 0.3) !important;
        .el-button {
            color: #fff !important;
            &:hover {
                color: #479dff !important;
            }
        }
        .el-time-panel__btn.cancel {
            color: #fff !important;
            &:hover {
                color: #fff !important;
            }
        }
    }
}
.command-custom-qrcode-popover {
    //background: url("@/assets/images/home/eventOverviewDetail/qrCodeBg.png") no-repeat center center !important;
    //background-size: cover !important;
    border: none !important;
    border-radius: 0 !important;
    box-shadow: none !important;
    padding: 5px;
    min-width: 173px !important;
    height: 180px !important;
    /* 隐藏默认箭头 */
    .el-popper__arrow {
        display: none !important;
    }
    /* 调整二维码内容区域样式 */
    .qrcode-content {
        background: #fff;
        padding: 5px;
        display: flex;
        justify-content: center;
        align-items: center;
        width: 146px;
        height: 130px;
        margin-top: 12px;
        .close-btn {
            position: absolute;
            top: 3px;
            right: 3px;
            width: 20px;
            height: 20px;
            color: white;
            border-radius: 50%;
            display: flex;
            align-items: center;
            justify-content: center;
            cursor: pointer;
            z-index: 100;
        }
    }
}
.command-dialog-video {
    background: #0f1929;
    box-shadow: inset 0px -50px 50px 0px rgba(27, 148, 255, 0.13);
    border-radius: 20px 0px 0px 0px;
    border: 2px solid;
    padding: 0 !important;
    border-image: linear-gradient(180deg,
            rgba(81, 168, 255, 0),
            rgba(48, 111, 202, 1),
            rgba(255, 255, 255, 1),
            rgba(27, 148, 255, 1)) 2 2;
    .el-dialog__header {
        width: 100%;
        height: 47px;
        //padding: 0;
        margin-bottom: 14px;
        //background: url("/src/assets/images/home/inspection-vector.png") no-repeat center;
        //background-size: 100% 100%;
        font-weight: bold;
        font-size: 16px;
        line-height: 47px;
    }
    .el-dialog__title {
        width: 112px;
        font-family: Segoe UI, Segoe UI;
        font-weight: bold;
        font-size: 16px;
        text-shadow: 0px 0px 5px rgba(154, 218, 255, 0.6);
        text-align: left;
        font-style: normal;
        text-transform: none;
        background: linear-gradient(90deg, #fbfdff 0%, #86d4ff 100%);
        margin-left: 16px;
        -webkit-background-clip: text;
        -webkit-text-fill-color: transparent;
    }
    .el-dialog .el-dialog__header {
        padding: 0px !important;
        padding-left: 0px !important;
    }
    .el-scrollbar__thumb {
        background: #13c6ff !important;
    }
}
//======以下针对表格功能 增删查改样式和弹窗=========
.command-dialog-mange {
    .el-dialog__body {
        padding: 2rem 2rem 4rem;
        flex: 1;
        overflow: scroll;
        border-top: 0.1rem solid #f0f0f0;
    }
    .el-dialog__footer {
        z-index: 2;
        display: block;
        padding: 1rem 1.6rem;
        box-sizing: border-box;
        border-top: 0.1rem solid #f0f0f0;
        width: 100%;
        position: absolute;
        left: 0;
        bottom: 0;
        background-color: #fff;
        text-align: right;
    }
}
.command-search-mange {
    height: 40px;
    .search-contain {
        display: flex;
        justify-content: space-between;
    }
}
.command-form-mange {
    .el-form-item {
        width: 300px;
        .el-form-item__content {
            width: 100%;
        }
        .el-form-item__label {
            width: 120px;
        }
    }
}
.command-form-search {
    .el-form-item {
        width: 100%;
        .el-form-item__label {
            width: 80px;
        }
        .el-form-item__content {
            display: flex;
            flex: 1;
        }
    }
}
.command-table-mange {
    th.el-table__cell {
        color: rgba(0, 0, 0, .85);
        background-color: #fafafa;
    }
}
.table-view-mange {
    width: 100%;
    border-top: 0.1rem solid #ebeef5;
    border-left: 0.1rem solid #ebeef5;
    margin-left: 0;
    margin-right: 0;
    .el-col {
        padding-left: 0;
        padding-right: 0;
        margin-bottom: 0;
        height: 32px;
        line-height: 32px;
        border-right: 0.1rem solid #ebeef5;
        text-align: center;
        align-items: center;
        .el-input__wrapper {
            box-shadow: none !important;
            border-bottom: 0.1rem solid #ebeef5;
        }
    }
    .label {
        color: #909399;
        box-sizing: border-box;
        background: #fafafa;
    }
}
applications/drone-command/src/utils/cesium/publicCesium.js
@@ -2,6 +2,7 @@
import * as Cesium from 'cesium'
import { Cartesian3, Terrain, Viewer } from 'cesium'
import store from '@/store/index'
import jaGeojsonRaw from '@/assets/geojson/ja.geojson?raw'
import getBaseConfig from '@/buildConfig/config'
@@ -32,6 +33,36 @@
/**
 * 公共的Cesium (蓝色,2d)
 */
const DEFAULT_VIEW_RECTANGLE = (() => {
    try {
        const geojson = JSON.parse(jaGeojsonRaw)
        let west = Infinity
        let east = -Infinity
        let south = Infinity
        let north = -Infinity
        const walk = coords => {
            if (!Array.isArray(coords)) return
            if (typeof coords[0] === 'number' && typeof coords[1] === 'number') {
                const lng = coords[0]
                const lat = coords[1]
                if (!Number.isFinite(lng) || !Number.isFinite(lat)) return
                west = Math.min(west, lng)
                east = Math.max(east, lng)
                south = Math.min(south, lat)
                north = Math.max(north, lat)
                return
            }
            coords.forEach(walk)
        }
        geojson?.features?.forEach(feature => walk(feature?.geometry?.coordinates))
        if ([west, east, south, north].every(Number.isFinite)) {
            return Cesium.Rectangle.fromDegrees(west, south, east, north)
        }
    } catch (error) {}
    return Cesium.Rectangle.fromDegrees(66, 4, 135, 53.55)
})()
// 封装的不用管
let cn = {
@@ -106,7 +137,7 @@
        } = options
        Cesium.Camera.DEFAULT_VIEW_FACTOR = -0.45
        // 西南东北,默认显示中国
        Cesium.Camera.DEFAULT_VIEW_RECTANGLE = Cesium.Rectangle.fromDegrees(66, 4, 135, 53.55)
        Cesium.Camera.DEFAULT_VIEW_RECTANGLE = DEFAULT_VIEW_RECTANGLE
        const viewerOptions = {
            infoBox: false, // 禁用沙箱,解决控制台报错
            animation: false, // 左下角的动画仪表盘
@@ -881,4 +912,4 @@
            this.viewer?.imageryLayers.remove(imageryLayers)
        }
    }
}
}
applications/drone-command/src/views/api.txt
@@ -1,22 +1,33 @@
## 列表
## 信号干扰,诱导驱离
**接口地址**:`/drone-fw/area/fwAreaDivide/list`
**接口地址**:`/drone-fw/cockpit/dataCockpit/interferenceAndExpulsion`
**请求方式**:`GET`
**请求方式**:`POST`
**请求数据类型**:`application/x-www-form-urlencoded`
**请求数据类型**:`application/json`
**响应数据类型**:`*/*`
**接口描述**:<p>传入filterSelected或sceneId</p>
**接口描述**:<p>传入fwEffectEval</p>
**请求示例**:
```javascript
{
  "alarmRecordId": 0,
  "counterWay": ""
}
```
**请求参数**:
@@ -27,8 +38,9 @@
| 参数名称 | 参数说明 | 请求类型    | 是否必须 | 数据类型 | schema |
| -------- | -------- | ----- | -------- | -------- | ------ |
|filterSelected|是否过滤已被选择的数据(1过滤 0不过滤)|query|false|integer(int32)||
|sceneId|场景id|query|false|integer(int64)||
|fwEffectEvalParam|fwEffectEvalParam|body|true|FwEffectEvalParam|FwEffectEvalParam|
|&emsp;&emsp;alarmRecordId|告警记录ID(ja_fw_drone_alarm_record.id)||false|integer(int64)||
|&emsp;&emsp;counterWay|反制方式:1.信号干扰/2.诱导驱离/无||false|string||
**响应状态**:
@@ -36,7 +48,8 @@
| 状态码 | 说明 | schema |
| -------- | -------- | ----- | 
|200|OK|R«List«FwAreaDivide对象»»|
|200|OK|R|
|201|Created||
|401|Unauthorized||
|403|Forbidden||
|404|Not Found||
@@ -48,32 +61,7 @@
| 参数名称 | 参数说明 | 类型 | schema |
| -------- | -------- | ----- |----- | 
|code|状态码|integer(int32)|integer(int32)|
|data|承载数据|array|FwAreaDivide对象|
|&emsp;&emsp;areaCode|区域编码|string||
|&emsp;&emsp;areaName|区域名称|string||
|&emsp;&emsp;areaSize|区域面积(km²)|number||
|&emsp;&emsp;areaType|区域类型:报警区/重点管制区|string||
|&emsp;&emsp;controlLevel|管控级别:日常/重点/严密|string||
|&emsp;&emsp;createDept|创建部门|integer(int64)||
|&emsp;&emsp;createTime|创建时间|string(date-time)||
|&emsp;&emsp;createUser|创建人|integer(int64)||
|&emsp;&emsp;deviceIds|关联设备ID,逗号分隔|string||
|&emsp;&emsp;flyDateEnd|可飞行日期时间-结束|string(date-time)||
|&emsp;&emsp;flyDateStart|可飞行日期时间-开始|string(date-time)||
|&emsp;&emsp;geom|经纬度面(存储地理面数据)|string||
|&emsp;&emsp;id|主键id|integer(int64)||
|&emsp;&emsp;isDeleted|是否已删除|integer(int32)||
|&emsp;&emsp;latitude|区域中心纬度|number(double)||
|&emsp;&emsp;longitude|区域中心经度|number(double)||
|&emsp;&emsp;policeStationContactPerson|派出所联系人|string||
|&emsp;&emsp;policeStationContactPhone|派出所联系电话|string||
|&emsp;&emsp;policeStationId|关联派出所id|integer(int64)||
|&emsp;&emsp;policeStationName|派出所名称|string||
|&emsp;&emsp;responseMechanism|响应机制内容|string||
|&emsp;&emsp;status|业务状态|integer(int32)||
|&emsp;&emsp;triggerCondition|触发条件|string||
|&emsp;&emsp;updateTime|更新时间|string(date-time)||
|&emsp;&emsp;updateUser|更新人|integer(int64)||
|data|承载数据|object||
|msg|返回消息|string||
|success|是否成功|boolean||
@@ -82,35 +70,7 @@
```javascript
{
    "code": 0,
    "data": [
        {
            "areaCode": "",
            "areaName": "",
            "areaSize": 0,
            "areaType": "",
            "controlLevel": "",
            "createDept": 0,
            "createTime": "",
            "createUser": 0,
            "deviceIds": "",
            "flyDateEnd": "",
            "flyDateStart": "",
            "geom": "",
            "id": 0,
            "isDeleted": 0,
            "latitude": 0,
            "longitude": 0,
            "policeStationContactPerson": "",
            "policeStationContactPhone": "",
            "policeStationId": 0,
            "policeStationName": "",
            "responseMechanism": "",
            "status": 0,
            "triggerCondition": "",
            "updateTime": "",
            "updateUser": 0
        }
    ],
    "data": {},
    "msg": "",
    "success": true
}
applications/drone-command/src/views/areaManage/areaStatistics/index.vue
@@ -2,12 +2,12 @@
    <basic-container>
        <el-form ref="queryParamsRef" :model="searchParams" class="command-page-history-search">
            <el-form-item label="区域名称" prop="areaName">
                <el-input class="command-data-cockpit-search-input" v-model="searchParams.areaName" placeholder="请输入"
                <el-input class="command-search-input" v-model="searchParams.areaName" placeholder="请输入"
                    clearable @clear="handleSearch" />
            </el-form-item>
            <el-form-item label="区域类型" prop="areaType">
                <el-select class="command-data-cockpit-select" popper-class="command-data-cockpit-select-popper"
                <el-select class="command-select" popper-class="command-select-popper"
                    v-model="searchParams.areaType" placeholder="请选择" clearable @change="handleSearch">
                    <el-option v-for="item in dictObj.areaType" :key="item.dictKey" :label="item.dictValue"
                        :value="item.dictKey" />
@@ -15,7 +15,7 @@
            </el-form-item>
            <el-form-item label="场景类型" prop="sceneType">
                <el-select class="command-data-cockpit-select" popper-class="command-data-cockpit-select-popper"
                <el-select class="command-select" popper-class="command-select-popper"
                    v-model="searchParams.sceneType" placeholder="请选择" clearable @change="handleSearch">
                    <el-option v-for="item in dictObj.sceneType" :key="item.dictKey" :label="item.dictValue"
                        :value="item.dictKey" />
@@ -30,7 +30,7 @@
        <div class="command-table-container" v-loading="loading" element-loading-background="rgba(5, 5, 15, 0.6)">
            <div class="command-table-content command-table-content-bg">
                <el-table class="command-data-cockpit-table" :data="list">
                <el-table class="command-table" :data="list">
                    <el-table-column type="index" show-overflow-tooltip width="64" label="序号" />
                    <el-table-column prop="areaName" show-overflow-tooltip label="区域名称" />
                    <el-table-column prop="areaType" show-overflow-tooltip label="区域类型">
@@ -58,7 +58,7 @@
            </div>
            <div class="command-table-pagination">
                <el-pagination popper-class="command-data-cockpit-select-popper"
                <el-pagination popper-class="command-select-popper"
                    v-model:current-page="searchParams.current" v-model:page-size="searchParams.size"
                    layout="total, prev, pager, next, sizes" :total="total" @change="getList" />
            </div>
applications/drone-command/src/views/areaManage/defenseZone/FormDiaLog.vue
@@ -34,7 +34,7 @@
                    <div class="detail-title">关联场景</div>
                    <div class="command-table-container">
                        <div class="command-table-content">
                            <el-table class="command-data-cockpit-table" :data="sceneList" row-key="id">
                            <el-table class="command-table" :data="sceneList" row-key="id">
                                <el-table-column prop="sceneName" label="场景名称" />
                                <el-table-column prop="sceneType" label="场景类型">
                                    <template v-slot="{ row }">
@@ -49,7 +49,7 @@
                <el-form class="dialog-form" v-else ref="formRef" :model="formData" :rules="rules" :disabled="readonly"
                    label-width="96px">
                    <el-form-item label="防区名称" prop="zoneName">
                        <el-input class="command-data-cockpit-search-input" v-model="formData.zoneName" maxlength="50"
                        <el-input class="command-search-input" v-model="formData.zoneName" maxlength="50"
                            placeholder="请输入" clearable />
                    </el-form-item>
                    <el-form-item label="防区面积" prop="zoneArea">
@@ -62,12 +62,12 @@
                                关联场景
                            </div>
                            <el-input class="command-data-cockpit-search-input" v-model="searchName" placeholder="请输入"
                            <el-input class="command-search-input" v-model="searchName" placeholder="请输入"
                                clearable></el-input>
                        </div>
                        <el-form-item prop="defenseSceneIds" label-width="0">
                            <el-table class="command-data-cockpit-table" ref="sceneTableRef"
                            <el-table class="command-table" ref="sceneTableRef"
                                :data="sceneList.filter(item => item.sceneName.includes(searchName))" row-key="id"
                                @selection-change="handleSceneSelectionChange">
                                <el-table-column type="selection" width="55" :reserve-selection="true" />
applications/drone-command/src/views/areaManage/defenseZone/index.vue
@@ -2,7 +2,7 @@
    <basic-container>
        <el-form ref="queryParamsRef" :model="searchParams" class="command-page-history-search">
            <el-form-item label="防区名称" prop="zoneName">
                <el-input class="command-data-cockpit-search-input" v-model="searchParams.zoneName" placeholder="请输入"
                <el-input class="command-search-input" v-model="searchParams.zoneName" placeholder="请输入"
                    clearable @clear="handleSearch" />
            </el-form-item>
@@ -19,7 +19,7 @@
        <div class="command-table-container" v-loading="loading" element-loading-background="rgba(5, 5, 15, 0.6)">
            <div class="command-table-content command-table-content-bg">
                <el-table class="command-data-cockpit-table" :data="list" @selection-change="handleSelectionChange">
                <el-table class="command-table" :data="list" @selection-change="handleSelectionChange">
                    <el-table-column type="selection" width="46" />
                    <el-table-column type="index" show-overflow-tooltip width="64" label="序号" />
                    <el-table-column prop="zoneName" show-overflow-tooltip label="防区名称" />
@@ -38,7 +38,7 @@
            </div>
            <div class="command-table-pagination">
                <el-pagination popper-class="command-data-cockpit-select-popper"
                <el-pagination popper-class="command-select-popper"
                    v-model:current-page="searchParams.current" v-model:page-size="searchParams.size"
                    layout="total, prev, pager, next, sizes" :total="total" @change="getList" />
            </div>
applications/drone-command/src/views/areaManage/partition/FormDiaLog.vue
@@ -63,7 +63,7 @@
                    <div class="detail-title">关联设备</div>
                    <div class="command-table-container">
                        <div class="command-table-content">
                            <el-table class="command-data-cockpit-table" ref="deviceTableRef" :data="deviceOptions"
                            <el-table class="command-table" ref="deviceTableRef" :data="deviceOptions"
                                row-key="id">
                                <el-table-column prop="deviceName" label="设备名称" />
                                <el-table-column prop="deviceType" label="类型">
@@ -79,7 +79,7 @@
                <el-form class="dialog-form" v-else ref="formRef" :model="formData" :rules="rules" :disabled="readonly"
                    label-width="96px">
                    <el-form-item label="区域名称" prop="areaName">
                        <el-input class="command-data-cockpit-search-input" v-model="formData.areaName" maxlength="50"
                        <el-input class="command-search-input" v-model="formData.areaName" maxlength="50"
                            placeholder="请输入" clearable />
                    </el-form-item>
                    <el-form-item label="区域位置" prop="longitude">
@@ -89,35 +89,35 @@
                        <div class="val">{{ formData.areaSize || '-' }}k㎡</div>
                    </el-form-item>
                    <el-form-item label="区域类型" prop="areaType">
                        <el-select class="command-data-cockpit-select" popper-class="command-data-cockpit-select-popper"
                        <el-select class="command-select" popper-class="command-select-popper"
                            v-model="formData.areaType" placeholder="请选择" clearable>
                            <el-option v-for="item in dictObj.areaType" :key="item.dictKey" :label="item.dictValue"
                                :value="item.dictKey" />
                        </el-select>
                    </el-form-item>
                    <el-form-item label="响应机制" prop="responseMechanism">
                        <el-input class="command-data-cockpit-search-input" v-model="formData.responseMechanism"
                        <el-input class="command-search-input" v-model="formData.responseMechanism"
                            maxlength="200" placeholder="请输入" clearable />
                    </el-form-item>
                    <el-form-item label="触发条件" prop="triggerCondition">
                        <el-input class="command-data-cockpit-search-input" v-model="formData.triggerCondition"
                        <el-input class="command-search-input" v-model="formData.triggerCondition"
                            maxlength="200" placeholder="请输入" clearable />
                    </el-form-item>
                    <el-form-item label="管控级别" prop="controlLevel">
                        <el-select class="command-data-cockpit-select" popper-class="command-data-cockpit-select-popper"
                        <el-select class="command-select" popper-class="command-select-popper"
                            v-model="formData.controlLevel" placeholder="请选择" clearable>
                            <el-option v-for="item in dictObj.controlLevel" :key="item.dictKey" :label="item.dictValue"
                                :value="item.dictKey" />
                        </el-select>
                    </el-form-item>
                    <el-form-item label="可飞行时段" prop="flyDateStart">
                        <el-date-picker class="command-data-cockpit-date-picker"
                            popper-class="command-data-cockpit-date-picker-popper" v-model="flyDateRange"
                        <el-date-picker class="command-date-picker"
                            popper-class="command-date-picker-popper" v-model="flyDateRange"
                            type="datetimerange" range-separator="至" start-placeholder="开始时间" end-placeholder="结束时间"
                            value-format="YYYY-MM-DD HH:mm:ss" clearable />
                    </el-form-item>
                    <el-form-item label="关联派出所" prop="policeStationId">
                        <el-select class="command-data-cockpit-select" popper-class="command-data-cockpit-select-popper"
                        <el-select class="command-select" popper-class="command-select-popper"
                            v-model="formData.policeStationId" placeholder="请选择" clearable>
                            <el-option v-for="item in policeStationOptions" :key="item.id" :label="item.stationName"
                                :value="item.id" />
@@ -130,12 +130,12 @@
                                关联设备
                            </div>
                            <el-input class="command-data-cockpit-search-input" v-model="searchName" placeholder="请输入"
                            <el-input class="command-search-input" v-model="searchName" placeholder="请输入"
                                clearable></el-input>
                        </div>
                        <el-form-item prop="deviceIds" label-width="0">
                            <el-table class="command-data-cockpit-table" ref="deviceTableRef"
                            <el-table class="command-table" ref="deviceTableRef"
                                :data="deviceOptions.filter(item => item.deviceName.includes(searchName))" row-key="id"
                                @selection-change="handleDeviceSelectionChange">
                                <el-table-column type="selection" width="55" :reserve-selection="true" />
applications/drone-command/src/views/areaManage/partition/index.vue
@@ -2,12 +2,12 @@
    <basic-container>
        <el-form ref="queryParamsRef" :model="searchParams" class="command-page-history-search">
            <el-form-item label="区域名称" prop="areaName">
                <el-input class="command-data-cockpit-search-input" v-model="searchParams.areaName" placeholder="请输入"
                <el-input class="command-search-input" v-model="searchParams.areaName" placeholder="请输入"
                    clearable @clear="handleSearch" />
            </el-form-item>
            <el-form-item label="区域类型" prop="areaType">
                <el-select class="command-data-cockpit-select" popper-class="command-data-cockpit-select-popper"
                <el-select class="command-select" popper-class="command-select-popper"
                    v-model="searchParams.areaType" placeholder="请选择" clearable @change="handleSearch">
                    <el-option v-for="item in dictObj.areaType" :key="item.dictKey" :label="item.dictValue"
                        :value="item.dictKey" />
@@ -27,7 +27,7 @@
        <div class="command-table-container" v-loading="loading" element-loading-background="rgba(5, 5, 15, 0.6)">
            <div class="command-table-content command-table-content-bg">
                <el-table class="command-data-cockpit-table" :data="list" @selection-change="handleSelectionChange">
                <el-table class="command-table" :data="list" @selection-change="handleSelectionChange">
                    <el-table-column type="selection" width="46" />
                    <el-table-column type="index" show-overflow-tooltip width="64" label="序号" />
                    <el-table-column prop="areaName" show-overflow-tooltip width="150" label="区域名称" />
@@ -66,7 +66,7 @@
            </div>
            <div class="command-table-pagination">
                <el-pagination popper-class="command-data-cockpit-select-popper"
                <el-pagination popper-class="command-select-popper"
                    v-model:current-page="searchParams.current" v-model:page-size="searchParams.size"
                    layout="total, prev, pager, next, sizes" :total="total" @change="getList" />
            </div>
applications/drone-command/src/views/areaManage/precinctInfo/FormDiaLog.vue
@@ -26,19 +26,19 @@
            <el-row>
                <el-col :span="12">
                    <el-form-item label="派出所名称" prop="stationName">
                        <el-input class="command-data-cockpit-search-input" v-model="formData.stationName" maxlength="50"
                        <el-input class="command-search-input" v-model="formData.stationName" maxlength="50"
                            placeholder="请输入" clearable />
                    </el-form-item>
                </el-col>
                <el-col :span="12">
                    <el-form-item label="联系人" prop="contactPerson">
                        <el-input class="command-data-cockpit-search-input" v-model="formData.contactPerson" maxlength="50"
                        <el-input class="command-search-input" v-model="formData.contactPerson" maxlength="50"
                            placeholder="请输入" clearable />
                    </el-form-item>
                </el-col>
                <el-col :span="12">
                    <el-form-item label="联系方式" prop="contactPhone">
                        <el-input class="command-data-cockpit-search-input" v-model="formData.contactPhone" maxlength="50"
                        <el-input class="command-search-input" v-model="formData.contactPhone" maxlength="50"
                            placeholder="请输入" clearable />
                    </el-form-item>
                </el-col>
applications/drone-command/src/views/areaManage/precinctInfo/index.vue
@@ -2,7 +2,7 @@
    <basic-container>
        <el-form ref="queryParamsRef" :model="searchParams" class="command-page-history-search">
            <el-form-item label="派出所名称" prop="stationName">
                <el-input class="command-data-cockpit-search-input" v-model="searchParams.stationName" placeholder="请输入"
                <el-input class="command-search-input" v-model="searchParams.stationName" placeholder="请输入"
                    clearable @clear="handleSearch" />
            </el-form-item>
@@ -19,7 +19,7 @@
        <div class="command-table-container" v-loading="loading" element-loading-background="rgba(5, 5, 15, 0.6)">
            <div class="command-table-content command-table-content-bg">
                <el-table class="command-data-cockpit-table" :data="list" @selection-change="handleSelectionChange">
                <el-table class="command-table" :data="list" @selection-change="handleSelectionChange">
                    <el-table-column type="selection" width="46" />
                    <el-table-column type="index" show-overflow-tooltip width="64" label="序号" />
                    <el-table-column prop="stationName" show-overflow-tooltip label="派出所名称" />
@@ -38,7 +38,7 @@
            </div>
            <div class="command-table-pagination">
                <el-pagination popper-class="command-data-cockpit-select-popper"
                <el-pagination popper-class="command-select-popper"
                    v-model:current-page="searchParams.current" v-model:page-size="searchParams.size"
                    layout="total, prev, pager, next, sizes" :total="total" @change="getList" />
            </div>
applications/drone-command/src/views/areaManage/sceneConfig/FormDiaLog.vue
@@ -53,7 +53,7 @@
                    <div class="detail-title">关联区域</div>
                    <div class="command-table-container">
                        <div class="command-table-content">
                            <el-table class="command-data-cockpit-table" ref="areaTableRef" :data="areaList" row-key="id">
                            <el-table class="command-table" ref="areaTableRef" :data="areaList" row-key="id">
                                <el-table-column prop="areaName" label="区域名称" />
                                <el-table-column prop="areaType" label="区域类型">
                                    <template v-slot="{ row }">
@@ -68,29 +68,29 @@
                <el-form class="dialog-form" v-else ref="formRef" :model="formData" :rules="rules" :disabled="readonly"
                    label-width="96px">
                    <el-form-item label="场景名称" prop="sceneName">
                        <el-input class="command-data-cockpit-search-input" v-model="formData.sceneName" maxlength="50"
                        <el-input class="command-search-input" v-model="formData.sceneName" maxlength="50"
                            placeholder="请输入" clearable />
                    </el-form-item>
                    <el-form-item label="指挥点位置" prop="longitude">
                        <div class="val">{{ formatLocation(formData) }}</div>
                    </el-form-item>
                    <el-form-item label="场景类型" prop="sceneType">
                        <el-select class="command-data-cockpit-select" popper-class="command-data-cockpit-select-popper"
                        <el-select class="command-select" popper-class="command-select-popper"
                            v-model="formData.sceneType" placeholder="请选择" clearable>
                            <el-option v-for="item in dictObj.sceneType" :key="item.dictKey" :label="item.dictValue"
                                :value="item.dictKey" />
                        </el-select>
                    </el-form-item>
                    <el-form-item label="负责人" prop="defenseLeader">
                        <el-input class="command-data-cockpit-search-input" v-model="formData.defenseLeader" maxlength="50"
                        <el-input class="command-search-input" v-model="formData.defenseLeader" maxlength="50"
                            placeholder="请输入" clearable />
                    </el-form-item>
                    <el-form-item label="负责人电话" prop="leaderPhone">
                        <el-input class="command-data-cockpit-search-input" v-model="formData.leaderPhone" maxlength="50"
                        <el-input class="command-search-input" v-model="formData.leaderPhone" maxlength="50"
                            placeholder="请输入" clearable />
                    </el-form-item>
                    <el-form-item label="设备模式" prop="deviceMode">
                        <el-select class="command-data-cockpit-select" popper-class="command-data-cockpit-select-popper"
                        <el-select class="command-select" popper-class="command-select-popper"
                            v-model="formData.deviceMode" placeholder="请选择" clearable>
                            <el-option v-for="item in dictObj.deviceMode" :key="item.dictKey" :label="item.dictValue"
                                :value="item.dictKey" />
@@ -106,12 +106,12 @@
                                关联区域
                            </div>
                            <el-input class="command-data-cockpit-search-input" v-model="searchName" placeholder="请输入"
                            <el-input class="command-search-input" v-model="searchName" placeholder="请输入"
                                clearable></el-input>
                        </div>
                        <el-form-item prop="areaDivideIds" label-width="0">
                            <el-table class="command-data-cockpit-table" ref="areaTableRef"
                            <el-table class="command-table" ref="areaTableRef"
                                :data="areaList.filter(item => item.areaName.includes(searchName))" row-key="id"
                                @selection-change="handleAreaSelectionChange">
                                <el-table-column type="selection" width="55" :reserve-selection="true" />
applications/drone-command/src/views/areaManage/sceneConfig/index.vue
@@ -3,7 +3,7 @@
        <el-form ref="queryParamsRef" :model="searchParams" class="command-page-history-search">
            <el-form-item label="场景名称" prop="sceneName">
                <el-input
                    class="command-data-cockpit-search-input"
                    class="command-search-input"
                    v-model="searchParams.sceneName"
                    placeholder="请输入"
                    clearable
@@ -13,8 +13,8 @@
            <el-form-item label="场景类型" prop="sceneType">
                <el-select
                    class="command-data-cockpit-select"
                    popper-class="command-data-cockpit-select-popper"
                    class="command-select"
                    popper-class="command-select-popper"
                    v-model="searchParams.sceneType"
                    placeholder="请选择"
                    clearable
@@ -31,8 +31,8 @@
            <el-form-item label="场景状态" prop="status">
                <el-select
                    class="command-data-cockpit-select"
                    popper-class="command-data-cockpit-select-popper"
                    class="command-select"
                    popper-class="command-select-popper"
                    v-model="searchParams.status"
                    placeholder="请选择"
                    clearable
@@ -60,7 +60,7 @@
        <div class="command-table-container" v-loading="loading" element-loading-background="rgba(5, 5, 15, 0.6)">
            <div class="command-table-content command-table-content-bg">
                <el-table class="command-data-cockpit-table" :data="list" @selection-change="handleSelectionChange">
                <el-table class="command-table" :data="list" @selection-change="handleSelectionChange">
                    <el-table-column type="selection" width="46" />
                    <el-table-column type="index" show-overflow-tooltip width="64" label="序号" />
@@ -92,7 +92,7 @@
            <div class="command-table-pagination">
                <el-pagination
                    popper-class="command-data-cockpit-select-popper"
                    popper-class="command-select-popper"
                    v-model:current-page="searchParams.current"
                    v-model:page-size="searchParams.size"
                    layout="total, prev, pager, next, sizes"
applications/drone-command/src/views/basicManage/deviceScrap/index.vue
@@ -3,7 +3,7 @@
        <el-form ref="queryParamsRef" :model="searchParams" class="command-page-history-search">
            <el-form-item label="设备名称" prop="deviceName">
                <el-input
                    class="command-data-cockpit-search-input"
                    class="command-search-input"
                    v-model="searchParams.deviceName"
                    placeholder="请输入"
                    clearable
@@ -13,8 +13,8 @@
            <el-form-item label="设备类型" prop="deviceType">
                <el-select
                    class="command-data-cockpit-select"
                    popper-class="command-data-cockpit-select-popper"
                    class="command-select"
                    popper-class="command-select-popper"
                    v-model="searchParams.deviceType"
                    placeholder="请选择"
                    clearable
@@ -31,8 +31,8 @@
            <el-form-item label="所属部门" prop="belongDept">
                <el-tree-select
                    class="command-data-cockpit-select"
                    popper-class="command-data-cockpit-tree-select-popper"
                    class="command-select"
                    popper-class="command-tree-select-popper"
                    v-model="searchParams.belongDept"
                    :data="deptTree"
                    :props="treeProps"
@@ -51,7 +51,7 @@
        <div class="command-table-container" v-loading="loading" element-loading-background="rgba(5, 5, 15, 0.6)">
            <div class="command-table-content command-table-content-bg">
                <el-table class="command-data-cockpit-table" :data="list">
                <el-table class="command-table" :data="list">
                    <el-table-column type="index" show-overflow-tooltip width="64" label="序号" />
                    <el-table-column prop="deviceName" show-overflow-tooltip label="设备名称" />
                    <el-table-column prop="deviceType" show-overflow-tooltip label="设备类型">
@@ -82,7 +82,7 @@
            <div class="command-table-pagination">
                <el-pagination
                    popper-class="command-data-cockpit-select-popper"
                    popper-class="command-select-popper"
                    v-model:current-page="searchParams.current"
                    v-model:page-size="searchParams.size"
                    layout="total, prev, pager, next, sizes"
applications/drone-command/src/views/basicManage/deviceStock/DeviceScrapDiaLog.vue
@@ -4,17 +4,17 @@
            <el-row>
                <el-col :span="24">
                    <el-form-item label="报废原因" prop="scrapReason">
                        <el-input class="command-data-cockpit-search-input" v-model="formData.scrapReason" maxlength="200" type="textarea" placeholder="请输入" clearable />
                        <el-input class="command-search-input" v-model="formData.scrapReason" maxlength="200" type="textarea" placeholder="请输入" clearable />
                    </el-form-item>
                </el-col>
                <el-col :span="24">
                    <el-form-item label="处置方式" prop="disposeWay">
                        <el-input class="command-data-cockpit-search-input" v-model="formData.disposeWay" maxlength="200" type="textarea" placeholder="请输入" clearable />
                        <el-input class="command-search-input" v-model="formData.disposeWay" maxlength="200" type="textarea" placeholder="请输入" clearable />
                    </el-form-item>
                </el-col>
                <el-col :span="12">
                    <el-form-item label="报废时间" prop="scrapTime">
                        <el-date-picker class="command-data-cockpit-date-picker" popper-class="command-data-cockpit-date-picker-popper"
                        <el-date-picker class="command-date-picker" popper-class="command-date-picker-popper"
                            v-model="formData.scrapTime"
                            type="datetime"
                            placeholder="选择日期"
applications/drone-command/src/views/basicManage/deviceStock/DeviceTrackDiaLog.vue
@@ -4,21 +4,21 @@
            <el-row>
                <el-col :span="12">
                    <el-form-item label="负责人" prop="charger">
                        <el-select class="command-data-cockpit-select" popper-class="command-data-cockpit-select-popper" v-model="formData.charger" placeholder="请选择" clearable>
                        <el-select class="command-select" popper-class="command-select-popper" v-model="formData.charger" placeholder="请选择" clearable>
                            <el-option v-for="item in userList" :key="item.id" :label="item.name" :value="item.name" />
                        </el-select>
                    </el-form-item>
                </el-col>
                <el-col :span="12">
                    <el-form-item label="联系电话" prop="contactPhone">
                        <el-input class="command-data-cockpit-search-input" v-model="formData.contactPhone" maxlength="50" placeholder="请输入" clearable />
                        <el-input class="command-search-input" v-model="formData.contactPhone" maxlength="50" placeholder="请输入" clearable />
                    </el-form-item>
                </el-col>
                <el-col :span="12">
                    <el-form-item label="出库去向" prop="outTarget">
                        <el-select
                            class="command-data-cockpit-select"
                            popper-class="command-data-cockpit-select-popper"
                            class="command-select"
                            popper-class="command-select-popper"
                            v-model="formData.outTarget"
                            placeholder="请选择"
                            clearable
@@ -29,7 +29,7 @@
                </el-col>
                <el-col :span="12">
                    <el-form-item label="出库时间" prop="outTime">
                        <el-date-picker class="command-data-cockpit-date-picker" popper-class="command-data-cockpit-date-picker-popper"
                        <el-date-picker class="command-date-picker" popper-class="command-date-picker-popper"
                            v-model="formData.outTime"
                            type="date"
                            placeholder="选择日期"
@@ -40,7 +40,7 @@
                </el-col>
                <el-col :span="12">
                    <el-form-item label="用途" prop="purpose">
                        <el-input class="command-data-cockpit-search-input" v-model="formData.purpose" maxlength="50" placeholder="请输入" clearable />
                        <el-input class="command-search-input" v-model="formData.purpose" maxlength="50" placeholder="请输入" clearable />
                    </el-form-item>
                </el-col>
            </el-row>
applications/drone-command/src/views/basicManage/deviceStock/FormDiaLog.vue
@@ -53,7 +53,7 @@
            <div class="detail-title">设备跟踪流转</div>
            <div class="command-table-container" v-loading="loading" element-loading-background="rgba(5, 5, 15, 0.6)">
                <div class="command-table-content">
                    <el-table class="command-data-cockpit-table" :data="list">
                    <el-table class="command-table" :data="list">
                        <el-table-column type="index" width="60" label="序号" />
                        <el-table-column prop="charger" label="用户" />
                        <el-table-column prop="contactPhone" label="电话" />
@@ -64,7 +64,7 @@
                </div>
                <div class="command-table-pagination">
                    <el-pagination popper-class="command-data-cockpit-select-popper"
                    <el-pagination popper-class="command-select-popper"
                        v-model:current-page="searchParams.current" v-model:page-size="searchParams.size"
                        layout="total, prev, pager, next, sizes" :total="total" @change="getList" />
                </div>
@@ -75,13 +75,13 @@
            <el-row>
                <el-col :span="12">
                    <el-form-item label="设备名称" prop="deviceName">
                        <el-input class="command-data-cockpit-search-input" v-model="formData.deviceName" maxlength="50"
                        <el-input class="command-search-input" v-model="formData.deviceName" maxlength="50"
                            placeholder="请输入" clearable />
                    </el-form-item>
                </el-col>
                <el-col :span="12">
                    <el-form-item label="设备类型" prop="deviceType">
                        <el-select class="command-data-cockpit-select" popper-class="command-data-cockpit-select-popper"
                        <el-select class="command-select" popper-class="command-select-popper"
                            v-model="formData.deviceType" placeholder="请选择" clearable>
                            <el-option v-for="item in dictObj.deviceType" :key="item.dictKey" :label="item.dictValue"
                                :value="item.dictKey" />
@@ -90,7 +90,7 @@
                </el-col>
                <el-col :span="12">
                    <el-form-item label="设备属性" prop="deviceAtt">
                        <el-select class="command-data-cockpit-select" popper-class="command-data-cockpit-select-popper"
                        <el-select class="command-select" popper-class="command-select-popper"
                            v-model="formData.deviceAtt" placeholder="请选择" clearable>
                            <el-option v-for="item in dictObj.deviceAtt" :key="item.dictKey" :label="item.dictValue"
                                :value="item.dictKey" />
@@ -99,45 +99,45 @@
                </el-col>
                <el-col :span="12">
                    <el-form-item label="型号" prop="deviceModel">
                        <el-input class="command-data-cockpit-search-input" v-model="formData.deviceModel" maxlength="50"
                        <el-input class="command-search-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 class="command-data-cockpit-search-input" v-model="formData.deviceSpecification"
                        <el-input class="command-search-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 class="command-data-cockpit-search-input" v-model="formData.manufacturer" maxlength="50"
                        <el-input class="command-search-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 class="command-data-cockpit-search-input" v-model="formData.source" maxlength="50"
                        <el-input class="command-search-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 class="command-data-cockpit-search-input" v-model="formData.purpose" maxlength="50"
                        <el-input class="command-search-input" v-model="formData.purpose" maxlength="50"
                            placeholder="请输入" clearable />
                    </el-form-item>
                </el-col>
                <el-col :span="12">
                    <el-form-item label="所属部门" prop="belongDept">
                        <el-tree-select class="command-data-cockpit-select"
                            popper-class="command-data-cockpit-tree-select-popper" v-model="formData.belongDept"
                        <el-tree-select class="command-select"
                            popper-class="command-tree-select-popper" v-model="formData.belongDept"
                            node-key="id" :data="deptTree" :props="treeProps" check-strictly @change="belongDeptChange"
                            clearable />
                    </el-form-item>
                </el-col>
                <el-col :span="12">
                    <el-form-item label="负责人" prop="charger">
                        <el-select class="command-data-cockpit-select" popper-class="command-data-cockpit-select-popper"
                        <el-select class="command-select" popper-class="command-select-popper"
                            v-model="formData.charger" placeholder="请选择" :disabled="!formData.belongDept" clearable>
                            <el-option v-for="item in userList" :key="item.id" :label="item.name" :value="item.name" />
                        </el-select>
@@ -145,7 +145,7 @@
                </el-col>
                <el-col :span="12">
                    <el-form-item label="联系电话" prop="contactPhone">
                        <el-input class="command-data-cockpit-search-input" v-model="formData.contactPhone" maxlength="50"
                        <el-input class="command-search-input" v-model="formData.contactPhone" maxlength="50"
                            placeholder="请输入" clearable />
                    </el-form-item>
                </el-col>
applications/drone-command/src/views/basicManage/deviceStock/index.vue
@@ -9,7 +9,7 @@
        <el-form ref="queryParamsRef" :model="searchParams" class="command-page-history-search">
            <el-form-item label="设备名称" prop="deviceName">
                <el-input
                    class="command-data-cockpit-search-input"
                    class="command-search-input"
                    v-model="searchParams.deviceName"
                    placeholder="请输入"
                    clearable
@@ -19,8 +19,8 @@
            <el-form-item label="设备类型" prop="deviceType">
                <el-select
                    class="command-data-cockpit-select"
                    popper-class="command-data-cockpit-select-popper"
                    class="command-select"
                    popper-class="command-select-popper"
                    v-model="searchParams.deviceType"
                    placeholder="请选择"
                    clearable
@@ -37,8 +37,8 @@
            <el-form-item label="所属部门" prop="belongDept">
                <el-tree-select
                    class="command-data-cockpit-select"
                    popper-class="command-data-cockpit-tree-select-popper"
                    class="command-select"
                    popper-class="command-tree-select-popper"
                    v-model="searchParams.belongDept"
                    :data="deptTree"
                    :props="treeProps"
@@ -61,7 +61,7 @@
        <div class="command-table-container" v-loading="loading" element-loading-background="rgba(5, 5, 15, 0.6)">
            <div class="command-table-content command-table-content-bg">
                <el-table class="command-data-cockpit-table" :data="list" @selection-change="handleSelectionChange">
                <el-table class="command-table" :data="list" @selection-change="handleSelectionChange">
                    <el-table-column type="selection" width="46" />
                    <el-table-column type="index" show-overflow-tooltip width="64" label="序号" />
                    <el-table-column prop="deviceName" show-overflow-tooltip width="130" label="设备名称" />
@@ -101,7 +101,7 @@
            <div class="command-table-pagination">
                <el-pagination
                    popper-class="command-data-cockpit-select-popper"
                    popper-class="command-select-popper"
                    v-model:current-page="searchParams.current"
                    v-model:page-size="searchParams.size"
                    layout="total, prev, pager, next, sizes"
applications/drone-command/src/views/basicManage/maintainRecord/FormDiaLog.vue
@@ -49,7 +49,7 @@
            <div class="detail-title">维护详情</div>
            <div class="command-table-container" v-loading="loading" element-loading-background="rgba(5, 5, 15, 0.6)">
                <div class="command-table-content">
                    <el-table class="command-data-cockpit-table" :data="list">
                    <el-table class="command-table" :data="list">
                        <el-table-column type="index" width="60" label="序号" />
                        <el-table-column prop="maintainTime" label="维护时间" />
                        <el-table-column prop="maintainContent" label="维护内容" />
@@ -58,7 +58,7 @@
                </div>
                <div class="command-table-pagination">
                    <el-pagination popper-class="command-data-cockpit-select-popper"
                    <el-pagination popper-class="command-select-popper"
                        v-model:current-page="searchParams.current" v-model:page-size="searchParams.size"
                        layout="total, prev, pager, next, sizes" :total="total" @change="getList" />
                </div>
@@ -70,7 +70,7 @@
            <el-row>
                <el-col :span="12">
                    <el-form-item label="选择设备" prop="deviceId">
                        <el-select class="command-data-cockpit-select" popper-class="command-data-cockpit-select-popper"
                        <el-select class="command-select" popper-class="command-select-popper"
                            v-model="formData.deviceId" placeholder="请选择" filterable clearable>
                            <el-option v-for="item in deviceList" :key="item.id" :label="item.deviceName"
                                :value="item.id" />
@@ -79,7 +79,7 @@
                </el-col>
                <el-col :span="12">
                    <el-form-item label="维护计划周期" prop="planCycleType">
                        <el-select class="command-data-cockpit-select" popper-class="command-data-cockpit-select-popper"
                        <el-select class="command-select" popper-class="command-select-popper"
                            v-model="formData.planCycleType" placeholder="请选择" clearable
                            @change="formData.planCycleValue = []">
                            <el-option v-for="item in planCycleOptions" :key="item.value" :label="item.label"
@@ -89,7 +89,7 @@
                </el-col>
                <el-col :span="12">
                    <el-form-item label="维护计划时间" prop="planCycleValue">
                        <el-select class="command-data-cockpit-select" popper-class="command-data-cockpit-select-popper"
                        <el-select class="command-select" popper-class="command-select-popper"
                            v-model="formData.planCycleValue" placeholder="请选择" clearable multiple
                            :disabled="!formData.planCycleType">
                            <el-option v-for="item in planCycleValueOptions" :key="item.value" :label="item.value"
applications/drone-command/src/views/basicManage/maintainRecord/MaintenanceDiaLog.vue
@@ -32,7 +32,7 @@
                <el-col :span="24">
                    <el-form-item label="维护内容" prop="maintainContent">
                        <el-input
                            class="command-data-cockpit-search-input"
                            class="command-search-input"
                            v-model="formData.maintainContent"
                            maxlength="200"
                            type="textarea"
@@ -44,7 +44,7 @@
                <el-col :span="24">
                    <el-form-item label="更换部件" prop="replacePart">
                        <el-input
                            class="command-data-cockpit-search-input"
                            class="command-search-input"
                            v-model="formData.replacePart"
                            maxlength="200"
                            type="textarea"
@@ -56,8 +56,8 @@
                <el-col :span="12">
                    <el-form-item label="实际维护时间" prop="maintainTime">
                        <el-date-picker
                            class="command-data-cockpit-date-picker"
                            popper-class="command-data-cockpit-date-picker-popper"
                            class="command-date-picker"
                            popper-class="command-date-picker-popper"
                            v-model="formData.maintainTime"
                            type="datetime"
                            placeholder="选择日期"
applications/drone-command/src/views/basicManage/maintainRecord/index.vue
@@ -2,12 +2,12 @@
    <basic-container>
        <el-form ref="queryParamsRef" :model="searchParams" class="command-page-history-search">
            <el-form-item label="设备名称" prop="deviceName">
                <el-input class="command-data-cockpit-search-input" v-model="searchParams.deviceName" placeholder="请输入"
                <el-input class="command-search-input" v-model="searchParams.deviceName" placeholder="请输入"
                    clearable @clear="handleSearch" />
            </el-form-item>
            <el-form-item label="设备类型" prop="deviceType">
                <el-select class="command-data-cockpit-select" popper-class="command-data-cockpit-select-popper"
                <el-select class="command-select" popper-class="command-select-popper"
                    v-model="searchParams.deviceType" placeholder="请选择" clearable @change="handleSearch">
                    <el-option v-for="item in dictObj.deviceType" :key="item.dictKey" :label="item.dictValue"
                        :value="item.dictKey" />
@@ -15,7 +15,7 @@
            </el-form-item>
            <el-form-item label="所属部门" prop="belongDept">
                <el-tree-select class="command-data-cockpit-select" popper-class="command-data-cockpit-tree-select-popper"
                <el-tree-select class="command-select" popper-class="command-tree-select-popper"
                    v-model="searchParams.belongDept" :data="deptTree" :props="treeProps" node-key="id" check-strictly
                    clearable @change="handleSearch" />
            </el-form-item>
@@ -33,7 +33,7 @@
        <div class="command-table-container" v-loading="loading" element-loading-background="rgba(5, 5, 15, 0.6)">
            <div class="command-table-content command-table-content-bg">
                <el-table class="command-data-cockpit-table" :data="list" @selection-change="handleSelectionChange">
                <el-table class="command-table" :data="list" @selection-change="handleSelectionChange">
                    <el-table-column type="selection" width="46" />
                    <el-table-column prop="deviceName" show-overflow-tooltip label="设备名称" />
                    <el-table-column prop="deviceType" show-overflow-tooltip label="设备类型">
@@ -62,7 +62,7 @@
            </div>
            <div class="command-table-pagination">
                <el-pagination popper-class="command-data-cockpit-select-popper"
                <el-pagination popper-class="command-select-popper"
                    v-model:current-page="searchParams.current" v-model:page-size="searchParams.size"
                    layout="total, prev, pager, next, sizes" :total="total" @change="getList" />
            </div>
applications/drone-command/src/views/dataCockpit/components/DeviceHistoryDialog.vue
@@ -1,26 +1,26 @@
<template>
    <el-dialog class="command-data-cockpit-dialog" append-to-body v-model="visibleModel" :title="dialogTitle"
    <el-dialog class="command-dialog" append-to-body v-model="visibleModel" :title="dialogTitle"
        :close-on-click-modal="false" :destroy-on-close="true">
        <el-form ref="queryParamsRef" :model="searchParams" class="command-dialog-history-search">
            <el-form-item label="关键字" prop="keyword">
                <el-input class="command-data-cockpit-search-input" v-model="searchParams.keyword" placeholder="名称/序列号"
                <el-input class="command-search-input" v-model="searchParams.keyword" placeholder="名称/序列号"
                    clearable @clear="handleSearch" />
            </el-form-item>
            <el-form-item prop="dateRange">
                <el-date-picker class="command-data-cockpit-date-picker"
                    popper-class="command-data-cockpit-tree-select-popper" v-model="searchParams.dateRange"
                <el-date-picker class="command-date-picker"
                    popper-class="command-date-picker-popper" v-model="searchParams.dateRange"
                    type="daterange" range-separator="至" start-placeholder="开始日期" end-placeholder="结束日期"
                    value-format="YYYY/MM/DD" @change="handleSearch" />
            </el-form-item>
            <el-form-item label="区域" prop="area">
                <el-tree-select class="command-data-cockpit-select" popper-class="command-data-cockpit-tree-select-popper"
                <el-tree-select class="command-select" popper-class="command-tree-select-popper"
                    v-model="searchParams.area" :data="areaTree" :props="areaTreeProps" node-key="value" check-strictly filterable :filter-node-method="filterAreaNode" clearable placeholder="请选择" @change="handleSearch" />
            </el-form-item>
            <el-form-item label="无人机类型" prop="droneType">
                <el-select class="command-data-cockpit-select" popper-class="command-data-cockpit-select-popper"
                <el-select class="command-select" popper-class="command-select-popper"
                    v-model="searchParams.droneType" placeholder="请选择" clearable @change="handleSearch">
                    <el-option v-for="item in dictObj.droneType" :key="item.dictKey" :label="item.dictValue"
                        :value="item.dictKey" />
@@ -35,7 +35,7 @@
        <div class="command-table-container" v-loading="loading" element-loading-background="rgba(5, 5, 15, 0.6)">
            <div class="command-table-content">
                <el-table class="command-data-cockpit-table" :data="list">
                <el-table class="command-table" :data="list">
                    <el-table-column type="index" width="60" label="序号" />
                    <el-table-column prop="droneName" label="无人机名称" min-width="120" />
                    <el-table-column prop="droneSerialNo" label="无人机序列号" min-width="140" />
@@ -62,7 +62,7 @@
            </div>
            <div class="command-table-pagination">
                <el-pagination popper-class="command-data-cockpit-select-popper"
                <el-pagination popper-class="command-select-popper"
                    v-model:current-page="searchParams.current" v-model:page-size="searchParams.size"
                    layout="total, prev, pager, next, sizes" :total="total" @change="getList" />
            </div>
@@ -96,7 +96,7 @@
})
const dialogTitle = computed(() => {
    return `反制设备名称 ${props.device?.name || ''}`.trim()
    return `${props.device?.name || ''}`.trim()
})
const initSearchParams = () => ({
applications/drone-command/src/views/dataCockpit/components/EquipmentWarning.vue
@@ -15,14 +15,16 @@
        element-loading-background="rgba(5, 5, 15, 0.6)"
        element-loading-text="加载中..."
    >
        <EmptyState v-if="!equipmentWarningData.length" />
        <EquipmentTemplate
            v-else
            v-for="(item, ind) in equipmentWarningData"
            :key="ind"
            :data="item"
            @click="onCardClick"
        />
        <div class="list-content">
            <EmptyState v-if="!equipmentWarningData.length" />
            <EquipmentTemplate
                v-else
                v-for="(item, ind) in equipmentWarningData"
                :key="ind"
                :data="item"
                @click="onCardClick"
            />
        </div>
    </div>
</template>
@@ -94,8 +96,17 @@
<style lang="scss" scoped>
.equipment-warning {
    display: flex;
    flex-direction: column;
    width: 100%;
    height: 100%;
    overflow: hidden;
}
.list-content {
    height: 0;
    flex: 1;
    overflow-y: auto;
}
</style>
applications/drone-command/src/views/dataCockpit/components/HistoryWarning.vue
@@ -8,14 +8,14 @@
        <!-- 搜索区(设计稿红框) -->
        <div class="search-box">
            <!-- 关键字 -->
            <el-input v-model="query.keyword" class="command-data-cockpit-search-input" placeholder="请输入数据名称" clearable
            <el-input v-model="query.keyword" class="command-search-input" placeholder="请输入数据名称" clearable
                @keyup.enter="onSearch">
            </el-input>
            <!-- 日期范围 -->
            <el-date-picker v-model="query.dateRange" 
                  class="command-data-cockpit-date-picker"
                 popper-class="command-data-cockpit-date-picker-popper"
                  class="command-date-picker"
                 popper-class="command-date-picker-popper"
                type="daterange" 
                range-separator="~"
                start-placeholder="创建开始日期" end-placeholder="结束日期" format="YYYY年MM月DD日" value-format="YYYY-MM-DD"
@@ -103,13 +103,14 @@
    flex-direction: column;
    width: 100%;
    height: 100%;
    overflow: hidden;
    .search-box {
        display: flex;
        flex-direction: column;
        gap: 10px;
        ::v-deep(.command-data-cockpit-date-picker) {
        ::v-deep(.command-date-picker) {
            width: 100% !important;
        }
    }
@@ -117,6 +118,7 @@
    .list-content {
        height: 0;
        flex: 1;
        overflow-y: auto;
    }
}
applications/drone-command/src/views/dataCockpit/components/LeftContainer.vue
@@ -113,7 +113,7 @@
.collapse-btn {
    position: absolute;
    top: 50%;
    bottom: 454px;
    left: 300px;
    cursor: pointer;
    display: flex;
@@ -121,11 +121,11 @@
    justify-content: center;
    color: #fff;
    z-index: 10;
    transform: translateY(-50%);
    transform: translateY(50%);
    .arrow {
        width: 32px;
        height: 32px;
        width: 36px;
        height: 36px;
        background: url('@/assets/images/dataCockpit/left-btn.png') center / 100% 100% no-repeat;
    }
@@ -213,7 +213,6 @@
    height: 0;
    flex: 1;
    margin-top: 20px;
    overflow-x: hidden;
    overflow-y: auto;
    overflow: hidden;
}
</style>
applications/drone-command/src/views/dataCockpit/components/RealWarning.vue
@@ -2,7 +2,7 @@
 * @Author       : yuan
 * @Date         : 2026-01-08 09:29:07
 * @LastEditors  : yuan
 * @LastEditTime : 2026-01-08 14:49:09
 * @LastEditTime : 2026-01-19 11:31:09
 * @FilePath     : \applications\drone-command\src\views\dataCockpit\components\RealWarning.vue
 * @Description  : 
 * Copyright 2026 OBKoro1, All Rights Reserved. 
@@ -15,16 +15,18 @@
        element-loading-background="rgba(5, 5, 15, 0.6)"
        element-loading-text="加载中..."
    >
        <EmptyState v-if="!realWarningData.length" />
        <RealTemplate
            v-else
            v-for="(item, ind) in realWarningData"
            :key="ind"
            :data="item"
            @signal="() => handleAction('signal', item)"
            @counter="() => handleAction('counter', item)"
            @favorite="() => console.log('收藏', item.id)"
        />
        <div class="list-content">
            <EmptyState v-if="!realWarningData.length" />
            <RealTemplate
                v-else
                v-for="(item, ind) in realWarningData"
                :key="ind"
                :data="item"
                @signal="() => handleAction('signal', item)"
                @counter="() => handleAction('counter', item)"
                @favorite="() => console.log('收藏', item.id)"
            />
        </div>
    </div>
</template>
@@ -46,8 +48,7 @@
const buildPayload = (type, item) => ({
    counterWay: type === 'signal' ? 1 : type === 'counter' ? 2 : '',
    deviceId: item.deviceId,
    droneDeviceCode: item.droneDeviceCode ?? item.droneSerialNo
    alarmRecordId: item?.alarmRecordId ?? item?.id
})
const handleAction = async (type, item) => {
@@ -56,6 +57,7 @@
        const res = await interferenceAndExpulsionApi(buildPayload(type, item))
        if (res?.data?.success) {
            ElMessage({ type: 'success', message: `${actionText}成功` })
            await fetchRealWarning()
        } else {
            ElMessage({ type: 'error', message: res?.data?.msg || `${actionText}失败` })
        }
@@ -88,8 +90,16 @@
<style lang="scss" scoped>
.real-warning {
    display: flex;
    flex-direction: column;
    width: 100%;
    height: 100%;
    overflow: hidden;
}
.list-content {
    height: 0;
    flex: 1;
    overflow-y: auto;
}
</style>
applications/drone-command/src/views/dataCockpit/components/RightContainer.vue
@@ -2,7 +2,7 @@
 * @Author       : yuan
 * @Date         : 2026-01-07 15:17:54
 * @LastEditors  : yuan
 * @LastEditTime : 2026-01-16 17:23:06
 * @LastEditTime : 2026-01-19 14:05:35
 * @FilePath     : \applications\drone-command\src\views\dataCockpit\components\RightContainer.vue
 * @Description  : 
 * Copyright 2026 OBKoro1, All Rights Reserved. 
@@ -134,6 +134,7 @@
        azimuth: item.azimuth ?? 0,
        elevation: item.elevation ?? 0,
        status: item.status ?? '-',
        workMode: item.workMode ?? '-',
        manufacturer: item.manufacturer || '-',
        detectTargetCnt: item.detectTargetCnt ?? 0,
        effectiveRangeKm: item.effectiveRangeKm ?? 0
@@ -265,7 +266,7 @@
.collapse-btn {
    position: absolute;
    top: 50%;
    bottom: 454px;
    right: 300px;
    cursor: pointer;
    display: flex;
@@ -273,11 +274,11 @@
    justify-content: center;
    color: #fff;
    z-index: 10;
    transform: translateY(-50%);
    transform: translateY(50%);
    .arrow {
        width: 32px;
        height: 32px;
        width: 36px;
        height: 36px;
        background: url('@/assets/images/dataCockpit/right-btn.png') center / 100% 100% no-repeat;
    }
applications/drone-command/src/views/dataCockpit/components/templateComponents/RealEquipmentTemplate.vue
@@ -6,12 +6,12 @@
                <span class="name">{{ data.name }}</span>
                <span class="status">
                    <span :class="getStatusType(data.status)">
                    <span :class="getWorkModeType(data.workMode)">
                    </span>
                    <span>
                        {{ getStatusText(data.status) }}
                        {{ getWorkModeText(data.workMode) }}
                    </span>
                </span>
            </div>
@@ -90,9 +90,19 @@
    return value || '-'
}
const getStatusType = (value) => {
    if (value === 0 || value === '0') return 'detecting'
const getWorkModeText = (value) => {
    if (value === 1 || value === '1') return '侦测中'
    if (value === 2 || value === '2') return '信号干扰中'
    if (value === 3 || value === '3') return '诱导驱离中'
    if (value === 4 || value === '4') return '待机'
    return value || '-'
}
const getWorkModeType = (value) => {
    if (value === 1 || value === '1') return 'detecting'
    if (value === 2 || value === '2') return 'jamming'
    if (value === 3 || value === '3') return 'driving'
    if (value === 4 || value === '4') return 'standby'
    return ''
}
</script>
@@ -164,6 +174,20 @@
                    background: #FF4444;
                    border-radius: 50%;
                }
                span.driving {
                    width: 4px;
                    height: 4px;
                    background: #FFB020;
                    border-radius: 50%;
                }
                span.standby {
                    width: 4px;
                    height: 4px;
                    background: #9AA4B2;
                    border-radius: 50%;
                }
            }
        }
    }
applications/drone-command/src/views/dataCockpit/components/templateComponents/RealTemplate.vue
@@ -57,8 +57,8 @@
        </div>
        <div class="footer">
            <el-button class="general" color="#2B2B4C" @click="emit('signal')">信号干扰</el-button>
            <el-button color="#284FE3" type="primary" @click="emit('counter')">诱导驱离</el-button>
            <el-button v-if="showSignalBtn(data)" class="general" color="#2B2B4C" @click="emit('signal')">信号干扰</el-button>
            <el-button v-if="showCounterBtn(data)" color="#284FE3" type="primary" @click="emit('counter')">诱导驱离</el-button>
        </div>
    </div>
</template>
@@ -90,6 +90,21 @@
    return 'detecting'
}
const normalizeCounterWay = (value) => {
    if (value == null) return ''
    return String(value).trim()
}
const showSignalBtn = (item) => {
    const counterWay = normalizeCounterWay(item?.counterWay)
    return counterWay !== '1'
}
const showCounterBtn = (item) => {
    const counterWay = normalizeCounterWay(item?.counterWay)
    return counterWay !== '2'
}
const getDataSource = (item) => {
    return item?.deviceName || item?.areaName || '-'
}
applications/drone-command/src/views/detectionCountermeasure/countermeasureEvaluation/index.vue
@@ -3,7 +3,7 @@
        <el-form ref="queryParamsRef" :model="searchParams" class="command-page-history-search">
            <el-form-item label="设备名称" prop="deviceName">
                <el-input
                    class="command-data-cockpit-search-input"
                    class="command-search-input"
                    v-model="searchParams.deviceName"
                    placeholder="请输入"
                    clearable
@@ -13,8 +13,8 @@
            <el-form-item label="设备类型" prop="deviceType">
                <el-select
                    class="command-data-cockpit-select"
                    popper-class="command-data-cockpit-select-popper"
                    class="command-select"
                    popper-class="command-select-popper"
                    v-model="searchParams.deviceType"
                    placeholder="请选择"
                    clearable
@@ -31,8 +31,8 @@
            <el-form-item label="反制效果" prop="counterEffect">
                <el-select
                    class="command-data-cockpit-select"
                    popper-class="command-data-cockpit-select-popper"
                    class="command-select"
                    popper-class="command-select-popper"
                    v-model="searchParams.counterEffect"
                    placeholder="请选择"
                    clearable
@@ -55,7 +55,7 @@
        <div class="command-table-container" v-loading="loading" element-loading-background="rgba(5, 5, 15, 0.6)">
            <div class="command-table-content command-table-content-bg">
                <el-table class="command-data-cockpit-table" :data="list">
                <el-table class="command-table" :data="list">
                    <el-table-column type="index" width="64" show-overflow-tooltip label="序号" />
                    <el-table-column prop="droneName" show-overflow-tooltip width="130" label="无人机名称" />
                    <el-table-column prop="droneType" show-overflow-tooltip width="130" label="无人机类型" />
@@ -101,7 +101,7 @@
            <div class="command-table-pagination">
                <el-pagination
                    popper-class="command-data-cockpit-select-popper"
                    popper-class="command-select-popper"
                    v-model:current-page="searchParams.current"
                    v-model:page-size="searchParams.size"
                    layout="total, prev, pager, next, sizes"
applications/drone-command/src/views/detectionCountermeasure/detectionRange/DetectionRangeDialog.vue
@@ -55,8 +55,8 @@
                <el-form v-else ref="formRef" class="dialog-form" :model="formData" :rules="rules" label-width="110px">
                    <el-form-item label="侦测设备" prop="deviceId">
                        <el-select
                            class="command-data-cockpit-select"
                            popper-class="command-data-cockpit-select-popper"
                            class="command-select"
                            popper-class="command-select-popper"
                            v-model="formData.deviceId"
                            placeholder="请选择"
                            clearable
@@ -67,8 +67,8 @@
                    </el-form-item>
                    <el-form-item label="设备类型" prop="deviceType">
                        <el-select
                            class="command-data-cockpit-select"
                            popper-class="command-data-cockpit-select-popper"
                            class="command-select"
                            popper-class="command-select-popper"
                            v-model="formData.deviceType"
                            placeholder="请选择"
                            clearable
@@ -83,7 +83,7 @@
                    </el-form-item>
                    <el-form-item label="设备位置" prop="deployLocation">
                        <el-input
                            class="command-data-cockpit-search-input"
                            class="command-search-input"
                            v-model="formData.deployLocation"
                            disabled
                            placeholder="请选择位置"
@@ -95,7 +95,7 @@
                    </el-form-item>
                    <el-form-item label="设备编号" prop="deviceSn">
                        <el-input
                            class="command-data-cockpit-search-input"
                            class="command-search-input"
                            v-model="formData.deviceSn"
                            placeholder="请输入"
                            clearable
@@ -103,7 +103,7 @@
                    </el-form-item>
                    <el-form-item label="设备型号" prop="deviceModel">
                        <el-input
                            class="command-data-cockpit-search-input"
                            class="command-search-input"
                            v-model="formData.deviceModel"
                            placeholder="请输入"
                            clearable
@@ -111,7 +111,7 @@
                    </el-form-item>
                    <el-form-item label="覆盖范围(m)" prop="effectiveRangeKm">
                        <el-input-number
                            class="command-data-cockpit-search-input"
                            class="command-search-input"
                            v-model="formData.effectiveRangeKm"
                            :min="0"
                            :precision="2"
@@ -148,7 +148,8 @@
} from '@/api/detectionCountermeasure/detectionRange'
import CommonCesiumMap from '@/components/map-container/common-cesium-map.vue'
import * as Cesium from 'cesium'
import deviceZcImg from '@/assets/images/dataCockpit/device-zc.svg'
import commandPost from '@/assets/images/dataCockpit/legend/command-post.png'
const initForm = () => ({
    deviceId: '', // 侦测设备ID
@@ -276,9 +277,9 @@
        redPointEntity = viewer.entities.add({
            position: Cesium.Cartesian3.fromDegrees(longitude, latitude),
            billboard: {
                image: deviceZcImg, // 这里替换为你的图片路径或变量 deviceZcImg
                width: 30, // 可选:设置图片宽度
                height: 42, // 可选:设置图片高度
                image: commandPost, // 这里替换为你的图片路径或变量 deviceZcImg
                width: 40,
                height: 56,
                verticalOrigin: Cesium.VerticalOrigin.BOTTOM, // 设置图片底部对齐坐标点
            },
            label: {
@@ -293,7 +294,7 @@
                verticalOrigin: Cesium.VerticalOrigin.CENTER,
                outlineWidth: 1,
                outlineColor: Cesium.Color.WHITE,
                pixelOffset: new Cesium.Cartesian2(0, -60),
                pixelOffset: new Cesium.Cartesian2(0, -72),
                eyeOffset: new Cesium.Cartesian3(0, 0, -20),
            },
        })
@@ -335,7 +336,7 @@
                material: Cesium.Color.fromCssColorString('#6b9ca8').withAlpha(0.6),
                outline: true,
                outlineColor: Cesium.Color.fromCssColorString('#6b9ca8').withAlpha(0.6),
                heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
                heightReference: Cesium.HeightReference.NONE,
            },
        })
        return
applications/drone-command/src/views/detectionCountermeasure/detectionRange/index.vue
@@ -3,7 +3,7 @@
        <el-form ref="queryParamsRef" :model="searchParams" class="command-page-history-search">
            <el-form-item label="设备名称" prop="deviceName">
                <el-input
                    class="command-data-cockpit-search-input"
                    class="command-search-input"
                    v-model="searchParams.deviceName"
                    placeholder="请输入"
                    clearable
@@ -13,8 +13,8 @@
            <el-form-item label="设备类型" prop="deviceType">
                <el-select
                    class="command-data-cockpit-select"
                    popper-class="command-data-cockpit-select-popper"
                    class="command-select"
                    popper-class="command-select-popper"
                    v-model="searchParams.deviceType"
                    placeholder="请选择"
                    clearable
@@ -41,7 +41,7 @@
        <div class="command-table-container" v-loading="loading" element-loading-background="rgba(5, 5, 15, 0.6)">
            <div class="command-table-content command-table-content-bg">
                <el-table class="command-data-cockpit-table" :data="list">
                <el-table class="command-table" :data="list">
                    <el-table-column type="index" show-overflow-tooltip width="64" label="序号" />
                    <el-table-column prop="deviceName" show-overflow-tooltip label="设备名称" />
                    <el-table-column prop="deviceType" show-overflow-tooltip label="设备类型">
@@ -77,7 +77,7 @@
            <div class="command-table-pagination">
                <el-pagination
                    popper-class="command-data-cockpit-select-popper"
                    popper-class="command-select-popper"
                    v-model:current-page="searchParams.current"
                    v-model:page-size="searchParams.size"
                    layout="total, prev, pager, next, sizes"
applications/drone-command/src/views/detectionCountermeasure/deviceAppConfig/FormDiaLog.vue
@@ -51,7 +51,7 @@
                <el-col :span="12">
                    <el-form-item label="起始扇区" prop="startSector">
                        <el-input
                            class="command-data-cockpit-search-input"
                            class="command-search-input"
                            v-model="formData.startSector"
                            maxlength="50"
                            placeholder="请输入"
@@ -62,7 +62,7 @@
                <el-col :span="12">
                    <el-form-item label="终止扇区" prop="endSector">
                        <el-input
                            class="command-data-cockpit-search-input"
                            class="command-search-input"
                            v-model="formData.endSector"
                            maxlength="50"
                            placeholder="请输入"
@@ -73,8 +73,8 @@
                <el-col :span="12">
                    <el-form-item label="搜索模式" prop="searchMode">
                        <el-select
                            class="command-data-cockpit-select"
                            popper-class="command-data-cockpit-select-popper"
                            class="command-select"
                            popper-class="command-select-popper"
                            v-model="formData.searchMode"
                            placeholder="请选择"
                            clearable
@@ -86,7 +86,7 @@
                <el-col :span="12">
                    <el-form-item label="雷达频点" prop="radarFreq">
                        <el-input
                            class="command-data-cockpit-search-input"
                            class="command-search-input"
                            v-model="formData.radarFreq"
                            maxlength="50"
                            placeholder="请输入"
@@ -98,8 +98,8 @@
                <el-col :span="12">
                    <el-form-item label="伺服模式" prop="servoMode">
                        <el-select
                            class="command-data-cockpit-select"
                            popper-class="command-data-cockpit-select-popper"
                            class="command-select"
                            popper-class="command-select-popper"
                            v-model="formData.servoMode"
                            placeholder="请选择"
                            clearable
@@ -111,8 +111,8 @@
                <el-col :span="12">
                    <el-form-item label="伺服数据模式" prop="servoDataMode">
                        <el-select
                            class="command-data-cockpit-select"
                            popper-class="command-data-cockpit-select-popper"
                            class="command-select"
                            popper-class="command-select-popper"
                            v-model="formData.servoDataMode"
                            placeholder="请选择"
                            clearable
@@ -129,8 +129,8 @@
                <el-col :span="12">
                    <el-form-item label="轴选择" prop="axisSelect">
                        <el-select
                            class="command-data-cockpit-select"
                            popper-class="command-data-cockpit-select-popper"
                            class="command-select"
                            popper-class="command-select-popper"
                            v-model="formData.axisSelect"
                            placeholder="请选择"
                            clearable
@@ -142,7 +142,7 @@
                <el-col :span="12">
                    <el-form-item label="伺服转速度" prop="servoTurnSpeed">
                        <el-input
                            class="command-data-cockpit-search-input"
                            class="command-search-input"
                            v-model="formData.servoTurnSpeed"
                            maxlength="50"
                            placeholder="请输入"
applications/drone-command/src/views/detectionCountermeasure/deviceAppConfig/index.vue
@@ -3,7 +3,7 @@
        <el-form ref="queryParamsRef" :model="searchParams" class="command-page-history-search">
            <el-form-item label="设备名称" prop="deviceName">
                <el-input
                    class="command-data-cockpit-search-input"
                    class="command-search-input"
                    v-model="searchParams.deviceName"
                    placeholder="请输入"
                    clearable
@@ -13,8 +13,8 @@
            <el-form-item label="设备类型" prop="deviceType">
                <el-select
                    class="command-data-cockpit-select"
                    popper-class="command-data-cockpit-select-popper"
                    class="command-select"
                    popper-class="command-select-popper"
                    v-model="searchParams.deviceType"
                    placeholder="请选择"
                    clearable
@@ -31,8 +31,8 @@
            <el-form-item label="设备状态" prop="deviceStatus">
                <el-select
                    class="command-data-cockpit-select"
                    popper-class="command-data-cockpit-select-popper"
                    class="command-select"
                    popper-class="command-select-popper"
                    v-model="searchParams.deviceStatus"
                    placeholder="请选择"
                    clearable
@@ -55,7 +55,7 @@
        <div class="command-table-container" v-loading="loading" element-loading-background="rgba(5, 5, 15, 0.6)">
            <div class="command-table-content command-table-content-bg">
                <el-table class="command-data-cockpit-table" :data="list">
                <el-table class="command-table" :data="list">
                    <el-table-column type="index" width="64" show-overflow-tooltip label="序号" />
                    <el-table-column prop="deviceType" show-overflow-tooltip label="设备类型">
                        <template v-slot="{ row }">
@@ -94,7 +94,7 @@
            <div class="command-table-pagination">
                <el-pagination
                    popper-class="command-data-cockpit-select-popper"
                    popper-class="command-select-popper"
                    v-model:current-page="searchParams.current"
                    v-model:page-size="searchParams.size"
                    layout="total, prev, pager, next, sizes"
applications/drone-command/src/views/detectionCountermeasure/taskSchedule/FormDiaLog.vue
@@ -65,8 +65,8 @@
                <el-col :span="12">
                    <el-form-item label="设备" prop="deviceId">
                        <el-select
                            class="command-data-cockpit-select"
                            popper-class="command-data-cockpit-select-popper"
                            class="command-select"
                            popper-class="command-select-popper"
                            v-model="formData.deviceId"
                            placeholder="请选择"
                            clearable
@@ -79,7 +79,7 @@
                <el-col :span="12">
                    <el-form-item label="设备编码" prop="deviceSn">
                        <el-input
                            class="command-data-cockpit-search-input"
                            class="command-search-input"
                            v-model="formData.deviceSn"
                            disabled
                            placeholder="选择设备后自动带出"
@@ -89,8 +89,8 @@
                <el-col :span="12">
                    <el-form-item label="场景" prop="defenseSceneId">
                        <el-select
                            class="command-data-cockpit-select"
                            popper-class="command-data-cockpit-select-popper"
                            class="command-select"
                            popper-class="command-select-popper"
                            v-model="formData.defenseSceneId"
                            placeholder="请选择"
                            clearable
@@ -103,8 +103,8 @@
                <el-col :span="12">
                    <el-form-item label="区域" prop="areaDivideId">
                        <el-select
                            class="command-data-cockpit-select"
                            popper-class="command-data-cockpit-select-popper"
                            class="command-select"
                            popper-class="command-select-popper"
                            v-model="formData.areaDivideId"
                            placeholder="请先选择场景"
                            clearable
@@ -118,7 +118,7 @@
                <el-col :span="12">
                    <el-form-item label="调度人员" prop="dispatchUser">
                        <el-input
                            class="command-data-cockpit-search-input"
                            class="command-search-input"
                            v-model="formData.dispatchUser"
                            maxlength="50"
                            placeholder="请输入"
@@ -129,8 +129,8 @@
                <el-col :span="12">
                    <el-form-item label="调度日期" prop="dispatchDateRange">
                        <el-date-picker
                            class="command-data-cockpit-date-picker"
                            popper-class="command-data-cockpit-date-picker-popper"
                            class="command-date-picker"
                            popper-class="command-date-picker-popper"
                            v-model="formData.dispatchDateRange"
                            type="datetimerange"
                            range-separator="至"
@@ -153,7 +153,7 @@
                <el-col :span="24">
                    <el-form-item label="调度内容" prop="dispatchContent">
                        <el-input
                            class="command-data-cockpit-search-input"
                            class="command-search-input"
                            v-model="formData.dispatchContent"
                            type="textarea"
                            :rows="3"
@@ -166,7 +166,7 @@
                <el-col :span="24">
                    <el-form-item label="调度结果" prop="dispatchResult">
                        <el-input
                            class="command-data-cockpit-search-input"
                            class="command-search-input"
                            v-model="formData.dispatchResult"
                            type="textarea"
                            :rows="3"
@@ -179,7 +179,7 @@
                <el-col :span="24">
                    <el-form-item label="处理措施" prop="disposeMeasure">
                        <el-input
                            class="command-data-cockpit-search-input"
                            class="command-search-input"
                            v-model="formData.disposeMeasure"
                            type="textarea"
                            :rows="3"
applications/drone-command/src/views/detectionCountermeasure/taskSchedule/index.vue
@@ -3,8 +3,8 @@
        <el-form ref="queryParamsRef" :model="searchParams" class="command-page-history-search">
            <el-form-item label="设备名称" prop="deviceId">
                <el-select
                    class="command-data-cockpit-select"
                    popper-class="command-data-cockpit-select-popper"
                    class="command-select"
                    popper-class="command-select-popper"
                    v-model="searchParams.deviceId"
                    placeholder="请选择"
                    clearable
@@ -17,8 +17,8 @@
            <el-form-item label="设备状态" prop="status">
                <el-select
                    class="command-data-cockpit-select"
                    popper-class="command-data-cockpit-select-popper"
                    class="command-select"
                    popper-class="command-select-popper"
                    v-model="searchParams.status"
                    placeholder="请选择"
                    clearable
@@ -36,7 +36,7 @@
            <el-form-item label="设备编码" prop="deviceSn">
                <el-input
                    class="command-data-cockpit-search-input"
                    class="command-search-input"
                    v-model="searchParams.deviceSn"
                    placeholder="请输入"
                    clearable
@@ -57,7 +57,7 @@
        <div class="command-table-container" v-loading="loading" element-loading-background="rgba(5, 5, 15, 0.6)">
            <div class="command-table-content command-table-content-bg">
                <el-table class="command-data-cockpit-table" :data="list" @selection-change="handleSelectionChange">
                <el-table class="command-table" :data="list" @selection-change="handleSelectionChange">
                    <el-table-column type="selection" width="46" />
                    <el-table-column type="index" show-overflow-tooltip width="64" label="序号" />
                    <el-table-column prop="deviceName" show-overflow-tooltip width="140" label="设备名称" />
@@ -92,7 +92,7 @@
            <div class="command-table-pagination">
                <el-pagination
                    popper-class="command-data-cockpit-select-popper"
                    popper-class="command-select-popper"
                    v-model:current-page="searchParams.current"
                    v-model:page-size="searchParams.size"
                    layout="total, prev, pager, next, sizes"
applications/drone-command/src/views/permissionManage/permissionDept/FormDiaLog.vue
@@ -46,19 +46,19 @@
            <el-row>
                <el-col :span="12">
                    <el-form-item label="部门名称" prop="deptName">
                        <el-input class="command-data-cockpit-search-input" v-model="formData.deptName" maxlength="50" placeholder="请输入" clearable />
                        <el-input class="command-search-input" v-model="formData.deptName" maxlength="50" placeholder="请输入" clearable />
                    </el-form-item>
                </el-col>
                <el-col :span="12">
                    <el-form-item label="部门全称" prop="fullName">
                        <el-input class="command-data-cockpit-search-input" v-model="formData.fullName" maxlength="50" placeholder="请输入" clearable />
                        <el-input class="command-search-input" v-model="formData.fullName" maxlength="50" placeholder="请输入" clearable />
                    </el-form-item>
                </el-col>
                <el-col :span="12">
                    <el-form-item label="上级部门" prop="parentId">
                        <el-tree-select
                            class="command-data-cockpit-select"
                            popper-class="command-data-cockpit-tree-select-popper"
                            class="command-select"
                            popper-class="command-tree-select-popper"
                            v-model="formData.parentId"
                            :data="deptTree"
                            :props="treeProps"
@@ -70,14 +70,14 @@
                </el-col>
                <el-col :span="12">
                    <el-form-item label="部门类型" prop="deptCategory">
                        <el-select class="command-data-cockpit-select" popper-class="command-data-cockpit-select-popper" v-model="formData.deptCategory" placeholder="请选择" clearable>
                        <el-select class="command-select" popper-class="command-select-popper" v-model="formData.deptCategory" placeholder="请选择" clearable>
                            <el-option v-for="item in dictObj.org_category" :key="item.dictKey" :label="item.dictValue" :value="item.dictKey" />
                        </el-select>
                    </el-form-item>
                </el-col>
                <el-col :span="12">
                    <el-form-item label="部门性质" prop="deptNature">
                        <el-select class="command-data-cockpit-select" popper-class="command-data-cockpit-select-popper" v-model="formData.deptNature" placeholder="请选择" clearable>
                        <el-select class="command-select" popper-class="command-select-popper" v-model="formData.deptNature" placeholder="请选择" clearable>
                            <el-option v-for="item in dictObj.org_nature" :key="item.dictKey" :label="item.dictValue" :value="item.dictKey" />
                        </el-select>
                    </el-form-item>
@@ -90,8 +90,8 @@
                <el-col :span="12">
                    <el-form-item label="行政区划" prop="areaCode">
                        <el-cascader
                            class="command-data-cockpit-cascader"
                            popper-class="command-data-cockpit-cascader-popper"
                            class="command-cascader"
                            popper-class="command-cascader-popper"
                            v-model="formData.areaCode"
                            :props="areaProps"
                            clearable
@@ -100,7 +100,7 @@
                </el-col>
                <el-col :span="12">
                    <el-form-item label="部署模式" prop="deploymentMode">
                        <el-radio-group v-model="formData.deploymentMode">
                        <el-radio-group v-model="formData.deploymentMode" class="command-radio-group">
                            <el-radio :label="0">统一部署</el-radio>
                            <el-radio :label="1">独立部署</el-radio>
                        </el-radio-group>
@@ -108,7 +108,7 @@
                </el-col>
                <el-col :span="24">
                    <el-form-item label="备注" prop="remark">
                        <el-input class="command-data-cockpit-search-input" v-model="formData.remark" type="textarea" :rows="3" placeholder="请输入" clearable />
                        <el-input class="command-search-input" v-model="formData.remark" type="textarea" :rows="3" placeholder="请输入" clearable />
                    </el-form-item>
                </el-col>
            </el-row>
applications/drone-command/src/views/permissionManage/permissionDept/index.vue
@@ -3,7 +3,7 @@
        <el-form ref="queryParamsRef" :model="searchParams" class="command-page-history-search">
            <el-form-item label="部门名称" prop="deptName">
                <el-input
                    class="command-data-cockpit-search-input"
                    class="command-search-input"
                    v-model="searchParams.deptName"
                    placeholder="请输入"
                    clearable
@@ -13,7 +13,7 @@
            <el-form-item label="部门全称" prop="fullName">
                <el-input
                    class="command-data-cockpit-search-input"
                    class="command-search-input"
                    v-model="searchParams.fullName"
                    placeholder="请输入"
                    clearable
@@ -37,7 +37,7 @@
        <div class="command-table-container" v-loading="loading" element-loading-background="rgba(5, 5, 15, 0.6)">
            <div class="command-table-content command-table-content-bg">
                <el-table
                    class="command-data-cockpit-table"
                    class="command-table"
                    :data="list"
                    row-key="id"
                    lazy
@@ -80,7 +80,7 @@
            <div class="command-table-pagination">
                <el-pagination
                    popper-class="command-data-cockpit-select-popper"
                    popper-class="command-select-popper"
                    v-model:current-page="searchParams.current"
                    v-model:page-size="searchParams.size"
                    layout="total, prev, pager, next, sizes"
applications/drone-command/src/views/permissionManage/permissionRole/FormDiaLog.vue
@@ -26,19 +26,19 @@
            <el-row>
                <el-col :span="12">
                    <el-form-item label="角色名称" prop="roleName">
                        <el-input class="command-data-cockpit-search-input" v-model="formData.roleName" maxlength="50" placeholder="请输入" clearable />
                        <el-input class="command-search-input" v-model="formData.roleName" maxlength="50" placeholder="请输入" clearable />
                    </el-form-item>
                </el-col>
                <el-col :span="12">
                    <el-form-item label="角色别名" prop="roleAlias">
                        <el-input class="command-data-cockpit-search-input" v-model="formData.roleAlias" maxlength="50" placeholder="请输入" clearable />
                        <el-input class="command-search-input" v-model="formData.roleAlias" maxlength="50" placeholder="请输入" clearable />
                    </el-form-item>
                </el-col>
                <el-col :span="12">
                    <el-form-item label="上级角色" prop="parentId">
                        <el-tree-select
                            class="command-data-cockpit-select"
                            popper-class="command-data-cockpit-tree-select-popper"
                            class="command-select"
                            popper-class="command-tree-select-popper"
                            v-model="formData.parentId"
                            :data="roleTree"
                            :props="treeProps"
applications/drone-command/src/views/permissionManage/permissionRole/index.vue
@@ -3,7 +3,7 @@
        <el-form ref="queryParamsRef" :model="searchParams" class="command-page-history-search">
            <el-form-item label="角色名称" prop="roleName">
                <el-input
                    class="command-data-cockpit-search-input"
                    class="command-search-input"
                    v-model="searchParams.roleName"
                    placeholder="请输入"
                    clearable
@@ -13,7 +13,7 @@
            <el-form-item label="角色别名" prop="roleAlias">
                <el-input
                    class="command-data-cockpit-search-input"
                    class="command-search-input"
                    v-model="searchParams.roleAlias"
                    placeholder="请输入"
                    clearable
@@ -46,7 +46,7 @@
        <div class="command-table-container" v-loading="loading" element-loading-background="rgba(5, 5, 15, 0.6)">
            <div class="command-table-content command-table-content-bg">
                <el-table
                    class="command-data-cockpit-table"
                    class="command-table"
                    :data="list"
                    row-key="id"
                    :tree-props="{ children: 'children', hasChildren: 'hasChildren' }"
@@ -70,7 +70,7 @@
            <div class="command-table-pagination">
                <el-pagination
                    popper-class="command-data-cockpit-select-popper"
                    popper-class="command-select-popper"
                    v-model:current-page="searchParams.current"
                    v-model:page-size="searchParams.size"
                    layout="total, prev, pager, next, sizes"
applications/drone-command/src/views/permissionManage/permissionUser/FormDiaLog.vue
@@ -67,13 +67,13 @@
            <el-row :gutter="16">
                <el-col :span="12">
                    <el-form-item label="登录账号" prop="account">
                        <el-input class="command-data-cockpit-search-input" v-model="formData.account" maxlength="50" placeholder="请输入" clearable />
                        <el-input class="command-search-input" v-model="formData.account" maxlength="50" placeholder="请输入" clearable />
                    </el-form-item>
                </el-col>
                <el-col :span="12" v-if="dialogMode === 'add'">
                    <el-form-item label="密码" prop="password">
                        <el-input
                            class="command-data-cockpit-search-input"
                            class="command-search-input"
                            v-model="formData.password"
                            type="password"
                            maxlength="50"
@@ -86,7 +86,7 @@
                <el-col :span="12" v-if="dialogMode === 'add'">
                    <el-form-item label="确认密码" prop="password2">
                        <el-input
                            class="command-data-cockpit-search-input"
                            class="command-search-input"
                            v-model="formData.password2"
                            type="password"
                            maxlength="50"
@@ -102,22 +102,22 @@
            <el-row :gutter="16">
                <el-col :span="12">
                    <el-form-item label="用户姓名" prop="realName">
                        <el-input class="command-data-cockpit-search-input" v-model="formData.realName" maxlength="50" placeholder="请输入" clearable />
                        <el-input class="command-search-input" v-model="formData.realName" maxlength="50" placeholder="请输入" clearable />
                    </el-form-item>
                </el-col>
                <el-col :span="12">
                    <el-form-item label="手机号" prop="phone">
                        <el-input class="command-data-cockpit-search-input" v-model="formData.phone" maxlength="20" placeholder="请输入" clearable />
                        <el-input class="command-search-input" v-model="formData.phone" maxlength="20" placeholder="请输入" clearable />
                    </el-form-item>
                </el-col>
                <el-col :span="12">
                    <el-form-item label="电子邮箱" prop="email">
                        <el-input class="command-data-cockpit-search-input" v-model="formData.email" maxlength="50" placeholder="请输入" clearable />
                        <el-input class="command-search-input" v-model="formData.email" maxlength="50" placeholder="请输入" clearable />
                    </el-form-item>
                </el-col>
                <el-col :span="12">
                    <el-form-item label="用户性别" prop="sex">
                        <el-select class="command-data-cockpit-select" popper-class="command-data-cockpit-select-popper" v-model="formData.sex" placeholder="请选择" clearable>
                        <el-select class="command-select" popper-class="command-select-popper" v-model="formData.sex" placeholder="请选择" clearable>
                            <el-option label="男" :value="1" />
                            <el-option label="女" :value="2" />
                            <el-option label="未知" :value="3" />
@@ -127,8 +127,8 @@
                <el-col :span="12">
                    <el-form-item label="用户生日" prop="birthday">
                        <el-date-picker
                            class="command-data-cockpit-date-picker"
                            popper-class="command-data-cockpit-date-picker-popper"
                            class="command-date-picker"
                            popper-class="command-date-picker-popper"
                            v-model="formData.birthday"
                            type="datetime"
                            placeholder="请选择"
@@ -144,14 +144,14 @@
            <el-row :gutter="16">
                <el-col :span="12">
                    <el-form-item label="用户编号" prop="code">
                        <el-input class="command-data-cockpit-search-input" v-model="formData.code" maxlength="50" placeholder="请输入" clearable />
                        <el-input class="command-search-input" v-model="formData.code" maxlength="50" placeholder="请输入" clearable />
                    </el-form-item>
                </el-col>
                <el-col :span="12">
                    <el-form-item label="所属角色" prop="roleId">
                        <el-tree-select
                            class="command-data-cockpit-select"
                            popper-class="command-data-cockpit-tree-select-popper"
                            class="command-select"
                            popper-class="command-tree-select-popper"
                            v-model="formData.roleId"
                            :data="roleTree"
                            :props="treeProps"
@@ -165,8 +165,8 @@
                <el-col :span="12">
                    <el-form-item label="所属部门" prop="deptId">
                        <el-tree-select
                            class="command-data-cockpit-select"
                            popper-class="command-data-cockpit-tree-select-popper"
                            class="command-select"
                            popper-class="command-tree-select-popper"
                            v-model="formData.deptId"
                            :data="deptTree"
                            :props="deptTreeSelectProps"
@@ -184,8 +184,8 @@
                <el-col :span="12">
                    <el-form-item label="到期时间" prop="expireTime">
                        <el-date-picker
                            class="command-data-cockpit-date-picker"
                            popper-class="command-data-cockpit-date-picker-popper"
                            class="command-date-picker"
                            popper-class="command-date-picker-popper"
                            v-model="formData.expireTime"
                            type="datetime"
                            placeholder="请选择"
@@ -197,14 +197,14 @@
                </el-col>
                <el-col :span="12">
                    <el-form-item label="次数限制" prop="maxLoginNum">
                        <el-input class="command-data-cockpit-search-input" v-model="formData.maxLoginNum" placeholder="请输入" clearable />
                        <el-input class="command-search-input" v-model="formData.maxLoginNum" placeholder="请输入" clearable />
                    </el-form-item>
                </el-col>
                <el-col :span="12">
                    <el-form-item label="飞行开始时间" prop="flightStartTime">
                        <el-time-picker
                            class="command-data-cockpit-date-picker"
                            popper-class="command-data-cockpit-date-picker-popper"
                            class="command-date-picker"
                            popper-class="command-date-picker-popper"
                            v-model="formData.flightStartTime"
                            placeholder="请选择"
                            format="HH:mm"
@@ -216,8 +216,8 @@
                <el-col :span="12">
                    <el-form-item label="飞行结束时间" prop="flightEndTime">
                        <el-time-picker
                            class="command-data-cockpit-date-picker"
                            popper-class="command-data-cockpit-date-picker-popper"
                            class="command-date-picker"
                            popper-class="command-date-picker-popper"
                            v-model="formData.flightEndTime"
                            placeholder="请选择"
                            format="HH:mm"
applications/drone-command/src/views/permissionManage/permissionUser/index.vue
@@ -3,7 +3,7 @@
        <el-form ref="queryParamsRef" :model="searchParams" class="command-page-history-search">
            <el-form-item label="登录账号" prop="account">
                <el-input
                    class="command-data-cockpit-search-input"
                    class="command-search-input"
                    v-model="searchParams.account"
                    placeholder="请输入"
                    clearable
@@ -13,7 +13,7 @@
            <el-form-item label="用户姓名" prop="realName">
                <el-input
                    class="command-data-cockpit-search-input"
                    class="command-search-input"
                    v-model="searchParams.realName"
                    placeholder="请输入"
                    clearable
@@ -23,8 +23,8 @@
            <el-form-item label="所属部门" prop="deptId">
                <el-tree-select
                    class="command-data-cockpit-select"
                    popper-class="command-data-cockpit-tree-select-popper"
                    class="command-select"
                    popper-class="command-tree-select-popper"
                    v-model="searchParams.deptId"
                    :data="deptTree"
                    :props="treeProps"
@@ -59,7 +59,7 @@
        <div class="command-table-container" v-loading="loading" element-loading-background="rgba(5, 5, 15, 0.6)">
            <div class="command-table-content command-table-content-bg">
                <el-table class="command-data-cockpit-table" :data="list" @selection-change="handleSelectionChange">
                <el-table class="command-table" :data="list" @selection-change="handleSelectionChange">
                    <el-table-column type="selection" width="46" />
                    <el-table-column type="index" show-overflow-tooltip width="64" label="序号" />
                    <el-table-column prop="account" show-overflow-tooltip label="登录账号" />
@@ -79,7 +79,7 @@
            <div class="command-table-pagination">
                <el-pagination
                    popper-class="command-data-cockpit-select-popper"
                    popper-class="command-select-popper"
                    v-model:current-page="searchParams.current"
                    v-model:page-size="searchParams.size"
                    layout="total, prev, pager, next, sizes"
applications/drone-command/src/views/recordManage/alarmRecords/index.vue
@@ -3,7 +3,7 @@
        <el-form ref="queryParamsRef" :model="searchParams" class="command-page-history-search">
            <el-form-item label="无人机名称" prop="droneName">
                <el-input
                    class="command-data-cockpit-search-input"
                    class="command-search-input"
                    v-model="searchParams.droneName"
                    placeholder="请输入"
                    clearable
@@ -12,7 +12,7 @@
            </el-form-item>
            <el-form-item label="区域" prop="areaName">
                <el-input
                    class="command-data-cockpit-search-input"
                    class="command-search-input"
                    v-model="searchParams.areaName"
                    placeholder="请输入"
                    clearable
@@ -21,8 +21,8 @@
            </el-form-item>
            <el-form-item label="设备类型" prop="droneType">
                <el-select
                    class="command-data-cockpit-select"
                    popper-class="command-data-cockpit-select-popper"
                    class="command-select"
                    popper-class="command-select-popper"
                    v-model="searchParams.droneType"
                    placeholder="请选择"
                    clearable
@@ -38,8 +38,8 @@
            </el-form-item>
            <el-form-item label="告警时间">
                <el-date-picker
                    popper-class="command-data-cockpit-date-picker-popper"
                    class="command-data-cockpit-date-picker"
                    popper-class="command-date-picker-popper"
                    class="command-date-picker"
                    v-model="dateRange"
                    type="daterange"
                    range-separator="至"
@@ -63,7 +63,7 @@
        <div class="command-table-container" v-loading="loading" element-loading-background="rgba(5, 5, 15, 0.6)">
            <div class="command-table-content command-table-content-bg">
                <el-table class="command-data-cockpit-table" :data="list" @selection-change="handleSelectionChange">
                <el-table class="command-table" :data="list" @selection-change="handleSelectionChange">
                    <el-table-column type="selection" width="46" />
                    <el-table-column type="index" show-overflow-tooltip width="64" label="序号" />
                    <el-table-column prop="droneName" show-overflow-tooltip width="140" label="无人机名称" />
@@ -88,7 +88,7 @@
            <div class="command-table-pagination">
                <el-pagination
                    popper-class="command-data-cockpit-select-popper"
                    popper-class="command-select-popper"
                    v-model:current-page="searchParams.current"
                    v-model:page-size="searchParams.size"
                    layout="total, prev, pager, next, sizes"
applications/drone-command/src/views/recordManage/historyTracks/TrajectoryDiaLog.vue
@@ -40,7 +40,7 @@
                    <div class="detail-title">轨迹点</div>
                    <div class="command-table-container">
                        <div class="command-table-content">
                            <el-table class="command-data-cockpit-table" :data="list">
                            <el-table class="command-table" :data="list">
                                <el-table-column type="index" width="60" label="序号" />
                                <el-table-column label="经纬度">
                                    <template #default="{ row }">{{ row.longitude }},{{ row.latitude }}</template>
applications/drone-command/src/views/recordManage/historyTracks/index.vue
@@ -3,7 +3,7 @@
        <el-form ref="queryParamsRef" :model="searchParams" class="command-page-history-search">
            <el-form-item label="无人机名称" prop="droneName">
                <el-input
                    class="command-data-cockpit-search-input"
                    class="command-search-input"
                    v-model="searchParams.droneName"
                    placeholder="请输入"
                    clearable
@@ -12,7 +12,7 @@
            </el-form-item>
            <el-form-item label="区域" prop="areaName">
                <el-input
                    class="command-data-cockpit-search-input"
                    class="command-search-input"
                    v-model="searchParams.areaName"
                    placeholder="请输入"
                    clearable
@@ -21,8 +21,8 @@
            </el-form-item>
            <el-form-item label="告警时间">
                <el-date-picker
                    popper-class="command-data-cockpit-date-picker-popper"
                    class="command-data-cockpit-date-picker"
                    popper-class="command-date-picker-popper"
                    class="command-date-picker"
                    v-model="dateRange"
                    type="daterange"
                    range-separator="至"
@@ -44,7 +44,7 @@
        <div class="command-table-container" v-loading="loading" element-loading-background="rgba(5, 5, 15, 0.6)">
            <div class="command-table-content command-table-content-bg">
                <el-table class="command-data-cockpit-table" :data="list">
                <el-table class="command-table" :data="list">
                    <el-table-column type="index" show-overflow-tooltip width="64" label="序号" />
                    <el-table-column prop="droneName" show-overflow-tooltip width="140" label="无人机名称" />
                    <el-table-column prop="serialNo" show-overflow-tooltip label="无人机序列号" />
@@ -66,7 +66,7 @@
            <div class="command-table-pagination">
                <el-pagination
                    popper-class="command-data-cockpit-select-popper"
                    popper-class="command-select-popper"
                    v-model:current-page="searchParams.current"
                    v-model:page-size="searchParams.size"
                    layout="total, prev, pager, next, sizes"
applications/mobile-web-view/src/appComponents/LeafletMap/indexWX.vue
New file
@@ -0,0 +1,607 @@
<template>
    <div class="page-container">
        <div class="map" id="map"></div>
        <!-- <div class="layer-btn" @click="layerChangePopupShow = true" v-show="layerShow">
            <van-image width="20" height="20" :src="layerIcon" />
            <div class="label">图层</div>
        </div>
        <div class="location-btn" @click="setMapLocation" v-show="locationShow">
            <van-image width="20" height="20" :src="locationIcon" />
            <div class="label">定位</div>
        </div> -->
        <slot name="searchBar"></slot>
        <van-popup v-model:show="layerChangePopupShow" position="bottom" round>
            <div class="popup-container">
                <div class="category-content">
                    <div class="header">
                        <div class="title">底图切换</div>
                    </div>
                    <div class="content">
                        <div
                            class="layer-box"
                            :class="{ on: setSelectMapLayerKey === item.key }"
                            v-for="(item, ind) in layers"
                            :key="ind"
                            @click="setMapLayer(item)"
                        >
                            <div class="image">
                                <van-image :src="item.src" width="100%" height="100%"></van-image>
                            </div>
                            <div class="label">{{ item.name }}</div>
                        </div>
                    </div>
                </div>
            </div>
        </van-popup>
    </div>
</template>
<script setup>
    import * as turf from '@turf/turf'
import addressLocationIcon from '@/appDataSource/leafletMapIcon/address-location.svg'
import droneIcon from '@/appDataSource/leafletMapIcon/drone-icon.svg'
import userLocationIcon from '@/appDataSource/leafletMapIcon/user-location.svg'
import layerIcon from '@/appDataSource/leafletMapIcon/layer-icon.svg'
import locationIcon from '@/appDataSource/leafletMapIcon/location-icon.svg'
import { useStore } from 'vuex'
import { showToast } from 'vant'
import L from 'leaflet'
import 'leaflet/dist/leaflet.css'
import sl from '@/appDataSource/leafletMapIcon/sl.svg'
import yx from '@/appDataSource/leafletMapIcon/yx.svg'
import EventBus from '@/utils/eventBus'
import { getEventImage } from '@/utils/stateToImageMap/event'
const emit = defineEmits(['location-selected'])
const { weatherShow, layerShow, locationShow, createWorkShow } = defineProps({
    weatherShow: {
        type: Boolean,
        default: false,
    },
    layerShow: {
        type: Boolean,
        default: false,
    },
    locationShow: {
        type: Boolean,
        default: false,
    },
    createWorkShow: {
        type: Boolean,
        default: false,
    },
})
const isProd = import.meta.env.VITE_APP_ENV === 'production'
import { basemapLayer0, basemapLayer1, basemapLayer2, basemapLayer3 } from '@/const/leafletConst'
const basemap0 = L.layerGroup([basemapLayer0, basemapLayer1])
const basemap1 = L.layerGroup([basemapLayer2, basemapLayer3])
let map = null
const isMapReady = ref(false)
const layers = [
    {
        src: sl,
        name: '矢量',
        key: 1,
        map: basemap0,
    },
    {
        src: yx,
        name: '影像',
        key: 2,
        map: basemap1,
    },
]
const layerChangePopupShow = ref(false)
const setSelectMapLayerKey = ref(1) // 选择的地图图层
let droneMarkersLayer = null
let eventMarkersLayer = null
let addressMarkersLayer = null
let mapLayerSourceLayer = null // 空域信息
const initMap = () => {
    if (map) return
    map = L.map('map', {
        preferCanvas: true,
        crs: L.CRS.EPSG4326,
        zoomControl: false,
        attributionControl: false,
        doubleClickZoom: false,
        editable: true, //绘制控件
    }).setView([27.117445, 114.984917], 10)
    map.whenReady(() => {
        isMapReady.value = true
    })
    droneMarkersLayer = L.layerGroup([], { pane: 'drones' }).addTo(map) // 创建一个标注层,便于管理和移除
    eventMarkersLayer = L.layerGroup([], { pane: 'events' }).addTo(map) // 创建一个标注层,便于管理和移除
    addressMarkersLayer = L.layerGroup([], { pane: 'addresses' }).addTo(map) // 创建一个标注层,便于管理和移除
    // 空域信息
    mapLayerSourceLayer = L.layerGroup([], { pane: 'mapLayerSource' }).addTo(map)
    map.on('zoomend', function () {
        var currentZoom = map.getZoom()
        if (currentZoom >= 11) {
            eventMarkersLayer.addTo(map)
        } else {
            eventMarkersLayer.remove()
        }
    })
    if (createWorkShow) {
        getMapLocation()
    }
}
const getCurMap = () => {
    return map
}
const setMapLayer = item => {
    map.removeLayer(layers.find(i => i.key === setSelectMapLayerKey.value).map)
    map.addLayer(item.map)
    setSelectMapLayerKey.value = item.key
}
let locationFlag = false
let watchId = null
let userLocationMarker = null
const setMapLocation = () => {
    locationFlag = true
    // 在WebView加载的网页中
    // 检查浏览器是否支持 geolocation
    if (navigator.geolocation) {
        if (watchId) {
            // 停止监听位置
            navigator.geolocation.clearWatch(watchId)
        }
        // 开始持续获取用户的位置
        watchId = navigator.geolocation.watchPosition(
            function (position) {
                // 成功获取位置信息时回调
                const lat = position.coords.latitude // 纬度
                const lng = position.coords.longitude // 经度
                if (locationFlag) {
                    if (userLocationMarker) {
                        userLocationMarker.setLatLng([lat, lng])
                    } else {
                        userLocationMarker = L.marker([lat, lng], {
                            icon: L.icon({
                                iconUrl: userLocationIcon, // 图片路径
                                iconSize: [24, 24], // 图标尺寸
                                iconAnchor: [12, 12], // 锚点位置
                            }),
                        }).addTo(map)
                    }
                    mapSetView({
                        lat,
                        lng,
                    })
                    locationFlag = false
                    return
                }
                if (userLocationMarker) {
                    userLocationMarker.setLatLng([lat, lng])
                }
            },
            function (error) {
                // 如果获取位置失败,执行回调
                console.error('Error occurred: ' + error.message)
            },
            {
                enableHighAccuracy: true, // 尝试获取更高精度的定位
                timeout: 10000, // 如果10秒内没有获取到位置,就中止
                maximumAge: 0, // 始终请求新的定位,不使用缓存
            }
        )
    } else {
        console.log('该浏览器不支持地理定位功能。')
    }
}
let lastLocationMarker = null
const getMapLocation = () => {
    map.off('click')
    map.on('click', function (e) {
        const { lat, lng } = e.latlng
        if (lastLocationMarker) {
            map.removeLayer(lastLocationMarker)
        }
        lastLocationMarker = L.marker([lat, lng]).addTo(map)
        emit('location-selected', {
            latitude: lat,
            longitude: lng,
        })
    })
}
const mapSetView = data => {
    const { lat, lng, zoom = 16 } = data
    if (!map) return
    map.setView([lat, lng], zoom, {
        animate: false, // 使用动画过渡
    })
}
const mapAddMarker = data => {
    if (!map) return
    const { lat, lng, zoom = 16, name = '', customClassName = '' } = data
    mapSetView(data)
    // 创建带有图标和文字的 divIcon
    let droneHtmlIcon = L.divIcon({
        html: `
                <div class="content ${customClassName}">
                    <img src="${addressLocationIcon}">
                    <span>
                        ${name}
                    </span>
                </div>
            `,
        className: 'ztzf-address-custom-icon', // 可选,用于添加CSS类
        iconSize: [24, 38], // 设置图标大小
        iconAnchor: [12, 19],
    })
    L.marker([lat, lng], { icon: droneHtmlIcon }).addTo(addressMarkersLayer)
}
// 吉安项目-空域信息
// 统一的飞行函数
function flyVisual(coordinates) {
    // 确保map对象存在且坐标有效
    if (!map || !coordinates || !coordinates.length) return;
    try {
        // 改进坐标格式判断
        let isSinglePoint = false;
        let latLng;
        let bounds;
        // 处理不同格式的坐标输入
        if (Array.isArray(coordinates[0])) {
            if (coordinates[0].length === 2) {
                // 格式: [[lng, lat]] - 单个点
                isSinglePoint = true;
                latLng = [coordinates[0][1], coordinates[0][0]]; // 转换为 [lat, lng]
            } else if (coordinates[0].length > 2 && Array.isArray(coordinates[0][0])) {
                // 格式: [[[lng, lat], [lng, lat], ...]] - 多边形
                const polygonCoords = coordinates[0].map(coord => [coord[1], coord[0]]);
                bounds = L.latLngBounds(polygonCoords);
            } else {
                // 格式: [[lng, lat], [lng, lat], ...] - 多个点或线
                if (coordinates.length === 1) {
                    // 单个点
                    isSinglePoint = true;
                    latLng = [coordinates[0][1], coordinates[0][0]];
                } else {
                    // 多个点
                    const leafletCoords = coordinates.map(coord => [coord[1], coord[0]]);
                    bounds = L.latLngBounds(leafletCoords);
                }
            }
        } else if (coordinates.length === 2) {
            // 格式: [lng, lat] - 单个点
            isSinglePoint = true;
            latLng = [coordinates[1], coordinates[0]];
        }
        if (isSinglePoint && latLng) {
            // 单个坐标点
            map.flyTo(latLng, 10, {
                duration: 1,
                easeLinearity: 0.2
            });
        } else if (bounds) {
            // 多边形或多个点
            map.flyToBounds(bounds, {
                padding: [30, 30],
                duration: 2,
                maxZoom: 13
            });
        }
    } catch (error) {
        console.error('flyVisual 函数执行错误:', error);
    }
}
// 点击单个飞行
function signFlyToMarker(item) {
    const positionsData = JSON.parse(item.geoJson);
    const coordinates = positionsData.coordinates;
    // 更全面的空值检查
    let hasValidCoordinates = false;
    // 检查不同格式的坐标数据
    if (Array.isArray(coordinates)) {
        if (coordinates.length > 0) {
            // 检查是否有有效的坐标点
            if (Array.isArray(coordinates[0])) {
                if (coordinates[0].length === 2 || coordinates[0].length === 3) {
                    // 格式: [lng, lat] 或 [lng, lat, alt]
                    hasValidCoordinates = true;
                } else if (Array.isArray(coordinates[0][0])) {
                    // 格式: [[lng, lat], [lng, lat], ...]
                    hasValidCoordinates = coordinates[0].length > 0;
                } else if (Array.isArray(coordinates[0][0][0])) {
                    // 格式: [[[lng, lat], [lng, lat], ...]]
                    hasValidCoordinates = coordinates[0][0].length > 0;
                }
            }
        }
    }
    if (!hasValidCoordinates) {
        console.log('没有有效的坐标数据,显示提示');
        return showToast('暂无区域数据');
    }
    // 单个位置飞行
    flyVisual(coordinates);
}
// 清空所有空域信息
function mapClearAirMarker() {
    if (!map) return
    // 清空所有图层
    if (mapLayerSourceLayer) {
        mapLayerSourceLayer.clearLayers();
    }
}
function mapAddAirMarker(data) {
    // 清空所有图层
    mapClearAirMarker()
    data
        .filter(item => item.geoJson)
        .forEach(item => {
            const parseParsed = JSON.parse(item.geoJson); // 转为数组
            if (parseParsed.type !== 'Polygon') return
            const parsed = parseParsed.coordinates[0]
            const grouped = parsed.flat(); // 再展开
            // 3. 计算多边形质心
            const turfPolygon = turf.polygon([parsed]);
            const center = turf.centerOfMass(turfPolygon);
            const centerLatLng = [center.geometry.coordinates[1], center.geometry.coordinates[0]];
            const labelMarker = L.marker(centerLatLng, {
                icon: L.divIcon({
                    className: 'polygon-label',
                    html: `
                            <div style="
                                color: ${item.airspaceType === '0' ? '#008013' : '#ff0000'};
                                font-weight: bold;
                                font-size: 12px;
                                font-family: 'Source Han Sans CN', 'Source Han Sans CN';
                                white-space: nowrap;
                            ">
                                ${item.airspaceType === '1' ? '禁飞区' : item.airspaceType === '2' ? '危险区' : item.airspaceType === '3' ? '限制区' : item.airspaceType === '0' ? '适飞区' : '未知'}
                            </div>
                        `,
                    iconSize: null,    // 让div决定大小
                    iconAnchor: null   // 不需要锚点,用CSS transform居中
                }),
                interactive: false,    // 标签不参与交互
                // zIndexOffset: 1000     // 确保标签在最上层
            });
            // 将坐标数组转换为 Leaflet 格式 [lat, lng, lat, lng...] -> [[lat, lng], [lat, lng]...]
            const latLngs = [];
            for (let i = 0; i < grouped.length; i += 2) {
                latLngs.push([grouped[i + 1], grouped[i]]); // 注意:Leaflet 是 [lat, lng] 顺序
            }
            // 创建多边形(填充区域)
            const polygon = L.polygon(latLngs, {
                color: item.airspaceType === '0' ? '#00ff06' : '#ff0000',
                fillColor: item.airspaceType === '0' ? '#00ff06' : '#ff0000',
                fillOpacity: 0.5,
                weight: 0, // 隐藏多边形边框,使用折线作为边框
            });
            // 创建折线(边框)
            const polyline = L.polyline([...latLngs, latLngs[0]], { // 闭合多边形
                color: item.airspaceType === '0' ? '#00ff06' : '#ff0000',
                weight: 1.5,
                opacity: 1,
                fill: false
            });
            // 将两个图层组合在一起
            const group = L.featureGroup([polygon, polyline, labelMarker]);
            // 添加到图层组
            mapLayerSourceLayer.addLayer(group);
        });
}
const mapClearMarker = () => {
    addressMarkersLayer.clearLayers()
}
// 天气
const store = useStore()
const selectedAreaCode = computed(() => store.state.user.selectedAreaCode)
onMounted(async () => {
    await nextTick()
    initMap()
    map.addLayer(layers[0].map)
    EventBus.on('mapSetView', mapSetView)
    EventBus.on('mapAddMarker', mapAddMarker)
    EventBus.on('mapAddAirMarker', mapAddAirMarker)
    EventBus.on('signFlyToMarker', signFlyToMarker)
    EventBus.on('mapClearAirMarker', mapClearAirMarker)
    EventBus.on('mapClearMarker', mapClearMarker)
    // L.circle([24, 112], {
    //     color: 'red', // 边框颜色
    //     fillColor: '#f03', // 填充颜色
    //     fillOpacity: 0.5, // 填充透明度
    //     radius: 5000, // 半径,单位是米
    // }).addTo(map)
})
onUnmounted(() => {
    EventBus.off('mapSetView', mapSetView)
    EventBus.off('mapAddMarker', mapAddMarker)
    EventBus.off('mapAddAirMarker', mapAddAirMarker)
    EventBus.off('signFlyToMarker', signFlyToMarker)
    EventBus.off('mapClearAirMarker', mapClearAirMarker)
    EventBus.off('mapClearMarker', mapClearMarker)
})
</script>
<style lang="scss" scoped>
.page-container {
    position: relative;
    width: 100%;
    height: 100%;
    .map {
        width: 100%;
        height: 100%;
    }
    .location-btn,
    .layer-btn {
        display: flex;
        flex-direction: column;
        justify-content: center;
        align-items: center;
        position: absolute;
        right: 8px;
        width: 40px;
        height: 40px;
        background: #ffffff;
        box-shadow: 0px 0px 4px 0px rgba(0, 0, 0, 0.2);
        border-radius: 6px 6px 6px 6px;
        z-index: 996;
        .label {
            font-size: 10px;
        }
    }
    .layer-btn {
        bottom: 130px;
    }
    .location-btn {
        bottom: 80px;
    }
}
.popup-container {
    height: 300px;
    overflow-y: auto;
    padding: 10px 22px;
    background: #fff;
    border-radius: 12px 12px 0 0;
    .category-content {
        margin-bottom: 10px;
        .header {
            margin-bottom: 10px;
            height: 20px;
            font-family: Source Han Sans CN, Source Han Sans CN;
            font-weight: bold;
            font-size: 16px;
            color: #222324;
            line-height: 20px;
            text-align: left;
            font-style: normal;
            text-transform: none;
        }
        .base-header {
            margin-top: 10px;
        }
        .content {
            //padding: 12px;
            display: flex;
            background: #fff;
            border-radius: 16px;
            .layer-box {
                margin-left: calc((100% / 3 - 84px) * 3 / 2);
                &:first-child {
                    margin-left: 0;
                }
                &.on {
                    .image {
                        position: relative;
                        &::after {
                            content: '';
                            position: absolute;
                            top: 0;
                            left: 0;
                            width: 100%;
                            height: 100%;
                            border-radius: 4px 4px 4px 4px;
                            border: 4px solid #1d6fe9;
                            z-index: 1;
                            box-sizing: border-box;
                        }
                    }
                    .label {
                        color: #1d6fe9;
                    }
                }
                .image {
                    width: 84px;
                    height: 82px;
                    border-radius: 4px 4px 4px 4px;
                    overflow: hidden;
                    box-sizing: border-box;
                    border: none;
                }
                .label {
                    margin-top: 6px;
                    height: 20px;
                    font-family: Source Han Sans CN, Source Han Sans CN;
                    font-weight: 400;
                    font-size: 14px;
                    color: #222324;
                    line-height: 20px;
                    text-align: center;
                    font-style: normal;
                    text-transform: none;
                }
            }
            .layer-box:nth-child(3n + 1) {
                margin-left: 0;
            }
        }
    }
}
</style>
applications/task-work-order/src/views/orderView/orderDataManage/supplyAdd/FormDiaLog.vue
@@ -187,7 +187,6 @@
            </el-row>
        </el-form>
        <template #footer>
            <el-button color="#F2F3F5" @click="visible = false">{{ dialogReadonly ? '关闭' : '取消' }}</el-button>
            <el-button
                class="save-btn"
                color="#4C34FF"
@@ -198,6 +197,8 @@
            >
                保存
            </el-button>
            <el-button color="#F2F3F5" :loading="submitting" :disabled="submitting" @click="handleApply">申请</el-button>
        </template>
    </el-dialog>
</template>
@@ -226,6 +227,7 @@
    responsibleDeptId: '',
    dataSource: '',
    demandInfo: '',
    demandStatus: '0'
})
const dictObj = inject('dictObj')
@@ -262,6 +264,7 @@
    if (!isValid) return
    submitting.value = true
    try {
        formData.value.demandStatus = '0'
        await gdSupplyDemandSubmitApi(formData.value)
        ElMessage.success(dialogMode.value === 'add' ? '新增成功' : '更新成功')
        visible.value = false
@@ -271,6 +274,22 @@
    }
}
// 申请提交
async function handleApply() {
    const isValid = await formRef.value?.validate().catch(() => false)
    if (!isValid) return
    submitting.value = true
    try {
        formData.value.demandStatus = '1'
        await gdSupplyDemandSubmitApi(formData.value)
        ElMessage.success('申请成功')
        visible.value = false
        emit('success')
    } finally {
        submitting.value = false
    }
}
// 加载详情
async function loadDetail() {
    if (!formData.value.id) return
applications/task-work-order/src/views/orderView/orderDataManage/supplyAdd/index.vue
@@ -54,9 +54,9 @@
                    <el-table-column prop="contactPhone" show-overflow-tooltip label="需求联系人电话" />
                    <el-table-column prop="contactEmail" show-overflow-tooltip label="需求邮箱" />
                    <el-table-column prop="demandStatus" show-overflow-tooltip label="需求状态">
                        <!-- <template v-slot="{ row }">
                        <template v-slot="{ row }">
                            {{ getDictLabel(row.demandStatus, dictObj.demandStatus) }}
                        </template> -->
                        </template>
                    </el-table-column>
                    <el-table-column prop="updateCycle" show-overflow-tooltip label="更新周期" />
                    <el-table-column prop="applyBasis" show-overflow-tooltip label="申请依据" />
@@ -196,7 +196,7 @@
// 获取字典
function getDictList() {
    getDictionaryByCode('requirementType,sharedType,appSceneType').then(res => {
    getDictionaryByCode('requirementType,sharedType,appSceneType,demandStatus').then(res => {
        dictObj.value = res.data.data
    })
}
uniapps/work-wx/src/subPackages/deviceRegistration/add.vue
@@ -597,9 +597,11 @@
onMounted(async () => {
    getProTypeApi()
    getManufacturerInfoApi()
    // 动态导入xzqhData,确保在使用前已初始化
    const { xzqhData } = await import('@/static/xzqh/index')
    areaData.value = xzqhData
    // 动态从外部URL导入xzqhData,确保在使用前已初始化
    // 注意:直接动态导入外部URL可能会有跨域或构建问题,建议检查服务器CORS设置
    const response = await fetch('https://wrj.shuixiongit.com/aiskyminio/cloud-bucket/ja-app-wx/xzqh/index.json')
    const text = await response.text()
    areaData.value = JSON.parse(text)
})
</script>
<style scoped lang="scss">