From b33e28bc2843555355ecad59a80c83e3c26445a3 Mon Sep 17 00:00:00 2001
From: riku <risaku@163.com>
Date: 星期一, 01 九月 2025 17:29:36 +0800
Subject: [PATCH] 走航季度报告模块(待完成)

---
 src/views/sourcetrace/SourceTrace.vue |  389 +++++++++++++++++++++++++++++++------------------------
 1 files changed, 221 insertions(+), 168 deletions(-)

diff --git a/src/views/sourcetrace/SourceTrace.vue b/src/views/sourcetrace/SourceTrace.vue
index 0145b9a..73dcd07 100644
--- a/src/views/sourcetrace/SourceTrace.vue
+++ b/src/views/sourcetrace/SourceTrace.vue
@@ -1,18 +1,32 @@
 <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">
@@ -27,21 +41,25 @@
             <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> -->
             <!-- 鏁版嵁鍒囩墖缁熻 -->
             <div style="border-left: 1px solid white" class="p-l-8">
               <el-space direction="vertical">
-                <el-text type="primary">婧簮锛歿{ countMsg1.type1 }}鏉�</el-text>
-                <el-text type="primary">绾跨储锛歿{ countMsg1.type2 }}鏉�</el-text>
-                <el-text type="primary">鎻愰啋锛歿{ countMsg1.type3 }}鏉�</el-text>
+                <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">
+          <el-scrollbar
+            ref="scrollbarRef"
+            class="scrollbar"
+            v-loading="loading"
+          >
             <TransitionGroup name="list">
               <div
                 v-for="item in filterStreams"
@@ -57,10 +75,25 @@
         </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>
@@ -72,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';
@@ -85,30 +119,57 @@
 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 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;
@@ -123,9 +184,9 @@
   }, 100);
 }
 
-const streams = reactive([]);
+const streams = ref([]);
 const filterStreams = computed(() => {
-  return streams.filter((v) => {
+  return streams.value.filter((v) => {
     // 鍒ゆ柇娑堟伅绫诲瀷鏄惁閫変腑
     const b1 = selectedMsgTypes.value.indexOf(v._type) != -1;
     let b2, b3;
@@ -133,9 +194,16 @@
       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) {
+        if (
+          v.pollutedSource == undefined ||
+          v.pollutedSource.sceneList.length == 0
+        ) {
           b3 = selectedSceneTypes.value.indexOf(NO_SCENE) != -1;
         } else {
           b3 =
@@ -163,7 +231,7 @@
     type2: 0,
     type3: 0
   };
-  streams.forEach((v) => {
+  streams.value.forEach((v) => {
     switch (v._type) {
       case '1':
         count.type1++;
@@ -187,10 +255,15 @@
 function dealMsg(data) {
   const { type, content } = websocketMsgParser.parseMsg(data);
   const obj = reactive(JSON.parse(content));
-  obj._type = type;
+  if (obj.deviceCode == props.deviceCode) {
+    obj._type = type;
+    dealObj(obj);
+  }
+}
 
+function dealObj(obj) {
   // 姹℃煋绾跨储 PollutedClue
-  if (type == '1') {
+  if (obj._type == '1') {
     obj.showMore = false;
     console.log('姹℃煋寮傚父鍒囩墖: ', obj);
 
@@ -201,13 +274,13 @@
     // scrollToTop();
     // drawPolygon(obj.pollutedArea);
     parseChartData(obj);
-  } else if (type == '2') {
+  } else if (obj._type == '2') {
     // const obj = JSON.parse(content);
     // obj._type = type;
     console.log('姹℃煋绾跨储缁撴灉: ', obj);
     obj._timestr = timeFormatter(obj.time);
     addNewMsg(obj);
-  } else if (type == '3') {
+  } else if (obj._type == '3') {
     console.log('姹℃煋鎻愰啋鍒囩墖: ', obj);
     addNewMsg(obj);
     parseChartData(obj);
@@ -222,37 +295,43 @@
     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);
-      }
-      // 绛涢�夊満鏅被鍨�
-      if (objData.pollutedSource.sceneList.length == 0) {
-        // 鑻ユ病鏈夋壘鍒伴闄╂簮鏃讹紝灏嗚鍒嗙被璁惧畾涓簄ull
-        if (sceneOptions.value.findIndex((v) => v.value == NO_SCENE) == -1) {
-          sceneOptions.value.push({
-            label: '鏃�',
-            value: NO_SCENE
+      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
           });
-          selectedSceneTypes.value.push(NO_SCENE);
+          selectedFactorTypes.value.push(value.factorId);
         }
-      } else {
-        objData.pollutedSource.sceneList.forEach((s) => {
-          if (sceneOptions.value.findIndex((v) => v.value == s.typeId) == -1) {
+      }
+
+      // 绛涢�夊満鏅被鍨�
+      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: s.type,
-              value: s.typeId
+              label: '鏈煡',
+              value: NO_SCENE
             });
-            selectedSceneTypes.value.push(s.typeId);
+            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;
@@ -264,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;
@@ -278,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);
@@ -297,29 +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':
-    case '3':
-      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));
@@ -336,7 +468,7 @@
   } else {
     if (polygonMap.has(item.guid)) {
       map.remove(polygonMap.get(item.guid));
-      selectedException.value._selected = false;
+      item._selected = false;
     }
   }
 }
@@ -368,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>
@@ -486,7 +539,7 @@
   --el-statistic-content-color: white;
 }
 
-:deep(.el-text.el-text--primary) {
+:deep(.el-text.el-text--info) {
   --el-text-color: white;
 }
 
@@ -512,7 +565,7 @@
 .scrollbar {
   width: 400px;
   /* max-width: 60vw; */
-  height: 45vh;
+  height: 65vh;
   /* color: #02ffea; */
   padding-right: 10px;
 }

--
Gitblit v1.9.3