From 7f6661cca40e3530111d628222fa25462022ec78 Mon Sep 17 00:00:00 2001 From: riku <risaku@163.com> Date: 星期四, 04 九月 2025 18:25:36 +0800 Subject: [PATCH] 2025.9.4 --- src/views/sourcetrace/SourceTrace.vue | 490 +++++++++++++++++++++++++++++++++++------------------ 1 files changed, 321 insertions(+), 169 deletions(-) diff --git a/src/views/sourcetrace/SourceTrace.vue b/src/views/sourcetrace/SourceTrace.vue index d4c97a6..73dcd07 100644 --- a/src/views/sourcetrace/SourceTrace.vue +++ b/src/views/sourcetrace/SourceTrace.vue @@ -1,34 +1,65 @@ <template> - <el-row> + <el-row + :style=" + direction == 'left' + ? 'flex-direction: row;' + : 'flex-direction: row-reverse' + " + > <el-col span="2" class="flex-col"> - <el-row justify="end"> + <el-row :justify="direction == 'left' ? 'end' : 'start'"> <CardButton - direction="left" + :direction="direction" name="鍔ㄦ�佹函婧�" - @click="() => (show = !show)" + @click="handleDisplayChange" ></CardButton> </el-row> <el-row class="flex-col"> + <PollutedWarnItem + :item="selectedWarning" + @showMarksAndPolygon="showMarksAndPolygon" + ></PollutedWarnItem> <PollutedExceptionItem :item="selectedException" @showMarksAndPolygon="showMarksAndPolygon" ></PollutedExceptionItem> + <PollutedClueItem + v-model="clueDialog" + :item="selectedClue" + ></PollutedClueItem> </el-row> </el-col> <el-col v-show="show" span="10"> <BaseCard> <template #content> - <el-checkbox-group v-model="selectedMsgTypes" size="default" :min="1"> - <el-space> - <el-checkbox value="1">寮傚父鍒囩墖</el-checkbox> - <el-checkbox value="2">姹℃煋绾跨储</el-checkbox> - </el-space> - </el-checkbox-group> - <el-scrollbar ref="scrollbarRef" class="scrollbar"> - <!-- <div - ref="scrollContentRef" - style="display: flex; width: fit-content" - > --> + <el-row + justify="space-between" + align="middle" + style="border-bottom: 1px solid white" + > + <!-- 鏁版嵁鍒囩墖绛涢�夋潯浠� --> + <SourceTraceFilter + v-model:data-slice="selectedMsgTypes" + v-model:factor-type="selectedFactorTypes" + v-model:scene-type="selectedSceneTypes" + :factor-options="factorOptions" + :scene-options="sceneOptions" + ></SourceTraceFilter> + <!-- <el-divider direction="vertical"></el-divider> --> + <!-- 鏁版嵁鍒囩墖缁熻 --> + <div style="border-left: 1px solid white" class="p-l-8"> + <el-space direction="vertical"> + <el-text type="info">婧簮锛歿{ countMsg1.type1 }}鏉�</el-text> + <el-text type="info">绾跨储锛歿{ countMsg1.type2 }}鏉�</el-text> + <el-text type="info">鎻愰啋锛歿{ countMsg1.type3 }}鏉�</el-text> + </el-space> + </div> + </el-row> + <el-scrollbar + ref="scrollbarRef" + class="scrollbar" + v-loading="loading" + > <TransitionGroup name="list"> <div v-for="item in filterStreams" @@ -40,15 +71,29 @@ ></ClueRecordItem> </div> </TransitionGroup> - <!-- </div> --> </el-scrollbar> </template> </BaseCard> </el-col> - <PollutedClueItem - v-model="clueDialog" - :item="selectedClue" - ></PollutedClueItem> + <!-- <el-col v-if="direction == 'left'" span="2" class="flex-col"> + <el-row justify="start"> + <CardButton + direction="right" + name="鍔ㄦ�佹函婧�" + @click="handleDisplayChange" + ></CardButton> + </el-row> + <el-row class="flex-col"> + <PollutedExceptionItem + :item="selectedException" + @showMarksAndPolygon="showMarksAndPolygon" + ></PollutedExceptionItem> + <PollutedClueItem + v-model="clueDialog" + :item="selectedClue" + ></PollutedClueItem> + </el-row> + </el-col> --> </el-row> </template> <script setup> @@ -60,6 +105,7 @@ import moment from 'moment'; import websocket from '@/api/websocket'; +import dataAnalysisApi from '@/api/dataAnalysisApi'; import sector from '@/utils/map/sector'; import mapUtil from '@/utils/map/util'; import { sceneTypes, sceneIcon } from '@/constant/scene-types'; @@ -72,24 +118,58 @@ import PollutedExceptionItem from './component/PollutedExceptionItem.vue'; import ClueRecordItem from './component/ClueRecordItem.vue'; import PollutedClueItem from '@/views/sourcetrace/component/PollutedClueItem.vue'; +import SourceTraceFilter from '@/views/sourcetrace/component/SourceTraceFilter.vue'; +import PollutedWarnItem from './component/PollutedWarnItem.vue'; + +const NO_SCENE = 'no_scene'; + +const MODE_REALTIME = 'realtime'; +const MODE_HISTORY = 'history'; const props = defineProps({ - factorType: String + direction: { + type: String, + default: 'right' + }, + factorType: String, + // 妯″紡锛宺ealtime锛氬疄鏃舵ā寮忥紱history锛氬巻鍙叉暟鎹ā寮� + mode: { + type: String, + default: 'realtime' + }, + missionCode: String, + deviceCode: String }); const emits = defineEmits(['update:factorType']); -const height = `30vh`; -const width = `60vh`; - const show = ref(false); -const clueDialog = ref(false); const scrollContentRef = ref(); const scrollbarRef = ref(); +const selectedWarning = ref(); const selectedException = ref(); const selectedClue = ref(); -const selectedMsgTypes = ref(['1', '2']); +const clueDialog = ref(false); + +const selectedMsgTypes = ref(['1', '2', '3']); +const selectedFactorTypes = ref([]); +const factorOptions = ref([]); +const selectedSceneTypes = ref([]); +const sceneOptions = ref([]); + +const loading = ref(false); + +function handleDisplayChange() { + show.value = !show.value; + if ( + !show.value && + selectedException.value && + selectedException.value.showMore + ) { + showMarksAndPolygon(selectedException.value); + } +} function scrollToBottom() { const h1 = scrollContentRef.value.clientHeight + 100; @@ -104,11 +184,67 @@ }, 100); } -const streams = reactive([]); +const streams = ref([]); const filterStreams = computed(() => { - return streams.filter((v) => { - return selectedMsgTypes.value.indexOf(v._type) != -1; + return streams.value.filter((v) => { + // 鍒ゆ柇娑堟伅绫诲瀷鏄惁閫変腑 + const b1 = selectedMsgTypes.value.indexOf(v._type) != -1; + let b2, b3; + switch (v._type) { + case '1': + case '3': + // 鍒ゆ柇鐩戞祴鍥犲瓙绫诲瀷鏄惁閫変腑 + for (const key in v.pollutedData.statisticMap) { + const value = v.pollutedData.statisticMap[key]; + b2 = b2 || selectedFactorTypes.value.indexOf(value.factorId) != -1; + } + + // 鍒ゆ柇鍦烘櫙绫诲瀷鏄惁閫変腑 + if ( + v.pollutedSource == undefined || + v.pollutedSource.sceneList.length == 0 + ) { + b3 = selectedSceneTypes.value.indexOf(NO_SCENE) != -1; + } else { + b3 = + v.pollutedSource.sceneList.findIndex( + (v) => selectedSceneTypes.value.indexOf(v.typeId) != -1 + ) != -1; + } + break; + case '2': + b2 = true; + b3 = + v.sortedSceneList.findIndex( + (v) => selectedSceneTypes.value.indexOf(v.first.typeId) != -1 + ) != -1; + break; + } + + return b1 && b2 && b3; }); +}); +// 缁熻鍚勭被鍨嬫秷鎭殑鏁伴噺 +const countMsg1 = computed(() => { + const count = { + type1: 0, + type2: 0, + type3: 0 + }; + streams.value.forEach((v) => { + switch (v._type) { + case '1': + count.type1++; + break; + case '2': + count.type2++; + break; + case '3': + count.type3++; + break; + } + }); + return count; }); const inputVal = ref(''); @@ -116,27 +252,21 @@ websocket.send(inputVal.value); }; -let showFirstClueTask; function dealMsg(data) { const { type, content } = websocketMsgParser.parseMsg(data); - - // 姹℃煋绾跨储 PollutedClue - if (type == '1') { - const obj = reactive(JSON.parse(content)); + const obj = reactive(JSON.parse(content)); + if (obj.deviceCode == props.deviceCode) { obj._type = type; - // obj.showMore = true; + dealObj(obj); + } +} + +function dealObj(obj) { + // 姹℃煋绾跨储 PollutedClue + if (obj._type == '1') { obj.showMore = false; console.log('姹℃煋寮傚父鍒囩墖: ', obj); - // if (streams.length == 0) { - // streams.push(obj); - // } else { - // // streams.forEach((s) => { - // // showMarksAndPolygon(s); - // // }); - // // hideAll(); - // streams.unshift(obj); - // } addNewMsg(obj); show.value = true; @@ -144,20 +274,67 @@ // scrollToTop(); // drawPolygon(obj.pollutedArea); parseChartData(obj); - - // if (showFirstClueTask) { - // clearTimeout(showFirstClueTask); - // } - // showFirstClueTask = setTimeout(() => { - // showMarksAndPolygon(obj); - // }, 1000); - } else if (type == '2') { - const obj = JSON.parse(content); - obj._type = type; + } else if (obj._type == '2') { + // const obj = JSON.parse(content); + // obj._type = type; console.log('姹℃煋绾跨储缁撴灉: ', obj); obj._timestr = timeFormatter(obj.time); - // streams.unshift(obj); addNewMsg(obj); + } else if (obj._type == '3') { + console.log('姹℃煋鎻愰啋鍒囩墖: ', obj); + addNewMsg(obj); + parseChartData(obj); + } + + optionsFilte(obj); +} + +// 瀵规暟鎹繘琛岀瓫閫夛紝鍖呮嫭鐩戞祴鍥犲瓙鍜屽満鏅被鍨� +function optionsFilte(objData) { + switch (objData._type) { + case '1': + case '3': + // 绛涢�夌洃娴嬪洜瀛愮被鍨� + for (const key in objData.pollutedData.statisticMap) { + const value = objData.pollutedData.statisticMap[key]; + if ( + factorOptions.value.findIndex((v) => v.value == value.factorId) == -1 + ) { + factorOptions.value.push({ + label: value.factorName, + value: value.factorId + }); + selectedFactorTypes.value.push(value.factorId); + } + } + + // 绛涢�夊満鏅被鍨� + if (objData.pollutedSource != undefined) { + if (objData.pollutedSource.sceneList.length == 0) { + // 鑻ユ病鏈夋壘鍒伴闄╂簮鏃讹紝灏嗚鍒嗙被璁惧畾涓簄ull + if (sceneOptions.value.findIndex((v) => v.value == NO_SCENE) == -1) { + sceneOptions.value.push({ + label: '鏈煡', + value: NO_SCENE + }); + selectedSceneTypes.value.push(NO_SCENE); + } + } else { + objData.pollutedSource.sceneList.forEach((s) => { + if ( + sceneOptions.value.findIndex((v) => v.value == s.typeId) == -1 + ) { + sceneOptions.value.push({ + label: s.type, + value: s.typeId + }); + selectedSceneTypes.value.push(s.typeId); + } + }); + } + } + // case '2': + // break; } } @@ -166,7 +343,7 @@ const leftMsgList = []; function addNewMsg(msg, inside) { if (!addNewMsgTask && (leftMsgList.length == 0 || inside)) { - streams.splice(0, 0, msg); + streams.value.splice(0, 0, msg); addNewMsgTask = setTimeout(() => { clearTimeout(addNewMsgTask); addNewMsgTask = undefined; @@ -180,8 +357,40 @@ } } +function fetchPollutionTraceHistory() { + loading.value = true; + dataAnalysisApi + .fetchPollutionTraceHistory(props.missionCode) + .then((res) => { + factorOptions.value = []; + selectedFactorTypes.value = []; + sceneOptions.value = []; + selectedSceneTypes.value = []; + const objList = JSON.parse(res.data); + objList.forEach((obj) => { + obj._type = obj.msgType + ''; + if (obj._type == '1') { + obj.showMore = false; + show.value = true; + parseChartData(obj); + } else if (obj._type == '2') { + obj._timestr = timeFormatter(obj.time); + } else if (obj._type == '3') { + parseChartData(obj); + } + optionsFilte(obj); + }); + streams.value = objList; + }) + .finally(() => (loading.value = false)); +} + onMounted(() => { - websocket.registerReceiveEvent(dealMsg); + if (props.mode == MODE_REALTIME) { + websocket.registerReceiveEvent(dealMsg); + } else if (props.missionCode) { + fetchPollutionTraceHistory(); + } }); onUnmounted(() => { websocket.removeReceiveEvent(dealMsg); @@ -199,28 +408,50 @@ } }); +watch( + () => props.missionCode, + (nV, oV) => { + if (nV != oV) { + fetchPollutionTraceHistory(); + } + } +); + function handleOpen(item) { + // 鍘婚櫎涓婁竴涓�滄函婧愨�濆拰鈥滄彁閱掆�濇秷鎭殑閫変腑鏍囧織 + if (selectedWarning.value && selectedWarning.value._selected) { + selectedWarning.value._selected = false; + showMarksAndPolygon(selectedWarning.value); + } + if (selectedException.value && selectedException.value._selected) { + selectedException.value._selected = false; + showMarksAndPolygon(selectedException.value); + } + if (selectedClue.value && selectedClue.value._selected) { + selectedClue.value._selected = false; + clueDialog.value = false; + } switch (item._type) { case '1': - if (selectedException.value) { - selectedException.value._selected = false; - } + // 鏄剧ず褰撳墠閫変腑鐨勭浉鍏冲湴鍥炬爣璁� showMarksAndPolygon(item); + // 鏇存柊閫変腑鐨勫璞� selectedException.value = item; break; case '2': - if (selectedClue.value) { - selectedClue.value._selected = false; - } selectedClue.value = item; clueDialog.value = true; + break; + case '3': + showMarksAndPolygon(item); + selectedWarning.value = item; break; } item._selected = true; } function hideAll() { - streams.forEach((s) => { + streams.value.forEach((s) => { if (polygonMap.has(s.guid)) { s.showMore = false; map.remove(polygonMap.get(s.guid)); @@ -237,7 +468,7 @@ } else { if (polygonMap.has(item.guid)) { map.remove(polygonMap.get(item.guid)); - selectedException.value._selected = false; + item._selected = false; } } } @@ -269,116 +500,37 @@ function parseChartData(obj) { // console.log('鎶樼嚎鍥撅細start'); + obj.pollutedData._startTime = moment(obj.pollutedData.startTime).format( + 'HH:mm:ss' + ); + obj.pollutedData._endTime = moment(obj.pollutedData.endTime).format( + 'HH:mm:ss' + ); const factorDatas = new FactorDatas(); factorDatas.setData(obj.pollutedData.historyDataList, 0, () => { - obj._chartOptions = factorDataParser.parseData(factorDatas, [ - { - label: obj.pollutedData.factorName, - name: obj.pollutedData.factorName, - value: obj.pollutedData.factorId + '' - } - ]); + for (const key in obj.pollutedData.statisticMap) { + const value = obj.pollutedData.statisticMap[key]; + value._chartOptions = factorDataParser.parseData(factorDatas, [ + { + label: value.factorName, + name: value.factorName, + value: value.factorId + '' + } + ]); + } + // obj._chartOptions = factorDataParser.parseData(factorDatas, [ + // { + // label: obj.pollutedData.factorName, + // name: obj.pollutedData.factorName, + // value: obj.pollutedData.factorId + '' + // } + // ]); // console.log('鎶樼嚎鍥撅細', obj._chartOptions); }); } function timeFormatter(time) { return moment(time).format('YYYY-MM-DD HH:mm:ss'); -} - -/******************************************************************************************************************** */ - -/** - * 娣诲姞涓�鏉″伐浣滄祦淇℃伅 - * @param {*} data - */ -const putWorkStream = (data) => { - data.substring(); - const obj = JSON.parse(data); - console.log('sourcetrace: ', obj); - - obj._statusStr = exceptionStatus(obj.status); - - if (streams.length == 0) { - streams.push(obj); - } else { - const index = streams.findIndex((v) => { - return v.guid == obj.guid; - }); - if (index != -1) { - const old = streams[index]; - obj.showMore = old.showMore; - old.relatedSceneList.forEach((s) => { - const index = obj.relatedSceneList.findIndex((v) => { - return v.guid == s.guid; - }); - if (index == -1) { - obj.relatedSceneList.push(s); - } - }); - streams.splice(index, 1, obj); - } else { - streams.unshift(obj); - } - - show.value = true; - } - - // scrollToBottom(); - scrollToTop(); - - const excObj = streams.find((v) => { - return v.factorId + '' == props.factorType; - }); - if (excObj) { - drawSector(excObj); - } -}; - -function exceptionStatus(value) { - switch (value) { - case 1: - return '寮傚父鍙戠敓涓�'; - case 2: - return '寮傚父宸茬粨鏉�'; - default: - return '寮傚父宸茬粨鏉�'; - } -} - -let lastDrawObjGuid; -function drawSector(exceptionObj) { - emits('update:factorType', exceptionObj.factorId + ''); - setTimeout(() => { - if (exceptionObj.guid != lastDrawObjGuid) { - sector.clearSectorPt(); - lastDrawObjGuid = exceptionObj.guid; - } - // 1. 缁樺埗鏂版墖褰㈠尯鍩� - const datavo = exceptionObj.midData; - const factorDatas = new FactorDatas(); - factorDatas.setData([datavo], 0, () => { - const pr = sector.drawSectorPt(factorDatas, 0); - // 璋冩暣瑙嗚灞呬腑鏄剧ず - // mapUtil.setCenter(pr.p); - drawMarks(exceptionObj.relatedSceneList); - }); - }, 1000); -} - -let layer = undefined; -function drawMarks(sceneList) { - if (layer != undefined) { - mapUtil.removeViews(layer); - // layer = undefined; - } - if (sceneList.length != 0) { - const icons = []; - sceneList.forEach((s) => { - icons.push(sceneIcon(s.typeId)); - }); - layer = marks.createLabelMarks(icons, sceneList, true); - } } </script> <style scoped> @@ -387,7 +539,7 @@ --el-statistic-content-color: white; } -:deep(.el-text.el-text--primary) { +:deep(.el-text.el-text--info) { --el-text-color: white; } @@ -413,7 +565,7 @@ .scrollbar { width: 400px; /* max-width: 60vw; */ - height: 45vh; + height: 65vh; /* color: #02ffea; */ padding-right: 10px; } -- Gitblit v1.9.3