From a3b2d94cbfb9bea819346a1b738237f72819a833 Mon Sep 17 00:00:00 2001
From: riku <risaku@163.com>
Date: 星期四, 12 六月 2025 13:35:33 +0800
Subject: [PATCH] 动态溯源(待完成)

---
 src/views/sourcetrace/SourceTrace.vue |  188 ++++++++++++++++++++++++++++++++++++++---------
 1 files changed, 152 insertions(+), 36 deletions(-)

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>

--
Gitblit v1.9.3