This commit is contained in:
Teo
2025-09-12 20:37:59 +08:00
8 changed files with 305 additions and 267 deletions

View File

@ -13,6 +13,8 @@ VITE_APP_BASE_API_GO = 'http://xny.yj-3d.com:7464'
# ws # ws
VITE_APP_BASE_WS_API = 'ws://192.168.110.149:8899/resource/websocket' VITE_APP_BASE_WS_API = 'ws://192.168.110.149:8899/resource/websocket'
# EARTH
VITE_APP_BASE_EARTH_API="http://192.168.110.2:8895"
# 无人机接口地址 # 无人机接口地址
VITE_APP_BASE_DRONE_API = 'http://58.17.134.85:9512' VITE_APP_BASE_DRONE_API = 'http://58.17.134.85:9512'

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

View File

@ -87,4 +87,13 @@ export const setSelect = (data) => {
method: 'post', method: 'post',
data data
}); });
};
// 获取模型列表
export const getModelList = (params) => {
return request({
url: '/yjearth4.0/api/v1/source/list',
method: 'get',
params
});
}; };

View File

@ -1,224 +1,218 @@
<template> <template>
<div class="cardItem"> <div class="cardItem">
<el-card> <el-card>
<div class="tianqi" <div
style="display: flex;flex-direction: column;align-items: center;background-color: #FAFAFA;border-radius: 10px;padding-bottom: 40px;"> class="tianqi"
<div> style="display: flex; flex-direction: column; align-items: center; background-color: #fafafa; border-radius: 10px; padding-bottom: 40px"
<img src="/assets/demo/Sunny.png" style="display: block; width: 100px;height: 100px;" alt=""> >
</div> <div>
<div style="font-family: 'Alibaba-PuHuiTi-Bold';font-size: 24px;"> <img src="/assets/demo/sunnyBig.png" style="display: block; width: 100px; height: 100px" alt="" />
31 </div>
</div> <div style="font-family: 'Alibaba-PuHuiTi-Bold'; font-size: 24px">31</div>
<div>晴朗</div> <div>晴朗</div>
<div style="color: rgba(154, 154, 154, 1);font-size: 14px;"> <div style="color: rgba(154, 154, 154, 1); font-size: 14px">紫外线强度<span></span></div>
紫外线强度<span></span> <div class="tianqi2">
</div> <div class="item">
<div class="tianqi2"> <div>
<div class="item"> <img src="/assets/demo/shidu.png" alt="" />
<div>
<img src="/assets/demo/shidu.png" alt="">
</div>
<div class="text">相对湿度 <span>45%</span></div>
</div>
<div class="item">
<div>
<img src="/assets/demo/qiangdu.png" alt="">
</div>
<div class="text">光照强度 <span>45%</span></div>
</div>
<div class="item">
<div>
<img src="/assets/demo/fengshu.png" alt="">
</div>
<div class="text">风速 <span>2.3m/s</span></div>
</div>
<div class="item">
<div>
<img src="/assets/demo/riluo.png" alt="">
</div>
<div class="text">日落时间 <span>19.45</span></div>
</div>
</div>
</div> </div>
<div class="weather-timeline"> <div class="text">相对湿度 <span>45%</span></div>
<div class="time-box"> </div>
<div class="time-item"> <div class="item">
<div class="time">16:00</div> <div>
<div class="temp">30°C</div> <img src="/assets/demo/qiangdu.png" alt="" />
<div class="img-box">
<img src="/assets/demo/sunny_s.png" alt="">
</div>
</div>
<div class="time-item">
<div class="time">17:00</div>
<div class="temp">29°C</div>
<div class="img-box">
<img src="/assets/demo/sunny_s.png" alt="">
</div>
</div>
<div class="time-item">
<div class="child">
<div class="time">18:00</div>
<div class="temp">25°C</div>
<div class="img-box">
<img src="/assets/demo/rain.png" alt="">
</div>
</div>
</div>
<div class="time-item show">
<div class="time">现在</div>
<div class="temp">25°C</div>
<div class="img-box">
<img src="/assets/demo/rain_show.png" alt="">
</div>
</div>
<div class="time-item">
<div class="time">20:00</div>
<div class="temp">25°C</div>
<div class="img-box">
<img src="/assets/demo/yin.png" alt="">
</div>
</div>
<div class="time-item">
<div class="time">21:00</div>
<div class="temp">20°C</div>
<div class="img-box">
<img src="/assets/demo/yin.png" alt="">
</div>
</div>
</div>
</div> </div>
</el-card> <div class="text">光照强度 <span>45%</span></div>
</div> </div>
<div class="item">
<div>
<img src="/assets/demo/fengshu.png" alt="" />
</div>
<div class="text">风速 <span>2.3m/s</span></div>
</div>
<div class="item">
<div>
<img src="/assets/demo/riluo.png" alt="" />
</div>
<div class="text">日落时间 <span>19.45</span></div>
</div>
</div>
</div>
<div class="weather-timeline">
<div class="time-box">
<div class="time-item">
<div class="time">16:00</div>
<div class="temp">30°C</div>
<div class="img-box">
<img src="/assets/demo/sunny_s.png" alt="" />
</div>
</div>
<div class="time-item">
<div class="time">17:00</div>
<div class="temp">29°C</div>
<div class="img-box">
<img src="/assets/demo/sunny_s.png" alt="" />
</div>
</div>
<div class="time-item">
<div class="child">
<div class="time">18:00</div>
<div class="temp">25°C</div>
<div class="img-box">
<img src="/assets/demo/rain.png" alt="" />
</div>
</div>
</div>
<div class="time-item show">
<div class="time">现在</div>
<div class="temp">25°C</div>
<div class="img-box">
<img src="/assets/demo/rain_show.png" alt="" />
</div>
</div>
<div class="time-item">
<div class="time">20:00</div>
<div class="temp">25°C</div>
<div class="img-box">
<img src="/assets/demo/yin.png" alt="" />
</div>
</div>
<div class="time-item">
<div class="time">21:00</div>
<div class="temp">20°C</div>
<div class="img-box">
<img src="/assets/demo/yin.png" alt="" />
</div>
</div>
</div>
</div>
</el-card>
</div>
</template> </template>
<style scoped lang="scss"> <style scoped lang="scss">
.cardItem { .cardItem {
padding: -20px !important; padding: -20px !important;
} }
.tianqi2 { .tianqi2 {
width: 100%; width: 100%;
display: flex;
justify-content: space-around;
margin-top: 50px;
img {
width: 40px;
height: 40x;
display: block;
}
.item {
display: flex; display: flex;
justify-content: space-around; flex-direction: column;
margin-top: 50px; align-items: center;
font-size: 14px;
img { .text {
width: 40px; margin-top: 10px;
height: 40x;
display: block;
} }
}
.item {
display: flex;
flex-direction: column;
align-items: center;
font-size: 14px;
.text {
margin-top: 10px;
}
}
} }
.weather-timeline { .weather-timeline {
text-align: center; text-align: center;
color: #fff; color: #fff;
font-size: 14px; font-size: 14px;
margin: 15px 0; margin: 15px 0;
.time { .time {
margin: 10px 0; margin: 10px 0;
} }
.img-box { .img-box {
width: 40px; width: 40px;
height: 40px; height: 40px;
margin: 10px 0; margin: 10px 0;
} }
img { img {
width: 100%; width: 100%;
height: 100%; height: 100%;
display: block; display: block;
} }
// img[src*='Sunny'] { // img[src*='Sunny'] {
// width: 50px; // width: 50px;
// height: 50px; // height: 50px;
// } // }
// img[src*='rain'] { // img[src*='rain'] {
// width: 60px; // width: 60px;
// height: 60px; // height: 60px;
// } // }
padding: 15px;
background: linear-gradient(to right, #d6e2ff, #deebff);
border-radius: 15px;
padding: 15px; .time-box {
background: linear-gradient(to right, #D6E2FF, #DEEBFF); background: linear-gradient(to right, #447bff, #67a3fd);
border-radius: 15px; display: flex;
justify-content: space-between;
border-radius: 10px;
padding: 10px 20px;
align-items: center;
}
.time-box { .time-item.show {
background: linear-gradient(to right, #447BFF, #67A3FD); color: rgba(24, 109, 245, 1);
display: flex; position: relative;
justify-content: space-between; // z-index: 888;
border-radius: 10px; background-color: #fff;
padding: 10px 20px; padding: 0 5px;
align-items: center; }
}
.time-item.show { .show::after {
color: rgba(24, 109, 245, 1); // color: rgba(24, 109, 245, 1);
position: relative; // position: relative;
// z-index: 888; // z-index: 888;
background-color: #fff; // background-color: #fff;
padding: 0 5px; content: '';
position: absolute;
width: 100%;
height: 25px;
// background-color: red;
background-color: #fff;
left: 0;
border-radius: 0 0 25px 25px;
}
} .show::before {
// color: rgba(24, 109, 245, 1);
// position: relative;
// z-index: 888;
// background-color: #fff;
content: '';
position: absolute;
width: 100%;
height: 25px;
// background-color: red;
background-color: #fff;
left: 0;
top: -25px;
border-radius: 25px 25px 0 0;
}
.show::after { // .show::after {
// color: rgba(24, 109, 245, 1); // content: '';
// position: relative; // position: absolute;
// z-index: 888; // height: 155px;
// background-color: #fff; // background-color: #fff;
content: ''; // z-index: 999;
position: absolute; // width: 100%;
width: 100%; // top: -25px;
height: 25px; // left: 0;
// background-color: red; // border-radius: 20px;
background-color: #fff; // }
left: 0;
border-radius: 0 0 25px 25px;
}
.show::before {
// color: rgba(24, 109, 245, 1);
// position: relative;
// z-index: 888;
// background-color: #fff;
content: '';
position: absolute;
width: 100%;
height: 25px;
// background-color: red;
background-color: #fff;
left: 0;
top: -25px;
border-radius: 25px 25px 0 0;
}
// .show::after {
// content: '';
// position: absolute;
// height: 155px;
// background-color: #fff;
// z-index: 999;
// width: 100%;
// top: -25px;
// left: 0;
// border-radius: 20px;
// }
} }
</style> </style>
<script setup> <script setup></script>
</script>

View File

@ -118,21 +118,21 @@ const indicators = ref([
name: '风电项目', name: '风电项目',
value: '288.88', value: '288.88',
unit: '个', unit: '个',
iconPath: '/src/assets/images/contract.png' iconPath: '/assets/demo/contract.png'
}, },
{ {
id: '3', id: '3',
name: '光伏系统总容量', name: '光伏系统总容量',
value: '158.88', value: '158.88',
unit: 'MW', unit: 'MW',
iconPath: '/src/assets/images/totalCapacity.png' iconPath: '/assets/demo/totalCapacity.png'
}, },
{ {
id: '4', id: '4',
name: '风电项目总容量', name: '风电项目总容量',
value: '18', value: '18',
unit: 'MW', unit: 'MW',
iconPath: '/src/assets/images/todayConstruction.png' iconPath: '/assets/demo/todayConstruction.png'
} }
]); ]);

