From 6e0afaa5762765fad3e47b52f05df5553818b5ea Mon Sep 17 00:00:00 2001
From: chenyao <1219716595@qq.com>
Date: Wed, 02 Apr 2025 18:11:18 +0800
Subject: [PATCH] Merge branch 'master' of http://139.196.74.78:10010/r/drone/command-center-dashboard
---
src/views/Home/useUavHome/useUavHome.js | 283 ++++++++++++++++++++++++++++++++++++++++++++++----------
1 files changed, 230 insertions(+), 53 deletions(-)
diff --git a/src/views/Home/useUavHome/useUavHome.js b/src/views/Home/useUavHome/useUavHome.js
index 4e08252..655b589 100644
--- a/src/views/Home/useUavHome/useUavHome.js
+++ b/src/views/Home/useUavHome/useUavHome.js
@@ -1,61 +1,173 @@
import * as Cesium from 'cesium';
-import data2 from '@/assets/images/home/homeRight/data2.png';
-import data1 from '@/assets/images/home/homeRight/data1.png';
-import jiangxishi from '@/assets/geojson/jiangxishi.json';
-import jiangxi from '@/assets/geojson/jiangxi.json';
-import zg from '@/assets/geojson/zg.json';
+import aggregationImg from '@/assets/images/home/useUavHome/aggregation.png';
+import uavImg from '@/assets/images/home/useUavHome/uavImg.png';
import MapPopUpBox from '@/views/Home/useUavHome/MapPopUpBox.vue';
import { render } from 'vue';
+import { useStore } from 'vuex';
+import { getCenterPoint } from '@/utils/cesium/mapUtil';
+import cesiumOperation from '@/utils/cesium-tsa';
+import { HeadingPitchRange } from 'cesium';
+import { getDeviceRegion, getDeviceRegionCount } from '@/api/home/aggregation';
+
/**
* 机巢聚合功能
*/
export const useUavHome = () => {
- const scalingJudgment = [
- { name: '县', value: [0, 48651], gJson: null },
- { name: '市', value: [48651, 314863], gJson: jiangxishi },
- { name: '省', value: [314863, 1169651], gJson: jiangxi },
- { name: '国', value: [1169651, 37962800], gJson: zg },
+ const { flyTo } = cesiumOperation();
+
+ let scalingJudgment = [
+ { name: '县', splashedList: [], gJson: null, show: false,outline:{}, value: [0, 48651], height: 31753 },
+ { name: '市', splashedList: [], gJson: null, show: false,outline:{}, value: [48651, 314863], height: 257731 },
+ { name: '省', splashedList: [], gJson: null, show: false,outline:{}, value: [314863, 3796280000], height: 1987280 },
];
let viewer = null;
let active = null;
let handler = null;
let positionC3 = null;
+ let currentEntity = null;
const listenerHeight = () => {
determineScaling();
viewer.camera.moveEnd.addEventListener(determineScaling);
};
// 确定缩放比例
- const determineScaling = () => {
- if(!viewer) return
+ const determineScaling = index => {
+ console.log('确定缩放比例');
+ if (!viewer) return;
let height = viewer.camera.positionCartographic.height;
// 根据高度展示对应的 gJson
- for (let item of scalingJudgment) {
+ for (let [index, item] of scalingJudgment.entries()) {
+ if (!item.show) return;
if (height > item.value[0] && height <= item.value[1]) {
- if (active !== item.name) {
- removeEntities();
- removeLabel();
- active = item.name;
- item.gJson ? aggregation(item) : splashed();
- }
+ if (active === item.name) return;
+ active = item.name;
+ removeEntities();
+ removeLabel();
+ item.gJson ? aggregation(item) : splashed(item)
+ renderOutline(item)
break;
}
}
};
+ function convertToHierarchy(code) {
+ const codeStr = code.toString();
+ const provinceCode = codeStr.slice(0, 2) + '0000';
+ const cityCode = codeStr.slice(0, 4) + '00';
+ if (codeStr.slice(2, 4) === '00' && codeStr.slice(4, 6) === '00') {
+ return [provinceCode];
+ } else if (codeStr.slice(4, 6) === '00') {
+ return [provinceCode, cityCode];
+ }
+ return [provinceCode, cityCode, code];
+ }
+
+ const store = useStore();
+ const selectedAreaCode = computed(() => store.state.user.selectedAreaCode);
+
+ function getDeviceCount(areaCode) {
+ return getDeviceRegionCount({areaCode}).then(res => {
+ return res?.data?.data || [];
+ });
+ }
+
+ function getDeviceList(areaCode) {
+ return getDeviceRegion({areaCode}).then(res => {
+ return res?.data?.data || [];
+ });
+ }
+ const findFun = (featItem, numItem) => Number(featItem.region_code.slice(0, 6)) === numItem.properties.adcode;
+ const { VITE_APP_BASE } = import.meta.env;
+ const defaultDir = `${VITE_APP_BASE}public/geoJson/100000/`;
+
+ const getFiler = async (url) => {
+ const gJson = await import(/* @vite-ignore */ url);
+ return JSON.parse(JSON.stringify(gJson));
+ }
+ const getOutLine = async (jsonPathPre,hierarchy) => {
+ const parentGJson = await getFiler(`${defaultDir}${jsonPathPre}/index.json`)
+ let features = parentGJson.features.find(
+ item => item.properties.adcode === Number(hierarchy[hierarchy.length - 1])
+ );
+ return { type: "FeatureCollection", features: [features] }
+ }
+
+ const injectData = (gJson,dataList) => {
+ return {
+ ...gJson,
+ features: gJson.features.map(item => ({ ...item, data: dataList.find(item1 => findFun(item1, item)) })),
+ }
+ }
+
+
+
+ watch(
+ selectedAreaCode,
+ async (newValue, oldValue) => {
+ if (newValue) {
+ const list = await getDeviceCount(newValue);
+ const splashedList = await getDeviceList(newValue);
+ console.log(list);
+ console.log(splashedList);
+ const hierarchy = convertToHierarchy(newValue.slice(0, 6));
+ const jsonPath = hierarchy.join('/');
+ const jsonPathPre = hierarchy.slice(0, hierarchy.length - 1).join('/');
+ scalingJudgment = scalingJudgment.map(item => ({ ...item, show: true }));
+ scalingJudgment[0].gJson = null;
+ scalingJudgment[0].splashedList = splashedList;
+ active = null
+ // 省
+ if (hierarchy.length === 1) {
+ const gJson1 = await getFiler(`${defaultDir}${jsonPath}/indexDistrict.json`)
+ const gJson2 = await getFiler(`${defaultDir}${jsonPath}/index.json`)
+ scalingJudgment[1].gJson = {
+ ...gJson1,
+ features: gJson1.features.map(item => ({
+ ...item,
+ data: list.flatMap(item => item.childrens || []).find(item1 => findFun(item1, item)),
+ })),
+ };
+ scalingJudgment[2].gJson = injectData(gJson2,list);
+ const { lng, lat } = getCenterPoint(gJson2.features.map(item => item.properties.center));
+ flyTo({ longitude: lng, latitude: lat }, 0, scalingJudgment[2].height);
+ }
+ // 市
+ if (hierarchy.length === 2) {
+ scalingJudgment[2].gJson = null;
+ scalingJudgment[2].show = false;
+ const gJson1 = await getFiler(`${defaultDir}${jsonPath}/index.json`)
+ scalingJudgment[1].gJson = injectData(gJson1,list);
+ const center = getCenterPoint(gJson1.features.map(item => item.properties.center));
+ flyTo({ longitude: center.lng, latitude: center.lat }, 0, scalingJudgment[1].height);
+ }
+ // 区县
+ if (hierarchy.length === 3) {
+ scalingJudgment[1].gJson = null;
+ scalingJudgment[1].show = false;
+ scalingJudgment[2].gJson = null;
+ scalingJudgment[2].show = false;
+ const outlineGJson = await getOutLine(jsonPathPre,hierarchy)
+ const center = outlineGJson.features[0].properties.center;
+ flyTo({ longitude: center[0], latitude: center[1] }, 0, scalingJudgment[0].height);
+ }
+ // 轮廓
+ const outlineGJson = await getOutLine(jsonPathPre,hierarchy)
+ scalingJudgment.forEach(item => item.show &&(item.outline = outlineGJson))
+ }
+ },
+ { immediate: true, deep: true }
+ );
+
//散点机巢
- function splashed() {
- for (let i = 0; i < 50; i++) {
+ function splashed(row) {
+ row.splashedList.forEach(item => {
viewer.entities.add({
- position: Cesium.Cartesian3.fromDegrees(
- 115.89 + Math.random() * 0.2,
- 28.68 + Math.random() * 0.2
- ),
+ position: Cesium.Cartesian3.fromDegrees(item.longitude, item.latitude),
label: {
// 随机整数
- text: Math.floor(Math.random() * 100) + '号机巢',
- font: '14pt monospace',
+ text: item.nickname,
+ font: '12pt Source Han Sans CN',
fillColor: Cesium.Color.WHITE,
outlineColor: Cesium.Color.BLACK,
outlineWidth: 2,
@@ -64,51 +176,95 @@
pixelOffset: new Cesium.Cartesian2(0, -9),
},
billboard: {
- image: new Cesium.ConstantProperty(data1),
+ image: new Cesium.ConstantProperty(uavImg),
width: 24,
height: 24,
},
+ properties: {
+ customData: {
+ data: item,
+ },
+ },
});
- }
+ });
}
+ // 渲染轮廓
+ const renderOutline = (item) => {
+ item.outline && Cesium.GeoJsonDataSource.load(item.outline).then(dataSource => {
+ viewer.dataSources.add(dataSource);
+ const entities = dataSource.entities.values;
+ entities.forEach(entity => {
+ // 隐藏多边形填充
+ entity.polygon.material = Cesium.Color.TRANSPARENT;
+ entity.polygon.outline = false; // 关闭原生轮廓
+ // 创建独立折线作为轮廓
+ const positions = entity.polygon.hierarchy.getValue().positions;
+ viewer.entities.add({
+ polyline: {
+ positions: positions,
+ width: 5, // 直接设置宽度
+ material: new Cesium.PolylineGlowMaterialProperty({
+ glowPower: 0.5,
+ color: Cesium.Color.AQUA
+ }),
+ clampToGround: true // 贴地显示
+ }
+ });
+ });
+ });
+ };
+
// 聚合机巢
- const aggregation = item => {
+ const aggregation = (item, flyTo) => {
+ if (!item.gJson) return;
const featuresList = item.gJson.features.map(item => ({
name: item.properties.name,
position: item.properties.center,
+ data: item.data,
+ id: item.region_code,
}));
// 遍历特征并添加实体
featuresList.forEach(feature => {
if (!feature.position) return;
const position = Cesium.Cartesian3.fromDegrees(feature.position[0], feature.position[1]);
viewer.entities.add({
- id: feature.id,
position: position,
label: {
- // 随机整数
- text: feature.name + Math.floor(Math.random() * 100),
- font: '14pt monospace',
+ text: feature.name,
+ font: '14pt Source Han Sans CN',
fillColor: Cesium.Color.WHITE,
outlineColor: Cesium.Color.BLACK,
outlineWidth: 2,
style: Cesium.LabelStyle.FILL_AND_OUTLINE,
verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
pixelOffset: new Cesium.Cartesian2(0, -9),
+ }
+ });
+ viewer.entities.add({
+ id: feature.id,
+ position: position,
+ label: {
+ text: feature.data.total_device_count,
+ font: '12pt Source Han Sans CN',
+ fillColor: Cesium.Color.BLACK,
+ style: Cesium.LabelStyle.FILL_AND_OUTLINE,
+ eyeOffset: new Cesium.Cartesian3(0, 0, -10), // 让label "浮" 在广告牌前面
},
billboard: {
- image: new Cesium.ConstantProperty(data2),
- width: 24,
- height: 24,
+ image: new Cesium.ConstantProperty(aggregationImg),
+ width: 35,
+ height: 35,
},
properties: {
id: feature.id,
customData: {
- name: feature.name,
+ data: feature.data,
},
},
});
});
+
// 加载新的 GeoJSON 数据
Cesium.GeoJsonDataSource.load(item.gJson).then(dataSource => {
viewer.dataSources.add(dataSource);
@@ -120,14 +276,23 @@
Cesium.Color.YELLOW.withAlpha(0) // 透明填充
);
entity.polygon.outline = new Cesium.ConstantProperty(true); // 显示边框
- entity.polygon.outlineColor = new Cesium.ConstantProperty(Cesium.Color.YELLOW); // 黑色边框
+ entity.polygon.outlineColor = new Cesium.ConstantProperty(Cesium.Color.AQUAMARINE );
});
+ flyTo &&
+ viewer.flyTo(dataSource, {
+ offset: new Cesium.HeadingPitchRange(
+ 0, // heading: 0 (朝向不变)
+ Cesium.Math.toRadians(-90), // pitch: -90° (垂直向下)
+ 0 // range: 0 (默认距离)
+ ),
+ duration: 0.5,
+ });
});
};
// 获取弹框box
- const getLabelDom = () => {
- const vNode = h(MapPopUpBox, { data: '参数', removeLabel });
+ const getLabelDom = data => {
+ const vNode = h(MapPopUpBox, { data, removeLabel });
const tooltipContainer = document.createElement('div');
tooltipContainer.id = 'mapPopUpBox';
tooltipContainer.style.position = 'absolute';
@@ -139,10 +304,10 @@
};
// 弹框位置刷新
- const labelBox = () => {
+ const labelBoxRender = () => {
let dom = document.querySelector('#mapPopUpBox');
if (!dom) {
- dom = getLabelDom();
+ dom = getLabelDom(currentEntity.properties.customData._value.data);
}
const screenPosition = viewer.scene.cartesianToCanvasCoordinates(positionC3);
if (screenPosition) {
@@ -153,14 +318,28 @@
};
// 左键单机事件
- const singleMachineEvent = click => {
+ const singleMachineEvent = async click => {
const pickedObject = viewer.scene.pick(click.position);
if (Cesium.defined(pickedObject) && pickedObject.id) {
const entity = pickedObject.id;
+ currentEntity = entity;
positionC3 = entity?.position?._value;
if (!positionC3) return;
- viewer.scene.postRender.removeEventListener(labelBox);
- viewer.scene.postRender.addEventListener(labelBox);
+ removeLabel();
+ const customData = entity.properties.customData._value.data
+ console.log(customData);
+ if (customData.device_sn){
+ store.commit('setSingleUavHome', { id: '123' });
+ return
+ }
+ viewer.scene.postRender.addEventListener(labelBoxRender);
+ }
+ };
+
+ const removeDom = () => {
+ const dom = document.querySelector('#mapPopUpBox');
+ if (dom && dom.parentNode) {
+ dom.parentNode.removeChild(dom);
}
};
@@ -171,11 +350,8 @@
};
// 移除弹框标签
const removeLabel = () => {
- viewer.scene.postRender.removeEventListener(labelBox);
- const dom = document.querySelector('#mapPopUpBox');
- if (dom && dom.parentNode) {
- dom.parentNode.removeChild(dom);
- }
+ viewer.scene.postRender.removeEventListener(labelBoxRender);
+ removeDom();
};
// 移除所有监听事件,变量置空
@@ -186,9 +362,10 @@
handler?.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK);
handler?.destroy();
viewer = null;
- active = null
+ active = null;
handler = null;
positionC3 = null;
+ currentEntity = null;
};
const init = () => {
viewer = window.$viewer;
@@ -205,5 +382,5 @@
// });
// });
- return { init,removeAll };
+ return { init, removeAll };
};
--
Gitblit v1.9.3