Files
td_official/src/views/projectLarge/ProjectScreen/components/newmap.vue
2025-09-12 20:28:12 +08:00

346 lines
10 KiB
Vue

<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, getModelList } from '@/api/projectScreen/index.ts'
import videoDialog from "./video.vue"
import { getToken } from '@/utils/auth';
import axios from 'axios';
import md5 from 'js-md5';
const defaultExpandedKeys = [1, 2, 3] //默认展开第一级节点
const defaultCheckedKeys = ref([]) //默认选中节点
const data = ref([]);
const deviceId = ref('');
const videoDialogRef = ref(null);
const token = getToken();
let ws = new ReconnectingWebSocket(import.meta.env.VITE_APP_BASE_WS_API + '?Authorization=' + token + '&clientid=' + import.meta.env.VITE_APP_CLIENT_ID + '&projectId=' + '1897160897167638529');
// 连接ws
const connectWs = () => {
ws.onopen = (e) => {
// let message ={
// projectId:'1897160897167638529',
// }
// 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();
window.ModelList = new Map();
let list = ref([]);
// 模型list
let modelList = ref([]);
// 漫游实例
let roamingController = null;
// 获取模型列表
async function getModelListData() {
let res = await axios.post(import.meta.env.VITE_APP_BASE_EARTH_API + '/yjearth4.0/api/v1/user/sign-in',
{ "username": "admin", "password": "3598f66fbc93c0d5abd2dabab9de74cc" }
)
console.log('res', res.data);
if (res.data.code == 0) {
let toekn = res.data.data.token;
console.log('toekn', toekn);
let res1 = await axios({
url: import.meta.env.VITE_APP_BASE_EARTH_API + '/yjearth4.0/api/v1/source/list',
method: 'post',
data: {
data: { "page": 1, "page_size": 10 },
},
headers: {
'token': toekn
}
})
if (res1.data.code == 0) {
modelList.value = res1.data.data.list;
}
}
}
// 获取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);
}
}
// 初始化地球
async function initEarth() {
let earth = new YJ.YJEarth("earth");
window.Earth1 = earth;
// 加载底图
// earth.viewer.terrainProvider = Cesium.createWorldTerrain();
// Earth1.viewer
addArcgisLayer(Earth1.viewer, 'img_w')
// 添加倾斜数据
// 获取中心点
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;
}
async function loadTiltData(item) {
let tileset = new YJ.Obj.Tileset(window.Earth1, { id: item.source_id });
ModelList.set(item.source_id, tileset);
await tileset.on();
tileset.flyTo();
}
// 获取ArcGIS服务的URL
function getArcGisUrlByType(type) {
switch (type) {
//影像
case "img_w":
return "https://webst01.is.autonavi.com/appmaptile?style=6&x={x}&y={y}&z={z}";
//电子
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.UrlTemplateImageryProvider({
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(async () => {
// 连接ws
connectWs();
// 获取选中节点
getCheckedNode();
// 获取GPS数据
getGpsData();
await getModelListData();
await YJ.on({
username: 'admin',
password: md5('admin_admin123'),
host: 'http://192.168.110.2:8895/'
}).then((res) => {
initEarth();
modelList.value.forEach(item => {
loadTiltData(item)
})
});
});
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>