项目级页面添加漫游、摄像头、定位设备、无人机、摄像头视频播放

This commit is contained in:
2025-09-09 21:52:59 +08:00
parent 35a7825759
commit d5cf2a600e
7 changed files with 180 additions and 47 deletions

View File

@ -6,11 +6,11 @@ VITE_APP_ENV = 'development'
# 开发环境
VITE_APP_BASE_API = 'http://192.168.110.209:8899'
# VITE_APP_BASE_API = 'http://192.168.110.209:8899'
# 李陈杰 209
# VITE_APP_BASE_API = 'http://192.168.110.209:8899'
# 曾涛
# VITE_APP_BASE_API = 'http://192.168.110.180:8899'
VITE_APP_BASE_API = 'http://192.168.110.180:8899'
# 罗成
# VITE_APP_BASE_API = 'http://192.168.110.188:8899'
# 朱银

1
public/vite.svg Normal file
View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="31.88" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 257"><defs><linearGradient id="IconifyId1813088fe1fbc01fb466" x1="-.828%" x2="57.636%" y1="7.652%" y2="78.411%"><stop offset="0%" stop-color="#41D1FF"></stop><stop offset="100%" stop-color="#BD34FE"></stop></linearGradient><linearGradient id="IconifyId1813088fe1fbc01fb467" x1="43.376%" x2="50.316%" y1="2.242%" y2="89.03%"><stop offset="0%" stop-color="#FFEA83"></stop><stop offset="8.333%" stop-color="#FFDD35"></stop><stop offset="100%" stop-color="#FFA800"></stop></linearGradient></defs><path fill="url(#IconifyId1813088fe1fbc01fb466)" d="M255.153 37.938L134.897 252.976c-2.483 4.44-8.862 4.466-11.382.048L.875 37.958c-2.746-4.814 1.371-10.646 6.827-9.67l120.385 21.517a6.537 6.537 0 0 0 2.322-.004l117.867-21.483c5.438-.991 9.574 4.796 6.877 9.62Z"></path><path fill="url(#IconifyId1813088fe1fbc01fb467)" d="M185.432.063L96.44 17.501a3.268 3.268 0 0 0-2.634 3.014l-5.474 92.456a3.268 3.268 0 0 0 3.997 3.378l24.777-5.718c2.318-.535 4.413 1.507 3.936 3.838l-7.361 36.047c-.495 2.426 1.782 4.5 4.151 3.78l15.304-4.649c2.372-.72 4.652 1.36 4.15 3.788l-11.698 56.621c-.732 3.542 3.979 5.473 5.943 2.437l1.313-2.028l72.516-144.72c1.215-2.423-.88-5.186-3.54-4.672l-25.505 4.922c-2.396.462-4.435-1.77-3.759-4.114l16.646-57.705c.677-2.35-1.37-4.583-3.769-4.113Z"></path></svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@ -123,6 +123,8 @@ function addPre() {
// 视频播放
function videoPlay(obj: any) {
console.log('objobjobj',obj);
getAccessToken().then((res: any) => {
if (res.code == 200 && obj.deviceSerial) {
flvPlayer.value = new EZUIKit.EZUIKitPlayer({

View File

@ -1,7 +1,7 @@
<template>
<div class="centerPage">
<div class="topPage">
<newMap></newMap>
<newMap :isHide="isHide"></newMap>
</div>
<div class="endPage" :class="{ 'slide-out-down': isHide }">
<Title title="AI安全巡检">
@ -16,7 +16,7 @@
<div class="swiper_content" ref="swiperContent">
<div class="swiper_item" v-for="(item, i) in inspectionList" :key="i">
<img :src="item.picture" alt="安全巡检" class="swiper_img">
<div class="swiper_date">{{ item.createTime.slice(5) }}</div>
<!-- <div class="swiper_date">{{ item.createTime.slice(5) }}</div> -->
<div class="swiper_tip">{{ item.label }}</div>
</div>
</div>

View File

@ -1,11 +1,22 @@
<script setup>
import { onMounted, ref, onUnmounted } from 'vue';
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"
const defaultExpandedKeys = [1, 2, 3] //默认展开第一级节点
const defaultCheckedKeys = ref([]) //默认选中节点
const data = ref([]);
const deviceId = ref('');
const videoDialogRef = ref(null);
const props = defineProps({
isHide:{
type:Boolean,
default:true,
}
})
console.log('props', props);
const defaultProps = {
children: 'children',
label: 'label',
@ -58,15 +69,24 @@ function renderDevice(item) {
lat: Number(item.lat),
height: 0
},
imageWidth: 64,
imageHeight: 64,
name: item.label || item.id,
imageUrl: "/assets/demo/avatar.png",
onClick: entityClickHandler
imageUrl: `/image/${item.type}.png`,
onClick: (entity)=>{
entityClickHandler(entity,item);
}
});
window.deviceMap.set(item.id, imageEntity);
}
// 实体的点击事件
function entityClickHandler(entity) {
console.log('entity', entity);
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() {
@ -111,11 +131,6 @@ function loadTiltData(viewer) {
// url:"http://58.17.134.85:7363/yjearth4.0/data/pak/e904acb32aaa8b872c64866ebaaaf5e2"
url: import.meta.env.VITE_EARTH_URL + "/yjearth4.0/data/pak/4eb21d3fc02873092e75640e261544b3"
});
// var tileset = viewer.scene.primitives.add(new Cesium.Cesium3DTileset({
// // url: 'http://58.17.134.85:7363/zm/api/v1/data/tileset/b15be28d053fcdd98308bed74c6108e6/tileset.json',
// url:'http://58.17.134.85:7363/yjearth4.0/data/tileset/9c25649daa610a0cfb89e2cbea74bc55/tileset.json'
// }));
// console.log("加载倾斜数据:", tileset);
}
// 获取ArcGIS服务的URL
function getArcGisUrlByType(type) {
@ -218,17 +233,18 @@ onUnmounted(() => {
<template>
<div class="earth-container-big">
<div class="earth" id="earth"></div>
<div class="left">
<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 class="right">
<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">
@ -255,7 +271,7 @@ onUnmounted(() => {
.right,
.left {
position: absolute;
width: 200px;
width: 400px;
height: 100%;
transform: translateY(-50%);
background-color: #00000052;

View File

@ -0,0 +1,109 @@
<template>
<el-dialog v-model="visible" title="摄像头直播" :width="dialogWidth" :height="dialogHeight" :before-close="handleClose"
destroy-on-close>
<div class="video-container-entity" id="video-container-entity" style="width: 100%; height: 600px"></div>
<!-- <template #footer>
<el-button type="primary" @click="handlesubmit">确定</el-button>
<el-button type="danger" @click="handleClose">关闭</el-button>
</template> -->
</el-dialog>
</template>
<script setup>
import { ref, onMounted, defineEmits, defineProps,onUnmounted } from 'vue';
import { ElMessage } from 'element-plus';
import { getAccessToken } from '@/api/other/ys7Device';
import EZUIKit from 'ezuikit-js';
const emit = defineEmits(['send-data', 'close']);
const props = defineProps({
data: {
type: Object,
default: () => { }
}
});
// 弹窗控制变量
const visible = ref(false);
const dialogWidth = ref('950px');
const dialogHeight = ref('90%');
let loading = ref(true);
const flvPlayer = ref(null);
const show = () => {
visible.value = true;
}
// 关闭弹窗
const handleClose = () => {
visible.value = false;
};
// 处理数据传递
const handlesubmit = () => {
handleClose();
};
// 视频播放
function videoPlay(deviceSerial) {
getAccessToken().then((res) => {
if (res.code == 200 && deviceSerial) {
flvPlayer.value = new EZUIKit.EZUIKitPlayer({
audio: '0',
id: 'video-container-entity',
accessToken: res.data,
url: `ezopen://open.ys7.com/${deviceSerial}/1.hd.live`,
template: 'pcLive',
width: 870,
height: 600,
plugin: ['talk'],
handleError: function (err) {
console.log(err);
if (err?.data?.ret === 20020) {
// 20020 是并发连接限制的错误码
ElMessage.error('当前观看人数已达上限,请稍后再试');
}
}
});
}
});
}
// 组件挂载时设置容器ID
onMounted(() => {
});
// 暴露显示方法给父组件
defineExpose({
show,
videoPlay
});
//
onUnmounted(() => {
});
</script>
<style scoped>
.earth-container {
width: 100%;
height: 600px;
overflow: hidden;
position: relative;
}
:deep(.el-dialog__body) {
padding: 10px;
height: calc(100% - 100px);
overflow: hidden;
}
:deep(.el-dialog) {
display: flex;
flex-direction: column;
max-height: 90vh;
}
:deep(.el-dialog__content) {
flex: 1;
display: flex;
flex-direction: column;
overflow: hidden;
}
</style>

View File

@ -53,8 +53,12 @@ export default class CesiumImageLabelEntity {
// 创建实体
this.entity = this.createEntity();
// 初始化点击事件监听
this.initClickHandler();
// 为实体添加标识,方便后续判断
this.entity._isImageLabelEntity = true;
this.entity._imageLabelInstance = this;
// 初始化全局点击事件(确保只注册一次)
this.initGlobalClickHandler();
}
/**
@ -67,7 +71,7 @@ export default class CesiumImageLabelEntity {
position: Cesium.Cartesian3.fromDegrees(
this.options.position.lng,
this.options.position.lat,
this.options.position.alt
this.options.position.height || 0 // 修复使用height而非alt
),
show: this.options.show,
@ -79,8 +83,7 @@ export default class CesiumImageLabelEntity {
color: this.options.imageColor,
horizontalOrigin: this.options.horizontalOrigin,
verticalOrigin: this.options.verticalOrigin,
// 允许实体被选中
pickable: true
pickable: true // 确保可拾取
},
// 名称标签属性
@ -91,12 +94,10 @@ export default class CesiumImageLabelEntity {
horizontalOrigin: this.options.horizontalOrigin,
verticalOrigin: Cesium.VerticalOrigin.TOP,
pixelOffset: new Cesium.Cartesian2(0, this.options.labelOffsetY),
// 添加背景
backgroundColor: new Cesium.Color(0, 0, 0, 0),
backgroundColor: new Cesium.Color(0, 0, 0, 0.5), // 修复:半透明背景更易点击
backgroundPadding: new Cesium.Cartesian2(5, 5),
showBackground: true,
// 允许标签被选中
pickable: true
pickable: true // 确保可拾取
}
});
@ -107,29 +108,33 @@ export default class CesiumImageLabelEntity {
}
/**
* 初始化点击事件处理器
* 初始化全局点击事件处理器(只注册一次)
*/
initClickHandler() {
// 存储当前实例的引用,方便在回调中使用
const self = this;
initGlobalClickHandler() {
// 检查是否已注册全局事件,避免重复注册
if (!this.viewer._imageLabelGlobalClickHandler) {
const handler = new Cesium.ScreenSpaceEventHandler(this.viewer.scene.canvas);
// 注册左击事件
this.viewer.screenSpaceEventHandler.setInputAction(function onLeftClick(movement) {
// 检测是否点击了当前实体
const pickedObject = self.viewer.scene.pick(movement.position);
handler.setInputAction((movement) => {
const pickedObject = this.viewer.scene.pick(movement.position);
// 检查是否点击了当前实体或其实体的子组件billboard、label等
if (Cesium.defined(pickedObject) &&
(pickedObject.id === self.entity ||
pickedObject.id === self.entity.billboard ||
pickedObject.id === self.entity.label)) {
// 如果设置了点击回调,则执行
if (self.onClickCallback && typeof self.onClickCallback === 'function') {
self.onClickCallback(self.entity, movement.position);
// 判断是否点击了我们创建的图片标签实体
if (Cesium.defined(pickedObject) &&
Cesium.defined(pickedObject.id) &&
pickedObject.id._isImageLabelEntity) {
// 调用对应实例的回调函数
if (pickedObject.id._imageLabelInstance.onClickCallback) {
pickedObject.id._imageLabelInstance.onClickCallback(
pickedObject.id,
movement.position
);
}
}
}
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);
}, Cesium.ScreenSpaceEventType.LEFT_CLICK);
// 存储全局事件处理器引用,避免重复创建
this.viewer._imageLabelGlobalClickHandler = handler;
}
}
/**