From c2e36c45578e63ad17c5e258c92d62d9ae03dadb Mon Sep 17 00:00:00 2001
From: riku <risaku@163.com>
Date: 星期五, 30 五月 2025 11:55:52 +0800
Subject: [PATCH] Merge branch 'master' of ssh://114.215.109.124:29418/underway-vue

---
 src/views/sourcetrace/SourceTrace.vue   |  209 +++++++++++++++++++++-
 src/utils/factor/data.js                |    5 
 src/views/historymode/HistoryMode.vue   |    2 
 src/components/monitor/FactorRadio.vue  |   13 +
 src/api/index.js                        |    7 
 src/main.js                             |    1 
 src/api/websocket.js                    |    2 
 src/utils/map/sector.js                 |  131 ++++++++++----
 src/components.d.ts                     |    4 
 src/views/realtimemode/RealtimeMode.vue |   35 +--
 src/components/scene/SceneTable.vue     |  113 ++++++++++++
 11 files changed, 442 insertions(+), 80 deletions(-)

diff --git a/src/api/index.js b/src/api/index.js
index 130eb33..674b83a 100644
--- a/src/api/index.js
+++ b/src/api/index.js
@@ -12,9 +12,10 @@
 }
 
 if (debug) {
-  ip1 = 'http://192.168.0.110:8084/';
-  // ip1 = 'http://locahost:8084/';
-  ws = `192.168.0.110:9031`;
+  // ip1 = 'http://192.168.0.110:8084/';
+  ip1 = 'http://localhost:8084/';
+  // ws = `192.168.0.110:9031`;
+  ws = `localhost:9031`;
 }
 
 const $http = axios.create({
diff --git a/src/api/websocket.js b/src/api/websocket.js
index 1bb3cc4..682d08f 100644
--- a/src/api/websocket.js
+++ b/src/api/websocket.js
@@ -18,7 +18,7 @@
   };
   // 鏀跺埌鏈嶅姟鍣ㄥ彂閫佺殑娑堟伅锛歟vent澶勭悊鏈嶅姟鍣ㄨ繑鍥炵殑鏁版嵁
   socket.onmessage = (event) => {
-    console.log('receive: ', event.data);
+    // console.log('receive: ', event.data);
     onMsgEvents.forEach((e) => {
       if (typeof e === 'function') {
         e(event.data);
diff --git a/src/components.d.ts b/src/components.d.ts
index 12e94ad..d85f428 100644
--- a/src/components.d.ts
+++ b/src/components.d.ts
@@ -40,6 +40,7 @@
     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']
     ElPopover: typeof import('element-plus/es')['ElPopover']
@@ -50,11 +51,13 @@
     ElSelect: typeof import('element-plus/es')['ElSelect']
     ElSlider: typeof import('element-plus/es')['ElSlider']
     ElSpace: typeof import('element-plus/es')['ElSpace']
+    ElStatistic: typeof import('element-plus/es')['ElStatistic']
     ElSwitch: typeof import('element-plus/es')['ElSwitch']
     ElTable: typeof import('element-plus/es')['ElTable']
     ElTableColumn: typeof import('element-plus/es')['ElTableColumn']
     ElTabPane: typeof import('element-plus/es')['ElTabPane']
     ElTabs: typeof import('element-plus/es')['ElTabs']
+    ElTag: typeof import('element-plus/es')['ElTag']
     ElText: typeof import('element-plus/es')['ElText']
     FactorCheckbox: typeof import('./components/monitor/FactorCheckbox.vue')['default']
     FactorLegend: typeof import('./components/monitor/FactorLegend.vue')['default']
@@ -82,6 +85,7 @@
     RouterLink: typeof import('vue-router')['RouterLink']
     RouterView: typeof import('vue-router')['RouterView']
     SceneSearch: typeof import('./components/scene/SceneSearch.vue')['default']
+    SceneTable: typeof import('./components/scene/SceneTable.vue')['default']
     SearchBar: typeof import('./components/search/SearchBar.vue')['default']
     SliderBar: typeof import('./components/SliderBar.vue')['default']
     TrajectoryState: typeof import('./components/animation/TrajectoryState.vue')['default']
diff --git a/src/components/monitor/FactorRadio.vue b/src/components/monitor/FactorRadio.vue
index c686f68..e95e72d 100644
--- a/src/components/monitor/FactorRadio.vue
+++ b/src/components/monitor/FactorRadio.vue
@@ -17,13 +17,17 @@
 
 export default {
   props: {
+    modelValue: {
+      type: String,
+      default: defaultOptions(TYPE0).value
+    },
     deviceType: {
       type: String,
       // type0: 杞﹁浇鎴栨棤浜烘満; type1:鏃犱汉鑸�
       default: TYPE0
     }
   },
-  emits: ['change'],
+  emits: ['change', 'update:modelValue'],
   data() {
     return {
       radio: defaultOptions(TYPE0).value
@@ -38,6 +42,12 @@
     deviceType(nV, oV) {
       if (nV != oV) {
         this.radio = this.options[0].value;
+        this.$emit('update:modelValue', this.radio)
+      }
+    },
+    modelValue(nV, oV){
+      if (nV != oV) {
+        this.radio = nV
       }
     }
   },
@@ -45,6 +55,7 @@
     handleChange(value) {
       const item = this.options.find((v) => v.value == value);
       this.$emit('change', item.value, item);
+      this.$emit('update:modelValue', item.value)
       // todo 鍦板浘3d鍥惧儚鍒囨崲灞曠ず鐩戞祴鍥犲瓙
     }
   }
diff --git a/src/components/scene/SceneTable.vue b/src/components/scene/SceneTable.vue
new file mode 100644
index 0000000..9aa89ac
--- /dev/null
+++ b/src/components/scene/SceneTable.vue
@@ -0,0 +1,113 @@
+<template>
+  <el-table
+    :data="sceneList"
+    table-layout="fixed"
+    size="small"
+    height="30vh"
+    :show-overflow-tooltip="true"
+    border
+    row-class-name="t-row"
+    cell-class-name="t-cell"
+    header-row-class-name="t-header-row"
+    header-cell-class-name="t-header-cell"
+    @row-click="handleRowClick"
+    @filter-change="handleFilterChange"
+  >
+    <el-table-column type="index" label="#" width="25" />
+    <el-table-column
+      prop="type"
+      label="绫诲瀷"
+      width="56"
+      column-key="type"
+      :filters="sceneTypeFilter"
+      :filter-method="filterHandler"
+    />
+    <el-table-column prop="name" label="鍚嶇О" />
+    <!-- <el-table-column prop="location" label="鍦板潃" /> -->
+    <el-table-column
+      prop="districtName"
+      label="鍖哄幙"
+      align="center"
+      width="54"
+    />
+    <!-- <el-table-column label="绠$悊" width="70" align="center">
+      <template #default="{ row }">
+        <el-button
+          type="primary"
+          size="small"
+          class="el-button-custom"
+          @click="deleteDevice(row)"
+          >鍒犻櫎</el-button
+        >
+      </template>
+    </el-table-column> -->
+  </el-table>
+</template>
+<script setup>
+import { ref, computed, watch } from 'vue';
+import { sceneTypes, sceneIcon } from '@/constant/scene-types';
+import MapUtil from '@/utils/map/util';
+import marks from '@/utils/map/marks';
+
+const props = defineProps({
+  sceneList: Array
+});
+
+let layer = undefined;
+
+let showSceneTypes = ref([]);
+
+const sceneTypeFilter = computed(() => {
+  return sceneTypes()
+    .filter((v) => {
+      return !v.disabled;
+    })
+    .map((v) => {
+      return { text: v.label, value: v.label };
+    });
+});
+
+const showSceneList = computed(() => {
+  if (showSceneTypes.value.length == 0) {
+    return props.sceneList;
+  } else {
+    return props.sceneList.filter((v) => {
+      return showSceneTypes.value.indexOf(v.type) != -1;
+    });
+  }
+});
+
+watch(showSceneList, (nV, oV) => {
+  if (nV != oV) {
+    drawMarks(nV);
+  }
+});
+
+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, false);
+  }
+}
+
+function handleRowClick(row, col, event) {
+  MapUtil.setCenter([row.longitude, row.latitude], true);
+}
+
+function filterHandler(value, row, column) {
+  const property = column['property'];
+  return row[property] === value;
+}
+
+function handleFilterChange(newFilters) {
+  // console.log(newFilters);
+  showSceneTypes.value = newFilters['type'];
+}
+</script>
diff --git a/src/main.js b/src/main.js
index 559499c..5c317b9 100644
--- a/src/main.js
+++ b/src/main.js
@@ -4,6 +4,7 @@
 import { createApp } from 'vue';
 import { createPinia } from 'pinia';
 import * as ElementPlusIconsVue from '@element-plus/icons-vue';
+import 'element-plus/theme-chalk/dark/css-vars.css';
 import 'element-plus/theme-chalk/src/overlay.scss';
 import 'element-plus/theme-chalk/src/message.scss';
 import 'element-plus/theme-chalk/src/message-box.scss';
diff --git a/src/utils/factor/data.js b/src/utils/factor/data.js
index 80f5e14..4f47e41 100644
--- a/src/utils/factor/data.js
+++ b/src/utils/factor/data.js
@@ -186,7 +186,7 @@
  * 寮�鍚疄鏃舵暟鎹惊鐜幏鍙�
  * @param {Object} params
  */
-function startLoopFetchRealTimeData(onParam, callback) {
+function startLoopFetchRealTimeData(onParam, callback, _interval) {
   // 鏃堕棿闂撮殧
   let interval;
   // 鏁版嵁鑾峰彇鏂规硶
@@ -199,6 +199,9 @@
     fetchFun = fetchOriginRealTimeData;
     interval = 10 * 1000;
   }
+  if (_interval) {
+    interval = _interval
+  }
   // 寮�濮嬪惊鐜换鍔�
   clearFetchingTask();
   fetchingTask = setInterval(() => {
diff --git a/src/utils/map/sector.js b/src/utils/map/sector.js
index 25ae2d5..f409e4d 100644
--- a/src/utils/map/sector.js
+++ b/src/utils/map/sector.js
@@ -9,6 +9,9 @@
   // 鍔ㄧ敾杞ㄨ抗
   _sectorViewsAna = new Map();
 
+var _ptSector = undefined,
+  _ptSectorViews = new Map();
+
 const zoomStyleMapping = {
   14: 0,
   15: 0,
@@ -107,7 +110,14 @@
   });
 }
 
-function drawSectorMesh(sDeg, eDeg, lnglat, distance, distance2) {
+function drawSectorMesh(
+  sDeg,
+  eDeg,
+  lnglat,
+  distance,
+  distance2,
+  isPollutinTrace
+) {
   if (distance == 0 || distance2 == 0) {
     return false;
   }
@@ -143,59 +153,77 @@
     geometry.vertices.push(p0.x, p0.y, 0);
     geometry.vertices.push(l3.x, l3.y, 0);
     geometry.vertices.push(l4.x, l4.y, 0);
-    // 澶栦晶鎵囧舰
-    geometry.vertices.push(l3.x, l3.y, 0);
-    geometry.vertices.push(l4.x, l4.y, 0);
-    geometry.vertices.push(l1.x, l1.y, 0);
-    geometry.vertices.push(l2.x, l2.y, 0);
+    if (!isPollutinTrace) {
+      // 鍐呮祴鎵囧舰棰滆壊
+      geometry.vertexColors.push(1, 0.11, 0.25, 0.6);
+      geometry.vertexColors.push(1, 0.11, 0.25, 0.6);
+      geometry.vertexColors.push(1, 0.11, 0.25, 0.6);
+    } else {
+      geometry.vertexColors.push(0.25, 0.11, 1, 0.6);
+      geometry.vertexColors.push(0.25, 0.11, 1, 0.6);
+      geometry.vertexColors.push(0.25, 0.11, 1, 0.6);
+    }
+
+    if (!isPollutinTrace) {
+      // 澶栦晶鎵囧舰
+      geometry.vertices.push(l3.x, l3.y, 0);
+      geometry.vertices.push(l4.x, l4.y, 0);
+      geometry.vertices.push(l1.x, l1.y, 0);
+      geometry.vertices.push(l2.x, l2.y, 0);
+      //澶栦晶鎵囧舰棰滆壊
+      geometry.vertexColors.push(1, 0.37, 0.07, 0.5);
+      geometry.vertexColors.push(1, 0.37, 0.07, 0.5);
+      geometry.vertexColors.push(1, 0.37, 0.07, 0.5);
+      geometry.vertexColors.push(1, 0.37, 0.07, 0.5);
+    }
     // console.log(l3.x + ',' + l3.y + ' | ' + l1.x + ',' + l1.y);
 
-    // 鍐呮祴鎵囧舰棰滆壊
-    geometry.vertexColors.push(1, 0.11, 0.25, 0.6);
-    geometry.vertexColors.push(1, 0.11, 0.25, 0.6);
-    geometry.vertexColors.push(1, 0.11, 0.25, 0.6);
-    //澶栦晶鎵囧舰棰滆壊
-    geometry.vertexColors.push(1, 0.37, 0.07, 0.5);
-    geometry.vertexColors.push(1, 0.37, 0.07, 0.5);
-    geometry.vertexColors.push(1, 0.37, 0.07, 0.5);
-    geometry.vertexColors.push(1, 0.37, 0.07, 0.5);
-
-    var index = i * 7;
-    geometry.faces.push(index, index + 1, index + 2);
-    geometry.faces.push(index + 3, index + 4, index + 5);
-    geometry.faces.push(index + 4, index + 5, index + 6);
+    if (!isPollutinTrace) {
+      const index = i * 7;
+      geometry.faces.push(index, index + 1, index + 2);
+      geometry.faces.push(index + 3, index + 4, index + 5);
+      geometry.faces.push(index + 4, index + 5, index + 6);
+    } else {
+      const index = i * 3;
+      geometry.faces.push(index, index + 1, index + 2);
+      // geometry.faces.push(index + 3, index + 4, index + 5);
+      // geometry.faces.push(index + 4, index + 5, index + 6);
+    }
   }
   object3Dlayer.add(sector);
-  _sector = sector;
+  isPollutinTrace ? (_ptSector = sector) : (_sector = sector);
   return true;
 }
 
-function drawTextMaker(list, list2, distance, distance2) {
+function drawTextMaker(list, list2, distance, distance2, isPollutinTrace) {
+  const _sectorViewsTmp = isPollutinTrace ? _ptSectorViews : _sectorViews;
   //10鍒嗛挓鎵囧舰
-  const a = _sectorViews.get('text10-t');
-  if (a == undefined) {
-    const text10t = textMaker(list[2], '10鍒嗛挓');
-    _sectorViews.set('text10-t', text10t);
-    const textM10t = textMaker(list[1], distance + 'm');
-    _sectorViews.set('textM10-t', textM10t);
-    map.add([text10t, textM10t]);
-  } else {
-    _sectorViews.get('text10-t').setPosition(list[2]);
-    _sectorViews.get('textM10-t').setPosition(list[1]);
-    _sectorViews.get('textM10-t').setText(distance + 'm');
+  if (!isPollutinTrace) {
+    const a = _sectorViewsTmp.get('text10-t');
+    if (a == undefined) {
+      const text10t = textMaker(list[2], '10鍒嗛挓');
+      _sectorViewsTmp.set('text10-t', text10t);
+      const textM10t = textMaker(list[1], distance + 'm');
+      _sectorViewsTmp.set('textM10-t', textM10t);
+      map.add([text10t, textM10t]);
+    } else {
+      _sectorViewsTmp.get('text10-t').setPosition(list[2]);
+      _sectorViewsTmp.get('textM10-t').setPosition(list[1]);
+      _sectorViewsTmp.get('textM10-t').setText(distance + 'm');
+    } 
   }
   //5鍒嗛挓鎵囧舰
-  const b = _sectorViews.get('text5-t');
+  const b = _sectorViewsTmp.get('text5-t');
   if (b == undefined) {
     const text5t = textMaker(list2[1], '5鍒嗛挓');
-    _sectorViews.set('text5-t', text5t);
+    _sectorViewsTmp.set('text5-t', text5t);
     const textM5t = textMaker(list2[0], distance2 + 'm');
-    _sectorViews.set('textM5-t', textM5t);
+    _sectorViewsTmp.set('textM5-t', textM5t);
     map.add([text5t, textM5t]);
   } else {
-    _sectorViews.get('text5-t').setPosition(list2[1]);
-    _sectorViews.get('textM5-t').setPosition(list2[0]);
-    _sectorViews.get('textM5-t').setText(distance2 + 'm');
+    _sectorViewsTmp.get('text5-t').setPosition(list2[1]);
+    _sectorViewsTmp.get('textM5-t').setPosition(list2[0]);
+    _sectorViewsTmp.get('textM5-t').setText(distance2 + 'm');
   }
 }
 
@@ -232,6 +260,19 @@
       _sectorViews.clear();
     }
     this.clearSectorMesh();
+  },
+  clearSectorPt() {
+    var list = [];
+    for (const iterator of _ptSectorViews) {
+      list.push(iterator[1]);
+    }
+    if (list.length > 0) {
+      map.remove(list);
+      _ptSectorViews.clear();
+    }
+    if (_ptSector) {
+      object3Dlayer.remove(_ptSector);
+    }
   },
   /**
    * 鍙竻绌烘墖褰�
@@ -272,5 +313,17 @@
     if (drawSectorMesh(sDeg, eDeg, lnglat, distance, distance2)) {
       drawTextMaker(list, list2, distance, distance2);
     }
+  },
+
+  drawSectorPt(fDatas, i) {
+    if (_ptSector) {
+      object3Dlayer.remove(_ptSector);
+    }
+    const { sDeg, eDeg, lnglat, distance, distance2, list, list2 } =
+      sectorParams(fDatas, i);
+    if (drawSectorMesh(sDeg, eDeg, lnglat, distance, distance2, true)) {
+      drawTextMaker(list, list2, distance, distance2, true);
+    }
+    return { p: lnglat, r: distance };
   }
 };
diff --git a/src/views/historymode/HistoryMode.vue b/src/views/historymode/HistoryMode.vue
index 99b1303..2ced9f5 100644
--- a/src/views/historymode/HistoryMode.vue
+++ b/src/views/historymode/HistoryMode.vue
@@ -120,7 +120,7 @@
       if (nValue != oValue && this.status == 0) {
         Layer.clear();
         this.draw();
-        this.drawHighlightPollution();
+        // this.drawHighlightPollution();
       }
     }
   },
diff --git a/src/views/realtimemode/RealtimeMode.vue b/src/views/realtimemode/RealtimeMode.vue
index 41e5d4e..395cc4a 100644
--- a/src/views/realtimemode/RealtimeMode.vue
+++ b/src/views/realtimemode/RealtimeMode.vue
@@ -6,15 +6,18 @@
     <el-row class="m-t-2">
       <FactorRadio
         :device-type="deviceType"
-        @change="(e) => (factorType = e)"
+        v-model="factorType"
       ></FactorRadio>
     </el-row>
     <el-row class="m-t-2">
-      <FactorLegend
-        class="m-t-2"
-        :factor="factorDatas.factor[factorType]"
-      ></FactorLegend>
-      <SourceTrace></SourceTrace>
+      <el-col span="1">
+        <FactorLegend
+          :factor="factorDatas.factor[factorType]"
+        ></FactorLegend>
+      </el-col>
+      <el-col span="1">
+        <SourceTrace v-model:factorType="factorType"></SourceTrace>
+      </el-col>
     </el-row>
     <DashBoard class="dash-board" :factor-datas="factorDatas"></DashBoard>
     <RealTimeTrend
@@ -118,8 +121,8 @@
           mode == 'debug'
             ? {
                 deviceCode: this.deviceCode,
-                startTime: '2025-01-16 11:30:00',
-                endTime: '2025-01-16 11:32:00',
+                startTime: '2025-01-16 11:34:00',
+                endTime: '2025-01-16 11:35:00',
                 page,
                 perPage: 100
               }
@@ -145,14 +148,15 @@
           return {
             deviceCode: this.deviceCode,
             updateTime: this.latestTime,
-            perPage: 10
+            perPage: mode == 'debug' ? 1 : 10
           };
         },
         (res) => {
           this.onFetchData(res.data);
           this.onMapData(res.data);
           thirdPartyDataApi.fetchLatestData(this.deviceType, this.deviceCode);
-        }
+        },
+        mode == 'debug' ? 4000 : undefined
       );
     },
     onMapData(dataList) {
@@ -174,14 +178,9 @@
     }
   },
   mounted() {
-    // this.fetchRealTimeData();
-    // startLoopFetchRealTimeData({
-    //   compUser: 'user1',
-    //   compPassword: 'User1@jingan',
-    //   mn: 'TX105',
-    //   dtFrom: '2024-08-07 10:00:00',
-    //   dtTo: '2024-08-07 10:00:59'
-    // });
+    if (mode == 'debug') {
+      websocket.send('start');
+    }
   },
   unmounted() {
     this.clearFetchingTask();
diff --git a/src/views/sourcetrace/SourceTrace.vue b/src/views/sourcetrace/SourceTrace.vue
index b4a2a63..86de084 100644
--- a/src/views/sourcetrace/SourceTrace.vue
+++ b/src/views/sourcetrace/SourceTrace.vue
@@ -1,21 +1,78 @@
 <template>
-  <BaseCard>
-    <template #content>
-      <div>
+  <el-row>
+    <el-col v-show="show" span="10">
+      <BaseCard>
+        <template #content>
+          <!-- <div>
         <el-input type="text" v-model="inputVal" />
         <button @click="handleSend">send</button>
         <button @click="handleLink">link</button>
-      </div>
-      <div>涓氬姟鐘舵�佷腑鎺�</div>
-      <el-scrollbar ref="scrollbarRef" :height="height">
-        <div ref="scrollContentRef">
-          <div v-for="(item, index) in streams" :key="index">
-            <el-text type="primary">[{{ item }}]: </el-text>
-          </div>
-        </div>
-      </el-scrollbar>
-    </template>
-  </BaseCard>
+      </div> -->
+          <div>鍔ㄦ�佹函婧�</div>
+          <el-scrollbar ref="scrollbarRef" :height="height" class="scrollbar">
+            <div ref="scrollContentRef">
+              <div v-for="(item, index) in streams" :key="index">
+                <!-- <el-text type="primary">{{ item.guid }}</el-text> -->
+                <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 />
+              </div>
+            </div>
+          </el-scrollbar>
+        </template>
+      </BaseCard>
+    </el-col>
+    <el-col span="2">
+      <CardButton name="鍔ㄦ�佹函婧�" @click="() => (show = !show)"></CardButton>
+    </el-col>
+  </el-row>
 </template>
 <script setup>
 /**
@@ -24,9 +81,21 @@
  */
 import { reactive, ref, onMounted, onUnmounted, inject } 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 { FactorDatas } from '@/model/FactorDatas';
+
+const props = defineProps({
+  factorType: String
+});
+
+const emits = defineEmits(['update:factorType']);
 
 const height = `60vh`;
 
+const show = ref(false);
 const scrollContentRef = ref();
 const scrollbarRef = ref();
 
@@ -34,6 +103,12 @@
   const h1 = scrollContentRef.value.clientHeight + 100;
   setTimeout(() => {
     scrollbarRef.value.setScrollTop(h1);
+  }, 100);
+}
+
+function scrollToTop() {
+  setTimeout(() => {
+    scrollbarRef.value.setScrollTop(0);
   }, 100);
 }
 
@@ -50,14 +125,116 @@
  */
 const putWorkStream = (data) => {
   const obj = JSON.parse(data);
-  streams.push(obj);
-  scrollToBottom();
+  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);
+  }
+}
 
 onMounted(() => {
   websocket.registerReceiveEvent(putWorkStream);
 });
 onUnmounted(() => {
   websocket.removeReceiveEvent(putWorkStream);
+  sector.clearSectorPt();
+  mapUtil.clearMap();
+  // if (layer != undefined) {
+  //   mapUtil.removeViews(layer);
+  //   layer = undefined;
+  // }
 });
 </script>
+<style scoped>
+:deep(.el-statistic) {
+  --el-statistic-title-color: rgb(215, 215, 215);
+  --el-statistic-content-color: white;
+}
+
+:deep(.el-text) {
+  --el-text-color: white;
+}
+
+.scrollbar {
+  min-width: 300px;
+}
+</style>

--
Gitblit v1.9.3