From 306ef09707d6bcf9ffa67de55f86ab6f4362deee Mon Sep 17 00:00:00 2001 From: riku <risaku@163.com> Date: 星期五, 18 七月 2025 10:04:01 +0800 Subject: [PATCH] 2025.7.18 动态溯源-测试版本 --- src/utils/chart/chart-option.js | 34 ++++++ src/views/sourcetrace/SourceTrace.vue | 100 ++++++++++++------- src/views/historymode/HistoryMode.vue | 10 + src/views/sourcetrace/component/PollutedWarnItem.vue | 41 +++++++ src/api/index.js | 24 ++-- src/views/sourcetrace/component/PollutedExceptionItem.vue | 36 +++++-- src/components.d.ts | 2 src/views/sourcetrace/component/ClueRecordItem.vue | 4 src/components/chart/RealTimeLineChart.vue | 10 + 9 files changed, 190 insertions(+), 71 deletions(-) diff --git a/src/api/index.js b/src/api/index.js index efcd5a1..fb3b440 100644 --- a/src/api/index.js +++ b/src/api/index.js @@ -2,7 +2,7 @@ import { ElMessage } from 'element-plus'; const openLog = false; -const debug = true; +const debug = false; let ip1 = 'http://47.100.191.150:9029/'; let ws = `47.100.191.150:9030`; @@ -30,13 +30,13 @@ i.interceptors.request.use( function (config) { // 鍦ㄥ彂閫佽姹備箣鍓嶅仛浜涗粈涔� - if (import.meta.env.DEV && openLog) { - console.log('==>璇锋眰寮�濮�'); - console.log(`${config.baseURL}${config.url}`); - if (config.data) { - console.log('==>璇锋眰鏁版嵁', config.data); - } - } + // if (import.meta.env.DEV && openLog) { + // console.log('==>璇锋眰寮�濮�'); + // console.log(`${config.baseURL}${config.url}`); + // if (config.data) { + // console.log('==>璇锋眰鏁版嵁', config.data); + // } + // } return config; }, function (error) { @@ -59,8 +59,12 @@ // 2xx 鑼冨洿鍐呯殑鐘舵�佺爜閮戒細瑙﹀彂璇ュ嚱鏁般�� // 瀵瑰搷搴旀暟鎹仛鐐逛粈涔� if (import.meta.env.DEV && openLog) { - console.log(response); - console.log('==>璇锋眰缁撴潫'); + console.log('|------------------------------------------'); + console.log('|--璇锋眰: ', `${response.request.responseURL}`); + if (response.config.data) { + console.log('|--鏁版嵁: ', response.config.data); + } + console.log('|--缁撴灉: ', response.data); } if (response.status == 200) { if ( diff --git a/src/components.d.ts b/src/components.d.ts index 80dc883..fa422c5 100644 --- a/src/components.d.ts +++ b/src/components.d.ts @@ -14,7 +14,6 @@ 'CardDialog copy': typeof import('./components/CardDialog copy.vue')['default'] CheckButton: typeof import('./components/common/CheckButton.vue')['default'] ConfigManage: typeof import('./components/map/ConfigManage.vue')['default'] - copy: typeof import('./components/CardDialog copy.vue')['default'] CoreHeader: typeof import('./components/core/CoreHeader.vue')['default'] CoreMenu: typeof import('./components/core/CoreMenu.vue')['default'] DataSummary: typeof import('./components/monitor/DataSummary.vue')['default'] @@ -39,6 +38,7 @@ ElFormItem: typeof import('element-plus/es')['ElFormItem'] ElIcon: typeof import('element-plus/es')['ElIcon'] ElInput: typeof import('element-plus/es')['ElInput'] + ElInputNumber: typeof import('element-plus/es')['ElInputNumber'] ElLink: typeof import('element-plus/es')['ElLink'] ElOption: typeof import('element-plus/es')['ElOption'] ElPagination: typeof import('element-plus/es')['ElPagination'] diff --git a/src/components/chart/RealTimeLineChart.vue b/src/components/chart/RealTimeLineChart.vue index cc72183..bd75435 100644 --- a/src/components/chart/RealTimeLineChart.vue +++ b/src/components/chart/RealTimeLineChart.vue @@ -9,7 +9,7 @@ </template> <script> import * as echarts from 'echarts'; -import { smallLineOption } from '@/utils/chart/chart-option'; +import { smallLineOption, baseVisualMap } from '@/utils/chart/chart-option'; export default { props: { @@ -31,7 +31,9 @@ yMinInterval: { type: Number, default: 1 - } + }, + // 寮傚父鏁版嵁绱㈠紩鑼冨洿闆嗗悎锛孾[i1,i2], [i3,i4],...] + exceptionIndexArr: Array }, data() { return { @@ -52,6 +54,10 @@ const { xAxis, series } = this.modelValue; if (!this.option) { this.option = smallLineOption(xAxis, series, this.yMinInterval); + if (this.exceptionIndexArr) { + const visualMap = baseVisualMap(this.exceptionIndexArr); + this.option.visualMap = visualMap; + } } else { this.option.xAxis[0].data = xAxis; this.option.series = series; diff --git a/src/utils/chart/chart-option.js b/src/utils/chart/chart-option.js index 99337d0..3395e29 100644 --- a/src/utils/chart/chart-option.js +++ b/src/utils/chart/chart-option.js @@ -14,6 +14,38 @@ return fontSize; } +function baseVisualMap(area) { + const _pieces = []; + area.forEach((v, i) => { + // if (i == 0) { + // _pieces.push({ + // lt: v[0], + // color: 'green' + // }); + // } + _pieces.push({ + gte: v[0], + lte: v[1], + color: 'red' + }); + }); + // const lastOne = area[area.length - 1]; + // _pieces.push({ + // gt: lastOne[1], + // color: 'green' + // }); + return { + type: 'piecewise', + // type: 'continuous', + show: false, + dimension: 0, + pieces: _pieces, + outOfRange: { + color: ['#5470c6'] + } + }; +} + // 鎶樼嚎鍥� function factorLineOption(_xAxis, _series) { var fontSize = fGetChartFontSize(); @@ -301,4 +333,4 @@ return option; } -export { factorLineOption, smallLineOption, gaugeOption }; +export { factorLineOption, smallLineOption, gaugeOption, baseVisualMap }; diff --git a/src/views/historymode/HistoryMode.vue b/src/views/historymode/HistoryMode.vue index 2865dec..452fc0d 100644 --- a/src/views/historymode/HistoryMode.vue +++ b/src/views/historymode/HistoryMode.vue @@ -126,7 +126,7 @@ factorType(nValue, oValue) { if (nValue != oValue && this.status == 0) { Layer.clear(); - this.draw(); + this.draw(true); // this.drawHighlightPollution(); } } @@ -169,13 +169,17 @@ done(); this.draw(); }, - draw() { + draw(notSetBound) { // 鍒锋柊鍥句緥 const factor = this.factorDatas.factor[this.factorType]; sector.clearSector(); // this.drawRoadLine(factor); this.drawRoadMap(factor); this.drawMassMarks(factor); + // 璋冩暣鍦板浘瑙嗚 + if (!notSetBound) { + mapUtil.setBound(this.factorDatas.lnglats_GD); + } }, // 缁樺埗3D璧拌璺嚎鍥� drawRoadMap(e) { @@ -190,8 +194,6 @@ marks.drawMassMarks(this.factorDatas, e, (index) => { this.handelIndexChange(index); }); - // 璋冩暣鍦板浘瑙嗚 - mapUtil.setBound(this.factorDatas.lnglats_GD); }, drawSector(index) { // 1. 缁樺埗鏂版墖褰㈠尯鍩� diff --git a/src/views/sourcetrace/SourceTrace.vue b/src/views/sourcetrace/SourceTrace.vue index 9cfbd0e..2ef9353 100644 --- a/src/views/sourcetrace/SourceTrace.vue +++ b/src/views/sourcetrace/SourceTrace.vue @@ -41,8 +41,8 @@ <SourceTraceFilter v-model:data-slice="selectedMsgTypes" v-model:factor-type="selectedFactorTypes" - :factor-options="factorOptions" v-model:scene-type="selectedSceneTypes" + :factor-options="factorOptions" :scene-options="sceneOptions" ></SourceTraceFilter> <!-- <el-divider direction="vertical"></el-divider> --> @@ -55,7 +55,11 @@ </el-space> </div> </el-row> - <el-scrollbar ref="scrollbarRef" class="scrollbar"> + <el-scrollbar + ref="scrollbarRef" + class="scrollbar" + v-loading="loading" + > <TransitionGroup name="list"> <div v-for="item in filterStreams" @@ -154,6 +158,8 @@ const selectedSceneTypes = ref([]); const sceneOptions = ref([]); +const loading = ref(false); + function handleDisplayChange() { show.value = !show.value; if ( @@ -188,7 +194,11 @@ case '1': case '3': // 鍒ゆ柇鐩戞祴鍥犲瓙绫诲瀷鏄惁閫変腑 - b2 = selectedFactorTypes.value.indexOf(v.pollutedData.factorId) != -1; + for (const key in v.pollutedData.statisticMap) { + const value = v.pollutedData.statisticMap[key]; + b2 = b2 || selectedFactorTypes.value.indexOf(value.factorId) != -1; + } + // 鍒ゆ柇鍦烘櫙绫诲瀷鏄惁閫変腑 if (v.pollutedSource.sceneList.length == 0) { b3 = selectedSceneTypes.value.indexOf(NO_SCENE) != -1; @@ -282,17 +292,19 @@ case '1': case '3': // 绛涢�夌洃娴嬪洜瀛愮被鍨� - if ( - factorOptions.value.findIndex( - (v) => v.value == objData.pollutedData.factorId - ) == -1 - ) { - factorOptions.value.push({ - label: objData.pollutedData.factorName, - value: objData.pollutedData.factorId - }); - selectedFactorTypes.value.push(objData.pollutedData.factorId); + 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.sceneList.length == 0) { // 鑻ユ病鏈夋壘鍒伴闄╂簮鏃讹紝灏嗚鍒嗙被璁惧畾涓簄ull @@ -339,23 +351,27 @@ } function fetchPollutionTraceHistory() { - dataAnalysisApi.fetchPollutionTraceHistory(props.missionCode).then((res) => { - 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; - }); + loading.value = true; + dataAnalysisApi + .fetchPollutionTraceHistory(props.missionCode) + .then((res) => { + 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(() => { @@ -481,13 +497,23 @@ ); 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); }); } diff --git a/src/views/sourcetrace/component/ClueRecordItem.vue b/src/views/sourcetrace/component/ClueRecordItem.vue index 25a1b59..ab8223c 100644 --- a/src/views/sourcetrace/component/ClueRecordItem.vue +++ b/src/views/sourcetrace/component/ClueRecordItem.vue @@ -108,7 +108,7 @@ </el-tag> <el-text type="info">{{ item.pollutedData.exception }}</el-text> </div> - <div v-if="item.pollutedSource.sceneList.length > 0"> + <!-- <div v-if="item.pollutedSource.sceneList.length > 0"> <div v-for="s in item.pollutedSource.sceneList" :key="s.guid"> <img style="width: 24px" :src="sceneIcon(s.typeId)" :alt="s.type" /> <el-text @@ -121,7 +121,7 @@ {{ s.name }} </el-text> </div> - </div> + </div> --> </el-col> </el-row> </div> diff --git a/src/views/sourcetrace/component/PollutedExceptionItem.vue b/src/views/sourcetrace/component/PollutedExceptionItem.vue index d269ccd..2482d6c 100644 --- a/src/views/sourcetrace/component/PollutedExceptionItem.vue +++ b/src/views/sourcetrace/component/PollutedExceptionItem.vue @@ -38,7 +38,10 @@ <div> <el-text type="info"> <el-icon><MapLocation /></el-icon> - {{ '椋庨櫓鍖哄煙锛�' + item.pollutedArea.address }} + {{ + '椋庨櫓鍖哄煙锛�' + + (item.pollutedArea.address ? item.pollutedArea.address : '') + }} </el-text> </div> <!-- <div> @@ -52,7 +55,7 @@ 寮傚父绫诲瀷锛歿{ item.pollutedData.exception }} </el-text> </div> - <div v-for="s in item.pollutedData.statisticMap" :key="s"> + <div v-for="s in item.pollutedData.statisticMap" :key="s.factorId"> <el-row style="border-top: 1px solid white"> <el-col :span="6"> <el-statistic title="绐佸彉鍥犲瓙" :value="s.factorName" /> @@ -77,10 +80,19 @@ <el-statistic title="骞冲潎椋庨��" :value="item.pollutedData.windSpeed" + :precision="1" suffix="m/s" /> </el-col> </el-row> + <RealTimeLineChart + v-for="(item1, index1) in s._chartOptions" + :key="index1" + :model-value="item1" + chart-height="80px" + :y-min-interval="20" + :exception-index-arr="exceptionIndexArr" + ></RealTimeLineChart> </div> <el-row justify="space-between"> <!-- <el-link @@ -97,13 +109,6 @@ </el-link> --> </el-row> <!-- <div style="width: 320px; height: 80px"> --> - <RealTimeLineChart - v-for="(item1, index1) in item._chartOptions" - :key="index1" - :model-value="item1" - chart-height="80px" - :y-min-interval="20" - ></RealTimeLineChart> <!-- </div> --> <div class="border-dashed"> <el-icon color="#ffbc58" size="20"><WarningFilled /></el-icon> @@ -122,13 +127,24 @@ </CardDialog> --> </template> <script setup> -import { ref } from 'vue'; +import { ref, computed } from 'vue'; const props = defineProps({ modelValue: Boolean, item: Object }); +const exceptionIndexArr = computed(() => { + const indexArr = []; + props.item.pollutedData.dataVoList.forEach((e) => { + const i = props.item.pollutedData.historyDataList.findIndex( + (v) => v.time == e.time + ); + indexArr.push([i - 1 < 0 ? 0 : i - 1, i]); + }); + return indexArr; +}); + const emits = defineEmits(['showMarksAndPolygon', 'update:modelValue']); function showMarksAndPolygon(item) { diff --git a/src/views/sourcetrace/component/PollutedWarnItem.vue b/src/views/sourcetrace/component/PollutedWarnItem.vue index d047320..90a8456 100644 --- a/src/views/sourcetrace/component/PollutedWarnItem.vue +++ b/src/views/sourcetrace/component/PollutedWarnItem.vue @@ -30,7 +30,10 @@ <div> <el-text type="info"> <el-icon><MapLocation /></el-icon> - {{ '鎵�鍦ㄥ尯鍩燂細' + item.pollutedArea.address }} + {{ + '鎵�鍦ㄥ尯鍩燂細' + + (item.pollutedArea.address ? item.pollutedArea.address : '') + }} </el-text> </div> <!-- <div> @@ -45,11 +48,23 @@ </el-text> </div> <el-row style="border-top: 1px solid white"> </el-row> - <RealTimeLineChart + <div v-for="s in item.pollutedData.statisticMap" :key="s.factorId"> + <el-row justify="space-between" class="wrap"> + <div class="flex-col m-r-4"> + <div class="factor-name">{{ s.factorName }}</div> + </div> + <RealTimeLineChart + v-for="(item1, index1) in s._chartOptions" + :key="index1" + :model-value="item1" + ></RealTimeLineChart> + </el-row> + </div> + <!-- <RealTimeLineChart v-for="(item1, index1) in item._chartOptions" :key="index1" :model-value="item1" - ></RealTimeLineChart> + ></RealTimeLineChart> --> </el-scrollbar> </template> </BaseCard> @@ -117,7 +132,7 @@ padding: 0 4px; /* margin-right: 2px; */ width: 340px; - height: 240px; + height: 260px; /* border-right: 1px solid white; */ border-radius: 2px; } @@ -130,4 +145,22 @@ padding: 0px 1px; margin-bottom: 4px; } + +.wrap { + border-bottom: 1px solid rgba(255, 255, 255, 0.329); +} + +.flex-col { + display: flex; + flex-direction: column; +} + +.factor-value { + font-weight: 600; + font-size: 20px; +} + +.factor-name { + color: #23dad1; +} </style> -- Gitblit v1.9.3