吉安感知网项目-前端
shuishen
2026-02-06 bbee739452ba6dd855e903bf62296114025b3fac
feat:区域划分及数据驾驶舱调整
4 files modified
88 ■■■■ changed files
applications/drone-command/src/components/map-container/components/DronePopup.vue 3 ●●●● patch | view | raw | blame | history
applications/drone-command/src/components/map-container/device-map-container.vue 7 ●●●● patch | view | raw | blame | history
applications/drone-command/src/utils/cesium/shapeTools/draw/DrawPolygonTool.js 11 ●●●●● patch | view | raw | blame | history
applications/drone-command/src/views/areaManage/partition/FormDiaLog.vue 67 ●●●● patch | view | raw | blame | history
applications/drone-command/src/components/map-container/components/DronePopup.vue
@@ -127,8 +127,7 @@
    const num = Number(value)
    if (!Number.isFinite(num)) return '-'
    const absVal = Math.abs(num).toFixed(6)
    const dir = type === 'lng' ? (num >= 0 ? 'E' : 'W') : num >= 0 ? 'N' : 'S'
    return `${absVal} ${dir}`
    return `${absVal}`
}
const height = computed(() => formatNumber(props.drone?.flightHeightM, 'm', 0))
applications/drone-command/src/components/map-container/device-map-container.vue
@@ -77,6 +77,7 @@
const DETAIL_HEIGHT = 10000
const POLYGON_HEIGHT_M = 0.2
const DRONE_TRACK_DURATION_S = 30 * 60
const FIXED_DRONE_TRACK_IDS = ['6000000000602', '6000000000601']
const props = defineProps({
    allDevices: {
@@ -718,7 +719,9 @@
    droneTrackPolylineCollection.show = detailVisible.value
    droneTrackRuntime = []
    const baseTrackColor = Cesium.Color.fromCssColorString('red')
        ; (list || []).forEach((item, trackIndex) => {
        ; (FIXED_DRONE_TRACK_IDS || []).forEach((trackId, trackIndex) => {
            const item = (list || []).find(entry => String(entry?.id) === String(trackId))
            if (!item) return
            const position = getDevicePosition(item)
            if (!position) return
            const points = buildSimulatedTrackPoints({ ...position, height: item.flightHeightM, trackIndex })
@@ -742,7 +745,7 @@
                width: 3,
                material: trackMaterial,
            })
            const droneId = `drone-alarm-${item?.alarmRecordId ?? item?.id ?? trackIndex}`
            const droneId = `drone-alarm-${trackId}`
            const startTime = viewer.clock.startTime
            const stopTime = viewer.clock.stopTime
            const positionProperty = new Cesium.SampledPositionProperty()
applications/drone-command/src/utils/cesium/shapeTools/draw/DrawPolygonTool.js
@@ -91,6 +91,9 @@
    }
    start() {
        if (!this.tooltip) {
            this.tooltip = new MapTooltip(this.viewer)
        }
        this.dataSource = new Cesium.CustomDataSource('draw-polygon')
        this.viewer.dataSources.add(this.dataSource)
        this.handler = new Cesium.ScreenSpaceEventHandler(this.viewer.scene.canvas)
@@ -139,10 +142,10 @@
        if (!this.isDrawing) return
        const tipText = this.getTipText()
        if (!this.tooltip?.isVisible) {
            this.tooltip.show(tipText, movement.endPosition)
            this.tooltip?.show(tipText, movement.endPosition)
        } else {
            this.tooltip.show(tipText)
            this.tooltip.move(movement.endPosition)
            this.tooltip?.show(tipText)
            this.tooltip?.move(movement.endPosition)
        }
        if (this.positions.length === 0) return
        const position = this.getPositionFromScreen(movement.endPosition)
@@ -283,7 +286,7 @@
        this.floatPosition = null
        this.isIntersecting = false
        this.notify('getPolygonPositions', this.positions)
        this.tooltip.hide()
        this.tooltip?.hide()
        this.clearPreviewEntities()
    }
applications/drone-command/src/views/areaManage/partition/FormDiaLog.vue
@@ -97,7 +97,7 @@
                    <div class="detail-title">绘制区域列表</div>
                    <div class="command-table-container">
                        <div class="command-table-content">
                            <el-table class="command-table" :data="shapeList" row-key="id">
                            <el-table class="command-table" :data="shapeList" row-key="id"  height="240">
                                <el-table-column prop="areaType" label="区域类型">
                                    <template v-slot="{ row }">
                                        {{ resolveShapeAreaTypeLabel(row) }}
@@ -116,7 +116,7 @@
                    <div class="command-table-container">
                        <div class="command-table-content">
                            <el-table class="command-table" ref="deviceTableRef" :data="deviceOptions" row-key="id"
                                @row-click="handleDeviceRowClick">
                                @row-click="handleDeviceRowClick"  height="240">
                                <el-table-column prop="deviceName" label="设备名称" />
                                <el-table-column prop="deviceType" label="类型">
                                    <template v-slot="{ row }">
@@ -169,7 +169,7 @@
                    <div class="shape-table-container">
                        <div class="shape-table-title">绘制区域列表</div>
                        <el-table class="command-table" :data="shapeList" row-key="id" height="auto">
                        <el-table class="command-table" :data="shapeList" row-key="id" height="240">
                            <el-table-column prop="areaType" label="区域类型">
                                <template v-slot="{ row }">
                                    {{ resolveShapeAreaTypeLabel(row) }}
@@ -201,7 +201,7 @@
                        <el-form-item prop="deviceIds" label-width="0">
                            <el-table class="command-table" ref="deviceTableRef"
                                :data="deviceOptions.filter(item => item.deviceName.includes(searchName))" row-key="id"
                                @selection-change="handleDeviceSelectionChange" @row-click="handleDeviceRowClick">
                                @selection-change="handleDeviceSelectionChange" @row-click="handleDeviceRowClick"  height="240">
                                <el-table-column type="selection" width="55" :reserve-selection="true" />
                                <el-table-column prop="deviceName" label="设备名称" />
                                <el-table-column prop="deviceType" label="类型">
@@ -323,6 +323,7 @@
let deviceRangeRenderToken = 0
let deviceListTimer = null
let deviceListRequestToken = 0
let deviceMapRequestToken = 0
const rules = {
    areaName: fieldRules(true, 50),
@@ -519,8 +520,6 @@
    deviceOptions.value = []
    selectedDeviceRows.value = []
    formData.value.deviceIds = ''
    clearDeviceRangePrimitives()
    clearDeviceIconEntities()
    if (deviceTableRef.value) {
        deviceTableRef.value.clearSelection()
    }
@@ -661,20 +660,6 @@
        if (wkt) polygons.push(wkt)
    })
    return polygons
}
async function renderDeviceRangeSingle (device) {
    if (!viewer) return
    clearDeviceRangePrimitives()
    clearDeviceIconEntities()
    const position = getDeviceLngLat(device)
    if (!position) return
    addDeviceIconEntity(device, position)
    const rangeMeters = normalizeDeviceRange(device.effectiveRangeKm)
    const primitive = await createDeviceRangePrimitive(viewer, position, rangeMeters)
    if (!primitive) return
    deviceRangePrimitiveMap.set(String(device?.id ?? Date.now()), primitive)
    viewer.scene.primitives.add(primitive)
}
async function renderDeviceRanges (rows) {
@@ -1384,9 +1369,29 @@
    suppressDeviceFly.value = true
    syncDeviceSelection()
    suppressDeviceFly.value = prevSuppressDeviceFly
    if (!readonly.value) {
        renderDeviceRanges(selectedDeviceRows.value)
    if (readonly.value) {
        await renderDeviceRanges(deviceOptions.value)
    }
}
// 设备上图(新增/编辑用)
async function getDeviceListForMapDisplay () {
    if (!visible.value || !viewer) return
    deviceMapRequestToken += 1
    const requestToken = deviceMapRequestToken
    const res = await fwDeviceListByPolygonsApi({
        areaId: dialogMode.value === 'add' ? '' : formData.value.id,
        isAreaSelect: 1,
        isTrack: 1,
    })
    if (requestToken !== deviceMapRequestToken) return
    const list = res?.data?.data ?? []
    if (!list.length) {
        clearDeviceRangePrimitives()
        clearDeviceIconEntities()
        return
    }
    await renderDeviceRanges(list)
}
// 关联设备变更
@@ -1394,7 +1399,6 @@
    selectedDeviceRows.value = rows
    const ids = rows.map(item => item.id)
    formData.value.deviceIds = ids.join(',')
    renderDeviceRanges(rows)
    if (suppressDeviceFly.value) {
        lastSelectedDeviceIds = [...ids]
        return
@@ -1409,12 +1413,13 @@
function handleDeviceRowClick (row) {
    if (readonly.value) {
        renderDeviceRangeSingle(row)
        void flyToDevice(row)
        return
    }
    renderDeviceRanges(selectedDeviceRows.value)
    void flyToDevice(row)
    const isSelected = selectedDeviceRows.value.some(item => String(item?.id) === String(row?.id))
    if (isSelected) {
        void flyToDevice(row)
    }
}
// 同步选择状态
@@ -1429,10 +1434,6 @@
    })
    selectedDeviceRows.value = rows
    formData.value.deviceIds = rows.map(item => item.id).join(',')
    if (readonly.value) {
        renderDeviceRanges(selectedDeviceRows.value)
        return
    }
    if (!deviceTableRef.value) return
    deviceTableRef.value.clearSelection()
    rows.forEach(row => {
@@ -1499,11 +1500,11 @@
    lastSelectedDeviceIds = selectedDeviceRows.value.map(row => row.id)
    await nextTick()
    suppressDeviceFly.value = false
    if (!readonly.value) {
        renderDeviceRanges(selectedDeviceRows.value)
    }
    isDialogInitializing.value = false
    queueDeviceListRefresh()
    if (dialogMode.value === 'add' || dialogMode.value === 'edit') {
        void getDeviceListForMapDisplay()
    }
    void getPoliceStationList()
}