Преглед изворни кода

[Mod 0000] 首页地图执法处标记信息更新,popup交互逻辑更新及样式优化

Co-authored-by: Copilot <copilot@github.com>
houzekong пре 1 недеља
родитељ
комит
116fe35263

Разлика између датотеке није приказан због своје велике величине
+ 0 - 0
public/js/shanxi.geo.json


+ 11 - 11
public/js/shanxi.map.json

@@ -3855,7 +3855,7 @@
       "layout": {
         "symbol-placement": "line",
         "symbol-spacing": 350,
-        "text-field": "{name:latin}\n{name:nonlatin}",
+        "text-field": "{name:nonlatin}",
         "text-font": [
           "Noto Sans Italic"
         ],
@@ -3927,7 +3927,7 @@
       "layout": {
         "symbol-placement": "point",
         "symbol-spacing": 350,
-        "text-field": "{name:latin}\n{name:nonlatin}",
+        "text-field": "{name:nonlatin}",
         "text-font": [
           "Noto Sans Italic"
         ],
@@ -3988,7 +3988,7 @@
       "layout": {
         "icon-image": "{class}_11",
         "text-anchor": "top",
-        "text-field": "{name:latin}\n{name:nonlatin}",
+        "text-field": "{name:nonlatin}",
         "text-font": [
           "Noto Sans Regular"
         ],
@@ -4047,7 +4047,7 @@
       "layout": {
         "icon-image": "{class}_11",
         "text-anchor": "top",
-        "text-field": "{name:latin}\n{name:nonlatin}",
+        "text-field": "{name:nonlatin}",
         "text-font": [
           "Noto Sans Regular"
         ],
@@ -4105,7 +4105,7 @@
       "layout": {
         "icon-image": "{class}_11",
         "text-anchor": "top",
-        "text-field": "{name:latin}\n{name:nonlatin}",
+        "text-field": "{name:nonlatin}",
         "text-font": [
           "Noto Sans Regular"
         ],
@@ -4160,7 +4160,7 @@
         "icon-optional": false,
         "text-allow-overlap": false,
         "text-anchor": "top",
-        "text-field": "{name:latin}\n{name:nonlatin}",
+        "text-field": "{name:nonlatin}",
         "text-font": [
           "Noto Sans Regular"
         ],
@@ -4587,7 +4587,7 @@
         "icon-image": "airport_11",
         "icon-size": 1,
         "text-anchor": "top",
-        "text-field": "{name:latin}\n{name:nonlatin}",
+        "text-field": "{name:nonlatin}",
         "text-font": [
           "Noto Sans Regular"
         ],
@@ -4622,7 +4622,7 @@
         "village"
       ],
       "layout": {
-        "text-field": "{name:latin}\n{name:nonlatin}",
+        "text-field": "{name:nonlatin}",
         "text-font": [
           "Noto Sans Regular"
         ],
@@ -4662,7 +4662,7 @@
         "town"
       ],
       "layout": {
-        "text-field": "{name:latin}\n{name:nonlatin}",
+        "text-field": "{name:nonlatin}",
         "text-font": [
           "Noto Sans Regular"
         ],
@@ -4710,7 +4710,7 @@
         ]
       ],
       "layout": {
-        "text-field": "{name:latin}\n{name:nonlatin}",
+        "text-field": "{name:nonlatin}",
         "text-font": [
           "Noto Sans Regular"
         ],
@@ -4761,7 +4761,7 @@
         "icon-image": "star_11",
         "icon-size": 0.8,
         "text-anchor": "left",
-        "text-field": "{name:latin}\n{name:nonlatin}",
+        "text-field": "{name:nonlatin}",
         "text-font": [
           "Noto Sans Regular"
         ],

+ 79 - 29
src/api/sys/map.ts

@@ -25,32 +25,32 @@ export function getShanxiGeoJSON() {
 }
 
 export function getGeoJSON(params: any) {
-  const getFeatColor = (gb) => {
-    const colorMap = {
-      // 邮编前7位:颜色
-      // '1566101': '#14baff',
-      // '1566102': '#14baff',
-      // '1566103': '#ffff12',
-      // '1566104': '#ffff12',
-      // '1566105': '#ffab12',
-      // '1566106': '#ffab12',
-      // '1566107': '#fe1414',
-      // '1566108': '#fe1414',
-      // '1566109': '#fe1414',
-      // '1566111': '#fe1414',
-      '1566101': StatusColorEnum.blue,
-      '1566102': StatusColorEnum.blue,
-      '1566103': StatusColorEnum.yellow,
-      '1566104': StatusColorEnum.yellow,
-      '1566105': StatusColorEnum.gold,
-      '1566106': StatusColorEnum.gold,
-      '1566107': StatusColorEnum.red,
-      '1566108': StatusColorEnum.red,
-      '1566109': StatusColorEnum.green,
-      '1566110': StatusColorEnum.green,
-    };
-    return get(colorMap, gb.slice(0, -2), StatusColorEnum.blue);
-  };
+  // const getFeatColor = (gb) => {
+  //   const colorMap = {
+  //     // 邮编前7位:颜色
+  //     // '1566101': '#14baff',
+  //     // '1566102': '#14baff',
+  //     // '1566103': '#ffff12',
+  //     // '1566104': '#ffff12',
+  //     // '1566105': '#ffab12',
+  //     // '1566106': '#ffab12',
+  //     // '1566107': '#fe1414',
+  //     // '1566108': '#fe1414',
+  //     // '1566109': '#fe1414',
+  //     // '1566111': '#fe1414',
+  //     '1566101': StatusColorEnum.blue,
+  //     '1566102': StatusColorEnum.yellow,
+  //     '1566103': StatusColorEnum.gold,
+  //     '1566104': StatusColorEnum.red,
+  //     '1566105': StatusColorEnum.green,
+  //     '1566106': StatusColorEnum.gray,
+  //     '1566107': StatusColorEnum.orange,
+  //     '1566108': StatusColorEnum.purple,
+  //     '1566109': StatusColorEnum.black,
+  //     '1566110': StatusColorEnum.blue,
+  //   };
+  //   return get(colorMap, gb.slice(0, -2), StatusColorEnum.blue);
+  // };
   const getAlarmColor = (lv) => {
     const colorMap = {
       4: StatusColorEnum.red,
@@ -63,6 +63,41 @@ export function getGeoJSON(params: any) {
     return get(colorMap, lv, StatusColorEnum.blue);
   };
 
+  // const pointInPolygon = (point, polygon) => {
+  //   const x = point[0],
+  //     y = point[1];
+  //   let inside = false;
+  //   for (let i = 0, j = polygon.length - 1; i < polygon.length; j = i++) {
+  //     const xi = polygon[i][0],
+  //       yi = polygon[i][1];
+  //     const xj = polygon[j][0],
+  //       yj = polygon[j][1];
+  //     const intersect = yi > y !== yj > y && x < ((xj - xi) * (y - yi)) / (yj - yi) + xi;
+  //     if (intersect) inside = !inside;
+  //   }
+  //   return inside;
+  // };
+
+  // const pointInMultiPolygon = (point, multiPolygon) => {
+  //   for (const polygon of multiPolygon.coordinates) {
+  //     // 外环
+  //     const outerRing = polygon[0];
+  //     if (pointInPolygon(point, outerRing)) {
+  //       // 检查内环(洞),如果点在任意一个内环内,则不算内部
+  //       let insideHole = false;
+  //       for (let i = 1; i < polygon.length; i++) {
+  //         const hole = polygon[i];
+  //         if (pointInPolygon(point, hole)) {
+  //           insideHole = true;
+  //           break;
+  //         }
+  //       }
+  //       if (!insideHole) return true;
+  //     }
+  //   }
+  //   return false;
+  // };
+
   return Promise.all([getShanxiGeoJSON(), getMarkers(params)]).then(([geojson, { records }]) => {
     const mineStore = useMineDepartmentStore();
 
@@ -118,9 +153,24 @@ export function getGeoJSON(params: any) {
 
     map.clear();
 
-    geojson.features.forEach(({ properties }) => {
-      properties.fillColor = getFeatColor(properties.gb);
-    });
+    // geojson.features.forEach(({ properties, geometry }) => {
+    //   properties.fillColor = getFeatColor(properties.gb);
+    //   // const temp = records.filter((item) => pointInMultiPolygon([item.longitude, item.latitude], geometry));
+    //   const temp = reduceRight(
+    //     records,
+    //     (acc, item) => {
+    //       acc.add(mineStore.getRootId!);
+    //       // 从右边开始,因为父节点都在最后面
+    //       if (pointInMultiPolygon([item.longitude, item.latitude], geometry)) {
+    //         acc.add(item.id);
+    //         acc.add(item.parentId);
+    //       }
+    //       return acc;
+    //     },
+    //     new Set()
+    //   );
+    //   properties.children = [...temp];
+    // });
 
     const markers = {
       type: 'FeatureCollection',

+ 33 - 62
src/layouts/default/feature/SimpleMap.vue

@@ -8,7 +8,7 @@
 
 <script lang="ts" setup>
   import 'vjmap/dist/vjmap.min.css';
-  import { ref, onMounted, onUnmounted, computed } from 'vue';
+  import { ref, onMounted, onUnmounted, computed, createApp } from 'vue';
   import { Button } from 'ant-design-vue';
   import { useAppStore } from '/@/store/modules/app';
   // import { useRoute } from 'vue-router';
@@ -19,9 +19,10 @@
   import { get, last } from 'lodash-es';
   // import { env } from '/@/views/system/cadFile/env';
   import { StatusColorEnum } from '/@/enums/jeecgEnum';
-  import { generatePopupContent, generateSimplePopup } from './hooks/popup';
+  import { generateSimplePopup } from './hooks/popup';
   import { initMap2d, renderGoafMarkers } from '/@/views/system/cadFile/app';
   import { getGoafList } from '/@/views/system/cadFile/cad.api';
+  import LeafPopup from './components/LeafPopup.vue';
   // import { useGlobSetting } from '/@/hooks/setting';
 
   const appStore = useAppStore();
@@ -36,6 +37,7 @@
   // let app: vjmap3d.App;
 
   const GEO_LAYER_ID = 'geojson-layer';
+  const GEO_BORDER_ID = 'geoline-layer';
   const CIRCLE_LAYER_ID = 'circle-layer';
   const SYMBOL_LAYER_ID = 'symbol-layer';
   const DEFAULT_NODE = {
@@ -62,11 +64,12 @@
       fillColor: ['get', 'fillColor'],
       fillOpacity: ['case', ['to-boolean', ['feature-state', 'hover']], 0.6, 0.2],
       fillOutlineColor: '#ff9100', // 边线颜色,没错,确实没有边线宽度这个选项,所以有了下面的LineLayer做边线
-      // filter: ['in', last(historyStack.value) as string, ['get', 'children']],
+      filter: ['in', last(historyStack.value)!.id, ['get', 'deptIds']],
     });
-    map.addLineLayer('geoline-layer', 'geojson-data', {
+    map.addLineLayer(GEO_BORDER_ID, 'geojson-data', {
       lineColor: '#ff9100',
       lineWidth: 2,
+      filter: ['in', last(historyStack.value)!.id, ['get', 'deptIds']],
     });
     // map.hoverPointer([GEO_LAYER_ID]);
     map.hoverFeatureState(GEO_LAYER_ID);
@@ -92,14 +95,12 @@
     circles.hoverFeatureState();
     circles.hoverPopup(
       (f) => {
-        if (f.properties.isLeaf) {
-          return generatePopupContent(f.properties);
-        } else {
+        if (!f.properties.isLeaf) {
           return generateSimplePopup(f.properties);
         }
       },
       {
-        maxWidth: '500px',
+        maxWidth: '300px',
       }
     );
 
@@ -131,17 +132,33 @@
     appStore.setSimpleMapParams({ deptId: node.id, isLeaf: node.isLeaf });
 
     // 标点点击后,如果是叶节点需要显示CAD图
-    if (node.isLeaf) {
-      toggleCADMap(true, node);
-    } else {
+    if (!node.isLeaf) {
       map.setFilter(CIRCLE_LAYER_ID, ['==', node.id, ['get', 'parentId']]);
       map.setFilter(SYMBOL_LAYER_ID, ['==', node.id, ['get', 'parentId']]);
-      // map.setFilter(GEO_LAYER_ID, ['in', node.id, ['get', 'children']]);
+      map.setFilter(GEO_LAYER_ID, ['in', node.id, ['get', 'deptIds']]);
+      map.setFilter(GEO_BORDER_ID, ['in', node.id, ['get', 'deptIds']]);
 
       map.flyTo({
         center: [node.longitude, node.latitude],
         zoom: node.zoom,
       });
+    } else {
+      const popup = new vjmap.Popup({ maxWidth: '1000' });
+      const app = createApp(LeafPopup, {
+        node,
+        callback() {
+          toggleCADMap(true, node).then(() => {
+            // 将历史栈推一个进去,因为用户要点击返回上一级时需要
+            historyStack.value.push(node);
+          });
+        },
+      });
+      const el = document.createElement('div');
+      app.mount(el);
+      // 将历史栈拉一个出来,因为点击后页面上并没有钻入下一级
+      historyStack.value.pop();
+
+      popup.setLngLat([node.longitude, node.latitude]).setDOMContent(el).addTo(map);
     }
   }
 
@@ -259,63 +276,17 @@
     //   background-color: @map-popup-bg;
     // }
 
-    &-tip {
-      background-color: @map-popup-bg;
+    &-anchor-bottom &-tip {
+      border-top-color: @map-popup-bg;
     }
 
-    .vjmapgis-popup-content {
+    &-content {
       // margin: 13px 20px;
       // min-width: 300px;
       background-color: @map-popup-bg;
+      box-shadow: 0 0 10px #00000088;
       // &__popup {
       // }
-
-      &__divider {
-        height: 1px;
-        background-color: @white;
-        margin: 10px 5px;
-      }
-
-      &__title {
-        color: @white;
-        text-align: center;
-      }
-
-      &__strong {
-        color: @white;
-        text-align: center;
-        font-weight: bold;
-        font-size: 20px;
-      }
-
-      &__board {
-        padding: 10px;
-        border-radius: 5px;
-        background-color: @map-popup-board-bg;
-        color: @text-color-base;
-        display: flex;
-        justify-content: space-between;
-      }
-
-      &__table {
-        color: @white;
-        text-align: center;
-
-        thead {
-          height: 20px;
-        }
-        tbody {
-          tr {
-            background-color: @map-popup-table-th-bg;
-          }
-          tr:nth-child(even) {
-            background-color: @map-popup-table-theven-bg;
-          }
-          td {
-            padding: 5px;
-          }
-        }
-      }
     }
   }
   .map-reset-btn {

+ 165 - 0
src/layouts/default/feature/components/LeafPopup.vue

@@ -0,0 +1,165 @@
+<template>
+  <div style="width: 430px">
+    <div class="vjmapgis-popup-content__title" :style="{ cursor: 'pointer' }" @click="clickHandler">{{ node.mineName }}</div>
+    <div class="vjmapgis-popup-content__divider"></div>
+    <div class="vjmapgis-popup-content__board mb-1">
+      <div class="mr-5px">所属上级</div>
+      <div>{{ node.parentArea }}</div>
+    </div>
+    <div class="vjmapgis-popup-content__board mb-1">
+      <div class="mr-5px">瓦斯等级</div>
+      <div>{{ node.gasLevelName }}</div>
+    </div>
+    <div class="vjmapgis-popup-content__board">
+      <div class="mr-5px">生产状态</div>
+      <div>{{ node.gjMineStatus }}</div>
+    </div>
+    <div class="vjmapgis-popup-content__divider"></div>
+    <div class="vjmapgis-popup-content__table_container">
+      <table class="vjmapgis-popup-content__table w-full mt-1">
+        <thead>
+          <tr>
+            <th>序号</th>
+            <th class="w-200px">煤层名称</th>
+            <th>自然发火倾向性</th>
+          </tr>
+        </thead>
+        <tbody>
+          <tr v-for="(item, index) in coalSeamList" :key="item.id">
+            <td>{{ (index as number) + 1 }}</td>
+            <td>{{ item.coalSeamName }}</td>
+            <td>
+              {{ item.coalSeamLevel }}
+            </td>
+          </tr>
+        </tbody>
+      </table>
+      <div v-if="!goafDataList.length" class="vjmapgis-popup-content__table_empty">暂无数据</div>
+    </div>
+    <div class="vjmapgis-popup-content__divider"></div>
+    <div class="vjmapgis-popup-content__table_container">
+      <table class="vjmapgis-popup-content__table w-full mt-1">
+        <thead>
+          <tr>
+            <th>序号</th>
+            <th class="w-140px">老空区密闭名称</th>
+            <th>最高风险等级</th>
+            <th>通讯状态</th>
+          </tr>
+        </thead>
+        <tbody>
+          <tr v-for="(item, index) in goafDataList" :key="item.id">
+            <td>{{ (index as number) + 1 }}</td>
+            <td>{{ item.devicePos }}</td>
+            <td
+              :style="{
+                color: get(alarmLevelColor, node.alarmLevel, alarmLevelText[0]),
+              }"
+            >
+              {{ get(alarmLevelText, node.alarmLevel, alarmLevelText[0]) }}
+            </td>
+            <td
+              :style="{
+                color: get(alarmLevelColor, node.linkStatus, linkStatusText[0]),
+              }"
+            >
+              {{ get(linkStatusText, node.linkStatus, linkStatusText[0]) }}
+            </td>
+          </tr>
+        </tbody>
+      </table>
+      <div v-if="!goafDataList.length" class="vjmapgis-popup-content__table_empty">暂无数据</div>
+    </div>
+  </div>
+</template>
+<script lang="ts" setup>
+  import { get } from 'lodash-es';
+  import { computed, ref } from 'vue';
+  import { StatusColorEnum } from '/@/enums/jeecgEnum';
+
+  const props = defineProps<{
+    node: any;
+    callback: any;
+  }>();
+
+  function clickHandler() {
+    props.callback(props.node);
+  }
+  console.log('debug rr', props.node);
+  const linkStatusText = ref(['断线', '正常', '标校']);
+  const alarmLevelText = ref(['暂无信息', '低风险', '一般风险', '较高风险', '高风险']);
+  const alarmLevelColor = ref([StatusColorEnum.red, StatusColorEnum.blue, StatusColorEnum.gold, StatusColorEnum.purple, StatusColorEnum.red]);
+
+  const coalSeamList = computed(() => {
+    return JSON.parse(props.node.coalSeamList);
+  });
+  const goafDataList = computed(() => {
+    return JSON.parse(props.node.goafDataList);
+  });
+</script>
+<style lang="less">
+  .vjmapgis-popup-content {
+    &__divider {
+      height: 1px;
+      background-color: @white;
+      margin: 10px 5px;
+    }
+
+    &__title {
+      margin-top: 10px;
+      font-size: 20px;
+      color: @white;
+      text-align: center;
+    }
+
+    &__strong {
+      color: @white;
+      text-align: center;
+      font-weight: bold;
+      font-size: 20px;
+    }
+
+    &__board {
+      font-size: 14px;
+      padding: 10px;
+      border-radius: 5px;
+      background-color: @map-popup-board-bg;
+      color: @text-color-base;
+      display: flex;
+      justify-content: space-between;
+    }
+
+    &__table_container {
+      max-height: 200px;
+      overflow-y: auto;
+    }
+
+    &__table {
+      color: @white;
+      text-align: center;
+      font-size: 14px;
+
+      thead {
+        height: 20px;
+      }
+      tbody {
+        tr {
+          background-color: @map-popup-table-th-bg;
+        }
+        tr:nth-child(even) {
+          background-color: @map-popup-table-theven-bg;
+        }
+        td {
+          padding: 5px;
+        }
+      }
+    }
+
+    &__table_empty {
+      font-size: 14px;
+      width: 100%;
+      text-align: center;
+      background-color: @map-popup-table-theven-bg;
+    }
+  }
+</style>

+ 0 - 60
src/layouts/default/feature/hooks/popup.ts

@@ -1,63 +1,3 @@
-import { get } from 'lodash-es';
-import { StatusColorEnum } from '/@/enums/jeecgEnum';
-
-// 状态文本与颜色映射(直接使用枚举值)
-export const linkStatusText = ['断线', '正常', '标校'];
-export const alarmLevelText = ['暂无信息', '低风险', '一般风险', '较高风险', '高风险'];
-export const alarmLevelColor = [StatusColorEnum.red, StatusColorEnum.blue, StatusColorEnum.gold, StatusColorEnum.purple, StatusColorEnum.red];
-
-/**
- * 生成标准标记点(子节点)的弹出框 HTML
- */
-export function generatePopupContent(data: any): string {
-  const { goafDataList = '[]', id, mineName, parentArea, gasLevelName, gjMineStatus } = data;
-  const list = JSON.parse(goafDataList);
-  const tbodyInnerHtml = list.reduce((html, { devicePos, alarmLevel, linkStatus }, index) => {
-    html += `
-      <tr>
-        <td>${index + 1}</td>
-        <td>${devicePos}</td>
-        <td style="color: ${get(alarmLevelColor, alarmLevel, alarmLevelColor[0])}">${get(alarmLevelText, alarmLevel, alarmLevelText[0])}</td>
-        <td style="color: ${get(alarmLevelColor, linkStatus, alarmLevelColor[0])}">${get(linkStatusText, linkStatus, linkStatusText[0])}</td>
-      </tr>
-    `;
-    return html;
-  }, '');
-
-  return `
-  <div style="width: 330px">
-    <div class="vjmapgis-popup-content__title">${mineName}</div>
-    <div class="vjmapgis-popup-content__divider"></div>
-    <div class="vjmapgis-popup-content__board mb-1">
-      <div class="mr-5px">所属上级</div>
-      <div>${parentArea}</div>
-    </div>
-    <div class="vjmapgis-popup-content__board mb-1">
-      <div class="mr-5px">瓦斯等级</div>
-      <div>${gasLevelName}</div>
-    </div>
-    <div class="vjmapgis-popup-content__board">
-      <div class="mr-5px">生产状态</div>
-      <div>${gjMineStatus}</div>
-    </div>
-    <div class="vjmapgis-popup-content__divider"></div>
-    <table id="${id}" class="vjmapgis-popup-content__table w-full mt-1">
-      <thead>
-        <tr>
-          <th>序号</th>
-          <th>采空区名称</th>
-          <th>风险等级</th>
-          <th>通讯状态</th>
-        </tr>
-      </thead>
-      <tbody>
-        ${tbodyInnerHtml.length ? tbodyInnerHtml : '<tr><td colspan="4">暂无数据</td></tr>'}
-      </tbody>
-    </table>
-  </div>
-  `;
-}
-
 export function generateSimplePopup(data: any): string {
   const { name } = data;
 

+ 7 - 1
src/views/analysis/warningAnalysis/reportAnalysis/index.vue

@@ -106,7 +106,13 @@
   // 注册历史数据表格
   const { tableContext, onExportXls } = useListPage({
     tableProps: {
-      columns,
+      columns: [
+        ...columns,
+        {
+          title: '恢复时间',
+          dataIndex: 'endTime',
+        },
+      ],
       // columns: historyColumns,
       api: getProvinceAlarmHistory,
       formConfig: {

Неке датотеке нису приказане због велике количине промена