吉安感知网项目-前端
shuishen
2026-01-30 8c450d784fe7bab2b27e3345ef9263e9f295ecaa
feat:数据驾驶舱地图渲染及区域划分、场景配置部分逻辑公用
4 files modified
1 files added
264 ■■■■ changed files
applications/drone-command/src/components/map-container/device-map-container.vue 155 ●●●●● patch | view | raw | blame | history
applications/drone-command/src/views/areaManage/partition/FormDiaLog.vue 36 ●●●●● patch | view | raw | blame | history
applications/drone-command/src/views/areaManage/sceneConfig/FormDiaLog.vue 36 ●●●●● patch | view | raw | blame | history
packages/constants/areaStyles.js 36 ●●●●● patch | view | raw | blame | history
packages/constants/index.js 1 ●●●● patch | view | raw | blame | history
applications/drone-command/src/components/map-container/device-map-container.vue
@@ -48,8 +48,10 @@
import * as Cesium from 'cesium'
import CommonCesiumMap from '@/components/map-container/common-cesium-map.vue'
import { geomAnalysis } from '@ztzf/utils'
import { buildEllipsePositions } from '@/utils/cesium/shapeTools'
import { AREA_TYPE_STYLE_MAP, BUFFER_LEVEL_STYLES, DEFAULT_AREA_STYLE } from '@ztzf/constants'
import { fwDefenseZonePageApi } from '@/views/areaManage/defenseZone/defenseZoneApi'
import { fwAreaDividePageApi } from '@/views/areaManage/partition/partitionApi'
import { fwAreaDivideListApi } 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'
@@ -791,6 +793,10 @@
    return list.map(item => Cesium.Cartesian3.fromDegrees(item.longitude, item.latitude))
}
const getAreaTypeStyle = areaType => {
    return AREA_TYPE_STYLE_MAP?.[String(areaType)] || DEFAULT_AREA_STYLE
}
const buildZonePrimitives = (zones, lineColor, fillColor1, fillColor2) => {
    if (!viewer) return { primitive: null, outlinePrimitive: null }
    const polygonInstances = []
@@ -849,6 +855,146 @@
    return { primitive, outlinePrimitive }
}
const buildPartitionPrimitives = shapes => {
    if (!viewer) return { primitive: null, outlinePrimitive: null }
    const polygonInstances = []
    const lineInstances = []
    const vertexFormat = Cesium.PerInstanceColorAppearance.VERTEX_FORMAT
        ; (shapes || []).forEach(shape => {
            if (!shape?.positions || shape.positions.length < 3) return
            const positions = shape.positions
            const polygon = new Cesium.PolygonGeometry({
                polygonHierarchy: new Cesium.PolygonHierarchy(positions),
                vertexFormat,
            })
            polygonInstances.push(
                new Cesium.GeometryInstance({
                    geometry: polygon,
                    attributes: {
                        color: Cesium.ColorGeometryInstanceAttribute.fromColor(shape.fillColor),
                    },
                })
            )
            const linePositions = positions.length > 1 ? [...positions, positions[0]] : positions
            lineInstances.push(
                new Cesium.GeometryInstance({
                    geometry: new Cesium.GroundPolylineGeometry({
                        positions: linePositions,
                        width: 2,
                    }),
                    attributes: {
                        color: Cesium.ColorGeometryInstanceAttribute.fromColor(
                            shape.outlineColor
                        ),
                    },
                })
            )
        })
    let primitive = null
    if (polygonInstances.length) {
        primitive = new Cesium.GroundPrimitive({
            geometryInstances: polygonInstances,
            appearance: new Cesium.PerInstanceColorAppearance({ translucent: true, flat: true }),
        })
        addCockpitPrimitive(primitive)
    }
    let outlinePrimitive = null
    if (lineInstances.length) {
        outlinePrimitive = new Cesium.GroundPolylinePrimitive({
            geometryInstances: lineInstances,
            appearance: new Cesium.PolylineColorAppearance(),
        })
        addCockpitPrimitive(outlinePrimitive)
    }
    return { primitive, outlinePrimitive }
}
const parseGeomJson = geomJson => {
    if (!geomJson) return null
    if (typeof geomJson === 'object') return geomJson
    if (typeof geomJson !== 'string') return null
    const trimmed = geomJson.trim()
    if (!trimmed) return null
    try {
        return JSON.parse(trimmed)
    } catch (error) {}
    return null
}
const normalizeShapePoint = point => {
    if (!point) return null
    const lng = point?.lng ?? point?.longitude
    const lat = point?.lat ?? point?.latitude
    const height = Number.isFinite(Number(point?.height)) ? Number(point.height) : 0
    if (!Number.isFinite(Number(lng)) || !Number.isFinite(Number(lat))) return null
    return { lng: Number(lng), lat: Number(lat), height }
}
const buildShapePositions = (points = []) => {
    const normalized = points.map(normalizeShapePoint).filter(Boolean)
    return normalized.map(point => Cesium.Cartesian3.fromDegrees(point.lng, point.lat, point.height))
}
const getShapeDisplayPoints = shape => {
    if (Array.isArray(shape?.displayPoints) && shape.displayPoints.length) {
        return shape.displayPoints
    }
    return shape?.points || []
}
const resolvePartitionShapes = areas => {
    const shapes = []
        ; (areas || []).forEach(area => {
            const extList = Array.isArray(area?.fwAreaDivideExtList) ? area.fwAreaDivideExtList : []
            extList.forEach((item, index) => {
                const isShapePayload = item?.drawType || item?.points
                const parsed = isShapePayload ? item : parseGeomJson(item?.geomJson)
                if (!parsed) return
                const shape = {
                    id: parsed?.id || `shape_${Date.now()}_${index}_${Math.random().toString(16).slice(2, 6)}`,
                    drawType: parsed?.drawType ?? 'polygon',
                    areaType: parsed?.areaType ?? item?.areaTypeKey ?? item?.areaType ?? '',
                    points: Array.isArray(parsed?.points) ? parsed.points : [],
                    displayPoints: Array.isArray(parsed?.displayPoints) ? parsed.displayPoints : null,
                    meta: parsed?.meta ?? null,
                }
                if (shape.drawType === 'buffer' && shape.meta?.bufferRadii?.length && shape.meta?.center) {
                    const center = shape.meta.center
                    const centerCartesian = Cesium.Cartesian3.fromDegrees(
                        center.lng,
                        center.lat,
                        center.height || 0
                    )
                    const radii = shape.meta.bufferRadii
                        .map(radius => Number(radius))
                        .filter(radius => Number.isFinite(radius) && radius > 0)
                    radii.forEach((radius, levelIndex) => {
                        const positions = buildEllipsePositions(centerCartesian, radius, radius)
                    const style = BUFFER_LEVEL_STYLES[levelIndex] || BUFFER_LEVEL_STYLES[BUFFER_LEVEL_STYLES.length - 1]
                        if (positions.length >= 3) {
                            shapes.push({
                                positions,
                                fillColor: style.fill,
                                outlineColor: style.outline,
                            })
                        }
                    })
                    return
                }
                const positions = buildShapePositions(getShapeDisplayPoints(shape))
                if (positions.length >= 3) {
                    const style = getAreaTypeStyle(shape.areaType)
                    shapes.push({
                        positions,
                        fillColor: style.fill,
                        outlineColor: style.outline,
                    })
                }
            })
        })
    return shapes
}
const renderDefenseZones = zones => {
    if (!viewer) return
    clearDefenseZoneEntities()
@@ -863,7 +1009,8 @@
const renderPartitions = zones => {
    if (!viewer) return
    clearPartitionEntities()
    const result = buildZonePrimitives(zones, '#FFD772', '#FFD772', '#A86B00')
    const shapes = resolvePartitionShapes(zones)
    const result = buildPartitionPrimitives(shapes)
    partitionPrimitive = result.primitive
    partitionOutlinePrimitive = result.outlinePrimitive
    if (partitionPrimitive) partitionPrimitive.show = detailVisible.value
@@ -884,8 +1031,8 @@
const loadPartitions = async () => {
    if (!viewer) return
    try {
        const res = await fwAreaDividePageApi({ current: 1, size: DEFAULT_ZONE_PAGE_SIZE })
        renderPartitions(res?.data?.data?.records ?? [])
        const res = await fwAreaDivideListApi()
        renderPartitions(res?.data?.data ?? [])
    } catch (error) {
        renderPartitions([])
    }
applications/drone-command/src/views/areaManage/partition/FormDiaLog.vue
@@ -236,6 +236,7 @@
import { DrawManager, EditManager, buildEllipsePositions } from '@/utils/cesium/shapeTools'
import { cartesian3Convert } from '@/utils/cesium/mapUtil'
import * as Cesium from 'cesium'
import { AREA_TYPE_STYLE_MAP, BUFFER_LEVEL_STYLES, DEFAULT_AREA_STYLE } from '@ztzf/constants'
import { fwPoliceStationListApi } from '@/views/areaManage/precinctInfo/precinctInfoApi'
import { fwDeviceListApi } from '@/views/basicManage/deviceStock/fwDevice'
import polygonIcon from '@/assets/images/areaMap/polygon.png'
@@ -285,20 +286,6 @@
const bufferAreaTypeValue = '1,2,3'
const showTypePanel = ref(false)
const suppressTypePanelOnce = ref(false)
const areaTypeStyleMap = {
    '1': {
        fill: Cesium.Color.fromBytes(25, 178, 230, 128),
        outline: Cesium.Color.fromBytes(0, 251, 255, 255),
    },
    '2': {
        fill: Cesium.Color.fromBytes(255, 235, 59, 128),
        outline: Cesium.Color.fromBytes(255, 235, 59, 255),
    },
    '3': {
        fill: Cesium.Color.fromBytes(247, 20, 20, 128),
        outline: Cesium.Color.fromBytes(255, 0, 0, 255),
    },
}
let viewer
let drawManager
let editManager
@@ -655,10 +642,7 @@
}
function getAreaTypeStyle (areaType) {
    return areaTypeStyleMap?.[String(areaType)] || {
        fill: Cesium.Color.fromBytes(45, 140, 240, 99),
        outline: Cesium.Color.fromBytes(45, 140, 240, 255),
    }
    return AREA_TYPE_STYLE_MAP?.[String(areaType)] || DEFAULT_AREA_STYLE
}
function renderShapeList () {
@@ -677,22 +661,8 @@
            const [radius1, radius2, radius3] = shape.meta.bufferRadii
            const radii = [radius1, radius2, radius3].filter(item => Number.isFinite(item) && item > 0)
            if (radii.length) {
                const styles = [
                    {
                        fill: Cesium.Color.fromBytes(247, 20, 20, 128),
                        outline: Cesium.Color.fromBytes(255, 0, 0, 255),
                    },
                    {
                        fill: Cesium.Color.fromBytes(255, 235, 59, 128),
                        outline: Cesium.Color.fromBytes(255, 235, 59, 255),
                    },
                    {
                        fill: Cesium.Color.fromBytes(25, 178, 230, 128),
                        outline: Cesium.Color.fromBytes(0, 251, 255, 255),
                    },
                ]
                radii.forEach((radius, index) => {
                    const style = styles[index] || styles[styles.length - 1]
                    const style = BUFFER_LEVEL_STYLES[index] || BUFFER_LEVEL_STYLES[BUFFER_LEVEL_STYLES.length - 1]
                    dataSource.entities.add({
                        name: 'shape-display',
                        customData: { shapeId: shape.id, drawType: shape.drawType, level: index + 1 },
applications/drone-command/src/views/areaManage/sceneConfig/FormDiaLog.vue
@@ -162,6 +162,7 @@
import { buildEllipsePositions } from '@/utils/cesium/shapeTools'
import { saveOperationLog } from '@ztzf/apis'
import { useRoute } from 'vue-router'
import { AREA_TYPE_STYLE_MAP, BUFFER_LEVEL_STYLES, DEFAULT_AREA_STYLE } from '@ztzf/constants'
const initForm = () => ({
    sceneName: '', // 场景名称
@@ -188,20 +189,6 @@
const route = useRoute()
let viewer
let areaDisplaySource
const areaTypeStyleMap = {
    '1': {
        fill: Cesium.Color.fromBytes(25, 178, 230, 128),
        outline: Cesium.Color.fromBytes(0, 251, 255, 255),
    },
    '2': {
        fill: Cesium.Color.fromBytes(255, 235, 59, 128),
        outline: Cesium.Color.fromBytes(255, 235, 59, 255),
    },
    '3': {
        fill: Cesium.Color.fromBytes(247, 20, 20, 128),
        outline: Cesium.Color.fromBytes(255, 0, 0, 255),
    },
}
const rules = {
    sceneName: fieldRules(true, 50),
@@ -298,10 +285,7 @@
}
function getAreaTypeStyle(areaType) {
    return areaTypeStyleMap?.[String(areaType)] || {
        fill: Cesium.Color.fromBytes(45, 140, 240, 99),
        outline: Cesium.Color.fromBytes(45, 140, 240, 255),
    }
    return AREA_TYPE_STYLE_MAP?.[String(areaType)] || DEFAULT_AREA_STYLE
}
function parseGeomJson(geomJson) {
@@ -365,22 +349,8 @@
                const radii = shape.meta.bufferRadii
                    .map(radius => Number(radius))
                    .filter(radius => Number.isFinite(radius) && radius > 0)
                const styles = [
                    {
                        fill: Cesium.Color.fromBytes(247, 20, 20, 128),
                        outline: Cesium.Color.fromBytes(255, 0, 0, 255),
                    },
                    {
                        fill: Cesium.Color.fromBytes(255, 235, 59, 128),
                        outline: Cesium.Color.fromBytes(255, 235, 59, 255),
                    },
                    {
                        fill: Cesium.Color.fromBytes(25, 178, 230, 128),
                        outline: Cesium.Color.fromBytes(0, 251, 255, 255),
                    },
                ]
                radii.forEach((radius, index) => {
                    const style = styles[index] || styles[styles.length - 1]
                    const style = BUFFER_LEVEL_STYLES[index] || BUFFER_LEVEL_STYLES[BUFFER_LEVEL_STYLES.length - 1]
                    dataSource.entities.add({
                        name: 'scene-area-display',
                        customData: { drawType: shape.drawType, level: index + 1 },
packages/constants/areaStyles.js
New file
@@ -0,0 +1,36 @@
import * as Cesium from 'cesium'
export const AREA_TYPE_STYLE_MAP = {
    '1': {
        fill: Cesium.Color.fromBytes(25, 178, 230, 128),
        outline: Cesium.Color.fromBytes(0, 251, 255, 255),
    },
    '2': {
        fill: Cesium.Color.fromBytes(255, 235, 59, 128),
        outline: Cesium.Color.fromBytes(255, 235, 59, 255),
    },
    '3': {
        fill: Cesium.Color.fromBytes(247, 20, 20, 128),
        outline: Cesium.Color.fromBytes(255, 0, 0, 255),
    },
}
export const DEFAULT_AREA_STYLE = {
    fill: Cesium.Color.fromBytes(45, 140, 240, 99),
    outline: Cesium.Color.fromBytes(45, 140, 240, 255),
}
export const BUFFER_LEVEL_STYLES = [
    {
        fill: Cesium.Color.fromBytes(247, 20, 20, 128),
        outline: Cesium.Color.fromBytes(255, 0, 0, 255),
    },
    {
        fill: Cesium.Color.fromBytes(255, 235, 59, 128),
        outline: Cesium.Color.fromBytes(255, 235, 59, 255),
    },
    {
        fill: Cesium.Color.fromBytes(25, 178, 230, 128),
        outline: Cesium.Color.fromBytes(0, 251, 255, 255),
    },
]
packages/constants/index.js
@@ -6,3 +6,4 @@
export * from './publicEnums';
export * from './workEnums';
export * from './fwDevice';
export * from './areaStyles';