From a3b2d94cbfb9bea819346a1b738237f72819a833 Mon Sep 17 00:00:00 2001
From: riku <risaku@163.com>
Date: 星期四, 12 六月 2025 13:35:33 +0800
Subject: [PATCH] 动态溯源(待完成)
---
src/utils/chart/chart-option.js | 2
src/views/sourcetrace/SourceTrace.vue | 188 ++++++-
src/api/index.js | 8
src/views/sourcetrace/component/PollutedExceptionItem.vue | 237 ++++++++++
src/views/sourcetrace/component/PollutedClueItem.vue | 309 +++++---------
src/views/sourcetrace/component/ClueRecordItem.vue | 96 ++++
src/views/realtimemode/RealtimeMode.vue | 8
src/views/sourcetrace/SourceTrace copy.vue | 345 +++++++++++++++
src/components/scene/SceneTable.vue | 1
src/views/sourcetrace/UnderwayAdvice.vue | 98 ++-
10 files changed, 1,007 insertions(+), 285 deletions(-)
diff --git a/src/api/index.js b/src/api/index.js
index 1792861..efcd5a1 100644
--- a/src/api/index.js
+++ b/src/api/index.js
@@ -13,10 +13,10 @@
}
if (debug) {
- // ip1 = 'http://192.168.0.103:8084/';
- ip1 = 'http://localhost:8084/';
- // ws = `192.168.0.103:9031`;
- ws = `localhost:9031`;
+ ip1 = 'http://192.168.0.103:8084/';
+ // ip1 = 'http://localhost:8084/';
+ ws = `192.168.0.103:9031`;
+ // ws = `localhost:9031`;
}
const $http = axios.create({
diff --git a/src/components/scene/SceneTable.vue b/src/components/scene/SceneTable.vue
index 2333209..f88bf65 100644
--- a/src/components/scene/SceneTable.vue
+++ b/src/components/scene/SceneTable.vue
@@ -29,6 +29,7 @@
<div>{{ parseInt(row.length) + '绫�' }}</div>
</template>
</el-table-column>
+ <slot></slot>
<!-- <el-table-column
prop="districtName"
label="鍖哄幙"
diff --git a/src/utils/chart/chart-option.js b/src/utils/chart/chart-option.js
index 5d9269a..346c602 100644
--- a/src/utils/chart/chart-option.js
+++ b/src/utils/chart/chart-option.js
@@ -137,7 +137,7 @@
left: '12%',
right: '2%',
top: '7%',
- bottom: '20%'
+ bottom: '30%'
},
legend: {
show: false
diff --git a/src/views/realtimemode/RealtimeMode.vue b/src/views/realtimemode/RealtimeMode.vue
index c72f699..6935614 100644
--- a/src/views/realtimemode/RealtimeMode.vue
+++ b/src/views/realtimemode/RealtimeMode.vue
@@ -29,7 +29,7 @@
class="source-trace"
v-model:factorType="factorType"
></SourceTrace>
- <UnderwayAdvice></UnderwayAdvice>
+ <!-- <PollutedClueItem></PollutedClueItem> -->
</div>
</template>
@@ -45,6 +45,7 @@
import DeviceChange from './component/DeviceChange.vue';
import SourceTrace from '@/views/sourcetrace/SourceTrace.vue';
import UnderwayAdvice from '@/views/sourcetrace/UnderwayAdvice.vue';
+import PollutedClueItem from '@/views/sourcetrace/component/PollutedClueItem.vue';
import { realTimeMapAnimation } from '@/utils/map/animation';
import {
fetchHistoryData,
@@ -67,7 +68,8 @@
RealTimeTrend,
DeviceChange,
SourceTrace,
- UnderwayAdvice
+ UnderwayAdvice,
+ PollutedClueItem
},
setup() {
const { loading, fetchData } = useFetchData(10000);
@@ -142,7 +144,7 @@
// startTime: '2024-12-13 16:35:00',
// startTime: '2024-11-27 11:50:41', // Pm, 涓窛绂诲伐鍦�
// startTime: '2024-08-30 15:28:00', // voc 杩戣窛绂绘苯淇�
- startTime: '2024-07-23 15:22:00',
+ startTime: '2024-07-23 15:21:30',
// startTime: '2024-07-23 14:39:00',
endTime: '2025-01-16 11:51:41',
page,
diff --git a/src/views/sourcetrace/SourceTrace copy.vue b/src/views/sourcetrace/SourceTrace copy.vue
new file mode 100644
index 0000000..b0d6844
--- /dev/null
+++ b/src/views/sourcetrace/SourceTrace copy.vue
@@ -0,0 +1,345 @@
+<template>
+ <el-row>
+ <el-col span="2">
+ <CardButton
+ direction="left"
+ name="鍔ㄦ�佹函婧�"
+ @click="() => (show = !show)"
+ ></CardButton>
+ </el-col>
+ <el-col v-show="show" span="10">
+ <BaseCard>
+ <template #content>
+ <el-scrollbar ref="scrollbarRef" class="scrollbar">
+ <div
+ ref="scrollContentRef"
+ style="display: flex; width: fit-content"
+ >
+ <TransitionGroup name="list">
+ <div v-for="(item, index) in streams" :key="index">
+ <PollutedExceptionItem
+ :item="item"
+ @showMarksAndPolygon="showMarksAndPolygon"
+ ></PollutedExceptionItem>
+ </div>
+ </TransitionGroup>
+ </div>
+ </el-scrollbar>
+ </template>
+ </BaseCard>
+ </el-col>
+ </el-row>
+</template>
+<script setup>
+/**
+ * 鍔ㄦ�佹函婧愪俊鎭鐞�
+ * 閫氳繃websocket鏂瑰紡鎺ユ敹鍚庣鎺ㄩ�佺殑寮傚父淇℃伅骞跺睍绀�
+ */
+import { reactive, ref, onMounted, onUnmounted, unref } from 'vue';
+import websocket from '@/api/websocket';
+import sector from '@/utils/map/sector';
+import mapUtil from '@/utils/map/util';
+import { sceneTypes, sceneIcon } from '@/constant/scene-types';
+import marks from '@/utils/map/marks';
+import { map, onMapMounted } from '@/utils/map/index_old';
+import { FactorDatas } from '@/model/FactorDatas';
+import factorDataParser from '@/utils/chart/factor-data-parser';
+import websocketMsgParser from '@/views/sourcetrace/websocketMsgParser.js';
+
+import PollutedExceptionItem from './component/PollutedExceptionItem.vue';
+
+const props = defineProps({
+ factorType: String
+});
+
+const emits = defineEmits(['update:factorType']);
+
+const height = `30vh`;
+const width = `60vh`;
+
+const show = ref(false);
+const scrollContentRef = ref();
+const scrollbarRef = ref();
+
+function scrollToBottom() {
+ const h1 = scrollContentRef.value.clientHeight + 100;
+ setTimeout(() => {
+ scrollbarRef.value.setScrollTop(h1);
+ }, 100);
+}
+
+function scrollToTop() {
+ setTimeout(() => {
+ scrollbarRef.value.setScrollTop(0);
+ }, 100);
+}
+
+const streams = reactive([]);
+
+const inputVal = ref('');
+const handleSend = () => {
+ 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));
+ // obj.showMore = true;
+ obj.showMore = false;
+ console.log('姹℃煋绾跨储: ', obj);
+
+ if (streams.length == 0) {
+ streams.push(obj);
+ } else {
+ // streams.forEach((s) => {
+ // showMarksAndPolygon(s);
+ // });
+ hideAll();
+ streams.unshift(obj);
+ }
+ show.value = true;
+
+ // scrollToBottom();
+ scrollToTop();
+ // drawPolygon(obj.pollutedArea);
+ parseChartData(obj);
+
+ if (showFirstClueTask) {
+ clearTimeout(showFirstClueTask);
+ }
+ showFirstClueTask = setTimeout(() => {
+ showMarksAndPolygon(obj);
+ }, 1000);
+ }
+}
+
+onMounted(() => {
+ websocket.registerReceiveEvent(dealMsg);
+});
+onUnmounted(() => {
+ websocket.removeReceiveEvent(dealMsg);
+ sector.clearSectorPt();
+ mapUtil.clearMap();
+ // if (layer != undefined) {
+ // mapUtil.removeViews(layer);
+ // layer = undefined;
+ // }
+});
+
+function hideAll() {
+ streams.forEach((s) => {
+ if (polygonMap.has(s.guid)) {
+ s.showMore = false;
+ map.remove(polygonMap.get(s.guid));
+ }
+ });
+}
+
+function showMarksAndPolygon(item) {
+ item.showMore = !item.showMore;
+ if (item.showMore) {
+ hideAll();
+ item.showMore = true;
+ drawPolygon(item);
+ } else {
+ if (polygonMap.has(item.guid)) {
+ map.remove(polygonMap.get(item.guid));
+ }
+ }
+}
+
+// 缁樺埗姹℃煋鍖哄煙锛堥珮寰峰湴鍥剧殑澶氳竟褰㈠璞★紝閫氳繃vue鐨剅eactive鍖呰涓哄搷搴斿紡瀵硅薄鍚庯紝鏃犳硶姝g‘鍦ㄥ湴鍥句腑浣跨敤锛�
+const polygonMap = new Map();
+function drawPolygon(item) {
+ const pollutedArea = item.pollutedArea;
+ if (polygonMap.has(item.guid)) {
+ map.add(polygonMap.get(item.guid));
+ } else {
+ const bounds = pollutedArea.polygon.map((v) => [v.first, v.second]);
+ // eslint-disable-next-line no-undef
+ const pollutedAreaPolygon = new AMap.Polygon({
+ map: map, //鏄剧ず璇ヨ鐩栫墿鐨勫湴鍥惧璞�
+ strokeWeight: 2, //杞粨绾垮搴�
+ path: bounds, //澶氳竟褰㈣疆寤撶嚎鐨勮妭鐐瑰潗鏍囨暟缁�
+ fillOpacity: 0, //澶氳竟褰㈠~鍏呴�忔槑搴�
+ fillColor: '#CCF3FF', //澶氳竟褰㈠~鍏呴鑹�
+ strokeColor: '#02ffea', //绾挎潯棰滆壊
+ // strokeColor: '#0552f7', //绾挎潯棰滆壊
+ strokeStyle: 'dashed',
+ zIndex: 9
+ });
+ polygonMap.set(item.guid, pollutedAreaPolygon);
+ }
+ // map.setFitView(polygonMap.get(item.guid));
+}
+
+function parseChartData(obj) {
+ // console.log('鎶樼嚎鍥撅細start');
+ 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 + ''
+ }
+ ]);
+ // console.log('鎶樼嚎鍥撅細', obj._chartOptions);
+ });
+}
+
+/******************************************************************************************************************** */
+
+/**
+ * 娣诲姞涓�鏉″伐浣滄祦淇℃伅
+ * @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>
+:deep(.el-statistic) {
+ --el-statistic-title-color: rgb(215, 215, 215);
+ --el-statistic-content-color: white;
+}
+
+:deep(.el-text.el-text--primary) {
+ --el-text-color: white;
+}
+
+:deep(.el-link) {
+ --el-link-text-color: #23dad1;
+}
+
+.scrollbar {
+ min-width: 300px;
+ max-width: 60vw;
+ /* height: 35vh; */
+ /* color: #02ffea; */
+}
+
+.clue-card {
+ padding: 0 4px;
+ /* margin-right: 2px; */
+ width: 340px;
+ height: 35vh;
+ border-right: 1px solid white;
+ border-radius: 2px;
+}
+
+.border-dashed {
+ /* border: 1px dashed white; */
+ border: 1px dashed #ffbc58;
+ padding: 0px 1px;
+ margin-bottom: 4px;
+}
+</style>
+<style>
+.list-move, /* 瀵圭Щ鍔ㄤ腑鐨勫厓绱犲簲鐢ㄧ殑杩囨浮 */
+.list-enter-active,
+.list-leave-active {
+ transition: all 0.5s ease;
+}
+
+.list-enter-from,
+.list-leave-to {
+ opacity: 0;
+ transform: translateX(-30px);
+}
+
+/* 纭繚灏嗙寮�鐨勫厓绱犱粠甯冨眬娴佷腑鍒犻櫎
+ 浠ヤ究鑳藉姝g‘鍦拌绠楃Щ鍔ㄧ殑鍔ㄧ敾銆� */
+.list-leave-active {
+ position: absolute;
+}
+</style>
diff --git a/src/views/sourcetrace/SourceTrace.vue b/src/views/sourcetrace/SourceTrace.vue
index 0a122c8..d4c97a6 100644
--- a/src/views/sourcetrace/SourceTrace.vue
+++ b/src/views/sourcetrace/SourceTrace.vue
@@ -1,33 +1,54 @@
<template>
<el-row>
- <el-col span="2">
- <CardButton
- direction="left"
- name="鍔ㄦ�佹函婧�"
- @click="() => (show = !show)"
- ></CardButton>
+ <el-col span="2" class="flex-col">
+ <el-row justify="end">
+ <CardButton
+ direction="left"
+ name="鍔ㄦ�佹函婧�"
+ @click="() => (show = !show)"
+ ></CardButton>
+ </el-row>
+ <el-row class="flex-col">
+ <PollutedExceptionItem
+ :item="selectedException"
+ @showMarksAndPolygon="showMarksAndPolygon"
+ ></PollutedExceptionItem>
+ </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
+ <!-- <div
ref="scrollContentRef"
style="display: flex; width: fit-content"
- >
+ > -->
<TransitionGroup name="list">
- <div v-for="(item, index) in streams" :key="index">
- <PollutedClueItem
+ <div
+ v-for="item in filterStreams"
+ :key="item.guid ? item.guid : item.time"
+ >
+ <ClueRecordItem
:item="item"
- @showMarksAndPolygon="showMarksAndPolygon"
- ></PollutedClueItem>
+ @open="handleOpen(item)"
+ ></ClueRecordItem>
</div>
</TransitionGroup>
- </div>
+ <!-- </div> -->
</el-scrollbar>
</template>
</BaseCard>
</el-col>
+ <PollutedClueItem
+ v-model="clueDialog"
+ :item="selectedClue"
+ ></PollutedClueItem>
</el-row>
</template>
<script setup>
@@ -35,7 +56,9 @@
* 鍔ㄦ�佹函婧愪俊鎭鐞�
* 閫氳繃websocket鏂瑰紡鎺ユ敹鍚庣鎺ㄩ�佺殑寮傚父淇℃伅骞跺睍绀�
*/
-import { reactive, ref, onMounted, onUnmounted, unref } from 'vue';
+import { reactive, ref, onMounted, onUnmounted, computed, watch } from 'vue';
+import moment from 'moment';
+
import websocket from '@/api/websocket';
import sector from '@/utils/map/sector';
import mapUtil from '@/utils/map/util';
@@ -46,7 +69,9 @@
import factorDataParser from '@/utils/chart/factor-data-parser';
import websocketMsgParser from '@/views/sourcetrace/websocketMsgParser.js';
-import PollutedClueItem from './component/PollutedClueItem.vue';
+import PollutedExceptionItem from './component/PollutedExceptionItem.vue';
+import ClueRecordItem from './component/ClueRecordItem.vue';
+import PollutedClueItem from '@/views/sourcetrace/component/PollutedClueItem.vue';
const props = defineProps({
factorType: String
@@ -58,8 +83,13 @@
const width = `60vh`;
const show = ref(false);
+const clueDialog = ref(false);
const scrollContentRef = ref();
const scrollbarRef = ref();
+
+const selectedException = ref();
+const selectedClue = ref();
+const selectedMsgTypes = ref(['1', '2']);
function scrollToBottom() {
const h1 = scrollContentRef.value.clientHeight + 100;
@@ -75,6 +105,11 @@
}
const streams = reactive([]);
+const filterStreams = computed(() => {
+ return streams.filter((v) => {
+ return selectedMsgTypes.value.indexOf(v._type) != -1;
+ });
+});
const inputVal = ref('');
const handleSend = () => {
@@ -88,32 +123,60 @@
// 姹℃煋绾跨储 PollutedClue
if (type == '1') {
const obj = reactive(JSON.parse(content));
+ obj._type = type;
// obj.showMore = true;
obj.showMore = false;
- console.log('姹℃煋绾跨储: ', obj);
+ console.log('姹℃煋寮傚父鍒囩墖: ', obj);
- if (streams.length == 0) {
- streams.push(obj);
- } else {
- // streams.forEach((s) => {
- // showMarksAndPolygon(s);
- // });
- hideAll();
- streams.unshift(obj);
- }
+ // if (streams.length == 0) {
+ // streams.push(obj);
+ // } else {
+ // // streams.forEach((s) => {
+ // // showMarksAndPolygon(s);
+ // // });
+ // // hideAll();
+ // streams.unshift(obj);
+ // }
+ addNewMsg(obj);
show.value = true;
// scrollToBottom();
- scrollToTop();
+ // scrollToTop();
// drawPolygon(obj.pollutedArea);
parseChartData(obj);
- if (showFirstClueTask) {
- clearTimeout(showFirstClueTask);
- }
- showFirstClueTask = setTimeout(() => {
- showMarksAndPolygon(obj);
+ // if (showFirstClueTask) {
+ // clearTimeout(showFirstClueTask);
+ // }
+ // showFirstClueTask = setTimeout(() => {
+ // showMarksAndPolygon(obj);
+ // }, 1000);
+ } else if (type == '2') {
+ const obj = JSON.parse(content);
+ obj._type = type;
+ console.log('姹℃煋绾跨储缁撴灉: ', obj);
+ obj._timestr = timeFormatter(obj.time);
+ // streams.unshift(obj);
+ addNewMsg(obj);
+ }
+}
+
+// 鎸夌収涓�瀹氭椂闂撮棿闅旀柊澧炰竴鏉℃秷鎭�
+let addNewMsgTask;
+const leftMsgList = [];
+function addNewMsg(msg, inside) {
+ if (!addNewMsgTask && (leftMsgList.length == 0 || inside)) {
+ streams.splice(0, 0, msg);
+ addNewMsgTask = setTimeout(() => {
+ clearTimeout(addNewMsgTask);
+ addNewMsgTask = undefined;
+ if (leftMsgList.length > 0) {
+ const next = leftMsgList.shift();
+ addNewMsg(next, true);
+ }
}, 1000);
+ } else {
+ leftMsgList.push(msg);
}
}
@@ -129,6 +192,32 @@
// layer = undefined;
// }
});
+
+watch(clueDialog, (nV, oV) => {
+ if (nV != oV && !nV) {
+ selectedClue.value._selected = false;
+ }
+});
+
+function handleOpen(item) {
+ 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;
+ }
+ item._selected = true;
+}
function hideAll() {
streams.forEach((s) => {
@@ -148,6 +237,7 @@
} else {
if (polygonMap.has(item.guid)) {
map.remove(polygonMap.get(item.guid));
+ selectedException.value._selected = false;
}
}
}
@@ -190,6 +280,10 @@
]);
// console.log('鎶樼嚎鍥撅細', obj._chartOptions);
});
+}
+
+function timeFormatter(time) {
+ return moment(time).format('YYYY-MM-DD HH:mm:ss');
}
/******************************************************************************************************************** */
@@ -301,11 +395,27 @@
--el-link-text-color: #23dad1;
}
+.el-checkbox {
+ --el-checkbox-text-color: white;
+ --main-color: #23dad1;
+ --el-checkbox-checked-text-color: var(--main-color);
+ --el-checkbox-checked-input-border-color: var(--main-color);
+ --el-checkbox-checked-bg-color: var(--main-color);
+ --el-checkbox-input-border-color-hover: var(--main-color);
+
+ --el-checkbox-disabled-checked-input-fill: var(--main-color);
+ --el-checkbox-disabled-checked-input-border-color: var(--main-color);
+ --el-checkbox-disabled-checked-icon-color: white;
+ margin-right: 6px;
+ /* height: initial; */
+}
+
.scrollbar {
- min-width: 300px;
- max-width: 60vw;
- /* height: 35vh; */
+ width: 400px;
+ /* max-width: 60vw; */
+ height: 45vh;
/* color: #02ffea; */
+ padding-right: 10px;
}
.clue-card {
@@ -323,18 +433,24 @@
padding: 0px 1px;
margin-bottom: 4px;
}
+.flex-col {
+ display: flex;
+ flex-direction: column;
+ justify-content: space-between;
+}
</style>
<style>
.list-move, /* 瀵圭Щ鍔ㄤ腑鐨勫厓绱犲簲鐢ㄧ殑杩囨浮 */
.list-enter-active,
.list-leave-active {
+ /* transition: all 0.8s cubic-bezier(0.55, 0, 0.1, 1); */
transition: all 0.5s ease;
}
.list-enter-from,
.list-leave-to {
opacity: 0;
- transform: translateX(30px);
+ transform: scaleY(0.01) translate(300px, 0);
}
/* 纭繚灏嗙寮�鐨勫厓绱犱粠甯冨眬娴佷腑鍒犻櫎
@@ -342,4 +458,4 @@
.list-leave-active {
position: absolute;
}
-</style>
\ No newline at end of file
+</style>
diff --git a/src/views/sourcetrace/UnderwayAdvice.vue b/src/views/sourcetrace/UnderwayAdvice.vue
index b8eaf03..9615793 100644
--- a/src/views/sourcetrace/UnderwayAdvice.vue
+++ b/src/views/sourcetrace/UnderwayAdvice.vue
@@ -26,42 +26,45 @@
</el-text>
</el-row>
</template> -->
- <TransitionGroup name="list">
- <div v-for="(item, index) in analysisResultList" :key="index">
- <template v-if="index == 0">
- <el-row justify="space-between">
- <el-text size="small">{{ item._timestr }}</el-text>
- <el-tag type="danger" effect="dark">鏈�鏂扮嚎绱�</el-tag>
- </el-row>
- <el-space>
- <el-icon color="#F56C6C" :size="40"
- ><WarnTriangleFilled
- /></el-icon>
- <el-text>
- {{ item.advice }}
- </el-text>
- </el-space>
- <el-row justify="space-between">
- <el-link type="primary" :underline="true" @click="showPolyline">
- {{ lineShow ? '鏀惰捣璺嚎' : '瀹氫綅璺嚎' }}
- </el-link>
- <el-text size="small">
- 鎺ㄨ崘璺嚎鎬婚暱{{ item.direction.distance }}绫�
- </el-text>
- </el-row>
- <el-divider>鍘嗗彶绾跨储</el-divider>
- </template>
- <template v-else>
- <el-row>
- <el-text size="small">{{ item._timestr }}</el-text>
- </el-row>
- <el-space>
- <!-- <el-icon color="#F56C6C" :size="40"><WarnTriangleFilled /></el-icon> -->
- <el-text>
- {{ item.advice }}
- </el-text>
- </el-space>
- <!-- <el-row justify="space-between">
+ <el-button icon="Plus" @click="addAdvice"></el-button>
+ <el-button icon="Minus" @click="removeAdvice"></el-button>
+ <el-scrollbar height="200">
+ <TransitionGroup name="list">
+ <div v-for="(item, index) in analysisResultList" :key="index">
+ <template v-if="index == 0">
+ <el-row justify="space-between">
+ <el-text size="small">{{ item._timestr }}</el-text>
+ <el-tag type="danger" effect="dark">鏈�鏂扮嚎绱�</el-tag>
+ </el-row>
+ <el-space>
+ <el-icon color="#F56C6C" :size="40"
+ ><WarnTriangleFilled
+ /></el-icon>
+ <el-text>
+ {{ item.advice }}
+ </el-text>
+ </el-space>
+ <el-row justify="space-between">
+ <el-link type="primary" :underline="true" @click="showPolyline">
+ {{ lineShow ? '鏀惰捣璺嚎' : '瀹氫綅璺嚎' }}
+ </el-link>
+ <el-text size="small">
+ 鎺ㄨ崘璺嚎鎬婚暱{{ item.direction.distance }}绫�
+ </el-text>
+ </el-row>
+ <el-divider>鍘嗗彶绾跨储</el-divider>
+ </template>
+ <template v-else>
+ <el-row>
+ <el-text size="small">{{ item._timestr }}</el-text>
+ </el-row>
+ <el-space>
+ <!-- <el-icon color="#F56C6C" :size="40"><WarnTriangleFilled /></el-icon> -->
+ <el-text>
+ {{ item.advice }}
+ </el-text>
+ </el-space>
+ <!-- <el-row justify="space-between">
<el-link type="primary" :underline="true" @click="showPolyline">
{{ lineShow ? '鏀惰捣璺嚎' : '瀹氫綅璺嚎' }}
</el-link>
@@ -69,10 +72,11 @@
鎺ㄨ崘璺嚎鎬婚暱{{ item.direction.distance }}绫�
</el-text>
</el-row> -->
- <el-divider></el-divider>
- </template>
- </div>
- </TransitionGroup>
+ <el-divider></el-divider>
+ </template>
+ </div>
+ </TransitionGroup>
+ </el-scrollbar>
</template>
<template #footer> </template>
</CardDialog>
@@ -144,6 +148,14 @@
function timeFormatter(time) {
return moment(time).format('YYYY-MM-DD HH:mm:ss');
}
+
+function addAdvice() {
+ analysisResultList.unshift(analysisResultList[0]);
+}
+
+function removeAdvice() {
+ analysisResultList.splice(0, 1);
+}
</script>
<style scoped>
:deep(.el-text) {
@@ -155,7 +167,7 @@
/* color: #ffd82a; */
}
</style>
-<style>
+<!-- <style>
.list-move, /* 瀵圭Щ鍔ㄤ腑鐨勫厓绱犲簲鐢ㄧ殑杩囨浮 */
.list-enter-active,
.list-leave-active {
@@ -165,7 +177,7 @@
.list-enter-from,
.list-leave-to {
opacity: 0;
- transform: translateX(30px);
+ transform: translateX(-30px);
}
/* 纭繚灏嗙寮�鐨勫厓绱犱粠甯冨眬娴佷腑鍒犻櫎
@@ -173,4 +185,4 @@
.list-leave-active {
position: absolute;
}
-</style>
+</style> -->
diff --git a/src/views/sourcetrace/component/ClueRecordItem.vue b/src/views/sourcetrace/component/ClueRecordItem.vue
new file mode 100644
index 0000000..28f2918
--- /dev/null
+++ b/src/views/sourcetrace/component/ClueRecordItem.vue
@@ -0,0 +1,96 @@
+<template>
+ <div :class="'wrapper' + (item._selected ? ' wrapper-select' : '')">
+ <div v-if="item._type == '1'">
+ <el-row justify="space-between">
+ <el-space>
+ <el-tag v-if="noWarn" type="info" effect="dark" size="small"
+ >寮傚父</el-tag
+ >
+ <el-tag v-else type="warning" effect="dark" size="small">寮傚父</el-tag>
+ <el-text type="primary">{{
+ item.pollutedData.startTime + ' - ' + item.pollutedData.endTime
+ }}</el-text>
+ </el-space>
+ <el-link type="primary" @click="emits('open', item)"> 璇︽儏 </el-link>
+ </el-row>
+ <el-col :span="24">
+ <el-text type="primary">{{
+ item.pollutedData.factorName +
+ formatException(item.pollutedData.exceptionType) +
+ '锛�' +
+ formatDistanceType(item.pollutedArea.distanceType)
+ }}</el-text>
+ <el-text :type="noWarn ? 'primary' : 'warning'">
+ {{
+ item.pollutedSource.sceneList.length == 0
+ ? '鏈壘鍒板彲鐤戞薄鏌撴簮'
+ : '鎵惧埌' + item.pollutedSource.sceneList.length + '涓彲鐤戞薄鏌撴簮'
+ }}
+ </el-text>
+ </el-col>
+ <!-- <el-col :span="2"> </el-col> -->
+ </div>
+ <div v-else-if="item._type == '2'">
+ <el-row justify="space-between">
+ <el-tag type="danger" effect="dark" size="small">绾跨储</el-tag>
+ <el-link type="primary" @click="emits('open')"> 璇︽儏 </el-link>
+ </el-row>
+ <el-text type="danger">{{ item.advice }}</el-text>
+ </div>
+ </div>
+</template>
+<script setup>
+import { computed } from 'vue';
+
+const props = defineProps({
+ item: Object
+});
+
+const emits = defineEmits(['open']);
+
+const noWarn = computed(() => {
+ return props.item && props.item.pollutedSource.sceneList.length == 0;
+});
+
+function formatException(value) {
+ switch (value) {
+ case 4:
+ return '閲忕骇绐佸彉';
+ case 9:
+ return '蹇�熶笂鍗�';
+ default:
+ return '閲忕骇绐佸彉';
+ }
+}
+
+function formatDistanceType(value) {
+ switch (value) {
+ case 'TYPE1':
+ return '50绫充互鍐�';
+ case 'TYPE2':
+ return '50绫� - 500绫充互鍐�';
+ case 'TYPE3':
+ return '50绫� - 1鍏噷浠ュ唴';
+ case 'TYPE4':
+ return '50绫� - 2鍏噷浠ュ唴';
+
+ default:
+ break;
+ }
+}
+</script>
+<style scoped>
+.wrapper {
+ margin-bottom: 8px;
+ border-bottom: 1px dashed rgba(253, 253, 253, 0.651);
+}
+.wrapper-select {
+ background: linear-gradient(
+ rgba(228, 228, 228, 0.274),
+ rgba(64, 165, 248, 0.089)
+ );
+}
+.no-warning {
+ color: var(--el-text-color-disabled) !important;
+}
+</style>
diff --git a/src/views/sourcetrace/component/PollutedClueItem.vue b/src/views/sourcetrace/component/PollutedClueItem.vue
index 0bf7086..784771b 100644
--- a/src/views/sourcetrace/component/PollutedClueItem.vue
+++ b/src/views/sourcetrace/component/PollutedClueItem.vue
@@ -1,222 +1,135 @@
<template>
- <!-- <BaseCard>
- <template #content> -->
- <el-scrollbar class="clue-card">
- <el-row justify="space-between">
- <!-- <el-tag v-if="index == 0" type="danger">鏈�鏂�</el-tag> -->
- <el-text type="primary">{{
- '鍒囩墖鏃堕棿锛�' +
- item.pollutedData.startTime +
- ' - ' +
- item.pollutedData.endTime
- }}</el-text>
- <el-link
- type="primary"
- :underline="true"
- @click="showMarksAndPolygon(item)"
- >
- {{ item.showMore ? '鏀惰捣寮傚父' : '瀹氫綅寮傚父' }}
- </el-link>
- </el-row>
- <div>
- <el-text type="primary">
- 姹℃煋鍖哄煙锛歿{ item.pollutedArea.address }}
- </el-text>
- </div>
- <div>
- <el-text type="primary">
- 婧簮璺濈锛歿{ formatDistanceType(item.pollutedArea.distanceType) }}
- </el-text>
- </div>
- <div>
- <el-text type="primary">
- 寮傚父绫诲瀷锛歿{ item.pollutedData.exception }}
- </el-text>
- </div>
- <el-row style="border-top: 1px solid white">
- <el-col :span="6">
- <el-statistic title="绐佸彉鍥犲瓙" :value="item.pollutedData.factorName" />
- </el-col>
- <el-col :span="6">
- <el-statistic
- v-if="item.pollutedData.exceptionType == 4"
- title="鍙樺寲骞呭害"
- :value="formatPercentage(item.pollutedData.avgPer)"
- />
- <el-statistic
- v-else-if="item.pollutedData.exceptionType == 9"
- title="鍙樺寲閫熺巼"
- :value="formatPercentage(item.pollutedData.avgPer)"
- />
- </el-col>
- <el-col :span="6">
- <el-statistic title="鍙戠敓娆℃暟" :value="item.pollutedData.times" />
- </el-col>
- <el-col :span="6">
- <el-statistic
- title="骞冲潎椋庨��"
- :value="item.pollutedData.windSpeed"
- suffix="m/s"
- />
- </el-col>
- </el-row>
- <el-row justify="space-between">
- <!-- <el-link
- type="primary"
- underline
- @click="showMarksAndPolygon(item)"
- >
- {{
- (item.showMore ? '鏀惰捣婧簮鍦烘櫙' : '鏌ョ湅婧簮鍦烘櫙') +
- '锛�' +
- item.pollutedSource.sceneList.length +
- '锛�'
- }}
- </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"
- ></RealTimeLineChart>
- <!-- </div> -->
- <div class="border-dashed">
- <el-text type="" tag="mark">
- {{ item.pollutedSource.conclusion }}
- </el-text>
- </div>
- <SceneTable
- :show-marks="item.showMore"
- :scene-list="item.pollutedSource.sceneList"
- ></SceneTable>
-
- <!-- <el-space gap="4">
- <el-tag :type="item.status == 1 ? 'danger' : 'info'">{{
- item._statusStr
- }}</el-tag>
- <el-text type="default">{{ item.exception }}</el-text>
- </el-space>
- <el-row gap="4">
- <el-text type="primary">鍙戠敓鏃堕棿锛�</el-text>
- <el-text type="primary">{{
- item.startTime + ' 鑷� '
- }}</el-text>
- <el-text type="primary">{{
- item.status == 1 ? '褰撳墠' : item.endTime
- }}</el-text>
- </el-row>
- <el-row>
- <el-col :span="6">
- <el-statistic title="鍥犲瓙" :value="item.factorName" />
- </el-col>
- <el-col :span="6">
- <el-statistic title="鍧囧��" :value="item.avg" />
- </el-col>
- <el-col :span="6">
- <el-statistic title="宄板��" :value="item.max" />
- </el-col>
- <el-col :span="6">
- <el-statistic title="璋峰��" :value="item.min" />
- </el-col>
- </el-row>
- <el-row justify="space-between">
- <el-link
- type="primary"
- @click="item.showMore = !item.showMore"
- >
- {{
- (item.showMore ? '鏀惰捣婧簮鍦烘櫙' : '鏌ョ湅婧簮鍦烘櫙') +
- '锛�' +
- item.relatedSceneList.length +
- '锛�'
- }}
- </el-link>
- <el-link type="primary" @click="drawSector(item)">
- 鏌ョ湅寮傚父
- </el-link>
- </el-row>
- <SceneTable
- v-show="item.showMore"
- :scene-list="item.relatedSceneList"
- ></SceneTable>
- <el-divider /> -->
- </el-scrollbar>
- <!-- </template>
- </BaseCard> -->
+ <CardDialog
+ :model-value="modelValue"
+ @update:model-value="handleDialogShow"
+ title="姹℃煋绾跨储"
+ draggable
+ :modal="false"
+ width="400px"
+ >
+ <template #default>
+ <template v-if="item">
+ <el-row>
+ <el-text type="primary" size="small">{{ item._timestr }}</el-text>
+ </el-row>
+ <el-space>
+ <el-icon color="#F56C6C" :size="40"><WarnTriangleFilled /></el-icon>
+ <el-text type="primary">
+ {{ item.advice }}
+ </el-text>
+ </el-space>
+ <el-row justify="space-between">
+ <el-text type="primary" size="small">
+ 鎺ㄨ崘璺嚎鎬婚暱{{ item.direction.distance }}绫�
+ </el-text>
+ <el-link type="primary" size="small" @click="showPolyline">
+ {{ lineShow ? '鏀惰捣璺嚎' : '瀹氫綅璺嚎' }}
+ </el-link>
+ </el-row>
+ <SceneTable
+ :show-marks="lineShow"
+ :scene-list="formatSceneList(item.sortedSceneList)"
+ >
+ <el-table-column prop="_count" width="42" label="婧簮娆℃暟" />
+ </SceneTable>
+ </template>
+ </template>
+ <template #footer> </template>
+ </CardDialog>
</template>
<script setup>
-import { ref } from 'vue';
+import { ref, onMounted, onUnmounted, reactive, watch } from 'vue';
+
+import { sceneTypes, sceneIcon } from '@/constant/scene-types';
+import mapLine from '@/utils/map/line';
+import mapUtil from '@/utils/map/util';
+import marks from '@/utils/map/marks';
const props = defineProps({
+ modelValue: Boolean,
item: Object
});
-const emits = defineEmits(['showMarksAndPolygon']);
+const lineShow = ref(true);
+// 涓婁竴鏉″鑸矾绾�
+let lastPolyline = undefined;
+// 涓婁竴涓鑸洰鐨勫湴
+// let lastDestination = undefined;
+// let layer = undefined;
-function showMarksAndPolygon(item) {
- emits('showMarksAndPolygon', item);
-}
+const emits = defineEmits(['update:modelValue']);
-function formatPercentage(value) {
- return Math.round(value * 100) + '%';
-}
+watch(
+ () => [props.item, props.modelValue],
+ (nV, oV) => {
+ if (nV[0] != oV[0]) {
+ const polyline = mapLine.drawDirection(
+ nV[0].direction.paths.map((v) => [v.first, v.second])
+ );
+ // polylineList.unshift(polyline);
+ if (lastPolyline) {
+ mapUtil.removeViews(lastPolyline);
+ }
+ lastPolyline = polyline;
+ lineShow.value = true;
+ } else if (nV[1]) {
+ showPolyline(true);
+ }
+ }
+);
-function formatDistanceType(value) {
- switch (value) {
- case 'TYPE1':
- return '50绫�';
- case 'TYPE2':
- return '50绫� - 500绫�';
- case 'TYPE3':
- return '50绫� - 1鍏噷';
- case 'TYPE4':
- return '50绫� - 2鍏噷';
+function showPolyline(show) {
+ if (typeof show === 'boolean') {
+ lineShow.value = show;
+ } else {
+ lineShow.value = !lineShow.value;
+ }
- default:
- break;
+ if (lineShow.value && lastPolyline) {
+ mapUtil.addViews(lastPolyline);
+ } else {
+ mapUtil.removeViews(lastPolyline);
}
}
-function formatChangeRate() {
-
+// function removeLayer() {
+// if (layer != undefined) {
+// mapUtil.removeViews(layer);
+// layer = undefined;
+// }
+// }
+
+// function drawMarks(sceneList) {
+// removeLayer();
+// if (sceneList.length != 0) {
+// const icons = [];
+// sceneList.forEach((s) => {
+// icons.push(sceneIcon(s.typeId));
+// });
+// layer = marks.createLabelMarks(icons, sceneList, false);
+// }
+// }
+
+function formatSceneList(sceneList) {
+ return sceneList.map((v) => {
+ return {
+ ...v.first,
+ _count: v.second
+ };
+ });
+}
+
+function handleDialogShow(value) {
+ showPolyline(value);
+ emits('update:modelValue', value);
}
</script>
<style scoped>
-:deep(.el-statistic) {
- --el-statistic-title-color: rgb(215, 215, 215);
- --el-statistic-content-color: white;
-}
-
-:deep(.el-text.el-text--primary) {
+/* :deep(.el-text.el-text--primary) {
--el-text-color: white;
}
:deep(.el-link) {
--el-link-text-color: #23dad1;
-}
-
-.scrollbar {
- min-width: 300px;
- max-width: 60vw;
- /* height: 35vh; */
- /* color: #02ffea; */
-}
-
-.clue-card {
- padding: 0 4px;
- /* margin-right: 2px; */
- width: 340px;
- height: 35vh;
- border-right: 1px solid white;
- border-radius: 2px;
-}
-
-.border-dashed {
- /* border: 1px dashed white; */
- border: 1px dashed #ffbc58;
- padding: 0px 1px;
- margin-bottom: 4px;
-}
+} */
</style>
diff --git a/src/views/sourcetrace/component/PollutedExceptionItem.vue b/src/views/sourcetrace/component/PollutedExceptionItem.vue
new file mode 100644
index 0000000..e7defcc
--- /dev/null
+++ b/src/views/sourcetrace/component/PollutedExceptionItem.vue
@@ -0,0 +1,237 @@
+<template>
+ <!-- <CardDialog
+ :model-value="modelValue"
+ @update:model-value="handleDialogShow"
+ title="姹℃煋寮傚父"
+ draggable
+ :modal="false"
+ >
+ <template #default> -->
+ <BaseCard v-if="item" v-show="item.showMore">
+ <template #content>
+ <el-scrollbar class="clue-card">
+ <el-row justify="space-between">
+ <!-- <el-tag v-if="index == 0" type="danger">鏈�鏂�</el-tag> -->
+ <el-text type="primary">{{
+ '鍒囩墖鏃堕棿锛�' +
+ item.pollutedData.startTime +
+ ' - ' +
+ item.pollutedData.endTime
+ }}</el-text>
+ <el-link
+ type="primary"
+ :underline="true"
+ @click="showMarksAndPolygon(item)"
+ >
+ {{ item.showMore ? '鏀惰捣寮傚父' : '瀹氫綅寮傚父' }}
+ </el-link>
+ </el-row>
+ <div>
+ <el-text type="primary">
+ 姹℃煋鍖哄煙锛歿{ item.pollutedArea.address }}
+ </el-text>
+ </div>
+ <div>
+ <el-text type="primary">
+ 婧簮璺濈锛歿{ formatDistanceType(item.pollutedArea.distanceType) }}
+ </el-text>
+ </div>
+ <div>
+ <el-text type="primary">
+ 寮傚父绫诲瀷锛歿{ item.pollutedData.exception }}
+ </el-text>
+ </div>
+ <el-row style="border-top: 1px solid white">
+ <el-col :span="6">
+ <el-statistic
+ title="绐佸彉鍥犲瓙"
+ :value="item.pollutedData.factorName"
+ />
+ </el-col>
+ <el-col :span="6">
+ <el-statistic
+ v-if="item.pollutedData.exceptionType == 4"
+ title="鍙樺寲骞呭害"
+ :value="formatPercentage(item.pollutedData.avgPer)"
+ />
+ <el-statistic
+ v-else-if="item.pollutedData.exceptionType == 9"
+ title="鍙樺寲閫熺巼"
+ :value="formatChangeRate(item.pollutedData.avgRate)"
+ suffix=""
+ />
+ </el-col>
+ <el-col :span="6">
+ <el-statistic title="鍙戠敓娆℃暟" :value="item.pollutedData.times" />
+ </el-col>
+ <el-col :span="6">
+ <el-statistic
+ title="骞冲潎椋庨��"
+ :value="item.pollutedData.windSpeed"
+ suffix="m/s"
+ />
+ </el-col>
+ </el-row>
+ <el-row justify="space-between">
+ <!-- <el-link
+ type="primary"
+ underline
+ @click="showMarksAndPolygon(item)"
+ >
+ {{
+ (item.showMore ? '鏀惰捣婧簮鍦烘櫙' : '鏌ョ湅婧簮鍦烘櫙') +
+ '锛�' +
+ item.pollutedSource.sceneList.length +
+ '锛�'
+ }}
+ </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"
+ ></RealTimeLineChart>
+ <!-- </div> -->
+ <div class="border-dashed">
+ <el-text type="" tag="mark">
+ {{ item.pollutedSource.conclusion }}
+ </el-text>
+ </div>
+ <SceneTable
+ :show-marks="item.showMore"
+ :scene-list="item.pollutedSource.sceneList"
+ ></SceneTable>
+
+ <!-- <el-space gap="4">
+ <el-tag :type="item.status == 1 ? 'danger' : 'info'">{{
+ item._statusStr
+ }}</el-tag>
+ <el-text type="default">{{ item.exception }}</el-text>
+ </el-space>
+ <el-row gap="4">
+ <el-text type="primary">鍙戠敓鏃堕棿锛�</el-text>
+ <el-text type="primary">{{
+ item.startTime + ' 鑷� '
+ }}</el-text>
+ <el-text type="primary">{{
+ item.status == 1 ? '褰撳墠' : item.endTime
+ }}</el-text>
+ </el-row>
+ <el-row>
+ <el-col :span="6">
+ <el-statistic title="鍥犲瓙" :value="item.factorName" />
+ </el-col>
+ <el-col :span="6">
+ <el-statistic title="鍧囧��" :value="item.avg" />
+ </el-col>
+ <el-col :span="6">
+ <el-statistic title="宄板��" :value="item.max" />
+ </el-col>
+ <el-col :span="6">
+ <el-statistic title="璋峰��" :value="item.min" />
+ </el-col>
+ </el-row>
+ <el-row justify="space-between">
+ <el-link
+ type="primary"
+ @click="item.showMore = !item.showMore"
+ >
+ {{
+ (item.showMore ? '鏀惰捣婧簮鍦烘櫙' : '鏌ョ湅婧簮鍦烘櫙') +
+ '锛�' +
+ item.relatedSceneList.length +
+ '锛�'
+ }}
+ </el-link>
+ <el-link type="primary" @click="drawSector(item)">
+ 鏌ョ湅寮傚父
+ </el-link>
+ </el-row>
+ <SceneTable
+ v-show="item.showMore"
+ :scene-list="item.relatedSceneList"
+ ></SceneTable>
+ <el-divider /> -->
+ </el-scrollbar>
+ </template>
+ </BaseCard>
+ <!-- </template>
+ </CardDialog> -->
+</template>
+<script setup>
+import { ref } from 'vue';
+
+const props = defineProps({
+ modelValue: Boolean,
+ item: Object
+});
+
+const emits = defineEmits(['showMarksAndPolygon', 'update:modelValue']);
+
+function showMarksAndPolygon(item) {
+ emits('showMarksAndPolygon', item);
+}
+
+function formatPercentage(value) {
+ return Math.round(value * 100) + '%';
+}
+
+function formatDistanceType(value) {
+ switch (value) {
+ case 'TYPE1':
+ return '50绫�';
+ case 'TYPE2':
+ return '50绫� - 500绫�';
+ case 'TYPE3':
+ return '50绫� - 1鍏噷';
+ case 'TYPE4':
+ return '50绫� - 2鍏噷';
+
+ default:
+ break;
+ }
+}
+
+function formatChangeRate(value) {
+ return Math.round(value * 100) / 100 + '';
+}
+</script>
+<style scoped>
+:deep(.el-statistic) {
+ --el-statistic-title-color: rgb(215, 215, 215);
+ --el-statistic-content-color: white;
+}
+
+:deep(.el-text.el-text--primary) {
+ --el-text-color: white;
+}
+
+:deep(.el-link) {
+ --el-link-text-color: #23dad1;
+}
+
+.scrollbar {
+ min-width: 300px;
+ max-width: 60vw;
+ /* height: 35vh; */
+ /* color: #02ffea; */
+}
+
+.clue-card {
+ padding: 0 4px;
+ /* margin-right: 2px; */
+ width: 340px;
+ height: 35vh;
+ border-right: 1px solid white;
+ border-radius: 2px;
+}
+
+.border-dashed {
+ /* border: 1px dashed white; */
+ border: 1px dashed #ffbc58;
+ padding: 0px 1px;
+ margin-bottom: 4px;
+}
+</style>
--
Gitblit v1.9.3