Files
td_official/src/views/projectLarge/ProjectScreen/components/newmap.vue
2025-09-10 10:03:35 +08:00

311 lines
9.5 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<script setup>
import { onMounted, ref, onUnmounted,defineProps} from 'vue';
import CesiumImageLabelEntity from '../js/CesiumImageLabelEntity.js';
import CesiumFlyToRoamingController from '../js/CesiumFlyToRoamingController.js';
import { setSelect, getSelectList, getGps } from '@/api/projectScreen/index.ts'
import videoDialog from "./video.vue"
import { getToken } from '@/utils/auth';
const defaultExpandedKeys = [1, 2, 3] //默认展开第一级节点
const defaultCheckedKeys = ref([]) //默认选中节点
const data = ref([]);
const deviceId = ref('');
const videoDialogRef = ref(null);
let token = 'Bearer '+ getToken()
let ws = new ReconnectingWebSocket( import.meta.env.VITE_APP_BASE_WS_API + '?Authorization='+token+'&clientid='+import.meta.env.VITE_APP_CLIENT_ID);
// 连接ws
const connectWs = () => {
ws.onopen = (e) => {
console.log('this.gateWay', e);
// ws.send(JSON.stringify(message));
ws.onmessage = (e) => {
console.log('ws', e);
};
};
}
const props = defineProps({
isHide:{
type:Boolean,
default:true,
}
})
console.log('props', props);
const defaultProps = {
children: 'children',
label: 'label',
}
let entityManager = null;
window.deviceMap = new Map();
let list = ref([]);
// 漫游实例
let roamingController = null;
// 获取GPS数据
function getGpsData() {
getGps('1897160897167638529').then(res => {
console.log('res', res);
if (res.code === 200) {
data.value = res.data;
if (res.data.length > 0) {
res.data.forEach(element => {
list.value = [...list.value, ...element.children]
});
}
}
})
}
// 设置选中节点
function setCheckedNode(idList) {
let obj = {
projectId: '1897160897167638529',
idList
}
setSelect(obj).then(res => {
console.log('res', res);
})
}
// 获取选中节点
function getCheckedNode() {
getSelectList({
projectId: '1897160897167638529'
}).then(res => {
if (res.code == 200) {
defaultCheckedKeys.value = res.data || []
}
})
}
// 渲染无人机、摄像头、定位设备
function renderDevice(item) {
const imageEntity = new CesiumImageLabelEntity(Earth1.viewer, {
id: item.id,
position: {
lng: Number(item.lng),
lat: Number(item.lat),
height: 0
},
imageWidth: 64,
imageHeight: 64,
name: item.label || item.id,
imageUrl: `/image/${item.type}.png`,
onClick: (entity)=>{
entityClickHandler(entity,item);
}
});
window.deviceMap.set(item.id, imageEntity);
}
// 实体的点击事件
function entityClickHandler(entity,item) {
console.log('entity', entity,item);
if (item.type == 'camera') {
deviceId.value = 'AE9470016';
videoDialogRef.value.show();
videoDialogRef.value.videoPlay(deviceId.value);
}
}
// 初始化地球
function initEarth() {
YJ.on({
ws: true,
host: '', //资源所在服务器地址
username: '', //用户名 可以不登录(不填写用户名),不登录时无法加载服务端的数据
password: '', //密码 生成方式md5(用户名_密码)
}).then((res) => {
let earth = new YJ.YJEarth("earth");
window.Earth1 = earth;
// 加载底图
// earth.viewer.terrainProvider = Cesium.createWorldTerrain();
// Earth1.viewer
addArcgisLayer(Earth1.viewer, 'img_w')
// 添加倾斜数据
// loadTiltData(Earth1.viewer)
// 获取中心点
YJ.Global.CesiumContainer(window.Earth1, {
compass: false,//罗盘
legend: false, //图例
});
// 创建实体管理器实例
list.value.forEach(item => {
if (defaultCheckedKeys.value.includes(item.id)) {
console.log("defaultCheckedKeys", item.id);
renderDevice(item)
}
});
roamingController = new CesiumFlyToRoamingController(window.Earth1.viewer, {
duration: 5, // 每个点之间飞行5秒
pitch: -89 // 20度俯角
});
window.roamingController = roamingController;
})
}
// 加载倾斜数据
function loadTiltData(viewer) {
viewer.terrainProvider = new Cesium.CesiumTerrainProvider({
// url: 'http://192.168.110.2:8895/yjearth4.0/data/pak/e904acb32aaa8b872c64866ebaaaf5e2',
// url:"http://58.17.134.85:7363/yjearth4.0/data/pak/e904acb32aaa8b872c64866ebaaaf5e2"
url: import.meta.env.VITE_EARTH_URL + "/yjearth4.0/data/pak/4eb21d3fc02873092e75640e261544b3"
});
}
// 获取ArcGIS服务的URL
function getArcGisUrlByType(type) {
switch (type) {
//影像
case "img_w":
return "https://services.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer";
//电子
case "vec_w":
return "https://services.arcgisonline.com/ArcGIS/rest/services/World_Street_Map/MapServer";
//蓝色底图
case "vec_blue":
return "http://map.geoq.cn/arcgis/rest/services/ChinaOnlineStreetPurplishBlue/MapServer";
//灰色底图
case "vec_gray":
return "http://map.geoq.cn/arcgis/rest/services/ChinaOnlineStreetGray/MapServer";
//暖色底图
case "vec_warm":
return "http://map.geoq.cn/arcgis/rest/services/ChinaOnlineStreetWarm/MapServer";
}
}
// 添加ArcGIS图层
function addArcgisLayer(viewer, type) {
let url = getArcGisUrlByType(type)
const layerProvider = new Cesium.ArcGisMapServerImageryProvider({
url: url
});
viewer.imageryLayers.addImageryProvider(layerProvider);
}
// 节点单击事件
function handleNodeClick(data) {
console.log('data', data);
let entity = window.deviceMap.get(data.id);
if (entity) {
entity.flyTo();
}
}
// 复选框选中事件
function handleCheck(checkedNodes, nodes) {
console.log('check', checkedNodes, nodes);
// 处理单个节点的通用函数
const handleNode = (node) => {
if (!window.deviceMap.has(node.id)) {
console.log("defaultCheckedKeys", node.id);
renderDevice(node);
} else {
const device = window.deviceMap.get(node.id);
// 根据当前显示状态切换显示/隐藏
device[device.entity.show ? 'hide' : 'show']();
}
};
// 处理选中的节点(可能是单个节点或包含子节点的集合)
if (checkedNodes?.children?.length) {
console.log('children', checkedNodes.children);
checkedNodes.children.forEach(handleNode);
} else {
handleNode(checkedNodes);
}
setCheckedNode(nodes.checkedKeys);
}
// 开始漫游
function startRoaming() {
if (roamingController) {
roamingController.startPathRoaming([
Cesium.Cartesian3.fromDegrees(106.49556855602525, 29.534393226355515, 200),
Cesium.Cartesian3.fromDegrees(106.49142431645038, 29.534472802500083, 200),
Cesium.Cartesian3.fromDegrees(106.49142125177437, 29.541881138875755, 200)
], 3, false);
} else {
console.log('请先初始化地球');
}
}
// 停止漫游
function stopRoaming() {
if (roamingController) {
roamingController.stopRoaming();
} else {
console.log('请先初始化地球');
}
}
onMounted(() => {
// 连接ws
connectWs();
// 获取选中节点
getCheckedNode();
// 获取GPS数据
getGpsData();
// 初始化地球
initEarth();
});
onUnmounted(() => {
window.deviceMap.forEach((item) => {
item.destroy();
})
window.deviceMap.clear();
window.roamingController.destroy();
window.Earth1.destroy();
})
</script>
<template>
<div class="earth-container-big">
<div class="earth" id="earth"></div>
<div v-show="isHide" class="left">
<div style="width: 100%;height: 100%;">
<el-button type="primary" @click="startRoaming">开始漫游</el-button>
<el-button type="primary" @click="stopRoaming">停止漫游</el-button>
</div>
</div>
<div v-show="isHide" class="right">
<el-tree show-checkbox :data="data" :props="defaultProps" node-key="id" :expand-on-click-node="false"
:check-on-click-node="false" :check-on-click-leaf="false" :default-expanded-keys="defaultExpandedKeys"
:default-checked-keys="defaultCheckedKeys" @check="handleCheck" @node-click="handleNodeClick" />
</div>
<videoDialog :data="deviceId" ref="videoDialogRef"></videoDialog>
</div>
</template>
<style lang="scss">
.earth-container-big {
position: relative;
width: 100%;
height: 100%;
.earth {
width: 100%;
height: 100%;
}
.right {
top: 50%;
right: 0;
}
.left {
top: 50%;
left: 0;
}
.right,
.left {
position: absolute;
width: 400px;
height: 100%;
transform: translateY(-50%);
background-color: #00000052;
padding: 20px;
box-sizing: border-box;
z-index: 10;
.el-tree {
background-color: transparent;
--el-tree-node-hover-bg-color: transparent;
--el-tree-text-color: #fff;
.el-text {
color: azure;
}
.el-tree-node__content:hover {
background-color: transparent;
}
}
}
}
</style>