From 57412c916fca9c2c66446a3651c2ff7f6b2efa19 Mon Sep 17 00:00:00 2001
From: 张含笑 <zhx18749296735@163.com>
Date: Tue, 10 Jun 2025 16:46:51 +0800
Subject: [PATCH] feat:地图弹框
---
src/hooks/components/EventPopUpBox.vue | 142 ++++++++++++++++++++
src/views/dataCenter/dataCenter.vue | 26 +++
src/assets/images/dataCenter/datamap/popUpBox.png | 0
src/views/dataCenter/components/dataCenterMap.vue | 210 ++++++++++++++++++++++++++++++
src/assets/images/dataCenter/datamap/eventCompleted.png | 0
src/api/dataCenter/dataCenter.js | 8 +
src/assets/images/dataCenter/datamap/activeevent.png | 0
7 files changed, 384 insertions(+), 2 deletions(-)
diff --git a/src/api/dataCenter/dataCenter.js b/src/api/dataCenter/dataCenter.js
new file mode 100644
index 0000000..f73dec8
--- /dev/null
+++ b/src/api/dataCenter/dataCenter.js
@@ -0,0 +1,8 @@
+import request from '@/axios';
+export const getaiImagesPage = (data) => {
+ return request({
+ url: `/blade-resource/attach/aiImagesPage`,
+ method: 'post',
+ data
+ })
+ };
\ No newline at end of file
diff --git a/src/assets/images/dataCenter/datamap/activeevent.png b/src/assets/images/dataCenter/datamap/activeevent.png
new file mode 100644
index 0000000..1e6d965
--- /dev/null
+++ b/src/assets/images/dataCenter/datamap/activeevent.png
Binary files differ
diff --git a/src/assets/images/dataCenter/datamap/eventCompleted.png b/src/assets/images/dataCenter/datamap/eventCompleted.png
new file mode 100644
index 0000000..f606331
--- /dev/null
+++ b/src/assets/images/dataCenter/datamap/eventCompleted.png
Binary files differ
diff --git a/src/assets/images/dataCenter/datamap/popUpBox.png b/src/assets/images/dataCenter/datamap/popUpBox.png
new file mode 100644
index 0000000..ab9ea28
--- /dev/null
+++ b/src/assets/images/dataCenter/datamap/popUpBox.png
Binary files differ
diff --git a/src/hooks/components/EventPopUpBox.vue b/src/hooks/components/EventPopUpBox.vue
new file mode 100644
index 0000000..36953d4
--- /dev/null
+++ b/src/hooks/components/EventPopUpBox.vue
@@ -0,0 +1,142 @@
+<template>
+ <div class="mapPopUpBox">
+ <div class="title">
+ <span>222</span>
+
+ <el-icon class="header-close" @click.stop="props.removeLabel">
+ <Close />
+ </el-icon>
+ </div>
+ <div class="content">
+ <div class="medium">
+ <el-image
+ class="eventImage"
+ :src="infoList?.smallUrl"
+ :preview-src-list="[infoList?.smallUrl]"
+ fit="cover"
+ preview-teleported
+ ></el-image>
+ </div>
+
+ <div class="details">
+ <div class="label">时间:</div>
+ <div class="value point">
+ 11
+ </div>
+ <div class="label">地点:</div>
+ <div class="value">
+ 22
+ </div>
+ </div>
+ </div>
+ </div>
+</template>
+<script setup>
+import { ElImage, ElIcon } from 'element-plus'
+import { Close } from '@element-plus/icons-vue'
+// import { getEventDetails } from '@/api/home/aggregation'
+import _ from 'lodash'
+import { getSmallImg } from '@/utils/util'
+
+const props = defineProps(['data', 'removeLabel'])
+const loading = ref(true)
+
+const info = ref({
+ event_name: '',
+ status: 1,
+ url: '1',
+ longitude: '',
+ latitude: '',
+ create_time: '04/01 12:41',
+})
+const infoList = props.data
+
+onMounted(async () => {})
+
+const disposeUrl = ({ url }) => {
+ return getSmallImg(url)
+}
+</script>
+
+<style scoped lang="scss">
+.mapPopUpBox {
+ width: 271px;
+ height: 173px;
+ background: url('@/assets/images/dataCenter/datamap/popUpBox.png') no-repeat center / 100% 100%;
+ padding: 13px 15px;
+ pointer-events: all;
+
+ .title {
+ font-family: YouSheBiaoTiHei, YouSheBiaoTiHei, serif;
+ font-weight: 400;
+ font-size: 18px;
+ line-height: 16px;
+ background: linear-gradient(180deg, #a8e5fb 0%, #e6f8ff 100%);
+ -webkit-background-clip: text;
+ -webkit-text-fill-color: transparent;
+ -moz-background-clip: text;
+ -moz-text-fill-color: transparent;
+ background-clip: text;
+ text-fill-color: transparent;
+ margin-bottom: 10px;
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+
+ .header-close {
+ width: 20px;
+ height: 100%;
+ line-height: 100%;
+ display: flex;
+ align-items: center;
+ color: #9cd5ff;
+ pointer-events: all;
+ cursor: pointer;
+ }
+ }
+
+ .content {
+ height: 102px;
+ width: 240px;
+ display: flex;
+ align-items: center;
+
+ .medium {
+ height: 102px;
+ width: 120px;
+ margin-right: 10px;
+
+ > img,
+ video,
+ div {
+ width: 100%;
+ height: 100%;
+ }
+ }
+
+ .details {
+ .label {
+ font-family: Source Han Sans CN, Source Han Sans CN;
+ font-weight: 400;
+ font-size: 14px;
+ color: #7babd7;
+ line-height: 16px;
+ margin-bottom: 2px;
+ }
+
+ .value {
+ font-family: Source Han Sans CN, Source Han Sans CN;
+ font-weight: 400;
+ font-size: 14px;
+ color: #d8edff;
+ line-height: 16px;
+ margin-bottom: 2px;
+ }
+
+ .point {
+ margin-bottom: 14px;
+ }
+ }
+ }
+}
+</style>
diff --git a/src/views/dataCenter/components/dataCenterMap.vue b/src/views/dataCenter/components/dataCenterMap.vue
new file mode 100644
index 0000000..105d4a1
--- /dev/null
+++ b/src/views/dataCenter/components/dataCenterMap.vue
@@ -0,0 +1,210 @@
+<template>
+ <el-dialog modal-class="mapDialog" v-model="isShow" width="80%">
+ <div class="mapBox">
+ <div id="dataCenterMap" class="ztzf-cesium"></div>
+ </div>
+ </el-dialog>
+</template>
+<script setup>
+import { useStore } from 'vuex';
+import { PublicCesium } from '@/utils/cesium/publicCesium';
+import { Cartesian3 } from 'cesium';
+import * as Cesium from 'cesium';
+import EventPopUpBox from '@/hooks/components/EventPopUpBox.vue';
+import { render } from 'vue';
+import defaultIcon from '@/assets/images/dataCenter/datamap/eventCompleted.png';
+const isShow = defineModel('show');
+const viewerRef = shallowRef(null);
+let viewer = null;
+const viewInstance = shallowRef(null);
+const store = useStore();
+const currentAreaPosition = ref({ height: 1987280, latitude: 27.636112, longitude: 115.732975 });
+let handler = null;
+
+// 获取弹框box
+const createLabelDom = data => {
+console.log('data',data);
+
+ const vNode = h(EventPopUpBox, { data, removeLabel })
+ const tooltipContainer = document.createElement('div')
+ tooltipContainer.id = 'mapPopUpBox'
+ tooltipContainer.style.position = 'absolute'
+ tooltipContainer.style.transform = 'translate(-50%,-135%)'
+ tooltipContainer.style.pointerEvents = 'none'
+ document.querySelector('#dataCenterMap').append(tooltipContainer)
+ render(vNode, tooltipContainer)
+ return tooltipContainer
+};
+
+let currentClickEntity = null;
+// 弹框位置刷新
+const labelBoxUpdate = () => {
+ if (!currentClickEntity) return;
+ const mapPopUpBox = document.querySelector('#mapPopUpBox');
+ let dom = mapPopUpBox
+ ? mapPopUpBox
+ : createLabelDom(currentClickEntity.properties.customData._value.data);
+ const screenPosition = viewer?.scene.cartesianToCanvasCoordinates(
+ currentClickEntity?.position?._value
+ );
+ if (screenPosition) {
+ dom.style.left = `${screenPosition.x}px`;
+ dom.style.top = `${screenPosition.y}px`;
+ dom.style.display = 'block';
+ }
+};
+const removeDom = () => {
+ const dom = document.querySelector('#mapPopUpBox');
+ if (dom && dom.parentNode) {
+ dom.parentNode.removeChild(dom);
+ }
+};
+
+// 移除弹框标签
+const removeLabel = () => {
+ viewer?.scene.postRender.removeEventListener(labelBoxUpdate);
+ removeDom();
+};
+
+// 左键单机事件
+const singleMachineEvent = async click => {
+ let clickedEntities = viewer?.scene.drillPick(click.position).map(item => item.id);
+ if (!clickedEntities.length) return;
+ currentClickEntity = clickedEntities[0];
+ removeLabel();
+ viewer.scene.postRender.addEventListener(labelBoxUpdate);
+};
+
+// 事件初始化
+const handlerInit = () => {
+ if (handler) return;
+ handler = new Cesium.ScreenSpaceEventHandler(viewer?.scene.canvas);
+ handler.setInputAction(singleMachineEvent, Cesium.ScreenSpaceEventType.LEFT_CLICK);
+};
+
+const removeHandler = () => {
+ handler?.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_CLICK);
+ handler?.destroy();
+ handler = null;
+};
+
+const dataPointList = [
+ {
+ longitude: '115.85708286111111',
+ latitude: '28.62837602777778',
+ },
+ {
+ longitude: '115.8566981111111',
+ latitude: '28.624613027777777',
+ },
+ {
+ longitude: '115.85474438888889',
+ latitude: '28.624930444444445',
+ },
+ {
+ longitude: '115.85518375',
+ latitude: '28.62479547222222',
+ },
+];
+
+function renderDataPoint() {
+ dataPointList.forEach((item, index) => {
+ const sizeObj = { width: 30, height: 30 };
+
+ viewer.entities.add({
+ id: `renderDataPoint-${index}`,
+ position: Cesium.Cartesian3.fromDegrees(Number(item.longitude), Number(item.latitude)),
+ label: {
+ font: '12pt 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),
+ },
+ billboard: {
+ image: defaultIcon,
+ ...sizeObj,
+ },
+ properties: {
+ customData: {
+ data: item,
+ },
+ },
+ });
+ });
+}
+
+const initMap = () => {
+ const publicCesiumInstance = new PublicCesium({
+ dom: 'dataCenterMap',
+ flatMode: false,
+ terrain: false,
+ mapFilter: true,
+ });
+ viewerRef.value = publicCesiumInstance.getViewer();
+ viewer = publicCesiumInstance.getViewer();
+ const { longitude, latitude, height } = currentAreaPosition.value;
+ const position = Cartesian3.fromDegrees(longitude, latitude, height);
+ viewerRef.value.camera.flyTo({
+ duration: 0,
+ destination: position,
+ orientation: {
+ heading: Cesium.Math.toRadians(0.0),
+ pitch: Cesium.Math.toRadians(-90.0),
+ roll: 0.0,
+ },
+ });
+ viewInstance.value = publicCesiumInstance;
+};
+// 监听对话框状态
+watch(isShow, (newVal) => {
+ if (newVal) {
+ nextTick(() => {
+ initMap();
+ handlerInit();
+ renderDataPoint();
+ });
+ } else {
+ // 对话框关闭时清理资源
+ viewInstance.value?.viewerDestroy();
+ removeHandler();
+ }
+});
+onMounted(() => {
+ nextTick(() => {
+ initMap();
+ handlerInit();
+ renderDataPoint();
+ });
+});
+
+onBeforeUnmount(() => {
+ viewInstance.value?.viewerDestroy();
+ removeHandler();
+});
+</script>
+<style >
+
+.mapDialog .el-dialog__body {
+ height: 700px !important;
+ padding: 0 !important;
+}
+</style>
+<style scoped lang="scss">
+
+.mapBox {
+ z-index: 2;
+ height: 650px;
+ width: 98%;
+ position: absolute;
+ left: 13px;
+ top: 50px;
+
+ #dataCenterMap {
+ width: 100%;
+ height: 100%;
+ }
+}
+</style>
diff --git a/src/views/dataCenter/dataCenter.vue b/src/views/dataCenter/dataCenter.vue
index 185cc2f..96de4b7 100644
--- a/src/views/dataCenter/dataCenter.vue
+++ b/src/views/dataCenter/dataCenter.vue
@@ -49,7 +49,7 @@
<span class="delete" @click="deleteDetail()" v-if="scope.row.fileformat !== 'AI识别'"
>删除</span
>
- <span class="location" v-if="scope.row.fileformat !== '视频'">定位</span>
+ <span class="location" @click="positionDetail()" v-if="scope.row.fileformat !== '视频'">定位</span>
</template>
</el-table-column>
</el-table>
@@ -133,15 +133,19 @@
<video style="width:100%" class="videoBox" ref="videoRefs" controls autoplay :src="currentVideoUrl"></video>
</div>
</el-dialog>
+ <!-- 地图弹框 -->
+ <dataCenterMap v-model:show="dataCenterMapVisible"></dataCenterMap>
</div>
</template>
<script setup>
+import dataCenterMap from '@/views/dataCenter/components/dataCenterMap.vue'
import PanoramaPopup from '@/components/PanoramaPopup/PanoramaPopup.vue'; //全景
import { ElMessage, ElMessageBox } from 'element-plus';
import searchData from '@/views/dataCenter/components/searchData.vue';
import fy1 from '@/assets/images/dataCenter/1.jpeg';
-
+import {getaiImagesPage} from '@/api/dataCenter/dataCenter'
+import { onMounted } from 'vue';
function convertVideoUrlToThumbnail(videoUrl) {
// 检查是否是有效的视频URL
if (!videoUrl || typeof videoUrl !== 'string') {
@@ -151,6 +155,7 @@
const thumbnailUrl = videoUrl.replace(/\.mp4$/, '_small.jpg');
return thumbnailUrl;
}
+
const jobListParams = reactive({
current: 1,
size: 10,
@@ -213,6 +218,13 @@
fileformat: '正射',
},
];
+// 获取列表数据
+const getgetaiImagesPage =()=>{
+ getaiImagesPage(jobListParams).then(res=>{
+ console.log('res',res);
+
+ })
+}
const handleSizeChange = () => {};
const handleCurrentChange = () => {};
// 多选
@@ -260,6 +272,16 @@
currentVideoUrl.value = val.img;
console.log('视频', val);
};
+// 地图弹框
+const dataCenterMapVisible = ref(false)
+const positionDetail=()=>{
+ console.log('地图');
+ dataCenterMapVisible.value = true
+
+}
+onMounted(()=>{
+ // getgetaiImagesPage()
+})
</script>
<style scoped lang="scss">
--
Gitblit v1.9.3