View File

@ -1,33 +1,35 @@
<script setup> <script setup>
import { onMounted, ref, onUnmounted,defineProps} from 'vue'; import { onMounted, ref, onUnmounted, defineProps } from 'vue';
import CesiumImageLabelEntity from '../js/CesiumImageLabelEntity.js'; import CesiumImageLabelEntity from '../js/CesiumImageLabelEntity.js';
import CesiumFlyToRoamingController from '../js/CesiumFlyToRoamingController.js'; import CesiumFlyToRoamingController from '../js/CesiumFlyToRoamingController.js';
import { setSelect, getSelectList, getGps } from '@/api/projectScreen/index.ts' import { setSelect, getSelectList, getGps, getModelList } from '@/api/projectScreen/index.ts'
import videoDialog from "./video.vue" import videoDialog from "./video.vue"
import { getToken } from '@/utils/auth'; import { getToken } from '@/utils/auth';
import axios from 'axios';
import md5 from 'js-md5';
const defaultExpandedKeys = [1, 2, 3] //默认展开第一级节点 const defaultExpandedKeys = [1, 2, 3] //默认展开第一级节点
const defaultCheckedKeys = ref([]) //默认选中节点 const defaultCheckedKeys = ref([]) //默认选中节点
const data = ref([]); const data = ref([]);
const deviceId = ref(''); const deviceId = ref('');
const videoDialogRef = ref(null); const videoDialogRef = ref(null);
let token = 'Bearer '+ getToken() 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'); 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 // 连接ws
const connectWs = () => { const connectWs = () => {
ws.onopen = (e) => { ws.onopen = (e) => {
// let message ={ // let message ={
// projectId:'1897160897167638529', // projectId:'1897160897167638529',
// } // }
// ws.send(JSON.stringify(message)); // ws.send(JSON.stringify(message));
ws.onmessage = (e) => { ws.onmessage = (e) => {
console.log('ws', e); console.log('ws', e);
}; };
}; };
} }
const props = defineProps({ const props = defineProps({
isHide:{ isHide: {
type:Boolean, type: Boolean,
default:true, default: true,
} }
}) })
console.log('props', props); console.log('props', props);
@ -38,9 +40,37 @@ const defaultProps = {
} }
let entityManager = null; let entityManager = null;
window.deviceMap = new Map(); window.deviceMap = new Map();
window.ModelList = new Map();
let list = ref([]); let list = ref([]);
// 模型list
let modelList = ref([]);
// 漫游实例 // 漫游实例
let roamingController = null; 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数据 // 获取GPS数据
function getGpsData() { function getGpsData() {
getGps('1897160897167638529').then(res => { getGps('1897160897167638529').then(res => {
@ -88,15 +118,15 @@ function renderDevice(item) {
imageHeight: 64, imageHeight: 64,
name: item.label || item.id, name: item.label || item.id,
imageUrl: `/image/${item.type}.png`, imageUrl: `/image/${item.type}.png`,
onClick: (entity)=>{ onClick: (entity) => {
entityClickHandler(entity,item); entityClickHandler(entity, item);
} }
}); });
window.deviceMap.set(item.id, imageEntity); window.deviceMap.set(item.id, imageEntity);
} }
// 实体的点击事件 // 实体的点击事件
function entityClickHandler(entity,item) { function entityClickHandler(entity, item) {
console.log('entity', entity,item); console.log('entity', entity, item);
if (item.type == 'camera') { if (item.type == 'camera') {
deviceId.value = 'AE9470016'; deviceId.value = 'AE9470016';
videoDialogRef.value.show(); videoDialogRef.value.show();
@ -104,55 +134,46 @@ function entityClickHandler(entity,item) {
} }
} }
// 初始化地球 // 初始化地球
function initEarth() { async function initEarth() {
YJ.on({
ws: true,
host: '', //资源所在服务器地址
username: '', //用户名 可以不登录(不填写用户名),不登录时无法加载服务端的数据
password: '', //密码 生成方式md5(用户名_密码)
}).then((res) => {
let earth = new YJ.YJEarth("earth");
window.Earth1 = earth; let earth = new YJ.YJEarth("earth");
// 加载底图
// earth.viewer.terrainProvider = Cesium.createWorldTerrain(); window.Earth1 = earth;
// Earth1.viewer // 加载底图
addArcgisLayer(Earth1.viewer, 'img_w') // earth.viewer.terrainProvider = Cesium.createWorldTerrain();
// 添加倾斜数据 // Earth1.viewer
// loadTiltData(Earth1.viewer) addArcgisLayer(Earth1.viewer, 'img_w')
// 获取中心点 // 添加倾斜数据
YJ.Global.CesiumContainer(window.Earth1, { // 获取中心点
compass: false,//罗盘 YJ.Global.CesiumContainer(window.Earth1, {
legend: false, //图例 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"
}); });
// 创建实体管理器实例
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 // 获取ArcGIS服务的URL
function getArcGisUrlByType(type) { function getArcGisUrlByType(type) {
switch (type) { switch (type) {
//影像 //影像
case "img_w": case "img_w":
return "https://services.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer"; return "https://webst01.is.autonavi.com/appmaptile?style=6&x={x}&y={y}&z={z}";
//电子 //电子
case "vec_w": case "vec_w":
return "https://services.arcgisonline.com/ArcGIS/rest/services/World_Street_Map/MapServer"; return "https://services.arcgisonline.com/ArcGIS/rest/services/World_Street_Map/MapServer";
@ -164,13 +185,13 @@ function getArcGisUrlByType(type) {
return "http://map.geoq.cn/arcgis/rest/services/ChinaOnlineStreetGray/MapServer"; return "http://map.geoq.cn/arcgis/rest/services/ChinaOnlineStreetGray/MapServer";
//暖色底图 //暖色底图
case "vec_warm": case "vec_warm":
return "http://map.geoq.cn/arcgis/rest/services/ChinaOnlineStreetWarm/MapServer"; return "http://map.geoq.cn/arcgis/rest/services/ChinaOnlineStreetWarm/MapServer";
} }
} }
// 添加ArcGIS图层 // 添加ArcGIS图层
function addArcgisLayer(viewer, type) { function addArcgisLayer(viewer, type) {
let url = getArcGisUrlByType(type) let url = getArcGisUrlByType(type)
const layerProvider = new Cesium.ArcGisMapServerImageryProvider({ const layerProvider = new Cesium.UrlTemplateImageryProvider({
url: url url: url
}); });
viewer.imageryLayers.addImageryProvider(layerProvider); viewer.imageryLayers.addImageryProvider(layerProvider);
@ -197,7 +218,7 @@ function handleCheck(checkedNodes, nodes) {
device[device.entity.show ? 'hide' : 'show'](); device[device.entity.show ? 'hide' : 'show']();
} }
}; };
// 处理选中的节点(可能是单个节点或包含子节点的集合) // 处理选中的节点(可能是单个节点或包含子节点的集合)
if (checkedNodes?.children?.length) { if (checkedNodes?.children?.length) {
console.log('children', checkedNodes.children); console.log('children', checkedNodes.children);
@ -205,7 +226,7 @@ function handleCheck(checkedNodes, nodes) {
} else { } else {
handleNode(checkedNodes); handleNode(checkedNodes);
} }
setCheckedNode(nodes.checkedKeys); setCheckedNode(nodes.checkedKeys);
} }
// 开始漫游 // 开始漫游
@ -228,15 +249,26 @@ function stopRoaming() {
console.log('请先初始化地球'); console.log('请先初始化地球');
} }
} }
onMounted(() => {
onMounted(async () => {
// 连接ws // 连接ws
connectWs(); connectWs();
// 获取选中节点 // 获取选中节点
getCheckedNode(); getCheckedNode();
// 获取GPS数据 // 获取GPS数据
getGpsData(); getGpsData();
// 初始化地球 await getModelListData();
initEarth(); 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(() => { onUnmounted(() => {
window.deviceMap.forEach((item) => { window.deviceMap.forEach((item) => {
@ -250,12 +282,12 @@ onUnmounted(() => {
<template> <template>
<div class="earth-container-big"> <div class="earth-container-big">
<div class="earth" id="earth"></div> <div class="earth" id="earth"></div>
<div v-show="isHide" class="left"> <!-- <div v-show="isHide" class="left">
<div style="width: 100%;height: 100%;"> <div style="width: 100%;height: 100%;">
<el-button type="primary" @click="startRoaming">开始漫游</el-button> <el-button type="primary" @click="startRoaming">开始漫游</el-button>
<el-button type="primary" @click="stopRoaming">停止漫游</el-button> <el-button type="primary" @click="stopRoaming">停止漫游</el-button>
</div> </div>
</div> </div> -->
<div v-show="isHide" class="right"> <div v-show="isHide" class="right">
<el-tree show-checkbox :data="data" :props="defaultProps" node-key="id" :expand-on-click-node="false" <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" :check-on-click-node="false" :check-on-click-leaf="false" :default-expanded-keys="defaultExpandedKeys"
@ -300,6 +332,7 @@ onUnmounted(() => {
background-color: transparent; background-color: transparent;
--el-tree-node-hover-bg-color: transparent; --el-tree-node-hover-bg-color: transparent;
--el-tree-text-color: #fff; --el-tree-text-color: #fff;
.el-text { .el-text {
color: azure; color: azure;
} }