<template> <!-- 新版2024(cesium模型底图-水科院) --> <div class="oneMapModalPage"> <!-- 地图组件 --> <MapBox ref="boxMap" /> <!-- 底部导航 --> <footer class="mainFooter"> <n-tabs type="bar" @update:value="changeNav" v-model:value="currentVal" class="tabsNav"> <n-tab-pane :name="item.label" v-for="item in navArr" :key="item.value"></n-tab-pane> </n-tabs> </footer> <!-- 临时加载三方内容链接 --> <div class="otherFrame" v-if="showOther"> <iframe :src="otherIframeUrl" frameborder="0"></iframe> </div> <!-- 全域感知-雷达图相关 v-if="ifQixiang"--> <div class="cloudPic" v-if="ifQixiang"> <div class="color"></div> <div class="progress"> <div :class="['cast', ifPlay ? 'start' : 'end']" @click="goPlay"></div> <n-progress type="line" status="success" processing :show-indicator="false" color="#4BCCE5" rail-color="#081931" :percentage="percentage" /> <p class="currentTime">{{ dateLine }}</p> <n-select v-model:value="speedValue" style="width: 80px; margin-left: 10px" :options="yubaoOption" @update:value="changeSpeed" /> <n-date-picker v-model:value="timeRange" style="width: 300px; margin-left: 10px" type="daterange" /> <n-button class="leida" @click="searchWeather">查询</n-button> </div> </div> <!-- 内容切换 --> <OnePart v-if="currentVal == '全域感知'"></OnePart> <TwoPart v-if="currentVal == '规划引领'"></TwoPart> <FourPart v-if="currentVal == '长效治理'"></FourPart> <!-- 图例控制 --> <Legend /> <!-- 水质监测、水位流量报警提示信息 --> <div class="lyInfoWarn" v-if="ifStationWarn"> <vue3-seamless-scroll :list="listData" :singleHeight="49" :singleWaitTime="3000" :limitScrollNum="2" :hover="true" class="scroll"> <div class="item" v-for="(item, index) in listData" @click="checkDetail(item)" :key="index"> <span> {{ item.siteName }}:当前{{ item.factorsName }}值:{{ item.warnValue }}, {{ item.compareWayDesc }} {{ item.warnTypeDesc }}{{ item.warnConfigValue }},持续时间{{ item.durationTime }} </span> </div> </vue3-seamless-scroll> </div> <!-- 预警详情弹窗 --> <n-modal v-model:show="showWarnDetail" :show-icon="false" :mask-closable="false" preset="card" :title="modalTitle" class="modalWarns" style="width: 600px" > <WarnDetail ref="bjDetails" :warnDetailData="warnDetailData" @update:refeshData="getGdbjData" /> </n-modal> <!-- 社会工程网 工艺图链接查看 --> <n-modal title="工艺图详情" :mask-closable="false" preset="dialog" :show-icon="false" @update:show="handleModalChange" :style="{ width: '1900px' }" v-model:show="modalShowGy" > <!-- 视频 m3u8格式--> <!-- 工艺图链接 --> <div class="dialogGYT" v-if="gymodel"> <iframe :src="iframeUrl" frameborder="0" style="flex: 1; height: 770px"></iframe> </div> <div class="dialogGYT" v-else> <iframe :src="iframeUrl" frameborder="0" style="flex: 1; height: 770px"></iframe> <div class="videoGyt"> <video height="400" id="video" controls="" :src="videoSrc"></video> <video height="400" id="video1" controls="" :src="videoSrc"></video> </div> </div> </n-modal> <!-- 厂站详情弹窗页面 --> <n-modal v-model:show="showModalBZ" :show-icon="false" :mask-closable="false" preset="dialog" :title="BZtitle" style="width: 680px"> <BengZModal :valueModalbz="valueModalbz" /> </n-modal> </div> </template> <script> import Hls from 'hls.js'; import { ref, toRefs, onMounted, reactive, onBeforeUnmount, nextTick } from 'vue'; import { Vue3SeamlessScroll } from 'vue3-seamless-scroll'; import BengZModal from './modalPart/modal/BengZModal.vue'; //湖泊监测弹窗 import MapBox from './modalPart/Mapbox.vue'; import OnePart from './modalPart/natureNet.vue'; //全域感知 import TwoPart from './modalPart/sheHuiNet.vue'; //规划引领 import FourPart from './modalPart/liuYuWater.vue'; //长效治理 import Legend from './modalPart/legend.vue'; //图例 import WarnDetail from './modalPart/warnDetail.vue'; //报警详情弹窗 import { lyInfoReminder, getAllRainValue, getCamreaStream } from '@/services'; import bus from '@/utils/util'; import { formatDate } from '@/utils/util'; import 'video.js/dist/video-js.css'; // video.js样式 import videojs from 'video.js'; import bjGeoJSON from '@/assets/json/bianjie.json'; import NewFiberMapUtils from '@/utils/gis/NewfiberMap.js'; export default { name: 'oneMapModalPage', components: { MapBox, OnePart, TwoPart, FourPart, WarnDetail, Legend, Vue3SeamlessScroll, BengZModal, }, setup() { let hls = null; let hls1 = null; const allData = reactive({ indexCode: '', indexCode1: '', videoname: '', videoSrc: '', videoSrc1: '', gymodel: true, imgvideo: 'https://server1.wh-nf.cn:8125/video/mp4/1660035469.mp4', BZtitle: '', showModalBZ: false, showOther: false, otherIframeUrl: '', isPipelineflowShow: false, iframeUrl: '', modalShowGy: false, myPlayer: null, videoUrlLists: [], warnDetailData: {}, ifQixiang: false, ifStationWarn: false, showWarnDetail: false, modalTitle: '', percentage: 0, dateNumber: 0, timer: null, ifPlay: false, currentVal: '全域感知', datearry: [], dateTime: [], dateLine: formatDate(Date.now() - 24 * 30 * 60 * 60 * 1000, 'YYYY-MM-DD'), navArr: [ { value: '2', label: '规划引领' }, { value: '1', label: '全域感知' }, { value: '3', label: '长效治理' }, { value: '4', label: '孪生流域' }, ], speedValue: 1000, yubaoOption: [ { value: 1000, label: '1倍速' }, { value: 250, label: '4倍速' }, { value: 160, label: '6倍速' }, ], timeRange: [Date.now() - 24 * 30 * 60 * 60 * 1000, Date.now()], listData: [], rainAnalyses: {}, valueModalbz: {}, }); const boxMap = ref(null); // 底部菜单点击切换 const changeNav = (val) => { allData.currentVal = val; if (val == '孪生流域') { let A = window.location.host; if (A.includes('172.20')) { allData.otherIframeUrl = 'http://172.20.2.9:801/HJH/'; } else { allData.otherIframeUrl = 'http://192.168.10.50:802/HJH/'; } allData.showOther = true; } else { allData.showOther = false; } if (val != '全域感知') { clearTimer(); // mapbox.setLayerVisible(['marker_kriging', 'kriging'], false); allData.ifQixiang = false; // 暂停,清除图层 // mapbox.setLayerVisible(['marker_kriging', 'kriging'], false); } }; //获取降雨数据 转geojson const getAllRainValueRequest = async (time, time2) => { let { code, data } = await getAllRainValue({ startTime: time, endTime: time2 }); if (!(code == 200)) return; let result1 = []; let datelist = []; data.forEach((item) => { result1.push(item.list); datelist.push(item.date); }); bus.emit('datelist', datelist); window.rainstationlen = null; result1.map((item) => { item.map((reainitem) => { let { point } = reainitem; let lngLat = point.replace('POINT(', '').replace(')', '').split(' '); reainitem.lng = lngLat[0]; reainitem.lat = lngLat[1]; }); }); allData.rainAnalyses = result1; window.rainstationlen = result1.length; return Promise.resolve(); }; // 降水分布图 const initKriging = async (hour) => { // allData.index = allData.index == 30 ? 0 : allData.index + 1; // hour = allData.index; // let layerId = `kriging_layer`; // let sourceId = `kriging_source`; // let markerLayerId = `marker_kriging_layer`; // let markerSourceId = `marker_kriging_source`; let data = allData.rainAnalyses[hour]; if (!!data) return tokriging(data); function initLayer(kriging, marker) { // !mapbox._map.getSource(sourceId) && mapbox._map.addSource(sourceId, { type: 'geojson', data: kriging }); // !mapbox._map.getSource(markerSourceId) && mapbox._map.addSource(markerSourceId, { type: 'geojson', data: marker }); // !mapbox._map.getLayer(layerId) && // mapbox._map.addLayer({ // id: layerId, // type: 'fill', // source: sourceId, // layout: {}, // paint: { // 'fill-color': { type: 'identity', property: 'color' }, // 'fill-opacity': 0.6, // }, // }); newfiberMap.addGeojsonPolygon({ id: 'kriging_layer', data: kriging, text: '', fontSize: '', font: 'Source Han Sans CN', labelOffset: [0, 20], showBackground: false, backgroundColor: '#ff0000', fillColor: '#ffffff', outlineColor: '', outlineWidth: 1, style: Cesium.LabelStyle.FILL, //Cesium.LabelStyle.FILL_AND_OUTLINE Cesium.LabelStyle.OUTLINE material: null, width: 6, strokeColor: '#1c95ab', groundHeight: 0, distanceDisplayCondition: [0, 100000], }); // mapbox._map.moveLayer(layerId, 'bulding_layer'); // !mapbox._map.getLayer(markerLayerId) && // mapbox._map.addLayer({ // id: markerLayerId, // type: 'symbol', // source: markerSourceId, // layout: { // 'text-field': ['get', 'name'], // 'text-variable-anchor': ['top'], // 'text-radial-offset': 0.5, // 'text-justify': 'auto', // }, // paint: { // 'text-color': 'rgba(229,229,229,1)', // 'text-halo-color': 'rgba(0, 0, 0, 0.8)', // 'text-halo-width': 3, // }, // }); newfiberMap.addGeojsonPoint({ id: 'marker_kriging', data: marker, icon: '', text: '', fontSize: '18', font: 'Source Han Sans CN', height: 124, width: 65, labelOffset: [0, -180], imgOffset: [0, 0], showBackground: false, backgroundColor: '#ff0000', fillColor: 'rgba(152, 16, 192,1)', outlineColor: 'rgba(0, 0, 0, 0.8)', outlineWidth: 6, show: true, style: Cesium.LabelStyle.FILL_AND_OUTLINE, //Cesium.LabelStyle.FILL_AND_OUTLINE Cesium.LabelStyle.OUTLINE }); } function tokriging(data) { let geoJson = turf.featureCollection( data.map((item) => turf.point([Number(item.lng), Number(item.lat)], { value: item.value, name: `${item.value}mm`, }) ) ); let kriging = getKrigingByPoints(geoJson, bjGeoJSON); if (!!!layerSource || !!!markerSource) return initLayer(kriging, geoJson); // layerSource.setData(kriging); // markerSource.setData(geoJson); } }; // 播放进度选择 function changeSpeed(val) { allData.speedValue = val; searchWeather(); } // 搜索播放云图数据 initKriging(0,'nowRainResult','2022-07-02') const searchWeather = async () => { allData.ifPlay = true; clearTimer(); allData.percentage = 0; allData.dateNumber = 0; let startTime = formatDate(allData.timeRange[0], 'YYYY-MM-DD') + ' 00:00:00'; let endTime = formatDate(allData.timeRange[1], 'YYYY-MM-DD') + ' 23:59:59'; getAllRainValueRequest(startTime, endTime).then(() => { allData.dateTime = Object.values(allData.datearry); let DateStept = 100 / allData.dateTime.length; allData.timer = setInterval(() => { allData.dateLine = allData.dateTime[allData.dateNumber]; initKriging(allData.dateNumber); allData.percentage += DateStept; allData.dateNumber += 1; if (allData.dateNumber > window.rainstationlen) { allData.percentage = 0; allData.dateNumber = 0; } }, allData.speedValue); }); }; // 点击播放暂停云图 const goPlay = () => { allData.ifPlay = !allData.ifPlay; if (allData.ifPlay) { console.log('播放'); // 播放 searchWeather(); setTimeout(() => { // mapbox._map.setLayoutProperty('kriging_layer', 'visibility', ' '); // mapbox.setLayerVisible(['marker_kriging', 'kriging'], true); }, 500); } else { clearTimer(); // 暂停,清除图层 // mapbox.setLayerVisible(['marker_kriging', 'kriging'], false); console.log('暂停'); } }; // 清除定时器 const clearTimer = () => { clearInterval(allData.timer); allData.timer = null; }; // 查看报警详情弹窗 const bjDetails = ref(null); const checkDetail = async (item) => { allData.showWarnDetail = true; allData.warnDetailData = item; console.log('报警详情isWorkOrder---', item.isWorkOrder); allData.modalTitle = item.siteName + item.factorsName + '异常详情'; nextTick(() => { bjDetails.value.showModal = true; bjDetails.value.isWorkOrder = item.isWorkOrder; bjDetails.value.getHistoryData(); }); }; // 获取工单报警数据-跑马灯 async function getGdbjData() { let params = { current: 1, size: 100, }; let res = await lyInfoReminder(params); if (res && res.code == 1) { allData.listData = res.data.list; } } // 根据第三方值判断是否有孪生流域,临时添加 function getFooterList() { let urls = localStorage.getItem('HJH_IFRAME_SRC'); if (urls) { allData.navArr.push({ value: '4', label: '孪生流域' }); allData.otherIframeUrl = urls; } } // 视频地址发生变化时的处理 function changeVideoSource(src) { if (!src) return; allData.myPlayer = videojs('videoID', { preload: 'auto', // 预加载 controls: true, // 显示播放的控件 // fluid: true, // 自适应宽高 controlBar: { // 设置控制条组件 currentTimeDisplay: true, timeDivider: true, durationDisplay: true, remainingTimeDisplay: true, volumePanel: { inline: true, }, children: [ { name: 'playToggle', }, // 播放/暂停按钮 { name: 'currentTimeDisplay', }, // 视频当前已播放时间 { name: 'progressControl', }, // 播放进度条 { name: 'durationDisplay', }, // 视频播放总时间 { // 倍速播放 name: 'playbackRateMenuButton', playbackRates: [0.5, 1, 1.5, 2], }, { name: 'volumePanel', // 音量控制 inline: false, // 不使用水平方式 }, { name: 'FullscreenToggle', }, // 全屏 ], }, }); allData.myPlayer.src([ { type: 'application/x-mpegURL', src: src, }, ]); allData.myPlayer.play(); } // 加载基本信息数据 const getvideo = async () => { let params = { indexCode: allData.indexCode, protocolType: 'hls', streamType: 1, transmode: 1, expand: 'streamform=rtp&transcode=1&videotype=h264', }; let res = await getCamreaStream(params); if (res.code == 200) { allData.videoSrc = res.data.url; setTimeout(() => { bfvideo(); }, 1000); } }; const getvideo1 = async () => { let params = { indexCode: allData.indexCode1, protocolType: 'hls', streamType: 1, transmode: 1, expand: 'streamform=rtp&transcode=1&videotype=h264', }; let res = await getCamreaStream(params); if (res.code == 200) { allData.videoSrc1 = res.data.url; setTimeout(() => { bfvideo1(); }, 1000); } }; const bfvideo = () => { var video = document.getElementById('video'); if (Hls.isSupported()) { hls = new Hls(); hls.loadSource(allData.videoSrc); hls.attachMedia(video); hls.on(Hls.Events.MEDIA_ATTACHED, function () { video.muted = true; video.play(); }); } else if (video.canPlayType('application/vnd.apple.mpegurl')) { video.src = allData.videoSrc; video.addEventListener('canplay', function () { video.play(); }); } }; const bfvideo1 = () => { var video1 = document.getElementById('video1'); if (Hls.isSupported()) { hls1 = new Hls(); hls1.loadSource(allData.videoSrc1); hls1.attachMedia(video1); hls1.on(Hls.Events.MEDIA_ATTACHED, function () { video1.muted = true; video1.play(); }); } else if (video1.canPlayType('application/vnd.apple.mpegurl')) { video1.src = allData.videoSrc1; video1.addEventListener('canplay', function () { video1.play(); }); } }; const handleModalChange = () => { allData.modalShowGy = false; if (hls) { hls.destroy(); } if (hls1) { hls1.destroy(); } }; onMounted(() => { // getFooterList(); // 设置视频监控默认显示的code localStorage.setItem('defaultVideoCode', 'edaea623e40f45df8b1f3676aa283a79'); bus.on('showModalBZ', (e) => { allData.showModalBZ = true; allData.valueModalbz = e; allData.BZtitle = e.name + '详情'; }); bus.on('datelist', (e) => { allData.datearry = e; }); // 控制播放雨量图例显示 bus.on('ifQixiang', (e) => { if (e) { allData.ifQixiang = true; } else { allData.ifQixiang = false; } }); // 水质监测、临测水位流量报警信息显示 bus.on('ifStationWarn', (e) => { if (e) { allData.ifStationWarn = true; getGdbjData(); } else { allData.ifStationWarn = false; } }); // 工艺图弹窗展示 bus.on('getGongYt', (e) => { allData.videoname = e.name; if (e.name.includes('王家墩污水泵站') || e.name.includes('铁路桥地下') || e.name.includes('后湖泵站二期')) { if (allData.videoname.includes('王家墩污水泵站')) { allData.indexCode = '849d44eba4bb4291a46f263598e262df'; allData.indexCode1 = '363f0fdc8cd24bf1bac93181bfae5bb8'; } if (allData.videoname.includes('铁路桥地下')) { allData.indexCode = 'c4e4e19fb6e9466593d5fcaeb4cbeb62'; allData.indexCode1 = 'dd0b888f8cb8496ba7445ad20465de31'; } if (allData.videoname.includes('后湖泵站二期')) { allData.indexCode = '93c181ea91364627b55b77004a3aeeff'; allData.indexCode1 = 'c5fcac362040422e9fca7d390dd935fe'; } setTimeout(() => { getvideo(); getvideo1(); }, 100); allData.gymodel = false; } allData.iframeUrl = e.url; //工艺图链接 allData.videoUrlLists = e.videoCodes || []; //摄像头url数组 if (allData.videoUrlLists.length > 0) { allData.videoUrlLists.map((item) => { changeVideoSource(item); //播放视频 }); } allData.modalShowGy = true; }); }); onBeforeUnmount(() => { if (hls) { hls.destroy(); } if (hls1) { hls1.destroy(); } clearTimer(); bus.off('getGongYt'); bus.off('ifQixiang'); bus.off('ifStationWarn'); bus.off('datelist'); bus.off('showModalBZ'); if (allData.myPlayer) allData.myPlayer.dispose(); //视频销毁 }); return { ...toRefs(allData), changeNav, goPlay, searchWeather, changeSpeed, boxMap, clearTimer, checkDetail, getGdbjData, bjDetails, bfvideo, bfvideo1, handleModalChange, }; }, }; </script> <style lang="less"> .dialogGYT { display: flex; .imgs { width: 90%; } .videoGyt { width: 300px; height: 300px; margin-left: 30px; #video { width: 300px; height: 300px; } #video1 { width: 300px; height: 300px; } } .my-video { width: 100%; height: 245px; margin-bottom: 10px; } iframe { margin-left: 5px; border: 1px solid rgba(0, 0, 0, 0.3); } } .oneMapModalPage { width: 100%; height: 100%; position: relative; overflow: hidden; .Pipelineflow { position: absolute; left: 100px; bottom: 10px; z-index: 999; cursor: pointer; color: #fff; background: #15caf7; } .lyInfoWarn { position: absolute; top: 30px; left: 30%; z-index: 10; width: 682px; height: 49px; background: url('@/assets/newImgs/warnBg.png') no-repeat center; .scroll { width: 100%; height: 49px; overflow: hidden; padding: 0px 30px; .item { height: 49px; line-height: 49px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 16px; color: #f9feff; cursor: pointer; } } } .cloudPic { width: 100%; height: 70px; position: absolute; left: 20px; top: 10px; display: flex; align-items: center; .color { width: 324px; height: 70px; background: url('@/assets/newImgs/color.png') no-repeat center; } .progress { width: 850px; display: flex; align-items: center; margin-top: 20px; .n-progress.n-progress--line { flex: 1; } .n-base-selection-label, .n-input { background: #071322; } .currentTime { border: 1px solid #63e2b7; border-radius: 6px; color: #01cac0; width: 110px; height: 30px; line-height: 30px; text-align: center; margin-left: 10px; } .time { background: #071322; color: #fff; padding: 4px 6px; font-size: 14px; border-radius: 20px; margin: 0 10px; } .cast { width: 32px; height: 22px; cursor: pointer; margin-right: 10px; } .end { background: url('@/assets/newImgs/timeEnd.png'); background-size: 100% 100%; } .start { background: url('@/assets/newImgs/timeStart.png'); background-size: 100% 100%; } } .leida { border: 1px solid #14ccca; border-radius: 10px; opacity: 0.8; margin-left: 20px; } } .mainFooter { height: 67px; width: 100%; position: absolute; bottom: 0; left: 0; z-index: 9999; background: url('@/assets/newImgs/navBg.png') no-repeat center; background-size: 100% 100%; .tabsNav { margin-top: 20px; margin-left: 40%; .n-tabs-wrapper { .n-tabs-tab-wrapper { margin-right: 50px; } .n-tabs-tab { font-size: 16px; opacity: 0.3; } .n-tabs-tab:hover { color: #fff; opacity: 0.8; } .n-tabs-tab--active { color: #fff !important; opacity: 1; } } .n-tabs-bar { background: url('@/assets/newImgs/navSelected.png') no-repeat center !important; height: 16px; margin-right: 50px; } } } .otherFrame { width: 100%; height: 100%; position: absolute; bottom: 0; left: 0; z-index: 9990; background: #071322; iframe { width: 100%; height: 100%; } } } .mapboxgl-ctrl.mapboxgl-ctrl-scale { height: 10px; background-color: transparent; line-height: 10%; text-align: center; color: aliceblue; font-size: 15px; border-color: white white white; position: absolute; left: 10px; bottom: 5px; } </style>