feat:数据驾驶舱地图渲染及区域划分、场景配置部分逻辑公用
4 files modified
1 files added
| | |
| | | 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' |
| | |
| | | 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 = [] |
| | |
| | | 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() |
| | |
| | | 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 |
| | |
| | | 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([]) |
| | | } |
| | |
| | | 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' |
| | |
| | | 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 |
| | |
| | | } |
| | | |
| | | 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 () { |
| | |
| | | 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 }, |
| | |
| | | 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: '', // 场景名称 |
| | |
| | | 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), |
| | |
| | | } |
| | | |
| | | 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) { |
| | |
| | | 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 }, |
| New file |
| | |
| | | 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), |
| | | }, |
| | | ] |
| | |
| | | export * from './publicEnums'; |
| | | export * from './workEnums'; |
| | | export * from './fwDevice'; |
| | | export * from './areaStyles'; |