<template> <!-- 长效考核-内涝防治 --> <div class="longAssesPage"> <el-tabs v-model="tabActive" @tab-click="changeTab" class="tabsContent"> <el-tab-pane label="模型法" name="model"></el-tab-pane> <el-tab-pane label="监测法" name="monitor"></el-tab-pane> </el-tabs> <!-- gis地图 --> <MapBox :initJson="`/static/libs/mapbox/style/preventionSFQ.json`" l7=""></MapBox> <!-- 模型法 --> <div v-if="tabActive == 'model'"> <div class="tuli"> <div style="margin: 10px; font-size: 18px">图例</div> <div class="tuli_img"> <img src="/2.jpg" alt="" /> <div>内涝区域</div> </div> </div> <div class="content" style="width: 800px"> <el-table ref="tableModal" :data="tableData" max-height="500" v-loading="tableLoading" @row-click="clickModal" highlight-current-row > <el-table-column label="考核年度" prop="year" /> <el-table-column label="降雨重现期" prop="targetCxq" /> <el-table-column label="设计雨量(mm)" prop="rainfall" /> <el-table-column label="最大内涝面积(㎡)" prop="totalFloodArea" /> <el-table-column label="占建成区比例(%)" prop="floodPercent" /> </el-table> </div> </div> <!-- 监测法 --> <div v-if="tabActive == 'monitor'"> <div class="tuli"> <div style="margin: 10px; font-size: 18px">图例</div> <div class="tuli_img"> <img src="/1.1.jpg" alt="" /> <div>内涝点</div> </div> </div> <div class="content"> <div class="selectTitle"> <div class="name">监测法测算结果</div> <el-select v-model="currentYear" @change="changeMonitorYear" style="width: 100px" size="small"> <el-option v-for="item in yearList" :key="item.value" :label="item.label" :value="item.value"></el-option> </el-select> </div> <PieChart :echartData="echartData" :title="`建成区面积\n${areaData}k㎡`" :refresh="refresh" class="chartHeight"></PieChart> <div class="selectTitle"> <div class="name">内涝点监测感知情况</div> </div> <el-table :data="tableDataNL" height="450" v-loading="tableLoadingNL"> <el-table-column label="内涝点名称" prop="name" /> <el-table-column label="积水时长(h)" prop="yearTotalHour" /> <el-table-column label="积水深度(m)" prop="yearMaxDepth" /> </el-table> </div> </div> <div class="PopupWaterlogging" id="PopupWaterlogging" v-if="pipePopupShow"> <div class="titleTop"> <el-tabs class="PopupWaterloggingtabs"> <el-tab-pane label="降雨过程线"> <div class="allContent"> <div>开始时间:{{ yearMaxStartTime }}</div> <div>结束时间:{{ yearMaxEndTime }}</div> <empty v-if="pipePopupdata" emptyText="暂无降雨数据" :width="100" :height="100" style="margin-top: 50px"></empty> <div id="chartPopupRain"></div> </div> </el-tab-pane> </el-tabs> </div> <div class="closePopup"> <el-icon :size="18" @click="closePopup"><Close /></el-icon> </div> </div> </div> </template> <script setup> import MapBox from '@/views/gisMapPage/gisMapBox1'; //gis地图 import PieChart from '@/components/Echarts/pieChart.vue'; //饼图 import bus from '@/bus'; import { moduleFloodResultLongTerm, monitorEvaluateResultLongTerm } from '@/api/longTerm/index'; import { getConfigKey } from '@/api/system/config'; //获取参数值 import { nextTick } from 'vue'; import { graphicReport } from '@/api/dataAnalysis/syntherticData'; import chartOption from '@/components/Echarts/pieChart_1.js'; import * as echarts from 'echarts'; const { proxy } = getCurrentInstance(); const currentYear = ref('2024'); const yearList = ref([]); const timer = ref(null); const tabActive = ref('model'); const tableModal = ref(null); const tableLoading = ref(false); const tableData = ref([]); const areaData = ref(''); const resultList = ref([]); const echartData = ref([ { name: '内涝区域', value: 0 }, { name: '未发生内涝', value: 0 }, ]); const refresh = ref(1); const tableDataNL = ref([]); const tableLoadingNL = ref(false); const dataListNL = ref([]); const pipePopupShow = ref(false); const pipePopupdata = ref(false); const waterEchart = shallowRef(null); const yearMaxStartTime = ref(''); const yearMaxEndTime = ref(''); const stCodes = ref(''); const selectData = ref([]); const selectCode = ref(''); const seleceName = ref(''); const unitName = ref(''); const propertyMonitorXList = ref([]); // 模型法数据获取 async function getModalData() { tableLoading.value = true; let res = await moduleFloodResultLongTerm(); if (res && res.code == 200) { tableData.value = res.data; if (Boolean(tableData.value.length)) { tableData.value.forEach(i => { i.targetCxq = i.targetCxq + '年一遇24h'; }); } tableLoading.value = false; tableModal.value.setCurrentRow(tableData.value[0], true); //表格默认第一个高亮选中 resultList.value = tableData.value[0].resultList; let moduleGeojson = getFeatureGeojson(tableData.value[0].partitionList); let moduleBoundaryGeojson = getGeojsonBoundary(moduleGeojson); let modulelabelGeojson = getGeojsonCenter(moduleGeojson); //gis渲染内涝区域 addModuleLayer(moduleGeojson, 'moduleFlood', '#95f204'); addModuleBoundary(moduleBoundaryGeojson, 'moduleFloodBoundary'); addGeojsonLable(modulelabelGeojson, 'moduleFloodlabel', '#ffffff'); } } // 模型法表格点击 function clickModal(row) { resultList.value = row.resultList; let moduleGeojson = getFeatureGeojson(row.partitionList); let moduleBoundaryGeojson = getGeojsonBoundary(moduleGeojson); let modulelabelGeojson = getGeojsonCenter(moduleGeojson); //gis渲染内涝区域 newfiberMapbox.map.getSource('moduleFlood').setData(moduleGeojson); newfiberMapbox.map.getSource('moduleFloodBoundary').setData(moduleBoundaryGeojson); newfiberMapbox.map.getSource('moduleFloodlabel').setData(modulelabelGeojson); } //获取geojson const getFeatureGeojson = dataList => { let features = []; dataList && dataList.forEach(data => { let feature = turf.feature(Terraformer.WKT.parse(data.geometry), data); features.push(feature); }); return { type: 'FeatureCollection', features: features, }; }; //获取geojson中心点 const getGeojsonCenter = geojson => { let features = []; geojson.features.forEach(element => { let center = turf.center(element.geometry); center.properties = element.properties; features.push(center); }); return { type: 'FeatureCollection', features: features, }; }; //获取geojson边界 const getGeojsonBoundary = geojson => { let features = []; geojson.features.forEach(element => { let line = turf.polygonToLine(element.geometry); features.push(line); }); return { type: 'FeatureCollection', features: features, }; }; //添加模型法地图 const addModuleLayer = (geojson, layerName, color) => { if (!!!geojson) return; !newfiberMapbox.map.getSource(layerName) && newfiberMapbox.map.addSource(layerName, { type: 'geojson', data: geojson }); !newfiberMapbox.map.getLayer(layerName) && newfiberMapbox.map.addLayer({ id: layerName, type: 'fill', source: layerName, paint: { 'fill-color': '#95f204', 'fill-opacity': 0.5, }, }); }; const addModuleBoundary = (geojson, layerName) => { !newfiberMapbox.map.getSource(layerName) && newfiberMapbox.map.addSource(layerName, { type: 'geojson', data: geojson }); !newfiberMapbox.map.getLayer(layerName) && newfiberMapbox.map.addLayer({ id: layerName, type: 'line', source: layerName, paint: { 'line-color': '#95f204', 'line-width': 3, }, }); }; const addGeojsonLable = (geojson, layerName, color) => { !newfiberMapbox.map.getSource(layerName) && newfiberMapbox.map.addSource(layerName, { type: 'geojson', data: geojson }); !newfiberMapbox.map.getLayer(layerName) && !newfiberMapbox.map.addLayer({ id: layerName, type: 'symbol', source: layerName, paint: { 'text-color': geojson.features[0]?.properties.color ? ['get', 'color'] : color, 'text-halo-color': 'rgba(0,0,0,1)', 'text-halo-width': 2, }, layout: { 'text-allow-overlap': true, 'text-field': ['get', 'partitionName'], 'text-font': ['KlokanTech Noto Sans Regular'], 'text-size': 16, 'text-line-height': 3, 'text-anchor': 'bottom', 'text-max-width': 50, 'text-offset': [0, -1], }, }); }; // tab切换 function changeTab(e) { tabActive.value = e.props.name; if (tabActive.value == 'model') { bus.emit('removeMapDatas', ['error_zishui']); newfiberMapbox.popupService.popups.forEach(popup => { nextTick(() => { newfiberMapbox.removePopup(popup); }); }); getModalData(); } else { getMonitorData(); if (newfiberMapbox.map.getLayer('moduleFlood')) { newfiberMapbox.map.removeLayer('moduleFlood'); newfiberMapbox.map.removeLayer('moduleFloodBoundary'); newfiberMapbox.map.removeLayer('moduleFloodlabel'); newfiberMapbox.map.removeSource('moduleFlood'); newfiberMapbox.map.removeSource('moduleFloodBoundary'); newfiberMapbox.map.removeSource('moduleFloodlabel'); } } } // 获取监测法数据 async function getMonitorData() { tableLoadingNL.value = true; let res = await monitorEvaluateResultLongTerm(); if (res && res.code == 200) { yearList.value = []; let datas = res.data; dataListNL.value = datas || []; if (datas.length == 0) return; datas.map(item => { yearList.value.push({ value: item.year, label: item.year + '年', }); }); currentYear.value = dataListNL.value[0].year; changeMonitorYear(dataListNL.value[0].year); } tableLoadingNL.value = false; } // 监测法年份切换 function changeMonitorYear(val) { currentYear.value = val; let rows = dataListNL.value.filter(item => item.year == val); if (rows.length == 0) return; tableDataNL.value = rows[0].allWaterLoggingPointList; echartData.value[0].value = rows[0].floodArea; //内涝 echartData.value[1].value = areaData.value - rows[0].floodArea; //内涝未发生 refresh.value = Math.random(); //gis渲染内涝点 intiMapDataPoint(); } // 地图渲染点位 function intiMapDataPoint() { newfiberMapbox.popupService.popups.forEach((popup, index) => { nextTick(() => { newfiberMapbox.removePopup(popup); }); }); let geojson1 = turf.featureCollection( tableDataNL.value.map(item => turf.point([item.longitude, item.latitude], { ...item, waterlogName: `${item.name}`, waterlogTime: `${item.yearTotalHour} h`, waterlogDepth: `${item.yearMaxDepth} m`, color: item.isFlood == '1' ? '#d9001b' : item.isFlood == '0' ? '#95f204' : '', }) ) ); let key = 'error_zishui'; // bus.emit('getGeojsonByType', { // type: 'error_zishui', // callback: geojson => { // setTimeout(() => { // bus.emit('removeMapDatas', ['error_zishui']); // if (!!!geojson.features.length) bus.emit('setGeoJSON', { json: geojson1, key }); // bus.emit('setLayerVisible', { layername: key, isCheck: true }); // }, 2000); // }, // }); addWaterloggingLayer(geojson1, 'waterLoging'); geojson1.features.forEach(feature => { let popupClass; feature.properties.isFlood == '0' ? (popupClass = 'successPopup') : (popupClass = 'errorPopup'); !!feature.properties.isFlood ? (feature.properties.isFlood = '0') : (feature.properties.isFlood = '1'); return newfiberMapbox.addPopup( new mapboxL7.Popup({ title: '', html: ` <div class=${popupClass}><div class='title'>${feature.properties.waterlogName}</div> <div class='part'>积水总时长:${feature.properties.waterlogTime || 0}</div> <div class='part'>最大积水深度:${feature.properties.waterlogDepth || 0}</div> <div class='part'>雨量站监测累计雨量:${feature.properties.yearMaxRain || 0}mm</div> </div>`, lngLat: { lng: feature.geometry.coordinates[0], lat: feature.geometry.coordinates[1], }, anchor: 'center', offsets: [10, 60], autoClose: false, }) ); }); } // 获取建成区面积 function getAreaData() { getConfigKey('jcq_area').then(res => { areaData.value = res.data || '0'; }); } //地图渲染内涝点 const addWaterloggingLayer = (geojson, layerName) => { !!!newfiberMapbox.map.getSource(layerName) && newfiberMapbox.map.addSource(layerName, { type: 'geojson', data: geojson }); !!!newfiberMapbox.map.getLayer(layerName) && newfiberMapbox.map.addLayer({ id: layerName, type: 'circle', source: layerName, paint: { 'circle-color': ['get', 'color'], 'circle-radius': 7, }, }); }; //获取监测数据 const getSuperViseData = async () => { let params = { startTime: yearMaxStartTime.value, endTime: yearMaxEndTime.value, stCode: stCodes.value, }; let res = await graphicReport(params); if (res && res.code == 200) { console.log(res.data, 99999999); let datas = res.data; pipePopupShow.value = true; if (datas.propertyMonitorXList.length == 0) { pipePopupdata.value = true; return; } if (Boolean(datas.propertyMonitorXList.length)) { propertyMonitorXList.value = []; datas.propertyMonitorXList.forEach(i => { propertyMonitorXList.value.push(i.substr(0, 16)); }); } unitName.value = datas.propertyMonitorList[0].propertyUnit; selectData.value = datas.propertyMonitorList[0].ylist; //降雨过程线 setTimeout(() => { initEchartsPopup(); }, 1000); } }; const closePopup = () => { pipePopupShow.value = false; }; // 降雨趋势折线图 let chartPopupRain = null; const initEchartsPopup = () => { if (!!chartPopupRain) chartPopupRain.dispose(); chartPopupRain = echarts.init(document.getElementById('chartPopupRain')); chartOption.popupRainTrend.legend.data = [seleceName.value]; chartOption.popupRainTrend.yAxis.name = unitName.value; chartOption.popupRainTrend.xAxis.data = propertyMonitorXList.value; chartOption.popupRainTrend.series.name = seleceName.value; chartOption.popupRainTrend.series.data = selectData.value; // 设置鼠标滚轮放大缩小展示数据区间 chartOption.popupRainTrend.dataZoom = [{ type: 'inside', startValue: propertyMonitorXList.value[propertyMonitorXList.value.length / 2] }]; if (propertyMonitorXList.value.length > 0) { chartOption.popupRainTrend.graphic.invisible = true; //暂无数据 } else { chartOption.popupRainTrend.graphic.invisible = false; //暂无数据 } chartPopupRain.clear(); chartPopupRain.setOption(chartOption.popupRainTrend); }; onMounted(() => { getAreaData(); getModalData(); setTimeout(() => { newfiberMapbox.map.on('click', e => { let clickfeature = newfiberMapbox.map .queryRenderedFeatures([ [e.point.x - 10 / 2, e.point.y - 10 / 2], [e.point.x + 10 / 2, e.point.y + 10 / 2], ]) .filter(i => i.layer.id == 'waterLoging'); if (clickfeature[0].properties.isFlood == '0') return; yearMaxStartTime.value = clickfeature[0].properties.yearMaxStartTime; yearMaxEndTime.value = clickfeature[0].properties.yearMaxEndTime; stCodes.value = clickfeature[0].properties.stCodes; getSuperViseData(); }); }, 5000); }); onBeforeUnmount(() => { if (!!!newfiberMapbox) return; !!newfiberMapbox.map.getLayer('waterLoging') && newfiberMapbox.map.removeLayer('waterLoging'); !!newfiberMapbox.map.getSource('waterLoging') && newfiberMapbox.map.removeSource('waterLoging'); newfiberMapbox.popupService.popups.forEach(popup => { nextTick(() => { newfiberMapbox.removePopup(popup); }); }); if (timer.value) { clearInterval(timer.value); } }); </script> <style lang="scss"> @import '@/assets/styles/variables.module.scss'; .longAssesPage { width: 100%; height: 95%; .content { width: 500px; background: $mainBg; border-radius: 8px; position: absolute; top: 20px; right: 20px; z-index: 90; padding: 15px; overflow: auto; .chartHeight { width: 100%; height: 240px !important; } } .tabsContent { position: absolute; z-index: 99; left: 30px; top: 20px; } .imgTL { position: absolute; z-index: 99; left: 30px; bottom: 20px; } .tuli { left: 20px; bottom: 40px; z-index: 111; position: absolute; padding: 10px; background: #00314e; display: flex; flex-direction: column; justify-content: space-between; align-items: center; color: #fff; div { flex: 1; } .tuli_img { display: flex; width: 120px; align-items: center; margin-top: 5px; img { margin-right: 10px; width: 25px; } } } } .l7-popup-tip { display: none; } .l7-popup .l7-popup-content { padding: 0px; background: #033b4f; } .l7-popup .l7-popup-content .l7-popup-close-button { display: none; } // .l7-popup .l7-popup-content .l7-popup-content__title { // align-items: center; // height: 22px; // font-size: 16px; // font-family: PingFang SC; // font-weight: 400; // color: #ccf1ff; // line-height: 22px; // } .errorPopup { border-radius: 8px; background-color: rgba(247, 189, 15, 0.5); border: 2px solid #f7bd0f; padding: 5px; // color: #000; } .successPopup { border-radius: 8px; background-color: rgba(129, 211, 248, 0.5); border: 2px solid #81d3f8; padding: 5px; } .title { font-size: 16px; } .contentInfo { display: flex; align-items: center; .contentName { margin: 3px; height: 20px; width: 70px; font-size: 14px; font-weight: 400; line-height: 20px; color: #00d1ff; } .contentValue { height: 20px; width: 100px; font-size: 14px; font-weight: 400; line-height: 20px; color: #00d1ff; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; } } #PopupWaterlogging { position: fixed; left: 52%; top: 30%; transform: translate(-50%, -50%); width: 500px; height: 310px; background: #021534; border: 1px solid #114f89; z-index: 2000; display: flex; .allContent { width: 425px; height: 300px; display: flex; flex-direction: column; } #chartPopupRain { width: 425px; height: 200px; } .titleTop { width: 95%; display: flex; padding-top: 8px; margin-left: 20px; } .closePopup { width: 5%; margin: 15px; cursor: pointer; } .PopupWaterloggingtabs { width: 100%; } } .errorPopup { border-radius: 8px; background-color: rgba(247, 189, 15, 0.5); border: 2px solid #f7bd0f; padding: 5px; // color: #000; } .successPopup { border-radius: 8px; background-color: rgba(129, 211, 248, 0.5); border: 2px solid #81d3f8; padding: 5px; } </style>