ソースを参照

Merge branch 'master' of http://39.97.59.228:8013/hrx/goaf-monitoring-system

lxh 3 ヶ月 前
コミット
d925ec2bf5
60 ファイル変更3120 行追加9474 行削除
  1. 1 1
      package.json
  2. 478 7177
      pnpm-lock.yaml
  3. 6 5
      src/api/sys/menu.ts
  4. BIN
      src/assets/font/D-DIN-Bold.otf
  5. BIN
      src/assets/font/D-DIN.otf
  6. BIN
      src/assets/images/sealedGoaf/configurable/miniBoard/board-bg-A-1.png
  7. BIN
      src/assets/images/sealedGoaf/configurable/miniBoard/board-bg-A-11.png
  8. BIN
      src/assets/images/sealedGoaf/configurable/miniBoard/board-bg-A-2.png
  9. BIN
      src/assets/images/sealedGoaf/configurable/miniBoard/board-bg-A-3.png
  10. BIN
      src/assets/images/sealedGoaf/configurable/miniBoard/board-bg-A-4.png
  11. BIN
      src/assets/images/sealedGoaf/configurable/miniBoard/board-bg-A-5.png
  12. 7 5
      src/components/Configurable/ModulePrimary.vue
  13. 5 2
      src/components/Configurable/detail/CustomChart.vue
  14. 48 6
      src/components/Configurable/detail/CustomTable.vue
  15. 41 31
      src/components/Configurable/detail/MiniBoard.vue
  16. 6 2
      src/components/Configurable/preset/BlastDelta.vue
  17. 5 8
      src/components/Configurable/types.ts
  18. 183 183
      src/components/Container/src/AdaptiveContainer.vue
  19. 5 5
      src/components/Form/src/hooks/useFormEvents.ts
  20. 2 1
      src/components/Table/src/hooks/useTableScroll.ts
  21. 2 0
      src/design/color.less
  22. 34 0
      src/design/public.less
  23. 11 1
      src/views/analysis/warningAnalysis/airLeakStatus/airLeak.api.ts
  24. 76 143
      src/views/analysis/warningAnalysis/airLeakStatus/airLeakStatus.data.ts
  25. 100 71
      src/views/analysis/warningAnalysis/airLeakStatus/index.vue
  26. 21 8
      src/views/analysis/warningAnalysis/autoFireAnalysis/autoFire.api.ts
  27. 19 5
      src/views/analysis/warningAnalysis/autoFireAnalysis/autoFireAnalysis.data.ts
  28. 24 42
      src/views/analysis/warningAnalysis/autoFireAnalysis/index.vue
  29. 56 58
      src/views/analysis/warningAnalysis/connectAnalysis/index.vue
  30. 18 9
      src/views/analysis/warningAnalysis/fireAreaJudgeAnalysis/fireAreaJudge.api.ts
  31. 22 12
      src/views/analysis/warningAnalysis/fireAreaJudgeAnalysis/fireAreaJudgeAnalysis.data.ts
  32. 65 84
      src/views/analysis/warningAnalysis/fireAreaJudgeAnalysis/index.vue
  33. 65 84
      src/views/analysis/warningAnalysis/overlimitAlarm/index.vue
  34. 23 9
      src/views/analysis/warningAnalysis/overlimitAlarm/overlimit.api.ts
  35. 18 4
      src/views/analysis/warningAnalysis/overlimitAlarm/overlimitAlarm.data.ts
  36. 81 108
      src/views/analysis/warningAnalysis/pressureDiffAnalysis/index.vue
  37. 19 8
      src/views/analysis/warningAnalysis/pressureDiffAnalysis/pressureDiff.api.ts
  38. 17 5
      src/views/analysis/warningAnalysis/pressureDiffAnalysis/pressureDiffAnalysis.data.ts
  39. 73 92
      src/views/analysis/warningAnalysis/sealRiskJudgeAnalysis/index.vue
  40. 20 9
      src/views/analysis/warningAnalysis/sealRiskJudgeAnalysis/sealRiskJudge.api.ts
  41. 22 8
      src/views/analysis/warningAnalysis/sealRiskJudgeAnalysis/sealRiskJudgeAnalysis.data.ts
  42. 19 19
      src/views/dashboard/SealedGoaf/configurable.data.sealedGoaf.ts
  43. 50 59
      src/views/dashboard/basicInfo/accessStatistics/access.data.ts
  44. 75 23
      src/views/dashboard/basicInfo/accessStatistics/index.vue
  45. 2 2
      src/views/dashboard/basicInfo/basicInfo.api.ts
  46. 18 4
      src/views/dashboard/basicInfo/closedStatistics/closed.data.ts
  47. 11 10
      src/views/dashboard/basicInfo/closedStatistics/index.vue
  48. 116 156
      src/views/dashboard/basicInfo/dataQuality/dataQuality.data.ts
  49. 267 64
      src/views/dashboard/basicInfo/dataQuality/index.vue
  50. 90 15
      src/views/dashboard/basicInfo/minesInfo/index.vue
  51. 168 158
      src/views/dashboard/basicInfo/minesInfo/minesInfo.data.ts
  52. 13 11
      src/views/monitor/sealedMonitor/components/HistoricalDetailsModal.vue
  53. 130 74
      src/views/monitor/sealedMonitor/components/RealtimeDetailsModal.vue
  54. 44 0
      src/views/monitor/sealedMonitor/hooks/form.ts
  55. 108 78
      src/views/monitor/sealedMonitor/index.vue
  56. 13 2
      src/views/monitor/sealedMonitor/monitor.api.ts
  57. 218 549
      src/views/monitor/sealedMonitor/monitor.data.ts
  58. 11 9
      src/views/system/algorithm/algorithm.api.ts
  59. 129 27
      src/views/system/algorithm/algorithm.data.ts
  60. 65 28
      src/views/system/algorithm/index.vue

+ 1 - 1
package.json

@@ -59,7 +59,6 @@
     "path-to-regexp": "^6.3.0",
     "pinia": "2.1.7",
     "print-js": "^1.6.0",
-    "qiankun": "^2.10.16",
     "qrcode": "^1.5.4",
     "qs": "^6.14.0",
     "resize-observer-polyfill": "^1.5.1",
@@ -80,6 +79,7 @@
     "vxe-table": "4.13.31",
     "vxe-table-plugin-antd": "4.0.8",
     "xe-utils": "3.5.26",
+    "xlsx": "^0.18.5",
     "xss": "^1.0.15"
   },
   "devDependencies": {

ファイルの差分が大きいため隠しています
+ 478 - 7177
pnpm-lock.yaml


+ 6 - 5
src/api/sys/menu.ts

@@ -61,11 +61,12 @@ export const getMenuList: () => Promise<getMenuListResultModel> = () => {
       menu: __STATIC_ROUTES__.map((ele) => {
         if (ele.children && ele.children.length && ele.meta?.generation) {
           const template = ele.children[0];
-          ele.children.push(
-            ...tree.map((d) => {
-              return generateStaticSealedMonitorRoute(template, d);
-            })
-          );
+          const routes = tree.map((d) => {
+            const route = generateStaticSealedMonitorRoute(template, d);
+            route.meta.hideMenu = route.children?.length === 0;
+            return route;
+          });
+          ele.children.push(...routes);
         }
 
         return ele;

BIN
src/assets/font/D-DIN-Bold.otf


BIN
src/assets/font/D-DIN.otf


BIN
src/assets/images/sealedGoaf/configurable/miniBoard/board-bg-A-1.png


BIN
src/assets/images/sealedGoaf/configurable/miniBoard/board-bg-A-11.png


BIN
src/assets/images/sealedGoaf/configurable/miniBoard/board-bg-A-2.png


BIN
src/assets/images/sealedGoaf/configurable/miniBoard/board-bg-A-3.png


BIN
src/assets/images/sealedGoaf/configurable/miniBoard/board-bg-A-4.png


BIN
src/assets/images/sealedGoaf/configurable/miniBoard/board-bg-A-5.png


+ 7 - 5
src/components/Configurable/ModulePrimary.vue

@@ -118,14 +118,16 @@
 
       .common-navL {
         display: flex;
-        color: #234e8e;
-        font-size: 18px;
-        margin-top: -15px;
+        color: #103d82;
+        font-size: 16px;
+        font-style: normal;
+        font-family: 'Microsoft YaHei';
+        font-weight: 700;
+        margin-top: -10px;
         .navL-title {
-          font-weight: 600;
         }
         .navL-slot {
-          padding-left: 20px;
+          padding-left: 10px;
         }
       }
 

+ 5 - 2
src/components/Configurable/detail/CustomChart.vue

@@ -15,6 +15,7 @@
       chartConfig: ModuleDataChart;
       height?: string;
       width?: string;
+      chartOption?: EChartsOption;
     }>(),
     {
       chartData: () => [],
@@ -32,10 +33,10 @@
     const domWidth = inst ? inst.getWidth() : 500;
     // 依据每一个图表配置生成图表选项
     const { yAxis = [], xAxis = [], legend, order, type, sortBy, series, dataZoom = [] } = props.chartConfig;
-    const textStyle = {
+    const textStyle = get(props.chartOption, 'textStyle', {
       color: '#fff',
       // color: '#fff',
-    };
+    });
 
     let sorttedData: any[] = [];
     if (Array.isArray(props.chartData)) {
@@ -427,6 +428,8 @@
             textStyle: {
               fontSize: 18,
               color: '#000',
+              fontFamily:'DDIN',
+              fontWeight:'700'
             },
             data: e.data.map((e) => {
               return `${e[0]}: ${e[1]}`;

+ 48 - 6
src/components/Configurable/detail/CustomTable.vue

@@ -110,33 +110,75 @@
       width: 100%;
       padding-left: 10px;
       font-weight: bold;
-      font-size: 24px;
+      font-size: 28px;
     }
     /* 第一个子元素:黑色 */
     .table__content_list_row .table__content__list_item_A:nth-child(1) {
-      font-size: 12px;
+      font-size: 14px;
       text-align: left;
       color: #000000;
     }
 
     /* 第二个子元素:蓝色 */
     .table__content_list_row .table__content__list_item_A:nth-child(2) {
-      color: #1890ff;
+      color: #0052cc;
     }
 
     /* 第三个子元素:黄色 */
     .table__content_list_row .table__content__list_item_A:nth-child(3) {
-      color: #ffc107;
+      color: #B39F01;
     }
 
     /* 第四个子元素:橙色 */
     .table__content_list_row .table__content__list_item_A:nth-child(4) {
-      color: #ff7a45;
+      color: #E6A23D;
     }
 
     /* 第五个子元素:红色 */
     .table__content_list_row .table__content__list_item_A:nth-child(5) {
-      color: #ff4d4f;
+      color: #c45656;
+    }
+
+    .table__content_label_B {
+      background-image: var(--image-content-label-A);
+      background-size: 100% 100%;
+      background-repeat: no-repeat;
+      color: #000000;
+      width: 100%;
+      padding-left: 10px;
+    }
+
+    .table__content_list_B {
+      width: 100%;
+      padding-left: 10px;
+      font-weight: bold;
+      font-size: 28px;
+    }
+    /* 第一个子元素:黑色 */
+    .table__content_list_row .table__content__list_item_B:nth-child(1) {
+      font-size: 14px;
+      text-align: left;
+      color: #000000;
+    }
+
+    /* 第二个子元素:蓝色 */
+    .table__content_list_row .table__content__list_item_B:nth-child(2) {
+      color: #0052cc;;
+    }
+
+    /* 第三个子元素:绿色 */
+    .table__content_list_row .table__content__list_item_B:nth-child(3) {
+      color: #4caf50;
+    }
+
+    /* 第四个子元素:橙色 */
+    .table__content_list_row .table__content__list_item_B:nth-child(4) {
+      color: #c97800;
+    }
+
+    /* 第五个子元素:红色 */
+    .table__content_list_row .table__content__list_item_B:nth-child(5) {
+      color: #c45656;
     }
   }
 </style>

+ 41 - 31
src/components/Configurable/detail/MiniBoard.vue

@@ -104,6 +104,14 @@
 </script>
 <style lang="less" scoped>
   @import '/@/design/theme.less';
+  @font-face {
+    font-family: 'DDIN-Bold';
+    src: url('/@/assets/font//D-DIN-Bold.otf');
+  }
+  @font-face {
+    font-family: 'DDIN';
+    src: url('/@/assets/font//D-DIN.otf');
+  }
 
   .mini-board {
     --image-board-bg-A-1: url('/@/assets/images/sealedGoaf/configurable/miniBoard/board-bg-A-1.png');
@@ -130,15 +138,14 @@
     white-space: nowrap;
   }
   .mini-board_A {
-    width: 220px;
-    height: 52px;
+    width: 210px;
+    height: 43px;
     display: flex;
     justify-content: space-between;
-    align-items: center;
-    padding: 0 20px 0 20px;
+    align-items: end;
+    padding: 0 12px 0 20px;
     background-image: var(--image-board-bg-A-1);
     background-size: 100% 100%;
-    margin-top: 5px;
   }
   .mini-board_A:nth-child(2) {
     background-image: var(--image-board-bg-A-2);
@@ -157,17 +164,18 @@
   }
   .mini-board__label_A {
     color: #000000;
-    font-size: 13px;
-    font-family: 'Microsoft YaHei';
-    font-weight: bold;
-    padding-bottom: 6px;
+    font-size: 137x;
+    font-family: 'Source Han Sans SC';
+    font-style: normal;
+    font-weight: 700;
+    padding-bottom: 5px;
   }
   .mini-board__value_A {
     width: 55px;
     color: #000000;
-    font-size: 25px;
-    padding-bottom: 13px;
-    font-family: 'Microsoft YaHei';
+    font-size: 26px;
+    padding-bottom: 10px;
+    font-family: 'DDIN-Bold';
   }
   .mini-board_B {
     width: 98px;
@@ -180,37 +188,38 @@
   .mini-board__label_B {
     color: #000000;
     font-size: 14px;
-    font-family: 'Microsoft YaHei';
+    font-family: 'Source Han Sans SC';
+    font-weight: 700;
+
   }
   .mini-board__value_B {
     color: #000000;
     font-size: 26px;
-    font-weight: bold;
-    font-family: 'Microsoft YaHei';
+    font-family: 'DDIN-Bold';
     padding-bottom: 17px;
   }
   /* 1. 第一个容器:label和value为蓝色 */
   .mini-board_B:nth-child(1) .mini-board__label_B,
   .mini-board_B:nth-child(1) .mini-board__value_B {
-    color: #1890ff;
+    color: #0052cc;
   }
 
-  /* 2. 第二个容器:label和value为色 */
+  /* 2. 第二个容器:label和value为绿色 */
   .mini-board_B:nth-child(2) .mini-board__label_B,
   .mini-board_B:nth-child(2) .mini-board__value_B {
-    color: #36a64d;
+    color: #4caf50;
   }
 
   /* 3. 第三个容器:label和value为橙色 */
   .mini-board_B:nth-child(3) .mini-board__label_B,
   .mini-board_B:nth-child(3) .mini-board__value_B {
-    color: #a97523;
+    color: #c97800;
   }
 
   /* 4. 第四个容器:label和value为红色 */
   .mini-board_B:nth-child(4) .mini-board__label_B,
   .mini-board_B:nth-child(4) .mini-board__value_B {
-    color: #d6666c;
+    color: #c45656;
   }
   .mini-board_C {
     width: 98px;
@@ -223,55 +232,56 @@
   .mini-board__label_C {
     color: #000000;
     font-size: 14px;
-    font-family: 'Microsoft YaHei';
+    font-family: 'Source Han Sans SC';
+    font-weight: 700;
   }
   .mini-board__value_C {
     color: #000000;
     font-size: 26px;
-    font-weight: bold;
-    font-family: 'Microsoft YaHei';
+    font-family: 'DDIN-Bold';
     padding-bottom: 17px;
   }
   /* 1. 第一个容器:label和value为蓝色 */
   .mini-board_C:nth-child(1) .mini-board__label_C,
   .mini-board_C:nth-child(1) .mini-board__value_C {
-    color: #1890ff;
+    color: #0052cc;
   }
 
   /* 2. 第二个容器:label和value为黄色 */
   .mini-board_C:nth-child(2) .mini-board__label_C,
   .mini-board_C:nth-child(2) .mini-board__value_C {
-    color: #ffc107;
+    color: #B39F01;
   }
 
   /* 3. 第三个容器:label和value为橙色 */
   .mini-board_C:nth-child(3) .mini-board__label_C,
   .mini-board_C:nth-child(3) .mini-board__value_C {
-    color: #ff7a45;
+    color: #E6A23D;
   }
 
   /* 4. 第四个容器:label和value为红色 */
   .mini-board_C:nth-child(4) .mini-board__label_C,
   .mini-board_C:nth-child(4) .mini-board__value_C {
-    color: #ff4d4f;
+    color: #c45656;
   }
   .mini-board_D {
     width: 96px;
-    height: 65px;
+    height: 75px;
     background-image: var(--image-board-bg-D);
     background-size: 100% 100%;
-    padding-top: 6px;
+    padding-top: 12px;
   }
 
   .mini-board__label_D {
     color: #000000;
     font-size: 14px;
-    font-family: 'Microsoft YaHei';
+    font-weight: 800;
   }
   .mini-board__value_D {
     color: #2b6ff0;
     font-size: 22px;
-    font-family: 'Microsoft YaHei';
+    font-family: 'DDIN-Bold';
+    padding-bottom: 3px;
   }
 
   .mini-board_E {

+ 6 - 2
src/components/Configurable/preset/BlastDelta.vue

@@ -6,13 +6,13 @@
         <div :style="{ width: '5px', height: `${lengY}px`, 'border-top': '1px solid #0079ff' }" v-for="item in 10" :key="item"></div>
       </div>
       <div class="coord-labelY">
-        <div :style="{ width: '20px', height: `${lengY}px`, color: '#fff' }" v-for="(ite, ind) in 10" :key="ind">{{ ind == 0 ? maxY : '' }}</div>
+        <div :style="{ width: '20px', height: `${lengY}px`, color: textColor }" v-for="(ite, ind) in 10" :key="ind">{{ ind == 0 ? maxY : '' }}</div>
       </div>
       <div class="coord-lineX">
         <div :style="{ height: '5px', width: `${lengY}px`, 'border-right': '1px solid #0079ff' }" v-for="item in 15" :key="item"></div>
       </div>
       <div class="coord-labelX">
-        <div :style="{ height: '20px', width: `${lengY}px`, color: '#fff' }" v-for="(ite, ind) in 15" :key="ind">{{ ind == 14 ? maxX : '' }}</div>
+        <div :style="{ height: '20px', width: `${lengY}px`, color: textColor }" v-for="(ite, ind) in 15" :key="ind">{{ ind == 14 ? maxX : '' }}</div>
       </div>
       <div class="line-AB" :style="{ width: 'calc(100% - 10px)', height: 'calc(100% - 10px)' }">
         <canvas id="myCanvas" :width="canvasSize.width" :height="canvasSize.height"></canvas>
@@ -74,6 +74,10 @@
       type: Object,
       default: () => ({ width: 348, height: 245 }),
     },
+    textColor: {
+      type: String,
+      default: '#fff',
+    },
   });
 
   // 响应式数据

+ 5 - 8
src/components/Configurable/types.ts

@@ -133,12 +133,7 @@ export interface CommonItem {
 
 export interface ModuleDataBoard extends ReadFrom {
   /** 展示牌预设的背景类型 */
-  type:
-    | 'A'
-    | 'B'
-    | 'C'
-    | 'D'
-    | 'E'
+  type: 'A' | 'B' | 'C' | 'D' | 'E';
   /** 展示牌布局,决定是 label 部分在上方或是 value 在上方 */
   layout: 'val-top' | 'label-top' | 'new-top' | 'new1-top' | 'new2-top' | 'new3-top';
   /** 核心配置,每个展示牌对应一项 */
@@ -255,6 +250,7 @@ export interface ModuleDataChart extends ReadFrom {
       interval?: number;
       [key: string]: any; // 允许其他 ECharts 支持的属性
     };
+    [key: string]: any; // 允许其他 ECharts 支持的属性
   }[];
   /** 图表y轴配置(若有),支持多个,注意至少一个 */
   yAxis: {
@@ -263,6 +259,7 @@ export interface ModuleDataChart extends ReadFrom {
     name: string;
     /** y轴的对齐方式 */
     position: 'left' | 'right';
+    [key: string]: any; // 允许其他 ECharts 支持的属性
   }[];
   /**
    * 核心配置
@@ -276,7 +273,7 @@ export interface ModuleDataChart extends ReadFrom {
     type?: 'pie' | 'bar' | 'line' | 'scatter';
     /** 该系列的数据说明, formatter 格式,将用于 legend 相关的内容 */
     label: string;
-    /** 设置 series 系列时的基础路径,配合上级 readFrom 使用,其应指向一个数组,该数组将作为映射系列时的基准 */
+    /** 重要!该值99%的情况下必须设置!它会设置 series 系列时的基础路径,配合上级 readFrom 使用,其应指向一个数组,该数组将作为映射系列时的基准 */
     readFrom: string;
     /** 取值 prop,注意该项不支持 formatter 格式,将用于 xAxis 相关的内容 */
     xprop: string;
@@ -298,7 +295,7 @@ export interface ModuleDataChart extends ReadFrom {
 
 export interface ModuleDataTable extends ReadFrom {
   /** 表格的预设样式 */
-  type: 'A';
+  type: 'A' | 'B';
   /** 是否自动滚动 */
   autoScroll?: boolean;
   /** 核心配置,每个表格列对应一项 */

+ 183 - 183
src/components/Container/src/AdaptiveContainer.vue

@@ -6,200 +6,200 @@
 </template>
 
 <script lang="ts">
-  import { defineComponent, ref, onMounted, onUnmounted } from 'vue';
-  import { debounce } from 'lodash-es';
-  import { useAppStore } from '/@/store/modules/app';
-  import { computed } from 'vue';
-
-  // 类型定义
-  interface AdaptiveOptions {
-    width?: number;
-    height?: number;
-    baseWidth?: number; // 设计稿基准宽度,用于REM计算
-    minScale?: number; // 最小缩放比例
-    maxScale?: number; // 最大缩放比例
-    debounceTime?: number; // 防抖时间(ms)
-    ratio?: number; // 宽高比
-    tolerance?: number; // 宽高比容忍度
-  }
-
-  interface ScaleInfo {
-    widthScale: number;
-    heightScale: number;
-    scale: number;
-  }
-
-  export default defineComponent({
-    name: 'AdaptiveContainer',
-    props: {
-      options: {
-        type: Object as () => AdaptiveOptions,
-        default: () => ({}),
-      },
+import { defineComponent, ref, onMounted, onUnmounted } from 'vue';
+import { debounce } from 'lodash-es';
+import { useAppStore } from '/@/store/modules/app';
+import { computed } from 'vue';
+
+// 类型定义
+interface AdaptiveOptions {
+  width?: number;
+  height?: number;
+  baseWidth?: number; // 设计稿基准宽度,用于REM计算
+  minScale?: number; // 最小缩放比例
+  maxScale?: number; // 最大缩放比例
+  debounceTime?: number; // 防抖时间(ms)
+  ratio?: number; // 宽高比
+  tolerance?: number; // 宽高比容忍度
+}
+
+interface ScaleInfo {
+  widthScale: number;
+  heightScale: number;
+  scale: number;
+}
+
+export default defineComponent({
+  name: 'AdaptiveContainer',
+  props: {
+    options: {
+      type: Object as () => AdaptiveOptions,
+      default: () => ({}),
     },
-    setup(props) {
-      const appStore = useAppStore();
-      const containerRef = ref<HTMLElement | null>(null);
-      // const isReady = ref(false);
-
-      // 默认配置
-      const defaultOptions = ref<Required<AdaptiveOptions>>({
-        width: 1912,
-        height: 948,
-        baseWidth: 1920,
-        minScale: 0.5,
-        maxScale: 2,
-        debounceTime: 100,
-        ratio: 16 / 9,
-        tolerance: 0.1,
-      });
-
-      // 合并配置
-      const config = computed(() => {
-        return {
-          ...defaultOptions.value,
-          ...props.options,
-        };
-      });
-
-      // 设计稿尺寸
-      const designSize = computed(() => {
-        return {
-          width: config.value.width,
-          height: config.value.height,
-        };
-      });
-
-      /**
-       * 设置REM基准值
-       * @param baseSize 基准大小,默认16px
-       */
-      const setRem = (baseSize: number = 16): void => {
-        try {
-          const baseVal = baseSize / config.value.baseWidth;
-          const vW = window.innerWidth;
-          const rem = vW * baseVal;
-
-          // 设置全局缩放比例(如果有需要)
-          if (typeof window['$size'] !== 'number') {
-            Object.defineProperty(window, '$size', {
-              value: rem / 100,
-              writable: true,
-            });
-          } else {
-            window['$size'] = rem / 100;
-          }
-
-          // document.documentElement.style.fontSize = `${rem}px`;
-        } catch (error) {
-          console.error('设置REM失败:', error);
-          // 回退方案:使用固定REM
-          document.documentElement.style.fontSize = `${baseSize}px`;
-        }
+  },
+  setup(props) {
+    const appStore = useAppStore();
+    const containerRef = ref<HTMLElement | null>(null);
+    // const isReady = ref(false);
+
+    // 默认配置
+    const defaultOptions = ref<Required<AdaptiveOptions>>({
+      width: 1920,
+      height: 948,
+      baseWidth: 1920,
+      minScale: 0.5,
+      maxScale: 2,
+      debounceTime: 100,
+      ratio: 16 / 9,
+      tolerance: 0.1,
+    });
+
+    // 合并配置
+    const config = computed(() => {
+      return {
+        ...defaultOptions.value,
+        ...props.options,
       };
+    });
 
-      /**
-       * 计算缩放比例
-       */
-      const calculateScale = (): ScaleInfo => {
-        const { width: designWidth, height: designHeight } = designSize.value;
-        const { innerWidth: currentWidth, innerHeight: currentHeight } = window;
-        const { minScale, maxScale } = config.value;
-
-        // 计算原始比例
-        const rawWidthScale = currentWidth / designWidth;
-        const rawHeightScale = currentHeight / designHeight;
-
-        // 应用比例限制
-        const widthScale = Math.max(minScale, Math.min(maxScale, rawWidthScale));
-        const heightScale = Math.max(minScale, Math.min(maxScale, rawHeightScale));
-
-        // 选择最小比例保持内容完整显示
-        const scale = Math.min(widthScale, heightScale);
-
-        return { widthScale, heightScale, scale };
+    // 设计稿尺寸
+    const designSize = computed(() => {
+      return {
+        width: config.value.width,
+        height: config.value.height,
       };
+    });
+
+    /**
+     * 设置REM基准值
+     * @param baseSize 基准大小,默认18px
+     */
+    const setRem = (baseSize: number = 18): void => {
+      try {
+        const baseVal = baseSize / config.value.baseWidth;
+        const vW = window.innerWidth;
+        const rem = vW * baseVal;
+
+        // 设置全局缩放比例(如果有需要)
+        if (typeof window['$size'] !== 'number') {
+          Object.defineProperty(window, '$size', {
+            value: rem / 100,
+            writable: true,
+          });
+        } else {
+          window['$size'] = rem / 100;
+        }
 
-      /**
-       * 应用缩放变换
-       */
-      const applyScale = (): void => {
-        if (!containerRef.value) return;
-
+        // document.documentElement.style.fontSize = `${rem}px`;
+      } catch (error) {
+        console.error('设置REM失败:', error);
+        // 回退方案:使用固定REM
+        document.documentElement.style.fontSize = `${baseSize}px`;
+      }
+    };
+
+    /**
+     * 计算缩放比例
+     */
+    const calculateScale = (): ScaleInfo => {
+      const { width: designWidth, height: designHeight } = designSize.value;
+      const { innerWidth: currentWidth, innerHeight: currentHeight } = window;
+      const { minScale, maxScale } = config.value;
+
+      // 计算原始比例
+      const rawWidthScale = currentWidth / designWidth;
+      const rawHeightScale = currentHeight / designHeight;
+
+      // 应用比例限制
+      const widthScale = Math.max(minScale, Math.min(maxScale, rawWidthScale));
+      const heightScale = Math.max(minScale, Math.min(maxScale, rawHeightScale));
+
+      // 选择最小比例保持内容完整显示
+      const scale = Math.min(widthScale, heightScale);
+
+      return { widthScale, heightScale, scale };
+    };
+
+    /**
+     * 应用缩放变换
+     */
+    const applyScale = (): void => {
+      if (!containerRef.value) return;
+
+      const container = containerRef.value;
+      const { widthScale, heightScale } = calculateScale();
+
+      // 应用缩放
+      container.style.transform = `scale(${widthScale}, ${heightScale})`;
+      // container.style.transformOrigin = 'top left';
+
+      // 更新store中的比例信息(如果需要)
+      appStore.setWidthScale(widthScale);
+      appStore.setHeightScale(heightScale);
+    };
+
+    /**
+     * 处理窗口大小变化
+     */
+    const handleResize = debounce((): void => {
+      // 更新缩放和REM
+      applyScale();
+      setRem();
+    }, config.value.debounceTime);
+
+    onMounted(async () => {
+      // 生命周期
+      try {
+        if (!containerRef.value) {
+          // if (!document.getElementById('app')) {
+          throw new Error('容器元素未找到');
+        }
         const container = containerRef.value;
-        const { widthScale, heightScale } = calculateScale();
-
-        // 应用缩放
-        container.style.transform = `scale(${widthScale}, ${heightScale})`;
-        // container.style.transformOrigin = 'top left';
+        const { ratio, tolerance } = config.value;
+        const normalRatio = Math.abs(ratio - container.clientWidth / container.clientHeight) < ratio * tolerance;
+        // const container = document.getElementById('app')!;
+        if (normalRatio) {
+          defaultOptions.value.width = container.clientWidth;
+          defaultOptions.value.height = container.clientHeight;
+        }
 
-        // 更新store中的比例信息(如果需要)
-        appStore.setWidthScale(widthScale);
-        appStore.setHeightScale(heightScale);
-      };
+        const { width, height } = designSize.value;
+        container.style.width = `${width}px`;
+        container.style.height = `${height}px`;
 
-      /**
-       * 处理窗口大小变化
-       */
-      const handleResize = debounce((): void => {
-        // 更新缩放和REM
         applyScale();
         setRem();
-      }, config.value.debounceTime);
-
-      onMounted(async () => {
-        // 生命周期
-        try {
-          if (!containerRef.value) {
-            // if (!document.getElementById('app')) {
-            throw new Error('容器元素未找到');
-          }
-          const container = containerRef.value;
-          const { ratio, tolerance } = config.value;
-          const normalRatio = Math.abs(ratio - container.clientWidth / container.clientHeight) < ratio * tolerance;
-          // const container = document.getElementById('app')!;
-          if (normalRatio) {
-            defaultOptions.value.width = container.clientWidth;
-            defaultOptions.value.height = container.clientHeight;
-          }
-
-          const { width, height } = designSize.value;
-          container.style.width = `${width}px`;
-          container.style.height = `${height}px`;
-
-          applyScale();
-          setRem();
-        } catch (error) {
-          console.error('初始化自适应容器失败:', error);
-        }
-
-        window.addEventListener('resize', handleResize);
-      });
-
-      onUnmounted(() => {
-        window.removeEventListener('resize', handleResize);
-      });
-
-      return {
-        containerRef,
-        // isReady,
-      };
-    },
-  });
+      } catch (error) {
+        console.error('初始化自适应容器失败:', error);
+      }
+
+      window.addEventListener('resize', handleResize);
+    });
+
+    onUnmounted(() => {
+      window.removeEventListener('resize', handleResize);
+    });
+
+    return {
+      containerRef,
+      // isReady,
+    };
+  },
+});
 </script>
 
 <style lang="less" scoped>
-  .adaptive-container {
-    // position: relative;
-    // top: 0;
-    // left: 0;
-    overflow: hidden;
-    height: 100%;
-    width: 100%;
-    transform-origin: left top;
-    // z-index: 0;
-    // 防止缩放导致的模糊(开启GPU加速)
-    backface-visibility: hidden;
-    // -webkit-font-smoothing: antialiased;
-  }
+.adaptive-container {
+  // position: relative;
+  // top: 0;
+  // left: 0;
+  overflow: hidden;
+  height: 100%;
+  width: 100%;
+  transform-origin: left top;
+  // z-index: 0;
+  // 防止缩放导致的模糊(开启GPU加速)
+  backface-visibility: hidden;
+  // -webkit-font-smoothing: antialiased;
+}
 </style>

+ 5 - 5
src/components/Form/src/hooks/useFormEvents.ts

@@ -58,10 +58,10 @@ export function useFormEvents({
       let value = values[key];
 
       //antd3升级后,online表单时间控件选中值报js错 TypeError: Reflect.has called on non-object
-      if(!(values instanceof Object)){
+      if (!(values instanceof Object)) {
         return;
       }
-      
+
       const hasKey = Reflect.has(values, key);
 
       value = handleInputNumberValue(schema?.component, value);
@@ -100,14 +100,14 @@ export function useFormEvents({
    */
   function getSchemaByField(field: string): Nullable<FormSchema> {
     if (!isString(field)) {
-      return null
+      return null;
     }
     const schemaList: FormSchema[] = unref(getSchema);
     const index = schemaList.findIndex((schema) => schema.field === field);
     if (index !== -1) {
       return cloneDeep(schemaList[index]);
     }
-    return null
+    return null;
   }
 
   /**
@@ -270,7 +270,7 @@ export function useFormEvents({
     } catch (error) {
       // 代码逻辑说明: 列表查询表单会触发校验错误导致重置失败,原因不明
       emit('submit', {});
-      console.error('query form validate error, please ignore!', error)
+      console.error('query form validate error, please ignore!', error);
       //throw new Error(error);
     }
   }

+ 2 - 1
src/components/Table/src/hooks/useTableScroll.ts

@@ -58,6 +58,7 @@ export function useTableScroll(
   let paginationEl: HTMLElement | null;
   let footerEl: HTMLElement | null;
   let bodyEl: HTMLElement | null;
+  let headEl: HTMLElement | null;
 
   async function calcTableHeight() {
     const { resizeHeightOffset = 2, pagination, maxHeight, minHeight } = unref(propsRef);
@@ -97,7 +98,7 @@ export function useTableScroll(
     await nextTick();
     //Add a delay to get the correct bottomIncludeBody paginationHeight footerHeight headerHeight
 
-    const headEl = tableEl.querySelector('.ant-table-thead');
+    headEl = tableEl.querySelector('.ant-table-thead');
 
     if (!headEl) return;
 

+ 2 - 0
src/design/color.less

@@ -160,3 +160,5 @@ html {
 // ==============tabs===============
 // =================================
 @tabs-bg-not-active: #9e9e9e26;
+
+@card-bg-color: #f8f9fc;

+ 34 - 0
src/design/public.less

@@ -111,3 +111,37 @@
     bottom: -20px;
   }
 }
+
+.common-page-tabs {
+  padding: 0 12px 6px 12px;
+  margin: 16px;
+  border: 1px solid @border-color-base;
+}
+
+.action-btn {
+  cursor: pointer;
+  border: none;
+  // background: transparent;
+  padding: 4px;
+  margin-right: 10px;
+
+  &:hover {
+    color: @primary-color;
+  }
+
+  &:last-child {
+    margin-right: 0;
+  }
+
+  .action-text {
+    color: lighten(@primary-color, 10%);
+
+    &:hover {
+      color: @primary-color;
+    }
+  }
+  .action-icon {
+    width: 16px;
+    height: 16px;
+  }
+}

+ 11 - 1
src/views/analysis/warningAnalysis/airLeakStatus/airLeak.api.ts

@@ -7,6 +7,7 @@ enum Api {
   getProvinceAlarmHistory = '/province/alarm/getProvinceAlarmHistory',
   getEnfMineTreeData = '/jeecg-system/sys/user/getEnfMineTreeData',
   getProvinceAlarmNum = '/province/alarm/getProvinceAlarmNum',
+  resolveAlarm = '/province/alarm/solveProvinceAlarm',
 }
 //根据预警类型查询不同等级数量
 export const getProvinceAlarmNum = (params) =>
@@ -53,7 +54,10 @@ export const getProvinceAlarm = (params) =>
   defHttp.post(
     {
       url: Api.getProvinceAlarm,
-      params,
+      params: {
+        alarmType: 'leakageAlarm',
+        ...params,
+      },
     },
     {
       joinParamsToUrl: true,
@@ -64,3 +68,9 @@ export const getEnfMineTreeData = () =>
   defHttp.get({
     url: Api.getEnfMineTreeData,
   });
+// 解决预警
+export const resolveAlarm = (params) =>
+  defHttp.post({
+    url: Api.resolveAlarm,
+    params,
+  });

+ 76 - 143
src/views/analysis/warningAnalysis/airLeakStatus/airLeakStatus.data.ts

@@ -20,54 +20,125 @@ export const columns: BasicColumn[] = [
   {
     title: '序号',
     align: 'center',
+    width: 80,
     customRender: ({ index }: { index: number }) => `${index + 1}`,
   },
   {
     title: '区域',
     dataIndex: 'areaName',
+    width: 100,
   },
   {
     title: '煤矿名称',
     dataIndex: 'mineName',
+    width: 200,
   },
   {
     title: '密闭名称',
     dataIndex: 'devicePos',
+    width: 100,
   },
   {
     title: '所属煤层',
     dataIndex: 'coalSeamName',
+    width: 100,
   },
   {
     title: '自燃倾向性',
-    dataIndex: 'riskLevel',
+    dataIndex: 'coalSeamLevel',
+    width: 100,
   },
   {
     title: '密闭内压力',
-    dataIndex: 'interPressure',
+    dataIndex: 'sourcePressure',
+    width: 100,
   },
   {
     title: '密闭外压力',
-    dataIndex: 'outerPressure',
+    dataIndex: 'sourcePressure',
+    width: 100,
   },
   {
     title: '是否漏风',
     dataIndex: 'leakage',
+    width: 100,
   },
   {
     title: '风险分析',
-    dataIndex: 'explosionHazard',
+    dataIndex: 'alarmName',
+    width: 100,
   },
   {
     title: '预警时间',
-    dataIndex: 'alertTime',
+    dataIndex: 'createTime',
+    width: 100,
   },
   {
     title: '是否解决',
     dataIndex: 'isResolved',
+    width: 100,
   },
 ];
 
+// 历史数据相关
+export const historyColumns: BasicColumn[] = [
+  {
+    title: '序号',
+    align: 'center',
+    width: 80,
+    customRender: ({ index }: { index: number }) => `${index + 1}`,
+  },
+  {
+    title: '区域',
+    dataIndex: 'areaName',
+    width: 100,
+  },
+  {
+    title: '煤矿名称',
+    dataIndex: 'mineName',
+    width: 200,
+  },
+  {
+    title: '密闭名称',
+    dataIndex: 'devicePos',
+    width: 100,
+  },
+  {
+    title: '所属煤层',
+    dataIndex: 'coalSeamName',
+    width: 100,
+  },
+  {
+    title: '自燃倾向性',
+    dataIndex: 'coalSeamLevel',
+    width: 100,
+  },
+  {
+    title: '密闭内压力',
+    dataIndex: 'sourcePressure',
+    width: 100,
+  },
+  {
+    title: '密闭外压力',
+    dataIndex: 'sourcePressure',
+    width: 100,
+  },
+  {
+    title: '是否漏风',
+    dataIndex: 'leakage',
+    width: 100,
+  },
+  {
+    title: '预警时间',
+    dataIndex: 'createTime',
+    width: 100,
+  },
+  {
+    title: '解决时间',
+    dataIndex: 'endTime',
+    width: 100,
+  },
+];
 export const searchFormSchema: FormSchema[] = [
   {
     field: 'mineName',
@@ -134,141 +205,3 @@ export const searchFormSchema: FormSchema[] = [
     colProps: { span: 6 },
   },
 ];
-
-export const minesData = [
-  {
-    orderNo: 101, // 序号
-    enforcement: '执法一处', // 区域
-    mineName: '神木市三江', // 煤矿名称
-    sealedName: '采空区密闭', // 密闭名称
-    coalSeam: 'XX煤层', // 所属煤层
-    riskLevel: 'Ⅰ类容易自燃', // 自燃倾向性(与搜索框选项label一致)
-    COVal: 24, // CO浓度(ppm)
-    CH4Val: 0, // CH4浓度(%)
-    C2H2Val: 0, // C2H2浓度(ppm)
-    O2Val: 20, // O2浓度(%)
-    temperature: 35, // 温度(℃)
-    pressureDiff: 50, // 压差(Pa)
-    leakage: '气体涌出', // 是否漏风
-    fireHazard: '低风险', // 自然发火隐患
-    unsealing: '不可启封', // 密闭启封判定
-    explosionHazard: '低风险', // 爆炸危险性
-    updateTime: '2025-11-17 15:00:40', // 更新时间
-    alertTime: '2025-11-17 15:00:40',
-    interPressure: '10',
-    outerPressure: '20',
-  },
-  {
-    orderNo: 102, // 序号
-    enforcement: '执法一处', // 区域
-    mineName: '神木市三江', // 煤矿名称
-    sealedName: '采空区密闭', // 密闭名称
-    coalSeam: 'XX煤层', // 所属煤层
-    riskLevel: 'Ⅰ类容易自燃', // 自燃倾向性(与搜索框选项label一致)
-    COVal: 24, // CO浓度(ppm)
-    CH4Val: 0, // CH4浓度(%)
-    C2H2Val: 0, // C2H2浓度(ppm)
-    O2Val: 20, // O2浓度(%)
-    temperature: 35, // 温度(℃)
-    pressureDiff: 50, // 压差(Pa)
-    leakage: '气体涌出', // 是否漏风
-    fireHazard: '低风险', // 自然发火隐患
-    unsealing: '不可启封', // 密闭启封判定
-    explosionHazard: '低风险', // 爆炸危险性
-    updateTime: '2025-11-17 15:00:40', // 更新时间
-    alertTime: '2025-11-17 15:00:40',
-    interPressure: '10',
-    outerPressure: '20',
-  },
-  {
-    orderNo: 103, // 序号
-    enforcement: '执法一处', // 区域
-    mineName: '神木市三江', // 煤矿名称
-    sealedName: '采空区密闭', // 密闭名称
-    coalSeam: 'XX煤层', // 所属煤层
-    riskLevel: 'Ⅰ类容易自燃', // 自燃倾向性(与搜索框选项label一致)
-    COVal: 24, // CO浓度(ppm)
-    CH4Val: 0, // CH4浓度(%)
-    C2H2Val: 0, // C2H2浓度(ppm)
-    O2Val: 20, // O2浓度(%)
-    temperature: 35, // 温度(℃)
-    pressureDiff: 50, // 压差(Pa)
-    leakage: '气体涌出', // 是否漏风
-    fireHazard: '低风险', // 自然发火隐患
-    unsealing: '不可启封', // 密闭启封判定
-    explosionHazard: '低风险', // 爆炸危险性
-    updateTime: '2025-11-17 15:00:40', // 更新时间
-    alertTime: '2025-11-17 15:00:40',
-    interPressure: '10',
-    outerPressure: '20',
-  },
-];
-
-export const historicalMinesData = [
-  {
-    orderNo: 101, // 序号
-    enforcement: '执法一处', // 区域
-    mineName: '神木市三江', // 煤矿名称
-    sealedName: '采空区密闭', // 密闭名称
-    coalSeam: 'XX煤层', // 所属煤层
-    riskLevel: 'Ⅰ类容易自燃', // 自燃倾向性(与搜索框选项label一致)
-    COVal: 24, // CO浓度(ppm)
-    CH4Val: 0, // CH4浓度(%)
-    C2H2Val: 0, // C2H2浓度(ppm)
-    O2Val: 20, // O2浓度(%)
-    temperature: 35, // 温度(℃)
-    pressureDiff: 50, // 压差(Pa)
-    leakage: '气体涌出', // 是否漏风
-    fireHazard: '低风险', // 自然发火隐患
-    unsealing: '不可启封', // 密闭启封判定
-    explosionHazard: '低风险', // 爆炸危险性
-    updateTime: '2025-12-22 15:00:40', // 更新时间
-    alertTime: '2025-11-17 15:00:40',
-    interPressure: '10',
-    outerPressure: '20',
-  },
-  {
-    orderNo: 102, // 序号
-    enforcement: '执法一处', // 区域
-    mineName: '神木市三江', // 煤矿名称
-    sealedName: '采空区密闭', // 密闭名称
-    coalSeam: 'XX煤层', // 所属煤层
-    riskLevel: 'Ⅰ类容易自燃', // 自燃倾向性(与搜索框选项label一致)
-    COVal: 24, // CO浓度(ppm)
-    CH4Val: 0, // CH4浓度(%)
-    C2H2Val: 0, // C2H2浓度(ppm)
-    O2Val: 20, // O2浓度(%)
-    temperature: 35, // 温度(℃)
-    pressureDiff: 50, // 压差(Pa)
-    leakage: '气体涌出', // 是否漏风
-    fireHazard: '低风险', // 自然发火隐患
-    unsealing: '不可启封', // 密闭启封判定
-    explosionHazard: '低风险', // 爆炸危险性
-    updateTime: '2025-12-22 15:00:40', // 更新时间
-    alertTime: '2025-11-17 15:00:40',
-    interPressure: '10',
-    outerPressure: '20',
-  },
-  {
-    orderNo: 103, // 序号
-    enforcement: '执法一处', // 区域
-    mineName: '神木市三江', // 煤矿名称
-    sealedName: '采空区密闭', // 密闭名称
-    coalSeam: 'XX煤层', // 所属煤层
-    riskLevel: 'Ⅰ类容易自燃', // 自燃倾向性(与搜索框选项label一致)
-    COVal: 24, // CO浓度(ppm)
-    CH4Val: 0, // CH4浓度(%)
-    C2H2Val: 0, // C2H2浓度(ppm)
-    O2Val: 20, // O2浓度(%)
-    temperature: 35, // 温度(℃)
-    pressureDiff: 50, // 压差(Pa)
-    leakage: '气体涌出', // 是否漏风
-    fireHazard: '低风险', // 自然发火隐患
-    unsealing: '不可启封', // 密闭启封判定
-    explosionHazard: '低风险', // 爆炸危险性
-    updateTime: '2025-12-22 15:00:40', // 更新时间
-    alertTime: '2025-11-17 15:00:40',
-    interPressure: '10',
-    outerPressure: '20',
-  },
-];

+ 100 - 71
src/views/analysis/warningAnalysis/airLeakStatus/index.vue

@@ -1,39 +1,57 @@
+<!-- eslint-disable vue/multi-word-component-names -->
 <template>
-  <div class="monitoring-page">
-    <!-- 新增Tabs组件区分实时/历史数据 -->
-    <Tabs v-model:activeKey="activeTab" type="card" style="margin-bottom: 16px">
-      <TabPane tab="实时监测" key="realtime">
-        <div class="board-info">
-          <div :key="index" v-for="(item, index) in boardData" class="board-item">
-            <MiniBoard type="E" :label="item.label" :value="item.value" layout="label-top" />
-          </div>
+  <!-- 新增Tabs组件区分实时/历史数据 -->
+  <Tabs v-model:activeKey="activeTab" type="line" class="common-page-tabs">
+    <TabPane tab="实时监测" key="realtime">
+      <div class="board-info">
+        <div :key="index" v-for="(item, index) in boardData" class="board-item">
+          <MiniBoard type="A" :label="item.label" :value="item.value" layout="label-top" />
         </div>
-        <!-- 实时数据表格 -->
-        <BasicTable @register="registerTable" :scroll="{ x: 'max-content' }">
-          <template #action="{ record }">
-            <div class="action-buttons">
-              <button @click="openModal(record, 'realtime')" class="action-btn">
-                <SvgIcon name="details" />
-              </button>
-            </div>
-          </template>
-        </BasicTable>
-      </TabPane>
+      </div>
+      <!-- 实时数据表格 -->
+      <BasicTable @register="registerTable" :scroll="{ x: 'max-content' }" :style="{ padding: 0 }">
+        <template #action="{ record }">
+          <!-- 操作按钮 -->
+          <!-- <button @click="openModal(record, 'detail')" class="action-btn detail-btn" title="操作">
+            <span class="action-text">详情</span>
+          </button> -->
+          <!-- 已解决按钮 -->
+          <button @click="openModal(record, 'resolved')" class="action-btn resolved-btn" title="已解决">
+            <span class="action-text">解决</span>
+          </button>
+        </template>
+      </BasicTable>
+    </TabPane>
 
-      <TabPane tab="历史数据" key="history">
-        <!-- 历史数据表格 -->
-        <BasicTable @register="registerHistoryTable" :scroll="{ x: 'max-content' }">
-          <template #action="{ record }">
-            <div class="action-buttons">
-              <button @click="openModal(record, 'history')" class="action-btn">
-                <SvgIcon name="details" />
-              </button>
-            </div>
-          </template>
-        </BasicTable>
-      </TabPane>
-    </Tabs>
-  </div>
+    <TabPane tab="历史数据" key="history">
+      <!-- 历史数据表格 -->
+      <BasicTable @register="registerHistoryTable" :scroll="{ x: 'max-content' }" :style="{ padding: 0 }">
+        <template #action="{ record }">
+          <div class="action-buttons">
+            <button @click="openModal(record, 'history')" class="action-btn">
+              <SvgIcon name="details" />
+            </button>
+          </div>
+        </template>
+      </BasicTable>
+    </TabPane>
+  </Tabs>
+  <!-- 弹窗组件 -->
+  <a-modal style="top: 30%; left: 170px" v-model:visible="visibleModal" :width="450" title="实时监测数据">
+    <a-table></a-table>
+  </a-modal>
+  <!-- 弹窗组件 -->
+  <a-modal
+    style="height: 400px"
+    v-model:visible="visibleresolveModal"
+    :width="600"
+    centered
+    title="密闭漏风处理情况"
+    @ok="handleOkEdit"
+    @cancel="handleCancelEdit"
+  >
+    <a-textarea style="width: 90%; margin-left: 20px; margin-right: 20px" v-model:value="resolveValue" placeholder="请输入解决情况" :rows="4" />
+  </a-modal>
 </template>
 
 <script setup lang="ts">
@@ -42,14 +60,26 @@ import { BasicTable, useTable } from '/@/components/Table';
 import { Tabs, TabPane } from 'ant-design-vue';
 import MiniBoard from '/@/components/Configurable/detail/MiniBoard.vue';
 import { SvgIcon } from '/@/components/Icon';
-import { getMineData, getProvinceAlarm, getProvinceAlarmNum, getGoafData, getProvinceAlarmHistory, getEnfMineTreeData } from './airLeak.api';
+import {
+  getMineData,
+  getProvinceAlarm,
+  getProvinceAlarmNum,
+  getGoafData,
+  getProvinceAlarmHistory,
+  getEnfMineTreeData,
+  resolveAlarm,
+} from './airLeak.api';
 import formConfig from '/@/components/Form/src/jeecg/components/formCard/formConfig.vue';
 import JPopup from '/@/components/Form/src/jeecg/components/JPopup.vue';
 // 引入模拟数据
-import { columns, searchFormSchema, historicalMinesData } from './airLeakStatus.data';
+import { columns, historyColumns, searchFormSchema } from './airLeakStatus.data';
 
 // 激活的Tab页签
 const activeTab = ref('realtime');
+const visibleModal = ref(false);
+const visibleresolveModal = ref(false);
+const resolveValue = ref('');
+const resolveId = ref('');
 //煤矿列表数据
 const deviceOptions = ref([]);
 const goafOptions = ref([]);
@@ -78,20 +108,18 @@ const [registerTable] = useTable({
         field: 'mineCode', // 对应组件的value.mineCode(最终传给Table的查询参数)
         component: 'MineCascader', // 自定义组件名
         colProps: { span: 6 },
-        rules: [],
       },
     ],
     showAdvancedButton: false,
     schemaGroupNames: ['常规查询'],
   },
-  pagination: false,
-  striped: false,
+  pagination: true,
+  striped: true,
   useSearchForm: true,
   bordered: true,
   showIndexColumn: false,
-  canResize: false,
   actionColumn: {
-    width: 60,
+    width: 120,
     title: '操作',
     dataIndex: 'action',
     slots: { customRender: 'action' },
@@ -101,7 +129,7 @@ const [registerTable] = useTable({
 // 注册历史数据表格
 const [registerHistoryTable] = useTable({
   dataSource: historyData,
-  columns,
+  columns: historyColumns,
   api: getProvinceAlarmHistory,
   formConfig: {
     labelWidth: 120,
@@ -147,12 +175,7 @@ const [registerHistoryTable] = useTable({
         label: '采空区查询',
         field: 'goafId',
         component: 'Select',
-        defaultValue: goafOptions.value[0] ? goafOptions.value[0]['value'] : '',
         componentProps: {
-          showSearch: true,
-          filterOption: (input: string, option: any) => {
-            return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0;
-          },
           options: goafOptions,
           onChange: async (e, option) => {
             goafId.value = e;
@@ -184,19 +207,18 @@ const [registerHistoryTable] = useTable({
     showAdvancedButton: false,
     schemaGroupNames: ['常规查询'],
   },
-  pagination: false,
-  striped: false,
+  pagination: true,
+  striped: true,
   useSearchForm: true,
   bordered: true,
   showIndexColumn: false,
-  canResize: false,
-  actionColumn: {
-    width: 60,
-    title: '操作',
-    dataIndex: 'action',
-    slots: { customRender: 'action' },
-    fixed: undefined,
-  },
+  // actionColumn: {
+  //   width: 60,
+  //   title: '操作',
+  //   dataIndex: 'action',
+  //   slots: { customRender: 'action' },
+  //   fixed: undefined,
+  // },
 });
 
 // 弹窗引用
@@ -208,6 +230,13 @@ const openModal = (record, type) => {
   if (type === 'realtime') {
     // 可向实时弹窗传递当前记录数据
     realtimeModalRef.value?.showModal(record);
+  } else if (type === 'resolved') {
+    visibleresolveModal.value = true;
+    resolveValue.value = '';
+    // record.isResolved = resolveValue.value || '';
+    resolveId.value = record.id;
+  } else if (type === 'detail') {
+    visibleModal.value = true;
   } else {
     // 可向历史弹窗传递当前记录数据
     historyModalRef.value?.showModal(record);
@@ -269,9 +298,20 @@ async function getEnfMineData() {
     value: item.id,
     rawdata: item,
   }));
-  console.log(lawDeptOptions.value, '11111111');
   // deviceOptions.value = res;
 }
+// 解决预警
+async function handleOkEdit() {
+  const params = {
+    id: resolveId.value,
+    content: resolveValue.value,
+  };
+  await resolveAlarm(params);
+  visibleresolveModal.value = false;
+}
+const handleCancelEdit = () => {
+  visibleresolveModal.value = false;
+};
 onMounted(() => {
   // 页面挂载时的逻辑
   getMineDataList();
@@ -281,14 +321,12 @@ onMounted(() => {
 </script>
 
 <style lang="less" scoped>
-.monitoring-page {
-  padding: 16px;
-}
 .board-info {
   display: flex;
   padding: 10px;
-  background-color: #fff;
-  margin: 0 10px;
+  background-color: @white;
+  // margin: 0 10px;
+  margin-bottom: 5px;
   gap: 10px;
   box-sizing: border-box;
 }
@@ -296,15 +334,6 @@ onMounted(() => {
   flex: 1;
   box-sizing: border-box;
 }
-.action-btn {
-  cursor: pointer;
-  border: none;
-  padding: 4px;
-}
-.action-icon {
-  width: 16px;
-  height: 16px;
-}
 :deep(.jeecg-basic-table-form-container .ant-form) {
   border: none !important;
 }

+ 21 - 8
src/views/analysis/warningAnalysis/autoFireAnalysis/autoFire.api.ts

@@ -25,16 +25,29 @@ export const getMineData = (params) =>
   });
 //查询预警数据
 export const getProvinceAlarm = (params) =>
-  defHttp.post({
-    url: Api.getProvinceAlarm,
-    params,
-  });
+  defHttp.post(
+    {
+      url: Api.getProvinceAlarm,
+      params: {
+        alarmType: 'fireAlarm',
+        ...params,
+      },
+    },
+    {
+      joinParamsToUrl: true,
+    }
+  );
 //查询密闭列表
 export const getGoafData = (params) =>
-  defHttp.post({
-    url: Api.getGoafData,
-    params,
-  });
+  defHttp.post(
+    {
+      url: Api.getGoafData,
+      params,
+    },
+    {
+      joinParamsToUrl: true,
+    }
+  );
 //查询预警历史数据
 export const getProvinceAlarmHistory = (params) =>
   defHttp.post(

+ 19 - 5
src/views/analysis/warningAnalysis/autoFireAnalysis/autoFireAnalysis.data.ts

@@ -28,59 +28,73 @@ export const columns: BasicColumn[] = [
   {
     title: '序号',
     align: 'center',
+    width: 80,
     customRender: ({ index }: { index: number }) => `${index + 1}`,
   },
   {
     title: '区域',
     dataIndex: 'areaName',
+    width: 100,
   },
   {
     title: '煤矿名称',
     dataIndex: 'mineName',
+    width: 100,
   },
   {
     title: '密闭名称',
     dataIndex: 'devicePos',
+    width: 100,
   },
   {
     title: '所属煤层',
     dataIndex: 'coalSeamName',
+    width: 100,
   },
   {
     title: '自燃倾向性',
-    dataIndex: 'riskLevel',
+    dataIndex: 'coalSeamLevel',
+    width: 100,
   },
   {
     title: 'CO浓度(ppm)',
-    dataIndex: 'COVal',
+    dataIndex: 'coVal',
+    width: 100,
   },
   {
     title: 'CO日增率',
     dataIndex: 'coIncreaseRate',
+    width: 100,
   },
   {
     title: 'O2浓度(ppm)',
-    dataIndex: 'O2Val',
+    dataIndex: 'o2Val',
+    width: 100,
   },
   {
     title: '温度(℃)',
     dataIndex: 'temperature',
+    width: 100,
   },
   {
     title: '温差(℃)',
     dataIndex: 'temperatureDiff',
+    width: 100,
   },
   {
     title: '风险分析',
-    dataIndex: 'riskAnalysis',
+    dataIndex: 'alarmName',
+    width: 100,
   },
   {
     title: '预警时间',
-    dataIndex: 'alertTime',
+    dataIndex: 'createTime',
+    width: 100,
   },
   {
     title: '是否解决',
     dataIndex: 'isResolved',
+    width: 100,
   },
 ];
 

+ 24 - 42
src/views/analysis/warningAnalysis/autoFireAnalysis/index.vue

@@ -1,7 +1,7 @@
 <template>
   <div class="monitoring-page">
     <!-- 新增Tabs组件区分实时/历史数据 -->
-    <Tabs v-model:activeKey="activeTab" type="card" style="margin-bottom: 16px">
+    <Tabs v-model:activeKey="activeTab" type="line" style="margin-bottom: 16px">
       <TabPane tab="实时监测" key="realtime">
         <div class="board-info">
           <MiniBoard
@@ -15,7 +15,7 @@
           />
         </div>
         <!-- 实时数据表格 -->
-        <BasicTable @register="registerTable" :scroll="{ x: 'max-content' }">
+        <BasicTable @register="registerTable" :scroll="{ x: 'max-content' }" :style="{ padding: 0 }">
           <template #action="{ record }">
             <div class="action-buttons">
               <!-- 操作按钮 -->
@@ -29,7 +29,7 @@
 
       <TabPane tab="历史数据" key="history">
         <!-- 历史数据表格 -->
-        <BasicTable @register="registerHistoryTable" :scroll="{ x: 'max-content' }">
+        <BasicTable @register="registerHistoryTable" :scroll="{ x: 'max-content' }" :style="{ padding: 0 }">
           <template #action="{ record }">
             <div class="action-buttons">
               <button @click="openModal(record, 'history')" class="action-btn">
@@ -113,19 +113,18 @@ const [registerTable] = useTable({
     showAdvancedButton: false,
     schemaGroupNames: ['常规查询'],
   },
-  pagination: false,
-  striped: false,
+  pagination: true,
+  striped: true,
   useSearchForm: true,
   bordered: true,
   showIndexColumn: false,
-  canResize: false,
-  actionColumn: {
-    width: 60,
-    title: '操作',
-    dataIndex: 'action',
-    slots: { customRender: 'action' },
-    fixed: undefined,
-  },
+  // actionColumn: {
+  //   width: 60,
+  //   title: '操作',
+  //   dataIndex: 'action',
+  //   slots: { customRender: 'action' },
+  //   fixed: undefined,
+  // },
 });
 
 // 注册历史数据表格
@@ -177,12 +176,7 @@ const [registerHistoryTable] = useTable({
         label: '采空区查询',
         field: 'goafId',
         component: 'Select',
-        defaultValue: goafOptions.value[0] ? goafOptions.value[0]['value'] : '',
         componentProps: {
-          showSearch: true,
-          filterOption: (input: string, option: any) => {
-            return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0;
-          },
           options: goafOptions,
           onChange: async (e, option) => {
             goafId.value = e;
@@ -214,19 +208,18 @@ const [registerHistoryTable] = useTable({
     showAdvancedButton: false,
     schemaGroupNames: ['常规查询'],
   },
-  pagination: false,
-  striped: false,
+  pagination: true,
+  striped: true,
   useSearchForm: true,
   bordered: true,
   showIndexColumn: false,
-  canResize: false,
-  actionColumn: {
-    width: 60,
-    title: '操作',
-    dataIndex: 'action',
-    slots: { customRender: 'action' },
-    fixed: undefined,
-  },
+  // actionColumn: {
+  //   width: 60,
+  //   title: '操作',
+  //   dataIndex: 'action',
+  //   slots: { customRender: 'action' },
+  //   fixed: undefined,
+  // },
 });
 
 // 弹窗引用
@@ -306,9 +299,6 @@ onMounted(() => {
 </script>
 
 <style lang="less" scoped>
-.monitoring-page {
-  padding: 16px;
-}
 .board-info {
   display: grid;
   grid-template-columns: repeat(5, auto); /* 3列:改5则为5列 */
@@ -316,21 +306,13 @@ onMounted(() => {
   justify-content: start;
   flex-wrap: wrap;
   box-sizing: border-box;
-  background-color: #fff;
+  background-color: @white;
   padding: 10px;
-  margin: 0 10px;
   gap: 100px;
+  // margin: 0 10px;
+  margin-bottom: 5px;
 }
 .board-item {
   box-sizing: border-box;
 }
-.action-btn {
-  cursor: pointer;
-  border: none;
-  padding: 4px;
-}
-.action-icon {
-  width: 16px;
-  height: 16px;
-}
 </style>

+ 56 - 58
src/views/analysis/warningAnalysis/connectAnalysis/index.vue

@@ -6,7 +6,7 @@
           <div class="filter-section param-section">
             <span class="filter-label">煤矿名称:</span>
             <div class="param-selector">
-              <MineCascader style="width:300px"></MineCascader>
+              <MineCascader style="width: 300px"></MineCascader>
             </div>
           </div>
         </Col>
@@ -23,7 +23,7 @@
         <Col :span="6">
           <div class="filter-section param-section">
             <span class="filter-label">时间选择:</span>
-            <RangePicker v-model:value="dateRange"  format="YYYY-MM-DD HH:mm:ss" :placeholder="['开始时间', '结束时间']"
+            <RangePicker v-model:value="dateRange" format="YYYY-MM-DD HH:mm:ss" :placeholder="['开始时间', '结束时间']"
               style="width: 300px" :show-time="{ format: 'HH:mm:ss' }" @change="changeTime" />
           </div>
         </Col>
@@ -42,8 +42,7 @@
               <Input v-model="selectedParamsText" placeholder="请选择监测参数" readonly style="width: 300px" />
               <Button type="primary" @click="showTree = !showTree">+</Button>
               <div class="tree-popup" v-if="showTree">
-                <BasicTree :treeData="treeData" :checkable="true" defaultExpandAll @check="handleTreeCheck"
-                  :checkedKeys="checkedTreeKeys" />
+                <BasicTree :treeData="treeData" :checkable="true" defaultExpandAll @check="handleTreeCheck" :checkedKeys="checkedTreeKeys" />
               </div>
             </div>
           </div>
@@ -52,7 +51,7 @@
     </div>
     <!-- 动态图表区域-->
     <div class="chart-area">
-      <div class="chart-item" style="flex: 1 1 100%;">
+      <div class="chart-item" style="flex: 1 1 100%">
         <div class="chart-placeholder">
           <template v-if="generatedChartData.length">
             <CustomChart :chart-data="generatedChartData" :chart-config="generatedChartConfig"
@@ -85,15 +84,15 @@ import { useRouter } from 'vue-router';
 
 
 // 组件注册
-const RangePicker:any = DatePicker.RangePicker;
+const RangePicker: any = DatePicker.RangePicker;
 const { currentRoute } = useRouter();
-const mineCode=ref<any>(currentRoute.value['query']['mineCode'])//传递过来的矿ID
+const mineCode = ref<any>(currentRoute.value['query']['mineCode'])//传递过来的矿ID
 // 筛选相关响应式数据
 const dateRange = ref([dayjs().add(-30, 'day'), dayjs()]); // 默认时间范围(近1天)
 // const selectedParamsText = ref(''); // 参数选择框显示文本
 // const showTree = ref(false); // 控制树形选择器显示/隐藏
 // const checkedTreeKeys = ref([]); // 树形选中的key
-const selectedParams = ref(['coVal','ch4Val','c2h4Val','c2h2Val','co2Val','o2Val','sourcePressure','temperature']); // 选中的参数(实际用于图表)
+const selectedParams = ref(['coVal', 'ch4Val', 'c2h4Val', 'c2h2Val', 'co2Val', 'o2Val', 'sourcePressure', 'temperature']); // 选中的参数(实际用于图表)
 const generatedChartData = ref<any[]>([]); // 生成的图表数据
 const generatedChartConfig = ref({}); // 生成的图表配置
 const isChartGenerated = ref(false); // 是否已点击生成
@@ -104,7 +103,6 @@ const mineStore = useMineStore();
 const { getMine, getMineCode, getMinePath, getMineTree } = storeToRefs(mineStore);
 const innerValue = computed(() => getMinePath.value.map((e) => e.fax));
 
-
 // Tree Key 与参数名映射(关键:关联树形节点和实际参数)
 const treeKeyToParamMap = computed(() => ({
   '0-0-0': 'coVal',
@@ -120,14 +118,14 @@ const treeKeyToParamMap = computed(() => ({
 }));
 // 参数标签映射(图表系列名称)
 const paramLabelMap = computed(() => ({
-  'coVal': 'CO浓度(ppm)',
-  'ch4Val': 'CH4浓度(%)',
-  'c2h4Val': 'C2H4浓度(ppm)',
-  'c2h2Val': 'C2H2浓度(ppm)',
-  'co2Val': 'CO2浓度(%)',
-  'o2Val': 'O2浓度(%)',
-  'sourcePressure': '压力(kPa)',
-  'temperature': '温度(℃)',
+  coVal: 'CO浓度(ppm)',
+  ch4Val: 'CH4浓度(%)',
+  c2h4Val: 'C2H4浓度(ppm)',
+  c2h2Val: 'C2H2浓度(ppm)',
+  co2Val: 'CO2浓度(%)',
+  o2Val: 'O2浓度(%)',
+  sourcePressure: '压力(kPa)',
+  temperature: '温度(℃)',
   // 'innerPressure': '内压力(kPa)',
   // 'outerPressure': '外压力(kPa)',
   // 'pressureDiff': '压差(kPa)',
@@ -135,32 +133,32 @@ const paramLabelMap = computed(() => ({
 }));
 // 参数颜色映射
 const paramColorMap = computed(() => ({
-  'coVal': '#f5222d',    // 红色
-  'ch4Val': '#1890ff',   // 蓝色
-  'c2h4Val': '#faad14',  // 橙色
-  'c2h2Val': '#52c41a',  // 绿色
-  'co2Val': '#722ed1',   // 紫色
-  'o2Val': '#13c2c2',    // 青色
-  'sourcePressure': '#ff4d4f', // 浅红
+  coVal: '#f5222d', // 红色
+  ch4Val: '#1890ff', // 蓝色
+  c2h4Val: '#faad14', // 橙色
+  c2h2Val: '#52c41a', // 绿色
+  co2Val: '#722ed1', // 紫色
+  o2Val: '#13c2c2', // 青色
+  sourcePressure: '#ff4d4f', // 浅红
   // 'outerPressure': '#40a9ff',// 浅蓝
   // 'pressureDiff': '#fa8c16', // 浅橙
-  'temperature': '#9254de',  // 浅紫
+  temperature: '#9254de', // 浅紫
 }));
 
-// // 树形选择事件处理
-// const handleTreeCheck = (checkedKeys) => {
-//   checkedTreeKeys.value = checkedKeys;
-//   // 转换为实际参数名
-//   const params = checkedKeys
-//     .map(key => treeKeyToParamMap.value[key])
-//     .filter(param => param); // 过滤无效参数
-//   selectedParams.value = params;
-//  console.log( selectedParams.value,' selectedParams')
-//   // 更新输入框显示文本
-//   const paramLabels = params.map(param => paramLabelMap.value[param]);
-//   selectedParamsText.value = paramLabels.join('、');
-//   console.log( selectedParamsText.value,' selectedParamsText')
-// };
+//  // 树形选择事件处理
+//   const handleTreeCheck = (checkedKeys) => {
+//     checkedTreeKeys.value = checkedKeys;
+//     // 转换为实际参数名
+//     const params = checkedKeys
+//       .map(key => treeKeyToParamMap.value[key])
+//       .filter(param => param); // 过滤无效参数
+//     selectedParams.value = params;
+//     console.log(selectedParams.value, ' selectedParams')
+//     // 更新输入框显示文本
+//     const paramLabels = params.map(param => paramLabelMap.value[param]);
+//     selectedParamsText.value = paramLabels.join('、');
+//     console.log(selectedParamsText.value, ' selectedParamsText')
+//   };
 
 function changeTime(val) {
   dateRange.value[0] = val[0]
@@ -171,8 +169,8 @@ function changeTime(val) {
 async function generateChart() {
   // showTree.value = false
   //获取采空区历史数据列表
-  let startTime=dateRange.value[0].format('YYYY-MM-DD HH:mm:ss')
-  let endTime=dateRange.value[1].format('YYYY-MM-DD HH:mm:ss')
+  let startTime = dateRange.value[0].format('YYYY-MM-DD HH:mm:ss')
+  let endTime = dateRange.value[1].format('YYYY-MM-DD HH:mm:ss')
   let res = await getGoafHistory({ pageNo: 1, pageSize: 100, startTime: startTime, endTime: endTime, goafId: goafId.value })
   if (res && res.records) {
     filteredData.value = res.records
@@ -181,7 +179,7 @@ async function generateChart() {
     filteredData.value.length = 0
     isChartGenerated.value = true;
   }
-  console.log(filteredData.value,'filteredData')
+  console.log(filteredData.value, 'filteredData')
 
   // 2. 构建图表数据结构(适配 CustomChart 的 line 类型)
   const timeMap = new Map();
@@ -192,7 +190,7 @@ async function generateChart() {
       timeMap.set(timeStr, { time: timeStr });
     }
     // 只保留选中的参数数据
-    selectedParams.value.forEach(param => {
+    selectedParams.value.forEach((param) => {
       if (item[param] !== undefined) {
         timeMap.get(timeStr)[param] = item[param];
       }
@@ -204,7 +202,7 @@ async function generateChart() {
     return dayjs(a.time).valueOf() - dayjs(b.time).valueOf();
   });
   generatedChartData.value = chartData;
-  console.log(generatedChartData.value,'generatedChartData')
+  console.log(generatedChartData.value, 'generatedChartData')
 
   // 3. 构建图表配置(折线图类型,完善适配逻辑)
   generatedChartConfig.value = {
@@ -220,11 +218,11 @@ async function generateChart() {
             color: '#fff',
           },
           formatter: (value) => dayjs(value).format('HH:mm:ss'),
-          interval: Math.max(1, Math.floor(chartData.length / 10)) // 控制x轴标签密度
-        }
-      }
+          interval: Math.max(1, Math.floor(chartData.length / 10)), // 控制x轴标签密度
+        },
+      },
     ],
-    yAxis: selectedParams.value.map(param => ({
+    yAxis: selectedParams.value.map((param) => ({
       type: 'value',
       axisLabel: {
         textStyle: {
@@ -235,7 +233,7 @@ async function generateChart() {
       // nameTextStyle: { color: paramColorMap.value[param] },
       nameTextStyle: { color: '#fff' },
       axisLine: { lineStyle: { color: paramColorMap.value[param] } },
-      splitLine: { lineStyle: { opacity: 0.1 } }
+      splitLine: { lineStyle: { opacity: 0.1 } },
     })),
     series: selectedParams.value.map((param, index) => ({
       name: paramLabelMap.value[param],
@@ -255,20 +253,21 @@ async function generateChart() {
       axisPointer: { type: 'cross' },
       formatter: (params) => {
         let tooltipHtml = `<div>${dayjs(params[0].axisValue).format('YYYY-MM-DD HH:mm:ss')}</div>`;
-        params.forEach(param => {
+        params.forEach((param) => {
           tooltipHtml += `<div style="color: ${param.color}">${param.seriesName}: ${param.value[1]} ${param.seriesName.split('(')[1].replace(')', '')}</div>`;
         });
         return tooltipHtml;
-      }
+      },
     },
-    grid: { left: 60, top: 40, right: 60, bottom: 60 }
+    grid: { left: 60, top: 40, right: 60, bottom: 60 },
   };
 
   // 无数据提示
   if (chartData.length === 0) {
     message.info('当前筛选条件下无数据');
   }
-};
+}
+
 //获取采空区列表
 async function getGoafListData() {
   let res = await getGoafList({ mineCode: innerValue.value[innerValue.value.length - 1] })
@@ -284,9 +283,8 @@ async function getGoafListData() {
 }
 
 watchEffect(() => {
-  innerValue.value && getGoafListData()
-})
-
+  innerValue.value && getGoafListData();
+});
 </script>
 
 <style lang="less" scoped>
@@ -301,7 +299,7 @@ watchEffect(() => {
     padding: 20px;
     border: 1px solid #f0f0f0;
     border-radius: 10px;
-    background: #f8f9fc;
+    background: @card-bg-color;
     align-items: center;
   }
 
@@ -353,7 +351,7 @@ watchEffect(() => {
     padding: 20px;
     border: 1px solid #f0f0f0;
     border-radius: 10px;
-    background: #f8f9fc;
+    background: @card-bg-color;
   }
 
   .chart-item {

+ 18 - 9
src/views/analysis/warningAnalysis/fireAreaJudgeAnalysis/fireAreaJudge.api.ts

@@ -4,7 +4,7 @@ enum Api {
   getProvinceAlarm = '/province/alarm/getProvinceAlarm',
   getMineData = '/province/mineData/getMineData',
   getProvinceAlarmNum = '/province/alarm/getProvinceAlarmNum',
-  getGoafData = '/province/device/getGoafDList',
+  getGoafData = '/province/device/getGoafList',
   getProvinceAlarmHistory = '/province/alarm/getProvinceAlarmHistory',
   getEnfMineTreeData = '/jeecg-system/sys/user/getEnfMineTreeData',
 }
@@ -25,16 +25,25 @@ export const getMineData = (params) =>
   });
 //查询预警数据
 export const getProvinceAlarm = (params) =>
-  defHttp.post({
-    url: Api.getProvinceAlarm,
-    params,
-  });
+  defHttp.post(
+    {
+      url: Api.getProvinceAlarm,
+      params: {
+        alarmType: 'unsealAlarm',
+        ...params,
+      },
+    },
+    { joinParamsToUrl: true }
+  );
 //查询密闭列表
 export const getGoafData = (params) =>
-  defHttp.post({
-    url: Api.getGoafData,
-    params,
-  });
+  defHttp.post(
+    {
+      url: Api.getGoafData,
+      params,
+    },
+    { joinParamsToUrl: true }
+  );
 //查询预警历史数据
 export const getProvinceAlarmHistory = (params) =>
   defHttp.post(

+ 22 - 12
src/views/analysis/warningAnalysis/fireAreaJudgeAnalysis/fireAreaJudgeAnalysis.data.ts

@@ -28,68 +28,78 @@ export const columns: BasicColumn[] = [
   {
     title: '序号',
     align: 'center',
+    width: 80,
     customRender: ({ index }: { index: number }) => `${index + 1}`,
   },
   {
     title: '区域',
     dataIndex: 'areaName',
+    width: 100,
   },
   {
     title: '煤矿名称',
     dataIndex: 'mineName',
+    width: 200,
   },
   {
     title: '密闭名称',
     dataIndex: 'devicePos',
+    width: 100,
   },
   {
     title: '所属煤层',
     dataIndex: 'coalSeamName',
+    width: 100,
   },
   {
     title: '自燃倾向性',
-    dataIndex: 'riskLevel',
+    dataIndex: 'coalSeamLevel',
+    width: 100,
   },
   {
     title: '空气温度(℃)',
     dataIndex: 'temperature',
+    width: 100,
   },
   {
     title: 'O2浓度(ppm)',
-    dataIndex: 'O2Val',
+    dataIndex: 'o2Val',
+    width: 100,
   },
   {
     title: 'C2H4浓度(ppm)',
-    dataIndex: 'C2H4Val',
+    dataIndex: 'c2h4Val',
+    width: 100,
   },
   {
     title: 'C2H2浓度(ppm)',
-    dataIndex: 'C2H2Val',
+    dataIndex: 'c2h2Val',
+    width: 100,
   },
   {
     title: 'CO浓度(ppm)',
-    dataIndex: 'COVal',
+    dataIndex: 'coVal',
+    width: 100,
   },
   {
     title: '出水温度(℃)',
     dataIndex: 'temperature',
+    width: 100,
   },
-
   {
     title: '监测时长(天)',
     dataIndex: 'daysMonitored',
+    width: 100,
   },
   {
     title: '风险分析',
-    dataIndex: 'riskAnalysis',
+    dataIndex: 'alarmName',
+    width: 100,
   },
   {
     title: '预警时间',
-    dataIndex: 'alertTime',
-  },
-  {
-    title: '是否解决',
-    dataIndex: 'isResolved',
+    dataIndex: 'createTime',
+    width: 100,
   },
 ];
 

+ 65 - 84
src/views/analysis/warningAnalysis/fireAreaJudgeAnalysis/index.vue

@@ -1,57 +1,56 @@
+<!-- eslint-disable vue/multi-word-component-names -->
 <template>
-  <div class="monitoring-page">
-    <!-- 新增Tabs组件区分实时/历史数据 -->
-    <Tabs v-model:activeKey="activeTab" type="card" style="margin-bottom: 16px">
-      <TabPane tab="实时监测" key="realtime">
-        <div class="board-info">
-          <MiniBoard
-            :key="index"
-            v-for="(item, index) in boardData"
-            type="A"
-            :label="item.label"
-            :value="item.value"
-            layout="label-top"
-            class="board-item"
-          />
-        </div>
-        <!-- 实时数据表格 -->
-        <BasicTable @register="registerTable" :scroll="{ x: 'max-content' }">
-          <template #action="{ record }">
-            <div class="action-buttons">
-              <!-- 操作按钮 -->
-              <button @click="openModal(record, 'detail')" class="action-btn detail-btn" title="操作">
-                <span class="action-text">详情</span>
-              </button>
-            </div>
-          </template>
-        </BasicTable>
-      </TabPane>
+  <!-- 新增Tabs组件区分实时/历史数据 -->
+  <Tabs v-model:activeKey="activeTab" type="line" class="common-page-tabs">
+    <TabPane tab="实时监测" key="realtime">
+      <div class="board-info">
+        <MiniBoard
+          :key="index"
+          v-for="(item, index) in boardData"
+          type="A"
+          :label="item.label"
+          :value="item.value"
+          layout="label-top"
+          class="board-item"
+        />
+      </div>
+      <!-- 实时数据表格 -->
+      <BasicTable @register="registerTable" :scroll="{ x: 'max-content' }" :style="{ padding: 0 }">
+        <template #action="{ record }">
+          <div class="action-buttons">
+            <!-- 操作按钮 -->
+            <button @click="openModal(record, 'detail')" class="action-btn detail-btn" title="操作">
+              <span class="action-text">详情</span>
+            </button>
+          </div>
+        </template>
+      </BasicTable>
+    </TabPane>
 
-      <TabPane tab="历史数据" key="history">
-        <!-- 历史数据表格 -->
-        <BasicTable @register="registerHistoryTable" :scroll="{ x: 'max-content' }">
-          <template #action="{ record }">
-            <div class="action-buttons">
-              <button @click="openModal(record, 'history')" class="action-btn">
-                <SvgIcon name="details" />
-              </button>
-            </div>
-          </template>
-        </BasicTable>
-      </TabPane>
-    </Tabs>
-    <!-- 弹窗组件 -->
-    <a-modal
-      style="top: 30%; left: 170px"
-      v-model:visible="visibleModal"
-      :width="450"
-      title="实时监测数据"
-      @ok="handleOkEdit"
-      @cancel="handleCancelEdit"
-    >
-      <a-table></a-table>
-    </a-modal>
-  </div>
+    <TabPane tab="历史数据" key="history">
+      <!-- 历史数据表格 -->
+      <BasicTable @register="registerHistoryTable" :scroll="{ x: 'max-content' }" :style="{ padding: 0 }">
+        <template #action="{ record }">
+          <div class="action-buttons">
+            <button @click="openModal(record, 'history')" class="action-btn">
+              <SvgIcon name="details" />
+            </button>
+          </div>
+        </template>
+      </BasicTable>
+    </TabPane>
+  </Tabs>
+  <!-- 弹窗组件 -->
+  <a-modal
+    style="top: 30%; left: 170px"
+    v-model:visible="visibleModal"
+    :width="450"
+    title="实时监测数据"
+    @ok="handleOkEdit"
+    @cancel="handleCancelEdit"
+  >
+    <a-table></a-table>
+  </a-modal>
 </template>
 
 <script setup lang="ts">
@@ -105,19 +104,18 @@ const [registerTable] = useTable({
     showAdvancedButton: false,
     schemaGroupNames: ['常规查询'],
   },
-  pagination: false,
-  striped: false,
+  pagination: true,
+  striped: true,
   useSearchForm: true,
   bordered: true,
   showIndexColumn: false,
-  canResize: false,
-  actionColumn: {
-    width: 120,
-    title: '详情',
-    dataIndex: 'action',
-    slots: { customRender: 'action' },
-    fixed: undefined,
-  },
+  // actionColumn: {
+  //   width: 120,
+  //   title: '详情',
+  //   dataIndex: 'action',
+  //   slots: { customRender: 'action' },
+  //   fixed: undefined,
+  // },
 });
 
 // 注册历史数据表格
@@ -169,12 +167,7 @@ const [registerHistoryTable] = useTable({
         label: '采空区查询',
         field: 'goafId',
         component: 'Select',
-        defaultValue: goafOptions.value[0] ? goafOptions.value[0]['value'] : '',
         componentProps: {
-          showSearch: true,
-          filterOption: (input: string, option: any) => {
-            return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0;
-          },
           options: goafOptions,
           onChange: async (e, option) => {
             goafId.value = e;
@@ -206,12 +199,11 @@ const [registerHistoryTable] = useTable({
     showAdvancedButton: false,
     schemaGroupNames: ['常规查询'],
   },
-  pagination: false,
-  striped: false,
+  pagination: true,
+  striped: true,
   useSearchForm: true,
   bordered: true,
   showIndexColumn: false,
-  canResize: false,
   actionColumn: {
     width: 60,
     title: '操作',
@@ -295,9 +287,6 @@ onMounted(() => {
 </script>
 
 <style lang="less" scoped>
-.monitoring-page {
-  padding: 16px;
-}
 .board-info {
   display: grid;
   grid-template-columns: repeat(5, auto); /* 3列:改5则为5列 */
@@ -305,21 +294,13 @@ onMounted(() => {
   justify-content: start;
   flex-wrap: wrap;
   box-sizing: border-box;
-  background-color: #fff;
+  background-color: @white;
   padding: 10px;
-  margin: 0 10px;
   gap: 100px;
+  // margin: 0 10px;
+  margin-bottom: 5px;
 }
 .board-item {
   box-sizing: border-box;
 }
-.action-btn {
-  cursor: pointer;
-  border: none;
-  padding: 4px;
-}
-.action-icon {
-  width: 16px;
-  height: 16px;
-}
 </style>

+ 65 - 84
src/views/analysis/warningAnalysis/overlimitAlarm/index.vue

@@ -1,57 +1,56 @@
+<!-- eslint-disable vue/multi-word-component-names -->
 <template>
-  <div class="monitoring-page">
-    <!-- 新增Tabs组件区分实时/历史数据 -->
-    <Tabs v-model:activeKey="activeTab" type="card" style="margin-bottom: 16px">
-      <TabPane tab="实时监测" key="realtime">
-        <div class="board-info">
-          <MiniBoard
-            :key="index"
-            v-for="(item, index) in boardData"
-            type="A"
-            :label="item.label"
-            :value="item.value"
-            layout="label-top"
-            class="board-item"
-          />
-        </div>
-        <!-- 实时数据表格 -->
-        <BasicTable @register="registerTable" :scroll="{ x: 'max-content' }">
-          <template #action="{ record }">
-            <div class="action-buttons">
-              <!-- 操作按钮 -->
-              <button @click="openModal(record, 'detail')" class="action-btn detail-btn" title="操作">
-                <span class="action-text">详情</span>
-              </button>
-            </div>
-          </template>
-        </BasicTable>
-      </TabPane>
+  <!-- 新增Tabs组件区分实时/历史数据 -->
+  <Tabs v-model:activeKey="activeTab" type="line" class="common-page-tabs">
+    <TabPane tab="实时监测" key="realtime">
+      <div class="board-info">
+        <MiniBoard
+          :key="index"
+          v-for="(item, index) in boardData"
+          type="A"
+          :label="item.label"
+          :value="item.value"
+          layout="label-top"
+          class="board-item"
+        />
+      </div>
+      <!-- 实时数据表格 -->
+      <BasicTable @register="registerTable" :scroll="{ x: 'max-content' }" :style="{ padding: 0 }">
+        <template #action="{ record }">
+          <div class="action-buttons">
+            <!-- 操作按钮 -->
+            <button @click="openModal(record, 'detail')" class="action-btn detail-btn" title="操作">
+              <span class="action-text">详情</span>
+            </button>
+          </div>
+        </template>
+      </BasicTable>
+    </TabPane>
 
-      <TabPane tab="历史数据" key="history">
-        <!-- 历史数据表格 -->
-        <BasicTable @register="registerHistoryTable" :scroll="{ x: 'max-content' }">
-          <template #action="{ record }">
-            <div class="action-buttons">
-              <button @click="openModal(record, 'history')" class="action-btn">
-                <SvgIcon name="details" />
-              </button>
-            </div>
-          </template>
-        </BasicTable>
-      </TabPane>
-    </Tabs>
-    <!-- 弹窗组件 -->
-    <a-modal
-      style="top: 30%; left: 170px"
-      v-model:visible="visibleModal"
-      :width="450"
-      title="实时监测数据"
-      @ok="handleOkEdit"
-      @cancel="handleCancelEdit"
-    >
-      <a-table></a-table>
-    </a-modal>
-  </div>
+    <TabPane tab="历史数据" key="history">
+      <!-- 历史数据表格 -->
+      <BasicTable @register="registerHistoryTable" :scroll="{ x: 'max-content' }" :style="{ padding: 0 }">
+        <template #action="{ record }">
+          <div class="action-buttons">
+            <button @click="openModal(record, 'history')" class="action-btn">
+              <SvgIcon name="details" />
+            </button>
+          </div>
+        </template>
+      </BasicTable>
+    </TabPane>
+  </Tabs>
+  <!-- 弹窗组件 -->
+  <a-modal
+    style="top: 30%; left: 170px"
+    v-model:visible="visibleModal"
+    :width="450"
+    title="实时监测数据"
+    @ok="handleOkEdit"
+    @cancel="handleCancelEdit"
+  >
+    <a-table></a-table>
+  </a-modal>
 </template>
 
 <script setup lang="ts">
@@ -114,12 +113,11 @@ const [registerTable] = useTable({
     showAdvancedButton: false,
     schemaGroupNames: ['常规查询'],
   },
-  pagination: false,
-  striped: false,
+  pagination: true,
+  striped: true,
   useSearchForm: true,
   bordered: true,
   showIndexColumn: false,
-  canResize: false,
   actionColumn: {
     width: 120,
     title: '详情',
@@ -178,12 +176,7 @@ const [registerHistoryTable] = useTable({
         label: '采空区查询',
         field: 'goafId',
         component: 'Select',
-        defaultValue: goafOptions.value[0] ? goafOptions.value[0]['value'] : '',
         componentProps: {
-          showSearch: true,
-          filterOption: (input: string, option: any) => {
-            return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0;
-          },
           options: goafOptions,
           onChange: async (e, option) => {
             goafId.value = e;
@@ -215,19 +208,18 @@ const [registerHistoryTable] = useTable({
     showAdvancedButton: false,
     schemaGroupNames: ['常规查询'],
   },
-  pagination: false,
-  striped: false,
+  pagination: true,
+  striped: true,
   useSearchForm: true,
   bordered: true,
   showIndexColumn: false,
-  canResize: false,
-  actionColumn: {
-    width: 60,
-    title: '操作',
-    dataIndex: 'action',
-    slots: { customRender: 'action' },
-    fixed: undefined,
-  },
+  // actionColumn: {
+  //   width: 60,
+  //   title: '操作',
+  //   dataIndex: 'action',
+  //   slots: { customRender: 'action' },
+  //   fixed: undefined,
+  // },
 });
 
 // 弹窗引用
@@ -306,9 +298,6 @@ onMounted(() => {
 </script>
 
 <style lang="less" scoped>
-.monitoring-page {
-  padding: 16px;
-}
 .board-info {
   display: grid;
   grid-template-columns: repeat(5, auto); /* 3列:改5则为5列 */
@@ -316,21 +305,13 @@ onMounted(() => {
   justify-content: start;
   flex-wrap: wrap;
   box-sizing: border-box;
-  background-color: #fff;
+  background-color: @white;
   padding: 10px;
-  margin: 0 10px;
   gap: 100px;
+  // margin: 0 10px;
+  margin-bottom: 5px;
 }
 .board-item {
   box-sizing: border-box;
 }
-.action-btn {
-  cursor: pointer;
-  border: none;
-  padding: 4px;
-}
-.action-icon {
-  width: 16px;
-  height: 16px;
-}
 </style>

+ 23 - 9
src/views/analysis/warningAnalysis/overlimitAlarm/overlimit.api.ts

@@ -25,22 +25,36 @@ export const getMineData = (params) =>
   });
 //查询预警数据
 export const getProvinceAlarm = (params) =>
-  defHttp.post({
-    url: Api.getProvinceAlarm,
-    params,
-  });
+  defHttp.post(
+    {
+      url: Api.getProvinceAlarm,
+      params: {
+        alarmType: 'overLimitAlarm',
+        ...params,
+      },
+    },
+    { joinParamsToUrl: true }
+  );
 //查询密闭列表
 export const getGoafData = (params) =>
-  defHttp.post({
-    url: Api.getGoafData,
-    params,
-  });
+  defHttp.post(
+    {
+      url: Api.getGoafData,
+      params,
+    },
+    {
+      joinParamsToUrl: true,
+    }
+  );
 //查询预警历史数据
 export const getProvinceAlarmHistory = (params) =>
   defHttp.post(
     {
       url: Api.getProvinceAlarmHistory,
-      params,
+      params: {
+        alarmType: 'overLimitAlarm',
+        ...params,
+      },
     },
     { joinParamsToUrl: true }
   ); //获取执法处以及区域数据

+ 18 - 4
src/views/analysis/warningAnalysis/overlimitAlarm/overlimitAlarm.data.ts

@@ -28,59 +28,73 @@ export const columns: BasicColumn[] = [
   {
     title: '序号',
     align: 'center',
+    width: 80,
     customRender: ({ index }: { index: number }) => `${index + 1}`,
   },
   {
     title: '区域',
     dataIndex: 'areaName',
+    width: 100,
   },
   {
     title: '煤矿名称',
     dataIndex: 'mineName',
+    width: 200,
   },
   {
     title: '密闭名称',
     dataIndex: 'devicePos',
+    width: 100,
   },
   {
     title: '所属煤层',
     dataIndex: 'coalSeamName',
+    width: 100,
   },
   {
     title: '自燃倾向性',
-    dataIndex: 'riskLevel',
+    dataIndex: 'coalSeamLevel',
+    width: 100,
   },
   {
     title: 'CO浓度(ppm)',
-    dataIndex: 'COVal',
+    dataIndex: 'coVal',
+    width: 100,
   },
   {
     title: 'CO日增率',
     dataIndex: 'coIncreaseRate',
+    width: 100,
   },
   {
     title: 'O2浓度(ppm)',
-    dataIndex: 'O2Val',
+    dataIndex: 'o2Val',
+    width: 100,
   },
   {
     title: '温度(℃)',
     dataIndex: 'temperature',
+    width: 100,
   },
   {
     title: '温差(℃)',
     dataIndex: 'temperatureDiff',
+    width: 100,
   },
   {
     title: '风险分析',
     dataIndex: 'alarmName',
+    width: 100,
   },
   {
     title: '预警时间',
-    dataIndex: 'alertTime',
+    dataIndex: 'createTime',
+    width: 100,
   },
   {
     title: '是否解决',
     dataIndex: 'isResolved',
+    width: 100,
   },
 ];
 

+ 81 - 108
src/views/analysis/warningAnalysis/pressureDiffAnalysis/index.vue

@@ -1,73 +1,72 @@
+<!-- eslint-disable vue/multi-word-component-names -->
 <template>
-  <div class="monitoring-page">
-    <!-- 新增Tabs组件区分实时/历史数据 -->
-    <Tabs v-model:activeKey="activeTab" type="card" style="margin-bottom: 16px">
-      <TabPane tab="实时监测" key="realtime">
-        <div class="board-info">
-          <MiniBoard
-            :key="index"
-            v-for="(item, index) in boardData"
-            type="A"
-            :label="item.label"
-            :value="item.value"
-            layout="label-top"
-            class="board-item"
-          />
-        </div>
-        <!-- 实时数据表格 -->
-        <BasicTable @register="registerTable" :scroll="{ x: 'max-content' }">
-          <template #action="{ record }">
-            <div class="action-buttons">
-              <!-- 操作按钮 -->
-              <button @click="openModal(record, 'detail')" class="action-btn detail-btn" title="操作">
-                <span class="action-text">详情</span>
-              </button>
-              <!-- 已解决按钮 -->
-              <button @click="openModal(record, 'resolved')" class="action-btn resolved-btn" title="已解决">
-                <span class="action-text">已解决</span>
-              </button>
-            </div>
-          </template>
-        </BasicTable>
-      </TabPane>
+  <!-- 新增Tabs组件区分实时/历史数据 -->
+  <Tabs v-model:activeKey="activeTab" type="line" class="common-page-tabs">
+    <TabPane tab="实时监测" key="realtime">
+      <div class="board-info">
+        <MiniBoard
+          :key="index"
+          v-for="(item, index) in boardData"
+          type="A"
+          :label="item.label"
+          :value="item.value"
+          layout="label-top"
+          class="board-item"
+        />
+      </div>
+      <!-- 实时数据表格 -->
+      <BasicTable @register="registerTable" :scroll="{ x: 'max-content' }" :style="{ padding: 0 }">
+        <template #action="{ record }">
+          <div class="action-buttons">
+            <!-- 操作按钮 -->
+            <!-- <button @click="openModal(record, 'detail')" class="action-btn detail-btn" title="操作">
+              <span class="action-text">详情</span>
+            </button> -->
+            <!-- 已解决按钮 -->
+            <button @click="openModal(record, 'resolved')" class="action-btn resolved-btn" title="已解决">
+              <span class="action-text">解决</span>
+            </button>
+          </div>
+        </template>
+      </BasicTable>
+    </TabPane>
 
-      <TabPane tab="历史数据" key="history">
-        <!-- 历史数据表格 -->
-        <BasicTable @register="registerHistoryTable" :scroll="{ x: 'max-content' }">
-          <template #action="{ record }">
-            <div class="action-buttons">
-              <button @click="openModal(record, 'history')" class="action-btn">
-                <SvgIcon name="details" />
-              </button>
-            </div>
-          </template>
-        </BasicTable>
-      </TabPane>
-    </Tabs>
-    <!-- 弹窗组件 -->
-    <a-modal
-      style="top: 30%; left: 170px"
-      v-model:visible="visibleModal"
-      :width="450"
-      title="实时监测数据"
-      @ok="handleOkEdit"
-      @cancel="handleCancelEdit"
-    >
-      <a-table></a-table>
-    </a-modal>
-    <!-- 弹窗组件 -->
-    <a-modal
-      style="height: 400px"
-      v-model:visible="visibleresolveModal"
-      :width="600"
-      centered
-      title="密闭漏风处理情况"
-      @ok="handleOkEdit()"
-      @cancel="handleCancelEdit"
-    >
-      <a-textarea style="width: 90%; margin-left: 20px; margin-right: 20px" v-model:value="resolveValue" placeholder="请输入解决情况" :rows="4" />
-    </a-modal>
-  </div>
+    <TabPane tab="历史数据" key="history">
+      <!-- 历史数据表格 -->
+      <BasicTable @register="registerHistoryTable" :scroll="{ x: 'max-content' }" :style="{ padding: 0 }">
+        <template #action="{ record }">
+          <div class="action-buttons">
+            <button @click="openModal(record, 'history')" class="action-btn">
+              <SvgIcon name="details" />
+            </button>
+          </div>
+        </template>
+      </BasicTable>
+    </TabPane>
+  </Tabs>
+  <!-- 弹窗组件 -->
+  <a-modal
+    style="top: 30%; left: 170px"
+    v-model:visible="visibleModal"
+    :width="450"
+    title="实时监测数据"
+    @ok="handleOkEdit"
+    @cancel="handleCancelEdit"
+  >
+    <a-table></a-table>
+  </a-modal>
+  <!-- 弹窗组件 -->
+  <a-modal
+    style="height: 400px"
+    v-model:visible="visibleresolveModal"
+    :width="600"
+    centered
+    title="密闭漏风处理情况"
+    @ok="handleOkEdit()"
+    @cancel="handleCancelEdit"
+  >
+    <a-textarea style="width: 90%; margin-left: 20px; margin-right: 20px" v-model:value="resolveValue" placeholder="请输入解决情况" :rows="4" />
+  </a-modal>
 </template>
 
 <script setup lang="ts">
@@ -132,12 +131,11 @@ const [registerTable] = useTable({
     showAdvancedButton: false,
     schemaGroupNames: ['常规查询'],
   },
-  pagination: false,
-  striped: false,
+  pagination: true,
+  striped: true,
   useSearchForm: true,
   bordered: true,
   showIndexColumn: false,
-  canResize: false,
   actionColumn: {
     width: 120,
     title: '操作',
@@ -196,12 +194,7 @@ const [registerHistoryTable] = useTable({
         label: '采空区查询',
         field: 'goafId',
         component: 'Select',
-        defaultValue: goafOptions.value[0] ? goafOptions.value[0]['value'] : '',
         componentProps: {
-          showSearch: true,
-          filterOption: (input: string, option: any) => {
-            return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0;
-          },
           options: goafOptions,
           onChange: async (e, option) => {
             goafId.value = e;
@@ -233,19 +226,18 @@ const [registerHistoryTable] = useTable({
     showAdvancedButton: false,
     schemaGroupNames: ['常规查询'],
   },
-  pagination: false,
-  striped: false,
+  pagination: true,
+  striped: true,
   useSearchForm: true,
   bordered: true,
   showIndexColumn: false,
-  canResize: false,
-  actionColumn: {
-    width: 120,
-    title: '操作',
-    dataIndex: 'action',
-    slots: { customRender: 'action' },
-    fixed: undefined,
-  },
+  // actionColumn: {
+  //   width: 120,
+  //   title: '操作',
+  //   dataIndex: 'action',
+  //   slots: { customRender: 'action' },
+  //   fixed: undefined,
+  // },
 });
 
 // 弹窗引用
@@ -328,9 +320,6 @@ onMounted(() => {
 </script>
 
 <style lang="less" scoped>
-.monitoring-page {
-  padding: 16px;
-}
 .board-info {
   display: grid;
   grid-template-columns: repeat(5, auto); /* 3列:改5则为5列 */
@@ -338,29 +327,13 @@ onMounted(() => {
   justify-content: start;
   flex-wrap: wrap;
   box-sizing: border-box;
-  background-color: #fff;
+  background-color: @white;
   padding: 10px;
-  margin: 0 10px;
   gap: 100px;
+  // margin: 0 10px;
+  margin-bottom: 5px;
 }
 .board-item {
   box-sizing: border-box;
 }
-.action-buttons {
-  display: flex;
-  gap: 8px;
-}
-.action-btn {
-  cursor: pointer;
-  border: none;
-  padding: 4px;
-}
-.action-icon {
-  width: 16px;
-  height: 16px;
-}
-.action-text {
-  font-size: 12px;
-  color: #6398fc;
-}
 </style>

+ 19 - 8
src/views/analysis/warningAnalysis/pressureDiffAnalysis/pressureDiff.api.ts

@@ -25,16 +25,27 @@ export const getMineData = (params) =>
   });
 //查询预警数据
 export const getProvinceAlarm = (params) =>
-  defHttp.post({
-    url: Api.getProvinceAlarm,
-    params,
-  });
+  defHttp.post(
+    {
+      url: Api.getProvinceAlarm,
+      params: {
+        alarmType: 'sourcePressureAlarm',
+        ...params,
+      },
+    },
+    { joinParamsToUrl: true }
+  );
 //查询密闭列表
 export const getGoafData = (params) =>
-  defHttp.post({
-    url: Api.getGoafData,
-    params,
-  });
+  defHttp.post(
+    {
+      url: Api.getGoafData,
+      params,
+    },
+    {
+      joinParamsToUrl: true,
+    }
+  );
 //查询预警历史数据
 export const getProvinceAlarmHistory = (params) =>
   defHttp.post(

+ 17 - 5
src/views/analysis/warningAnalysis/pressureDiffAnalysis/pressureDiffAnalysis.data.ts

@@ -28,51 +28,63 @@ export const columns: BasicColumn[] = [
   {
     title: '序号',
     align: 'center',
+    width: 80,
     customRender: ({ index }: { index: number }) => `${index + 1}`,
   },
   {
     title: '区域',
     dataIndex: 'areaName',
+    width: 100,
   },
   {
     title: '煤矿名称',
     dataIndex: 'mineName',
+    width: 200,
   },
   {
     title: '密闭名称',
     dataIndex: 'devicePos',
+    width: 100,
   },
   {
     title: '所属煤层',
     dataIndex: 'coalSeamName',
+    width: 100,
   },
   {
     title: '自燃倾向性',
-    dataIndex: 'riskLevel',
+    dataIndex: 'coalSeamLevel',
+    width: 100,
   },
   {
     title: '密闭内压力',
-    dataIndex: 'interPressure',
+    dataIndex: 'sourcePressure',
+    width: 100,
   },
   {
     title: '密闭外压力',
-    dataIndex: 'outerPressure',
+    dataIndex: 'sourcePressure',
+    width: 100,
   },
   {
     title: '是否漏风',
     dataIndex: 'leakage',
+    width: 100,
   },
   {
     title: '风险分析',
-    dataIndex: 'explosionHazard',
+    dataIndex: 'alarmName',
+    width: 100,
   },
   {
     title: '预警时间',
-    dataIndex: 'alertTime',
+    dataIndex: 'createTime',
+    width: 100,
   },
   {
     title: '是否解决',
     dataIndex: 'isResolved',
+    width: 100,
   },
 ];
 

+ 73 - 92
src/views/analysis/warningAnalysis/sealRiskJudgeAnalysis/index.vue

@@ -1,59 +1,58 @@
+<!-- eslint-disable vue/multi-word-component-names -->
 <template>
-  <div class="monitoring-page">
-    <!-- 新增Tabs组件区分实时/历史数据 -->
-    <Tabs v-model:activeKey="activeTab" type="card" style="margin-bottom: 16px">
-      <TabPane tab="实时监测" key="realtime">
-        <div class="board-info">
-          <MiniBoard
-            :key="index"
-            v-for="(item, index) in boardData"
-            type="A"
-            :label="item.label"
-            :value="item.value"
-            layout="label-top"
-            class="board-item"
-          />
-        </div>
-        <!-- 实时数据表格 -->
-        <BasicTable @register="registerTable" :scroll="{ x: 'max-content' }">
-          <!-- 核心:判断record是否有有效数据,无则显示- -->
-          <template #action="{ record }">
-            <button @click="openModal(record, 'detail')" class="action-btn detail-btn" title="操作">
-              <span class="action-text">详情</span>
-            </button>
-          </template>
-          <template #empty>
-            <!-- 无数据时显示-,样式居中对齐 -->
-            <span class="empty-placeholder">-</span>
-          </template>
-        </BasicTable>
-      </TabPane>
+  <!-- 新增Tabs组件区分实时/历史数据 -->
+  <Tabs v-model:activeKey="activeTab" type="line" class="common-page-tabs">
+    <TabPane tab="实时监测" key="realtime">
+      <div class="board-info">
+        <MiniBoard
+          :key="index"
+          v-for="(item, index) in boardData"
+          type="A"
+          :label="item.label"
+          :value="item.value"
+          layout="label-top"
+          class="board-item"
+        />
+      </div>
+      <!-- 实时数据表格 -->
+      <BasicTable @register="registerTable" :scroll="{ x: 'max-content' }" :style="{ padding: 0 }">
+        <!-- 核心:判断record是否有有效数据,无则显示- -->
+        <template #action="{ record }">
+          <button @click="openModal(record, 'detail')" class="action-btn detail-btn" title="操作">
+            <span class="action-text">详情</span>
+          </button>
+        </template>
+        <template #empty>
+          <!-- 无数据时显示-,样式居中对齐 -->
+          <span class="empty-placeholder">-</span>
+        </template>
+      </BasicTable>
+    </TabPane>
 
-      <TabPane tab="历史数据" key="history">
-        <!-- 历史数据表格 -->
-        <BasicTable @register="registerHistoryTable" :scroll="{ x: 'max-content' }">
-          <template #action="{ record }">
-            <div class="action-buttons">
-              <button @click="openModal(record, 'history')" class="action-btn">
-                <SvgIcon name="details" />
-              </button>
-            </div>
-          </template>
-        </BasicTable>
-      </TabPane>
-    </Tabs>
-    <!-- 弹窗组件 -->
-    <a-modal
-      style="top: 30%; left: 170px"
-      v-model:visible="visibleModal"
-      :width="450"
-      title="实时监测数据"
-      @ok="handleOkEdit"
-      @cancel="handleCancelEdit"
-    >
-      <a-table></a-table>
-    </a-modal>
-  </div>
+    <TabPane tab="历史数据" key="history">
+      <!-- 历史数据表格 -->
+      <BasicTable @register="registerHistoryTable" :scroll="{ x: 'max-content' }" :style="{ padding: 0 }">
+        <template #action="{ record }">
+          <div class="action-buttons">
+            <button @click="openModal(record, 'history')" class="action-btn">
+              <SvgIcon name="details" />
+            </button>
+          </div>
+        </template>
+      </BasicTable>
+    </TabPane>
+  </Tabs>
+  <!-- 弹窗组件 -->
+  <a-modal
+    style="top: 30%; left: 170px"
+    v-model:visible="visibleModal"
+    :width="450"
+    title="实时监测数据"
+    @ok="handleOkEdit"
+    @cancel="handleCancelEdit"
+  >
+    <a-table></a-table>
+  </a-modal>
 </template>
 
 <script setup lang="ts">
@@ -116,18 +115,17 @@ const [registerTable] = useTable({
     showAdvancedButton: false,
     schemaGroupNames: ['常规查询'],
   },
-  pagination: false,
-  striped: false,
+  pagination: true,
+  striped: true,
   useSearchForm: true,
   bordered: true,
   showIndexColumn: false,
-  canResize: false,
-  actionColumn: {
-    width: 60,
-    title: '操作',
-    dataIndex: 'action',
-    slots: { customRender: 'action' },
-  },
+  // actionColumn: {
+  //   width: 60,
+  //   title: '操作',
+  //   dataIndex: 'action',
+  //   slots: { customRender: 'action' },
+  // },
 });
 
 // 注册历史数据表格
@@ -179,12 +177,7 @@ const [registerHistoryTable] = useTable({
         label: '采空区查询',
         field: 'goafId',
         component: 'Select',
-        defaultValue: goafOptions.value[0] ? goafOptions.value[0]['value'] : '',
         componentProps: {
-          showSearch: true,
-          filterOption: (input: string, option: any) => {
-            return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0;
-          },
           options: goafOptions,
           onChange: async (e, option) => {
             goafId.value = e;
@@ -216,19 +209,18 @@ const [registerHistoryTable] = useTable({
     showAdvancedButton: false,
     schemaGroupNames: ['常规查询'],
   },
-  pagination: false,
-  striped: false,
+  pagination: true,
+  striped: true,
   useSearchForm: true,
   bordered: true,
   showIndexColumn: false,
-  canResize: false,
-  actionColumn: {
-    width: 60,
-    title: '操作',
-    dataIndex: 'action',
-    slots: { customRender: 'action' },
-    fixed: undefined,
-  },
+  // actionColumn: {
+  //   width: 60,
+  //   title: '操作',
+  //   dataIndex: 'action',
+  //   slots: { customRender: 'action' },
+  //   fixed: undefined,
+  // },
 });
 
 // 弹窗引用
@@ -308,9 +300,6 @@ onMounted(() => {
 </script>
 
 <style lang="less" scoped>
-.monitoring-page {
-  padding: 16px;
-}
 .board-info {
   display: grid;
   grid-template-columns: repeat(5, auto); /* 3列:改5则为5列 */
@@ -318,21 +307,13 @@ onMounted(() => {
   justify-content: start;
   flex-wrap: wrap;
   box-sizing: border-box;
-  background-color: #fff;
+  background-color: @white;
   padding: 10px;
-  margin: 0 10px;
   gap: 100px;
+  // margin: 0 10px;
+  margin-bottom: 5px;
 }
 .board-item {
   box-sizing: border-box;
 }
-.action-btn {
-  cursor: pointer;
-  border: none;
-  padding: 4px;
-}
-.action-icon {
-  width: 16px;
-  height: 16px;
-}
 </style>

+ 20 - 9
src/views/analysis/warningAnalysis/sealRiskJudgeAnalysis/sealRiskJudge.api.ts

@@ -25,23 +25,34 @@ export const getMineData = (params) =>
   });
 //查询预警数据
 export const getProvinceAlarm = (params) =>
-  defHttp.post({
-    url: Api.getProvinceAlarm,
-    params,
-  });
+  defHttp.post(
+    {
+      url: Api.getProvinceAlarm,
+      params: {
+        alarmType: 'explosionAlarm',
+        ...params,
+      },
+    },
+    { joinParamsToUrl: true }
+  );
 //查询密闭列表
 export const getGoafData = (params) =>
-  defHttp.post({
-    url: Api.getGoafData,
-    params,
-  });
+  defHttp.post(
+    {
+      url: Api.getGoafData,
+      params,
+    },
+    {
+      joinParamsToUrl: true,
+    }
+  );
 //查询预警历史数据
 export const getProvinceAlarmHistory = (params) =>
   defHttp.post(
     {
       url: Api.getProvinceAlarmHistory,
       params: {
-        alarmType: 'overLimitAlarm',
+        alarmType: 'explosionAlarm',
         ...params,
       },
     },

+ 22 - 8
src/views/analysis/warningAnalysis/sealRiskJudgeAnalysis/sealRiskJudgeAnalysis.data.ts

@@ -28,66 +28,80 @@ export const columns: BasicColumn[] = [
   {
     title: '序号',
     align: 'center',
+    width: 80,
     customRender: ({ index }: { index: number }) => `${index + 1}`,
   },
   {
     title: '区域',
     dataIndex: 'areaName',
+    width: 100,
   },
   {
     title: '煤矿名称',
     dataIndex: 'mineName',
+    width: 200,
   },
   {
     title: '密闭名称',
     dataIndex: 'devicePos',
+    width: 100,
   },
   {
     title: '所属煤层',
     dataIndex: 'coalSeamName',
+    width: 100,
   },
   {
     title: '自燃倾向性',
-    dataIndex: 'riskLevel',
+    dataIndex: 'coalSeamLevel',
+    width: 100,
   },
   {
     title: 'CO(ppm)',
-    dataIndex: 'COVal',
+    dataIndex: 'coVal',
+    width: 100,
   },
   {
     title: 'CH4(%)',
-    dataIndex: 'CH4Val',
+    dataIndex: 'ch4Val',
+    width: 100,
   },
   {
     title: 'C2H4(ppm)',
-    dataIndex: 'C2H4Val',
+    dataIndex: 'c2h4Val',
+    width: 100,
   },
   {
     title: 'C2H2(ppm)',
-    dataIndex: 'C2H2Val',
+    dataIndex: 'c2h2Val',
+    width: 100,
   },
   {
     title: 'O2(%)',
-    dataIndex: 'O2Val',
+    dataIndex: 'o2Val',
+    width: 100,
   },
   {
     title: '爆炸危险性',
     dataIndex: 'explosionHazard',
+    width: 100,
   },
   {
     title: '处置意见',
     dataIndex: 'suggestion',
+    width: 100,
   },
   {
     title: '预警时间',
-    dataIndex: 'alertTime',
+    dataIndex: 'createTime',
+    width: 100,
   },
   {
     title: '是否解决',
     dataIndex: 'isResolved',
+    width: 100,
   },
 ];
-
 export const searchFormSchema: FormSchema[] = [
   {
     field: 'mineName',

+ 19 - 19
src/views/dashboard/SealedGoaf/configurable.data.sealedGoaf.ts

@@ -60,9 +60,9 @@ export const testConfigSealedGoaf: Config[] = [
       preset: [],
     },
     showStyle: {
-      size: 'width:440px;height:220px;',
+      size: 'width:440px;height:170px;',
       version: '原版',
-      position: 'top:20px;left:10px;',
+      position: 'top:20px;left:25px;',
     },
   },
   // 2. 当日生产状态
@@ -116,9 +116,9 @@ export const testConfigSealedGoaf: Config[] = [
       preset: [],
     },
     showStyle: {
-      size: 'width:440px;height:160px;',
+      size: 'width:440px;height:140px;',
       version: '原版',
-      position: 'top:250px;left:10px;',
+      position: 'top:190px;left:25px;',
     },
   },
   // 3. 煤层自燃倾向性
@@ -171,9 +171,9 @@ export const testConfigSealedGoaf: Config[] = [
       preset: [],
     },
     showStyle: {
-      size: 'width:440px;height:230px;',
+      size: 'width:440px;height:180px;',
       version: '原版',
-      position: 'bottom:440px;left:10px;',
+      position: 'top:320px;left:25px;',
     },
   },
   // 4. 联网状态
@@ -244,7 +244,7 @@ export const testConfigSealedGoaf: Config[] = [
       gallery_list: [],
       table: [
         {
-          type: 'A',
+          type: 'B',
           // parser: 'json',
           readFrom: 'tableArray',
           columns: [
@@ -345,9 +345,9 @@ export const testConfigSealedGoaf: Config[] = [
       },
     },
     showStyle: {
-      size: 'width:440px;height:400px;',
+      size: 'width:440px;height:315px;',
       version: '原版',
-      position: 'bottom:20px;left:10px;',
+      position: 'bottom:20px;left:25px;',
     },
   },
   // 5. 密闭情况总览
@@ -378,12 +378,12 @@ export const testConfigSealedGoaf: Config[] = [
         items: [
           {
             name: 'board',
-            basis: '35%',
+            basis: '40%',
             overflow: true,
           },
           {
             name: 'table',
-            basis: '65%',
+            basis: '60%',
             overflow: true,
           },
         ],
@@ -514,9 +514,9 @@ export const testConfigSealedGoaf: Config[] = [
       },
     },
     showStyle: {
-      size: 'width:440px;height:450px;',
+      size: 'width:440px;height:330px;',
       version: '原版',
-      position: 'top:-20px;right:10px;',
+      position: 'top:-20px;right:25px;',
     },
   },
   // 6. 采空区密闭预警分析
@@ -547,12 +547,12 @@ export const testConfigSealedGoaf: Config[] = [
         items: [
           {
             name: 'board',
-            basis: '40%',
+            basis: '42%',
             overflow: true,
           },
           {
             name: 'table',
-            basis: '60%',
+            basis: '58%',
             overflow: true,
           },
         ],
@@ -681,9 +681,9 @@ export const testConfigSealedGoaf: Config[] = [
       // },
     },
     showStyle: {
-      size: 'width:440px;height:400px;',
+      size: 'width:440px;height:300px;',
       version: '原版',
-      position: 'top:440px;right:10px;',
+      position: 'top:320px;right:25px;',
     },
   },
   // 7. 当日报警情况统计
@@ -768,9 +768,9 @@ export const testConfigSealedGoaf: Config[] = [
       preset: [],
     },
     showStyle: {
-      size: 'width:440px;height:210px;',
+      size: 'width:440px;height:205px;',
       version: '原版',
-      position: 'bottom:20px;right:10px;',
+      position: 'bottom:10px;right:25px;',
     },
   },
 ];

+ 50 - 59
src/views/dashboard/basicInfo/accessStatistics/access.data.ts

@@ -1,61 +1,52 @@
 import { BasicColumn } from '/@/components/Table/src/types/table';
 
-
-/**
- * 接入统计 - 多级表头配置
- * 一级表头:基础信息、统计数据
- * 二级表头:基础信息包含序号、区域;统计数据包含所有数值字段
- */
-export function getAccessStatisticsColumns(): BasicColumn[] {
-  return [
-    {
-      title: '区域',
-      dataIndex: 'name',
-      width: 150,
-      fixed: 'left',
-      align: 'center',
-    },
-    {
-      title: '煤矿总数',
-      dataIndex: 'mineNum',
-      width: 120,
-      align: 'center',
-    },
-    {
-      title: '应接入数量',
-      dataIndex: 'yjNum',
-      width: 120,
-      align: 'center',
-    },
-    {
-      title: '无需接入数量',
-      dataIndex: 'wxjrNum',
-      width: 120,
-      align: 'center',
-    },
-    {
-      title: '接入数量',
-      dataIndex: 'jrNum',
-      width: 120,
-      align: 'center',
-    },
-    {
-      title: '未接入数量',
-      dataIndex: 'wjNum',
-      width: 120,
-      align: 'center',
-    },
-    {
-      title: '在线数量',
-      dataIndex: 'zxNum',
-      width: 120,
-      align: 'center',
-    },
-    {
-      title: '离线数量',
-      dataIndex: 'lxNum',
-      width: 120,
-      align: 'center',
-    },
-  ];
-}
+export const accessStatisticsColumns: BasicColumn[] = [
+  {
+    title: '区域',
+    dataIndex: 'name',
+    width: 150,
+    align: 'center',
+  },
+  {
+    title: '煤矿总数',
+    dataIndex: 'mineNum',
+    width: 120,
+    align: 'center',
+  },
+  {
+    title: '应接入数量',
+    dataIndex: 'yjNum',
+    width: 120,
+    align: 'center',
+  },
+  {
+    title: '无需接入数量',
+    dataIndex: 'wxjrNum',
+    width: 120,
+    align: 'center',
+  },
+  {
+    title: '接入数量',
+    dataIndex: 'jrNum',
+    width: 120,
+    align: 'center',
+  },
+  {
+    title: '未接入数量',
+    dataIndex: 'wjNum',
+    width: 120,
+    align: 'center',
+  },
+  {
+    title: '在线数量',
+    dataIndex: 'zxNum',
+    width: 120,
+    align: 'center',
+  },
+  {
+    title: '离线数量',
+    dataIndex: 'lxNum',
+    width: 120,
+    align: 'center',
+  },
+]

+ 75 - 23
src/views/dashboard/basicInfo/accessStatistics/index.vue

@@ -1,36 +1,88 @@
+<!-- eslint-disable vue/multi-word-component-names -->
 <template>
   <div class="p-4">
-    <BasicTable @register="registerTable" :scroll="{ x: 'max-content' }"  />
+    <BasicTable @register="registerTable" />
   </div>
 </template>
-<script lang="ts">
-  import { defineComponent } from 'vue';
+<script setup lang="ts">
   import { BasicTable, useTable } from '/@/components/Table';
-  import { getAccessStatisticsColumns } from './access.data';
+  import { accessStatisticsColumns } from './access.data';
   import { getGoafAccessCount } from '../basicInfo.api';
+  import type { BasicColumn } from '/@/components/Table/src/types/table';
 
-  export default defineComponent({
-    components: { BasicTable },
-    setup() {
-      const [registerTable] = useTable({
-        api: getGoafAccessCount,
-        columns: getAccessStatisticsColumns(),
-        pagination: true,
-        showIndexColumn: true,
-      });
-
-      return {
-        registerTable,
-      };
+  // 封装接口调用,获取数据后手动添加「总计」行
+  const fetchTableData = async (params: any) => {
+    // 1. 调用原始接口,获取数据
+    const originalRecords = await getGoafAccessCount(params);
+    if (originalRecords.length === 0) return originalRecords; // 无数据时直接返回
+
+    // 2. 定义需要求和的数值列字段
+    const numberFields = ['mineNum', 'yjNum', 'wxjrNum', 'jrNum', 'wjNum', 'zxNum', 'lxNum'];
+
+    // 3. 构建「总计」行对象
+    const totalRow = {
+      name: '总计',
+      isTotal: true, // 合计行标识
+    };
+
+    // 4. 遍历数值列,计算每列的总和
+    numberFields.forEach((field) => {
+      totalRow[field] = originalRecords.reduce((sum: number, item: any) => {
+        const currentValue = Number(item[field]) || 0;
+        return sum + currentValue;
+      }, 0);
+    });
+
+    // 5. 把「总计」行拼接到原始数据的最前面
+    const newRecords = [totalRow, ...originalRecords];
+
+    // 6. 返回表格
+    return {
+      ...originalRecords,
+      records: newRecords,
+      total: newRecords.length,
+    };
+  };
+
+  // 手动添加自定义序号列
+  const customIndexColumn: BasicColumn = {
+    title: '序号',
+    dataIndex: 'index',
+    width: 40,
+    align: 'center',
+    // 自定义序号渲染:判断是否为合计行,合计行返回空字符串(无序号)
+    customRender: ({ record, index }) => {
+      // 若是合计行(带有isTotal标识),返回空,不显示序号
+      if (record.isTotal) return '';
+      // 普通数据行:序号从1开始(排除合计行,序号连续)
+      return index; // 因合计行在第0位,普通数据从索引1开始,直接返回index即为正确序号
     },
+  };
+
+  // 拼接最终列配置(序号列 + 原有业务列)
+  const finalTableColumns = [customIndexColumn, ...accessStatisticsColumns];
+
+  const [registerTable] = useTable({
+    title: '矿山信息表格',
+    api: fetchTableData, // 数据统计接口
+    columns: finalTableColumns,
+    pagination: false,
+    useSearchForm: false,
+    bordered: true,
+    showIndexColumn: false,
+    scroll: { x: 'max-content' },
   });
 </script>
-<style scoped>
-  /* 合计行样式优化 */
-  .bg-gray-50 {
-    background-color: #f9fafb;
+<style lang="less" scoped>
+  :deep(.ant-table-thead th:nth-child(1)) {
+    vertical-align: bottom;
+    padding-bottom: 0 !important;
+    border-bottom: none;
   }
-  .font-medium {
-    font-weight: 500;
+  :deep(.ant-table-tbody .ant-table-row:nth-child(2)) {
+    background-color: @table-thead-bg-color !important;
+    td {
+      background-color: @table-thead-bg-color !important;
+    }
   }
 </style>

+ 2 - 2
src/views/dashboard/basicInfo/basicInfo.api.ts

@@ -17,13 +17,13 @@ enum Api {
 
 export const getMineData = (params) => 
   defHttp.post({ 
-    headers: { 'Content-Type': 'x-www-form-urlencoded' },
+    headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
     url: Api.getMineData, 
     params
   });
 
 // 接入统计
-export const getGoafAccessCount = () =>
+export const getGoafAccessCount = (params) =>
   defHttp.get({
     url: Api.getGoafAccessCount,
   });

+ 18 - 4
src/views/dashboard/basicInfo/closedStatistics/closed.data.ts

@@ -1,7 +1,4 @@
 import { BasicColumn } from '/@/components/Table/src/types/table';
-import { EyeOutlined } from '@ant-design/icons-vue';
-import { h } from 'vue';
-
 /**
  * 密闭统计表格列配置
  */
@@ -10,91 +7,108 @@ export const dataColumns: BasicColumn[] = [
     title: '区域',
     dataIndex: 'name',
     align: 'center',
-  //   width: 80,
+    width: 100,
   },
   {
     title: '密闭总数',
     dataIndex: 'mbStatusNum',
     align: 'center',
+    width: 100,
   },
   {
     title: '正常生产',
     dataIndex: 'mbStatusNum0',
     align: 'center',
+    width: 100,
   },
   {
     title: '拟建矿井',
     dataIndex: 'mbStatusNum1',
     align: 'center',
+    width: 100,
   },
   {
     title: '正常建设',
     dataIndex: 'mbStatusNum2',
     align: 'center',
+    width: 100,
   },
   {
     title: '自行停产',
     dataIndex: 'mbStatusNum3',
     align: 'center',
+    width: 100,
   },
   {
     title: '正在关闭',
     dataIndex: 'mbStatusNum4',
     align: 'center',
+    width: 100,
   },
   {
     title: '责令停产',
     dataIndex: 'mbStatusNum5',
     align: 'center',
+    width: 100,
   },
   {
     title: '责令停止',
     dataIndex: 'mbStatusNum6',
     align: 'center',
+    width: 100,
   },
   {
     title: '已关闭',
     dataIndex: 'mbStatusNum7',
     align: 'center',
+    width: 100,
   },
   {
     title: '长期停产',
     dataIndex: 'mbStatusNum8',
     align: 'center',
+    width: 100,
   },
   {
     title: '长期停建',
     dataIndex: 'mbStatusNum9',
     align: 'center',
+    width: 100,
   },
   {
     title: '停产整改',
     dataIndex: 'mbStatusNum10',
     align: 'center',
+    width: 100,
   },
   {
     title: '长期停建(失联)',
     dataIndex: 'mbStatusNum11',
     align: 'center',
+    width: 100,
   },
   {
     title: '停建整改',
     dataIndex: 'mbStatusNum12',
     align: 'center',
+    width: 100,
   },
   {
     title: '自行停建',
     dataIndex: 'mbStatusNum13',
     align: 'center',
+    width: 100,
   },
   {
     title: '正在关闭',
     dataIndex: 'mbStatusNum14',
     align: 'center',
+    width: 100,
   },
   {
     title: '其他',
     dataIndex: 'mbStatusNumQt',
     align: 'center',
+    width: 100,
   },
 ];

+ 11 - 10
src/views/dashboard/basicInfo/closedStatistics/index.vue

@@ -1,12 +1,13 @@
 <template>
-    <!-- 表格:适配多列,设置横向滚动 & 边框 -->
-    <BasicTable @register="registerTable" :scroll="{ x: 'max-content' }">
+  <div class="p-4">
+    <BasicTable @register="registerTable" :scroll="{ x: 'fit-content' }">
       <template #action="{ record }">
-        <button @click="handleGoToPage(record, `/sealed/${record.code}`)" class="action-btn">
-          <SvgIcon name="view" />
-        </button>
-      </template>
-  </BasicTable>
+          <button @click="handleGoToPage(record, `/sealed/${record.code}`)" class="action-btn">
+            <SvgIcon name="view" />
+          </button>
+        </template>
+    </BasicTable>
+  </div>
 </template>
 
 <script setup lang="ts">
@@ -20,10 +21,10 @@
   const router = useRouter();
   // 注册表格并获取相关方法
   const [registerTable] = useTable({
-    title: '密闭统计表格',
-    api: getClosedAccessCount, // 密闭统计接口
+    title: '密闭统计',
+    api: getClosedAccessCount, // 数据统计接口
     columns: dataColumns,
-    pagination: true,
+    pagination: false,
     useSearchForm: false,
     // showTableSetting: true,
     bordered: true,

+ 116 - 156
src/views/dashboard/basicInfo/dataQuality/dataQuality.data.ts

@@ -1,176 +1,136 @@
 import { BasicColumn, FormSchema } from '/@/components/Table';
 import { h } from 'vue';
+import { Ref } from 'vue';
 
-// 生产状态映射表(扩展所有状态)
-const productionStatusMap: Record<string | number, { label: string; value: number; color: string }> = {
-  0: { label: '正常生产矿井', value: 0, color: 'green' },
-  1: { label: '拟建矿井', value: 1, color: 'blue' },
-  2: { label: '正常建设煤矿', value: 2, color: 'green' },
-  3: { label: '自行停产矿井', value: 3, color: 'green' },
-  4: { label: '正在关闭', value: 4, color: 'green' },
-  5: { label: '责令停产整顿', value: 5, color: 'green' },
-  6: { label: '责令停止建设', value: 6, color: 'green' },
-  7: { label: '已关闭矿井', value: 7, color: 'green' },
-  8: { label: '长期停产矿井', value: 8, color: 'green' },
-  9: { label: '长期停建矿井', value: 9, color: 'green' },
-  10: { label: '停产整改矿井', value: 10, color: 'green' },
-  11: { label: '长期停建无法联系', value: 11, color: 'green' },
-  12: { label: '停建整改', value: 12, color: 'green' },
-  13: { label: '自行停建', value: 13, color: 'green' },
-  14: { label: '正在实施关闭', value: 14, color: 'green' },
-  // 15: { label: '已关闭矿井', value: 15, color: 'green' },
-};
-
-// 颜色映射
-const colorHexMap: Record<string, string> = {
+// 1. 颜色映射(固定规则,可根据业务调整)
+export const colorHexMap: Record<string, string> = {
   blue: '#1890ff',
   green: '#208840',
   gold: '#faad14',
   red: '#f5222d',
   gray: '#8c8c8c',
-  black: '#000000',
-};
-// 解析queJson并拼接orderNum+queCon的辅助函数
-const formatQueJson = (queJsonStr: string) => {
-  // 空值处理
-  if (!queJsonStr) return '无质量问题';
-  try {
-    const queList = JSON.parse(queJsonStr);
-    // 非数组格式处理
-    if (!Array.isArray(queList)) return '问题格式异常';
-    // 拼接orderNum + queCon,多个问题用分号分隔
-    return queList.map((item) => `${item.orderNum || ''}:${item.queCon || ''}`).join('; ');
-  } catch (error) {
-    console.error('解析质量问题JSON失败:', error);
-    return '问题数据解析失败';
-  }
+  black: '#000000', 
 };
 
-/** 表格列配置 */
-export const columns: BasicColumn[] = [
-  {
-    title: '煤矿名称',
-    dataIndex: 'mineName',
-    width: 250,
-  },
-  {
-    title: '煤矿简称',
-    dataIndex: 'mineNameAbbr',
-    width: 150,
-  },
-  {
-    title: '生产状态',
-    dataIndex: 'mineProStatus',
-    width: 120,
-    customRender: ({ record }) => {
-      // 空值/异常值处理
-      const status = record.mineProStatus;
-      const { label, color } = productionStatusMap[status] || { label: '未知状态', color: 'balck' };
-      return h('span', { style: { color: colorHexMap[color] || colorHexMap.gray } }, label);
+// 2. 定义动态映射的类型(供外部传入)
+export type ProductionStatusMap = Record<string | number, { 
+  label: string; 
+  value: number | string; 
+  color: string; 
+}>;
+
+// 3. 生成表格列(支持传入动态映射)
+export function getColumns(dynamicStatusMap: Ref<ProductionStatusMap>) {
+  const columns: BasicColumn[] = [
+    {
+      title: '煤矿名称',
+      dataIndex: 'mineName',
+      width: 250,
     },
-  },
-  {
-    title: '在线状态',
-    dataIndex: 'mineLinkStatus',
-    width: 100,
-    customRender: ({ record }) => {
-      console.log(record.mineLinkStatus);
-      const status = record.mineLinkStatus;
-      if (status === undefined || status === null) {
-        return h('span', { style: { color: colorHexMap.black } }, '/');
-      }
-      const text = status === 1 ? '在线' : '离线';
-      const textColor = status === 1 ? colorHexMap.green : colorHexMap.red;
-      return h('span', { style: { color: textColor } }, text);
+    {
+      title: '煤矿简称',
+      dataIndex: 'mineNameAbbr',
+      width: 150,
+      ifShow: false,
     },
-  },
-  {
-    title: '质量问题详情',
-    dataIndex: 'queJson',
-    width: 400,
-    ellipsis: true,
-    customRender: ({ record, text }) => {
-      // 核心修改:使用辅助函数格式化显示文本
-      const displayText = formatQueJson(text);
-      return h('div', { style: { display: 'flex', alignItems: 'center', gap: '8px' } }, [
-        h('span', { style: { flex: 1, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' } }, displayText),
-      ]);
+    {
+      title: '生产状态',
+      dataIndex: 'mineProStatus',
+      width: 120,
+      customRender: ({ record }) => {
+        // 空值/异常值处理
+        const status = record.mineProStatus;
+        // 从动态映射中取值,兜底未知状态
+        const { label, color } = dynamicStatusMap.value[status] || { 
+          label: '-', 
+        };
+        return h('span', { 
+          style: { color: colorHexMap[color] } 
+        }, label);
+      },
     },
-    slots: {
-      customRender : 'queJson'
-    }
-  },
-  {
-    title: '当前状态',
-    dataIndex: 'isOk',
-    width: 100,
-    customRender: ({ record }) => {
-      const status = record.isOk;
-      const text = status ? '已解决' : '未解决';
-      const textColor = status ? colorHexMap.green : colorHexMap.red;
-      return h('span', { style: { color: textColor } }, text);
+    {
+      title: '在线状态',
+      dataIndex: 'mineLinkStatus',
+      width: 100,
+      customRender: ({ record }) => {
+        const status = record.mineLinkStatus;
+        if (status === undefined || status === null) {
+          return h('span', { style: { color: colorHexMap.black } }, '/');
+        }
+        const text = status === 1 ? '在线' : '离线';
+        const textColor = status === 1 ? colorHexMap.green : colorHexMap.red;
+        return h('span', { style: { color: textColor } }, text);
+      },
     },
-  },
-  {
-    title: '处理时间',
-    dataIndex: 'updateTime',
-    width: 180,
-  },
-];
-
-/** 查询表单配置 */
-export const searchFormSchema: FormSchema[] = [
-  {
-    field: 'mineCode',
-    label: '煤矿名称',
-    component: 'MineCascader',
-    colProps: { span: 6 },
-    groupName: '常规查询',
-  },
-  {
-    field: 'mineNameAbbr',
-    label: '煤矿简称',
-    component: 'Input',
-    colProps: { span: 6 },
-    groupName: '常规查询',
-  },
-  {
-    field: 'productionStatus',
-    label: '生产状态',
-    component: 'Select',
-    componentProps: {
-      options: [
-        { label: '拟建矿井', value: '0' },
-        { label: '正常生产矿井', value: '1' },
-        { label: '长期停产矿井', value: '1' },
-      ],
+    {
+      title: '质量问题详情',
+      dataIndex: 'queJson',
+      width: 400,
+      ellipsis: true,
+      slots: { customRender: 'queJson' },
     },
-    colProps: { span: 6 },
-    groupName: '常规查询',
-  },
-
-  {
-    field: 'mineLinkStatus',
-    label: '在线状态',
-    component: 'Select',
-    componentProps: {
-      options: [
-        { label: '离线', value: '0' },
-        { label: '在线', value: '1' },
-        { label: '未连接', value: '2' },
-      ],
+    {
+      title: '当前状态',
+      dataIndex: 'isOk',
+      width: 100,
+      customRender: ({ record }) => {
+        const status = record.isOk;
+        const text = status ? '已解决' : '未解决';
+        const textColor = status ? colorHexMap.green : colorHexMap.red;
+        return h('span', { style: { color: textColor } }, text);
+      },
     },
-    colProps: { span: 6 },
-    groupName: '常规查询',
-  },
-];
+    {
+      title: '处理时间',
+      dataIndex: 'updateTime',
+      width: 180,
+    },
+  ];
+  return columns;
+}
 
-// 模拟煤矿在线状态选项数据
-export const mineLinkStatusOptions = [
-  { label: '在线', value: 1 },
-  { label: '离线', value: 0 },
-];
-export const topFormSchema: FormSchema[]= [
+// 4. 查询表单配置(下拉框改为动态options)
+export function getSearchFormSchema(dynamicStatusOptions: Ref<{ label: string; value: string | number }[]>) {
+  const searchFormSchema: FormSchema[] = [
+    {
+      field: 'mineCode',
+      label: '煤矿名称',
+      component: 'MineCascader',
+      colProps: { span: 6 },
+      groupName: '常规查询',
+    },
+    // 启用生产状态下拉框(动态options)
+    {
+      field: 'productionStatus',
+      label: '生产状态',
+      component: 'Select',
+      componentProps: {
+        // 动态绑定下拉选项
+        options: dynamicStatusOptions,
+      },
+      colProps: { span: 6 },
+      groupName: '常规查询',
+      show: false,
+    },
+    {
+      field: 'mineLinkStatus',
+      label: '在线状态',
+      component: 'Select',
+      componentProps: {
+        options: [
+          { label: '离线', value: '0' },
+          { label: '在线', value: '1' },
+        ],
+      },
+      colProps: { span: 6 },
+      groupName: '常规查询',
+      show: false,
+    },
+  ];
+  return searchFormSchema;
+}
+export const topFormSchema: FormSchema[] = [
   {
     field: 'mineCode',
     label: '煤矿名称',

+ 267 - 64
src/views/dashboard/basicInfo/dataQuality/index.vue

@@ -1,15 +1,16 @@
+<!-- eslint-disable vue/multi-word-component-names -->
 <template>
   <!-- Tab标签页 -->
-  <Tabs v-model:activeKey="activeKey" class="data-quality-page" type="line">
+  <Tabs v-model:activeKey="activeKey" class="common-page-tabs" type="line" @change="handleTabChange">
     <TabPane key="unresolved" tab="未解决">
       <div class="add-button">
+        <a-button type="default" preIcon="mdi:download" @click="handleExportExcel" style="margin-right: 8px"> 导出 </a-button>
         <a-button type="primary" preIcon="mdi:page-next-outline" @click="handleOpenModal({}, 'add')"> 新增问题 </a-button>
       </div>
       <BasicTable style="padding: 0" @register="registerUnresolvedTable">
         <template #queJson="{ record }">
-          <div style="display: flex; align-items: center; gap: 8px; width: 100%;">
-            <!-- 文字span:添加 flex: 1 占据剩余空间,text-align: center 实现文字居中 -->
-            <span style="flex: 1; text-align: center;">
+          <div style="display: flex; align-items: center; gap: 8px; width: 100%">
+            <span style="flex: 1; text-align: center">
               {{ record?.queJson ? formatQueJson(record.queJson) : '' }}
             </span>
             <!-- 按钮:无需额外样式,自然靠最右侧 -->
@@ -17,7 +18,6 @@
               <SvgIcon name="view" />
             </button>
           </div>
-
         </template>
         <template #action="{ record }">
           <button @click="handleOpenModal(record, 'edit')" class="action-btn">
@@ -50,14 +50,28 @@
               <SvgIcon name="resolved" />
             </button>
           </Popconfirm>
-          <button @click="handleGoToPage(record, '/basicInfo/accessStatistics')" class="action-btn">
+          <button @click="handleGoToPage(record)" class="action-btn">
             <SvgIcon name="details" />
           </button>
         </template>
       </BasicTable>
     </TabPane>
     <TabPane key="resolved" tab="已解决">
+      <div class="add-button">
+        <a-button type="default" preIcon="mdi:download" @click="handleExportExcel" style="margin-right: 8px"> 导出 </a-button>
+      </div>
       <BasicTable style="padding: 0" @register="registerResolvedTable">
+        <template #queJson="{ record }">
+          <div style="display: flex; align-items: center; gap: 8px; width: 100%">
+            <span style="flex: 1; text-align: center">
+              {{ record?.queJson ? formatQueJson(record.queJson) : '' }}
+            </span>
+            <!-- 按钮:无需额外样式,自然靠最右侧 -->
+            <button @click="record && handleOpenModal(record, 'view')" class="action-btn">
+              <SvgIcon name="view" />
+            </button>
+          </div>
+        </template>
         <template #action="{ record }">
           <button @click="handleOpenModal(record, 'view')" class="action-btn">
             <SvgIcon name="details" />
@@ -72,62 +86,127 @@
 </template>
 
 <script setup lang="ts">
-  import { ref, nextTick, computed } from 'vue';
+  import { ref, nextTick, computed, onMounted } from 'vue';
   import { useRouter } from 'vue-router';
-  import { BasicTable, useTable } from '/@/components/Table';
+  import { BasicTable, useTable, BasicColumn, FormSchema  } from '/@/components/Table';
   import { useModal } from '/@/components/Modal';
-  import { Tabs, TabPane, Popconfirm } from 'ant-design-vue';
+  import { Tabs, TabPane, Popconfirm, message } from 'ant-design-vue';
   import DataQualityModal from './components/DataQualityModal.vue';
   import { SvgIcon } from '/@/components/Icon';
-  import { columns, searchFormSchema } from './dataQuality.data';
+  import { 
+    getColumns, 
+    getSearchFormSchema, 
+    type ProductionStatusMap,
+  } from './dataQuality.data';
   import { getDataQuaQueList, addDataQuaQue, deleteDataQuaQue, editDataQuaQue } from '../basicInfo.api';
+  import { findNode } from '/@/utils/helper/treeHelper';
+  import { useMineStore } from '/@/store/modules/mine';
+  import { getDictItemsByCode } from '/@/utils/dict';
   import dayjs from 'dayjs'; 
+  import * as XLSX from 'xlsx';
   // 路由实例
   const router = useRouter();
+  // 实例化矿井Store
+  const mineStore = useMineStore();
   // 响应式数据
   const activeKey = ref('unresolved'); // 激活的Tab键
   const pageMode = ref('add');
+
+  // ========== 定义动态状态映射/下拉选项 ==========
+  // 1. 动态生产状态映射(key: 状态value,value: 包含label/color的配置)
+  const dynamicProductionStatusMap = ref<ProductionStatusMap>({});
+  // 2. 动态下拉选项(供搜索表单使用)
+  const dynamicProductionStatusOptions = ref<{ label: string; value: string | number }[]>([]);
+
+  // 3. 颜色分配规则(可根据业务灵活调整)
+  const getStatusColor = (statusText: string) => {
+    if (statusText.includes('正常生产')) return 'green'; // 正常生产 → 绿色
+    if (statusText.includes('拟建矿井')) return 'blue';   // 拟建矿井 → 蓝色
+    else return 'red'; // 停产/停建/关闭/整改/责令 → 红色
+  };
+
+  // 4. 从接口获取生产状态列表并生成动态映射/下拉选项
+  const fetchProductionStatus = async () => {
+    try {
+      // 调用接口获取状态列表
+      const statusList = await getDictItemsByCode('mineProStatus');
+      if (!Array.isArray(statusList)) return;
+
+      // 生成动态映射和下拉选项
+      const statusMap: ProductionStatusMap = {};
+      const statusOptions: { label: string; value: string | number }[] = [];
+      
+      statusList.forEach((item) => {
+        const value = item.value; // 接口返回的value(数字/字符串)
+        const label = item.text || item.label; // 接口返回的文本
+        const color = getStatusColor(label); // 按规则分配颜色
+        
+        // 填充映射表
+        statusMap[value] = { label, value, color };
+        // 填充下拉选项
+        statusOptions.push({ label, value });
+      });
+
+      // 赋值到响应式变量
+      dynamicProductionStatusMap.value = statusMap;
+      dynamicProductionStatusOptions.value = statusOptions;
+
+      // 刷新表格(确保表格使用最新的映射)
+      await safeReloadActiveTable(); 
+    } catch (error) {
+      console.error('获取生产状态列表失败:', error);
+      message.error('生产状态数据加载失败');
+    }
+  };
+
+  // 生成动态列和搜索表单配置
+  const columns = computed(() => getColumns(dynamicProductionStatusMap));
+  const searchFormSchema = computed(() => getSearchFormSchema(dynamicProductionStatusOptions));
+
   // 未解决表格注册
-  const [registerUnresolvedTable, { reload: reloadUnresolved}] = useTable({
-    api: getQuaQueListByTab(),
-    columns,
+  const [registerUnresolvedTable, { reload: reloadUnresolved }] = useTable({
+    api: async (params: any) => {
+      return await getDataQuaQueList({ ...params, isOk: false });
+    },
+    columns: columns, // 绑定动态列
     formConfig: {
       labelWidth: 120,
-      schemas: searchFormSchema,
+      schemas: searchFormSchema.value, 
       showAdvancedButton: false,
       schemaGroupNames: ['常规查询'],
     },
     useSearchForm: true,
     pagination: true,
-    striped: true,
     showIndexColumn: false,
     indexColumnProps: {
       title: '序号',
     },
-    canResize: false,
+    // canResize: false,
     actionColumn: {
       width: 200,
       title: '操作',
       dataIndex: 'action',
       slots: { customRender: 'action' },
     },
-    immediate: true,
+    immediate: false, // 先不立即加载,等状态数据获取后再加载
   });
 
   // 已解决表格注册
   const [registerResolvedTable, { reload: reloadResolved }] = useTable({
-    api: getQuaQueListByTab(),
-    columns,
+    api: async (params: any) => {
+      return await getDataQuaQueList({ ...params, isOk: true });
+    },
+    columns: columns,
     formConfig: {
       labelWidth: 120,
-      schemas: searchFormSchema,
+      schemas: searchFormSchema.value,
       showAdvancedButton: false,
-      schemaGroupNames: ['常规查询', '高级查询'],
+      schemaGroupNames: ['常规查询'],
     },
     useSearchForm: true,
     pagination: true,
     striped: true,
-    bordered: true,
+    // bordered: true,
     showIndexColumn: false,
     indexColumnProps: {
       title: '序号',
@@ -138,14 +217,14 @@
       dataIndex: 'action',
       slots: { customRender: 'action' },
     },
-    immediate: true,
+    immediate: false, // 先不立即加载
   });
 
   // 弹框注册
   const [registerModal, { openModal }] = useModal();
 
   // 解析queJson并拼接orderNum+queCon的辅助函数
-  function formatQueJson (queJsonStr: string) {
+  function formatQueJson(queJsonStr: string) {
     // 空值处理
     if (!queJsonStr) return '无质量问题';
     try {
@@ -160,6 +239,46 @@
     }
   };
 
+  // 安全重载当前激活的表格
+  async function safeReloadActiveTable() {
+    await nextTick();
+    if (activeKey.value === 'unresolved') {
+      try {
+        await reloadUnresolved();
+      } catch (e) {
+        console.warn('未解决表格重载失败:', e);
+      }
+    } else {
+      try {
+        await reloadResolved();
+      } catch (e) {
+        console.warn('已解决表格重载失败:', e);
+      }
+    }
+  }
+  // 按需重载双表格(仅在「标记已解决」等跨Tab操作时用)
+  async function reloadBothTableSafely() {
+    await nextTick();
+    // 未解决表格:await + try/catch 捕获异步错误
+    try {
+      await reloadUnresolved(); 
+    } catch (e) {
+      console.warn('未解决表格暂未就绪,跳过重载:', e);
+    }
+    // 已解决表格:同理,一个报错不影响另一个
+    try {
+      await reloadResolved(); 
+    } catch (e) {
+      console.warn('已解决表格暂未就绪,跳过重载:', e);
+    }
+  }
+
+  // tabs切换事件
+  async function handleTabChange(key: string) {
+    activeKey.value = key;
+    await safeReloadActiveTable();
+  };
+
   /**
    * 根据标签获取表格数据(已解决/未解决)
    * @param result 弹框数据
@@ -177,10 +296,7 @@
    */
   function handleOpenModal(record: any, mode: 'view' | 'edit' | 'add' = 'view') {
     pageMode.value = mode;
-    openModal(true, {
-      record,
-      mode,
-    });
+    openModal(true, { record, mode });
   }
 
   /**
@@ -188,35 +304,45 @@
    * @param result 弹框数据
    */
   async function handleModalSuccess(result: any) {
-    try{
+    try {
       if (pageMode.value === 'add') {
-        console.log(result);
         await addDataQuaQue(result);
       } else if (pageMode.value === 'edit') {
         await editDataQuaQue(result);
       }
-      // 刷新表格
-      await nextTick();
-      reloadUnresolved();
-      reloadResolved();
-    } catch(error) {
+      await safeReloadActiveTable(); 
+    } catch (error) {
       console.log('操作失败:', error);
     }
   }
   /**
-   * 通用页面跳转方法
-   * @param record 当前行数据
-   * @param path 目标路径
-   */
-  function handleGoToPage(record: any, path: string) {
-    // 跳转时携带当前煤矿的编号作为参数(根据实际需求调整携带的参数)
-    router.push({
-      path,
-      // query: {
-      //   orderNo: record.orderNo, // 煤矿编号
-      //   mineName: record.mineName // 煤矿名称
-      // }
-    });
+ * 通用页面跳转方法
+ * @param record 当前行数据
+ * @param path 目标路径(树形结构所在页面的路由地址)
+ */
+  async function handleGoToPage(record: any) {
+    try {
+      const mineCode = record.mineCode;
+      const targetNode = findNode(
+        mineStore.getMineTree,
+        (item) => item.id === mineCode,
+        { id: 'id', pid: 'parentId', children: 'childDepart' }
+      );
+
+      let minePath = '';
+      if (targetNode) {
+        minePath = targetNode.parentId;
+      } else {
+        message.warning(`未找到矿码【${mineCode}】对应的矿井节点`);
+        return;
+      }
+
+      // 跳转页面(可携带拼接后的矿名/路径等参数)
+      router.push({ path: `/sealed/${minePath}`, query: {} });
+    } catch (error) {
+      console.error('矿节点定位失败:', error);
+      message.error('矿节点定位失败,请稍后重试');
+    }
   }
 
   /**
@@ -230,7 +356,7 @@
    * 生成已解决气泡提示文案:XX矿井XX问题是否解决了吗?
    */
   const getResolveDesc = computed(() => (record: any) => {
-    const mineName = record.mineName || '该'; // 矿井名称兜底
+    const mineName = record.mineName || '该';
     return `是否确认${mineName}矿井问题已解决?`;
   });
 
@@ -242,7 +368,7 @@
     try {
       await deleteDataQuaQue({ id: record.id });
       await nextTick();
-      reloadUnresolved();
+      await safeReloadActiveTable(); 
     } catch (error) {
       console.error('删除失败:', error);
     }
@@ -255,34 +381,111 @@
   async function handleOKRecord(record: any) {
     const copyRecord = {
       ...record,
-      isOk : true,
+      isOk: true,
       updateTime: dayjs().format('YYYY-MM-DD HH:mm:ss')
     };
-    copyRecord.isOk = true
     try {
       await editDataQuaQue(copyRecord);
-      await nextTick();
-      reloadUnresolved();
-      reloadResolved();
+      await safeReloadActiveTable(); 
     }catch (error) {
       console.error('操作失败:', error);
     }
   }
-</script>
 
-<style scoped lang="less">
-  .data-quality-page {
-    padding: 0 12px;
-    margin: 16px;
-    border: 1px solid @border-color-base;
-    .ant-form {
-      background-color: #fff;
+  /**
+   * 获取全部未解决数据(不分页)
+   */
+  async function getAllUnresolvedData() {
+    try {
+      const res = await getDataQuaQueList({ pageNum: 1, pageSize: 9999, isOk: false });
+      return res.records || [];
+    } catch (error) {
+      console.error('获取未解决数据失败:', error);
+      return [];
+    }
+  }
+
+  /**
+   * 获取全部已解决数据(不分页)
+   */
+  async function getAllResolvedData() {
+    try {
+      const res = await getDataQuaQueList({ pageNum: 1, pageSize: 9999, isOk: true });
+      return res.records || [];
+    } catch (error) {
+      console.error('获取已解决数据失败:', error);
+      return [];
     }
   }
+
+  /**
+   * 格式化导出数据(统一字段名 + 状态文本)
+   */
+  function formatExportData(dataList: any[]) {
+    return dataList.map((item) => ({
+      煤矿名称: item.mineName || '',
+      煤矿简称: item.mineNameAbbr || '',
+      生产状态: dynamicProductionStatusMap.value[item.mineProStatus]?.label || '-',
+      在线状态: item.mineLinkStatus === 1 ? '在线' : item.mineLinkStatus === 0 ? '离线' : '/',
+      质量问题详情: formatQueJson(item.queJson),
+      当前状态: item.isOk ? '已解决' : '未解决',
+      处理时间: item.updateTime || '',
+    }));
+  }
+
+  /**
+   * 导出Excel核心方法
+   */
+  async function handleExportExcel() {
+    let hideLoading: () => void = () => {};
+    try {
+      hideLoading = message.loading('正在导出数据,请稍候...');
+      
+      const unresolvedList = await getAllUnresolvedData();
+      const resolvedList = await getAllResolvedData();
+
+      const formattedUnresolved = formatExportData(unresolvedList);
+      const formattedResolved = formatExportData(resolvedList);
+
+      const workbook = XLSX.utils.book_new();
+      const unresolvedSheet = XLSX.utils.json_to_sheet(formattedUnresolved);
+      const resolvedSheet = XLSX.utils.json_to_sheet(formattedResolved);
+
+      XLSX.utils.book_append_sheet(workbook, unresolvedSheet, '未解决');
+      XLSX.utils.book_append_sheet(workbook, resolvedSheet, '已解决');
+
+      const fileName = `数据质量问题_${dayjs().format('YYYYMMDDHHmmss')}.xlsx`;
+      XLSX.writeFile(workbook, fileName);
+
+      hideLoading();
+      message.success('导出成功!');
+    } catch (error) {
+      if (hideLoading) hideLoading();
+      console.error('Excel导出失败:', error);
+      message.error('导出失败,请稍后重试');
+    }
+  }
+
+  // ========== 初始化:先获取状态数据,再加载表格 ==========
+  onMounted(async () => {
+    await fetchProductionStatus(); // 先获取动态状态数据
+    await safeReloadActiveTable(); 
+  });
+</script>
+
+<style scoped lang="less">
+  // .data-quality-page {
+  //   padding: 0 12px;
+  //   margin: 16px;
+  //   border: 1px solid @border-color-base;
+  //   .ant-form {
+  //     background-color: #fff;
+  //   }
+  // }
   .form-part {
     padding: 12px 10px 6px 10px;
     margin-bottom: 8px;
-    background-color: #ffffff;
+    background-color: @white;
     border-radius: 2px;
   }
   .add-button {

+ 90 - 15
src/views/dashboard/basicInfo/minesInfo/index.vue

@@ -1,6 +1,6 @@
 <!-- eslint-disable vue/multi-word-component-names -->
 <template>
-  <BasicTable @register="registerTable" :scroll="{ x: 'max-content' }">
+  <BasicTable @register="registerTable">
     <template #action="{ record }">
       <button @click="handleGoToPage(record, `/sealed/${record.areaId}`)" class="action-btn">
         <SvgIcon name="data" />
@@ -8,7 +8,7 @@
       <button @click="handleGoToPage(record, '/basicInfo/accessStatistics')" class="action-btn">
         <SvgIcon name="info" />
       </button>
-      <button @click="handleGoToPage(record, '/warningAnalysis/connectAnalysis')" class="action-btn">
+      <button @click="handleGoToPageQuery(record, '/warningAnalysis/connectAnalysis')" class="action-btn">
         <SvgIcon name="chart" />
       </button>
     </template>
@@ -16,57 +16,132 @@
 </template>
 
 <script setup lang="ts">
+  import { ref, nextTick, computed, onMounted } from 'vue';
   import { useRouter } from 'vue-router';
   import { BasicTable, useTable } from '/@/components/Table';
-  import { columns, searchFormSchema } from './minesInfo.data';
   import { SvgIcon } from '/@/components/Icon';
+  import { message } from 'ant-design-vue';
+  // 引入动态列/表单配置函数 + 类型
+  import { getColumns, getSearchFormSchema, type ProductionStatusMap } from './minesInfo.data';
   import { getMineData } from '../basicInfo.api';
+  // 引入字典获取方法
+  import { getDictItemsByCode } from '/@/utils/dict';
 
   // 路由实例
   const router = useRouter();
-  // 注册表格并获取相关方法
-  const [registerTable] = useTable({
+
+  // ========== 动态生产状态配置 ==========
+  // 1. 响应式存储动态状态映射(key: 状态值,value: 配置)
+  const dynamicProductionStatusMap = ref<ProductionStatusMap>({});
+  // 2. 响应式存储动态下拉选项(供搜索表单使用)
+  const dynamicProductionStatusOptions = ref<{ label: string; value: string | number }[]>([]);
+
+  // 3. 生产状态颜色分配规则(和dataQuality保持一致)
+  const getStatusColor = (statusText: string) => {
+    if (statusText.includes('正常生产')) return 'green';
+    if (statusText.includes('拟建矿井')) return 'blue';
+    return 'red'; // 其他状态统一红色
+  };
+
+  // 4. 从接口获取生产状态字典,生成动态映射/选项
+  const fetchProductionStatus = async () => {
+    try {
+      const statusList = await getDictItemsByCode('mineProStatus');
+      if (!Array.isArray(statusList)) return;
+
+      const statusMap: ProductionStatusMap = {};
+      const statusOptions: { label: string; value: string | number }[] = [];
+      
+      statusList.forEach((item) => {
+        const value = item.value;
+        const label = item.text || item.label;
+        const color = getStatusColor(label);
+        
+        statusMap[value] = { label, value, color };
+        statusOptions.push({ label, value });
+      });
+
+      // 赋值到响应式变量
+      dynamicProductionStatusMap.value = statusMap;
+      dynamicProductionStatusOptions.value = statusOptions;
+
+      // 刷新表格(使用最新的状态映射)
+      await safeReloadTable();
+    } catch (error) {
+      console.error('获取生产状态字典失败:', error);
+      message.error('生产状态数据加载失败');
+    }
+  };
+
+  // 5. 生成动态列和搜索表单(computed响应式更新)
+  const columns = computed(() => getColumns(dynamicProductionStatusMap));
+  const searchFormSchema = computed(() => getSearchFormSchema(dynamicProductionStatusOptions));
+
+  // ========== 表格注册 ==========
+  const [registerTable, { reload: reloadTable }] = useTable({
     title: '矿山信息表格',
     api: getMineData, // 数据统计接口
-    columns,
+    columns: columns, // 绑定动态列
     formConfig: {
       labelWidth: 120,
-      schemas: searchFormSchema,
+      schemas: searchFormSchema.value, // 绑定动态搜索表单
       showAdvancedButton: false,
       schemaGroupNames: ['常规查询'],
     },
     pagination: true,
     useSearchForm: true,
-    // showTableSetting: true,
     bordered: true,
     showIndexColumn: false,
-    // canResize: false,
+    scroll: { x: 'max-content' },
     actionColumn: {
       width: 180,
       title: '操作',
       dataIndex: 'action',
       slots: { customRender: 'action' },
     },
+    immediate: false, // 先不加载,等字典获取后再加载
   });
 
+  // ========== 辅助方法 ==========
+  // 安全刷新表格(避免表格未初始化导致的报错)
+  async function safeReloadTable() {
+    await nextTick();
+    try {
+      await reloadTable();
+    } catch (e) {
+      console.warn('矿山信息表格重载失败:', e);
+    }
+  }
+
   /**
    * 通用页面跳转方法
    * @param record 当前行数据
    * @param path 目标路径
    */
   function handleGoToPage(record: any, path: string) {
-    // 跳转时携带当前煤矿的编号作为参数(根据实际需求调整携带的参数)
     router.push({
       path,
-      // query: {
-      //   orderNo: record.orderNo, // 煤矿编号
-      //   mineName: record.mineName // 煤矿名称
-      // }
     });
   }
+
+  function handleGoToPageQuery(record: any, path: string) {
+    const mineCode = record.mineCode
+    router.push({
+      path,
+      query: { mineCode : mineCode},
+    });
+  }
+
+  // ========== 初始化 ==========
+  onMounted(async () => {
+    // 先获取生产状态字典,再加载表格
+    await fetchProductionStatus();
+  });
 </script>
+
 <style lang="less" scoped>
   .action-btn {
+    height: 30px;
     cursor: pointer;
     margin-right: 10px;
 
@@ -74,4 +149,4 @@
       margin-right: 0;
     }
   }
-</style>
+</style>

+ 168 - 158
src/views/dashboard/basicInfo/minesInfo/minesInfo.data.ts

@@ -1,29 +1,10 @@
 import { BasicColumn } from '/@/components/Table';
 import { FormSchema } from '/@/components/Table';
 import { h } from 'vue';
+import { Ref } from 'vue';
 
-// 生产状态映射表(扩展所有状态)
-const productionStatusMap: Record<string | number, { text: string; color: string }> = {
-  0: { text: '正常生产矿井', color: 'green' },
-  1: { text: '拟建矿井', color: 'blue' },
-  2: { text: '正常建设煤矿', color: 'green' },
-  3: { text: '自行停产矿井', color: 'green' },
-  4: { text: '正在关闭', color: 'green' },
-  5: { text: '责令停产整顿', color: 'green' },
-  6: { text: '责令停止建设', color: 'green' },
-  7: { text: '已关闭矿井', color: 'green' },
-  8: { text: '长期停产矿井', color: 'green' },
-  9: { text: '长期停建矿井', color: 'green' },
-  10: { text: '停产整改矿井', color: 'green' },
-  11: { text: '长期停建无法联系', color: 'green' },
-  12: { text: '停建整改', color: 'green' },
-  13: { text: '自行停建', color: 'green' },
-  14: { text: '正在实施关闭', color: 'green' },
-  // 15: { text: '已关闭矿井', color: 'green' },
-};
-
-// 颜色映射
-const colorHexMap: Record<string, string> = {
+// 1. 颜色映射(修正原拼写错误,统一规则)
+export const colorHexMap: Record<string, string> = {
   blue: '#1890ff',
   green: '#208840',
   gold: '#faad14',
@@ -32,140 +13,169 @@ const colorHexMap: Record<string, string> = {
   black: '#000000',
 };
 
-export const columns: BasicColumn[] = [
-  {
-    title: '煤矿编号',
-    dataIndex: 'mineCode',
-  },
-  {
-    title: '所属执法处',
-    dataIndex: 'managementName',
-  },
-  {
-    title: '煤矿名称',
-    dataIndex: 'mineName',
-  },
-  {
-    title: '煤矿简称',
-    dataIndex: 'mineNameAbbr',
-  },
-  {
-    title: '生产状态',
-    dataIndex: 'productionStatus',
-    customRender: ({ record }) => {
-      // 空值/异常值处理
-      const status = String(record.productionStatus || '');
-      const { text, color } = productionStatusMap[status] || { text: '未知状态', color: 'balck' };
-      // 渲染普通span,仅设置文字颜色
-      return h('span', { style: { color: colorHexMap[color] || colorHexMap.gray } }, text);
-    },
-  },
-  {
-    title: '自燃情况',
-    dataIndex: 'alarmLevel',
-  },
-  {
-    title: '接入状态',
-    dataIndex: 'accessStatus',
-    customRender: ({ record }) => {
-      // 空值/异常值处理
-      const status = String(record.accessStatus || '');
-      if (!status || status === 'undefined' || status === 'null') {
-        return h('span', { style: { color: colorHexMap.black } }, '/');
-      }
-      const text = status === '1' ? '接入' : '未接入';
-      const textColor = status === '1' ? colorHexMap.green : colorHexMap.gold;
-      return h('span', { style: { color: textColor } }, text);
-    },
-  },
-  {
-    title: '在线状态',
-    dataIndex: 'status',
-    customRender: ({ record }) => {
-      const status = String(record.status || '');
-      if (!status || status === 'undefined' || status === 'null') {
-        return h('span', { style: { color: colorHexMap.black } }, '/');
-      }
-      const text = status === '1' ? '在线' : '离线';
-      const textColor = status === '1' ? colorHexMap.green : colorHexMap.red;
-      return h('span', { style: { color: textColor } }, text);
-    },
-  },
-  {
-    title: '应接数量',
-    dataIndex: 'yingjieNum',
-  },
-  {
-    title: '已接数量',
-    dataIndex: 'accessGoafNum',
-  },
-  {
-    title: '未接数量',
-    dataIndex: 'notAccessGoafNum',
-  },
-];
+// 2. 定义生产状态映射类型(和dataQuality保持一致)
+export type ProductionStatusMap = Record<string | number, { 
+  label: string; 
+  value: number | string; 
+  color: string; 
+}>;
+
+// 3. 生成动态表格列(接收动态状态映射)
+export function getColumns(dynamicStatusMap: Ref<ProductionStatusMap>): BasicColumn[] {
+  return [
+    {
+      title: '煤矿编号',
+      dataIndex: 'mineCode',
+      width: 100,
+    },
+    {
+      title: '所属执法处',
+      dataIndex: 'managementName',
+      width: 100,
+    },
+    {
+      title: '煤矿名称',
+      dataIndex: 'mineName',
+      width: 200,
+    },
+    {
+      title: '煤矿简称',
+      dataIndex: 'mineNameAbbr',
+      width: 100,
+      ifShow: false,
+    },
+    {
+      title: '生产状态',
+      dataIndex: 'productionStatus',
+      width: 100,
+      customRender: ({ record }) => {
+        // 空值/异常值处理
+        const status = String(record.productionStatus || '');
+        // 从动态映射取值,兜底未知状态
+        const { label, color } = dynamicStatusMap.value[status] || { 
+          label: '-', 
+        };
+        // 渲染带颜色的文字
+        return h('span', { 
+          style: { color: colorHexMap[color] } 
+        }, label);
+      },
+    },
+    {
+      title: '自燃情况',
+      dataIndex: 'alarmLevel',
+      width: 100,
+    },
+    {
+      title: '接入状态',
+      dataIndex: 'accessStatus',
+      width: 100,
+      customRender: ({ record }) => {
+        // 空值/异常值处理
+        const status = String(record.accessStatus || '');
+        if (!status || status === 'undefined' || status === 'null') {
+          return h('span', { style: { color: colorHexMap.black } }, '/');
+        }
+        const text = status === '1' ? '接入' : '未接入';
+        const textColor = status === '1' ? colorHexMap.green : colorHexMap.gold;
+        return h('span', { style: { color: textColor } }, text);
+      },
+    },
+    {
+      title: '在线状态',
+      dataIndex: 'status',
+      width: 100,
+      customRender: ({ record }) => {
+        const status = String(record.status || '');
+        if (!status || status === 'undefined' || status === 'null') {
+          return h('span', { style: { color: colorHexMap.black } }, '/');
+        }
+        const text = status === '1' ? '在线' : '离线';
+        const textColor = status === '1' ? colorHexMap.green : colorHexMap.red;
+        return h('span', { style: { color: textColor } }, text);
+      },
+    },
+    {
+      title: '应接数量',
+      dataIndex: 'yingjieNum',
+      width: 100,
+    },
+    {
+      title: '已接数量',
+      dataIndex: 'accessGoafNum',
+      width: 100,
+    },
+    {
+      title: '未接数量',
+      dataIndex: 'notAccessGoafNum',
+      width: 100,
+    },
+  ];
+}
 
-export const searchFormSchema: FormSchema[] = [
-  {
-    field: 'mineName',
-    label: '煤矿名称',
-    component: 'MineCascader',
-    colProps: { span: 6 },
-  },
-  {
-    field: 'mineNameAbbr',
-    label: '煤矿简称',
-    component: 'Input',
-    colProps: { span: 6 },
-  },
-  {
-    field: 'productionStatus',
-    label: '生产状态',
-    component: 'Select',
-    componentProps: {
-      options: [
-        { label: '拟建矿井', value: '0' },
-        { label: '正常生产矿井', value: '1' },
-        { label: '长期停产矿井', value: '8' },
-      ],
-    },
-    colProps: { span: 6 },
-  },
-  {
-    field: 'accessStatus',
-    label: '接入状态',
-    component: 'Select',
-    componentProps: {
-      options: [
-        { label: '接入', value: 1 },
-        { label: '未接入', value: 0 },
-      ],
-    },
-    colProps: { span: 6 },
-  },
-  {
-    field: 'status',
-    label: '在线状态',
-    component: 'Select',
-    componentProps: {
-      options: [
-        { label: '离线', value: '0' },
-        { label: '在线', value: '1' },
-      ],
-    },
-    colProps: { span: 6 },
-  },
-  {
-    field: 'riskLevel',
-    label: '风险等级',
-    component: 'Select',
-    componentProps: {
-      options: [
-        { label: 'Ⅰ类容易自燃', value: '0' },
-        { label: 'Ⅱ类自燃', value: '1' },
-        { label: 'Ⅲ类不易自燃', value: '2' },
-      ],
-    },
-    colProps: { span: 6 },
-  },
-];
+// 4. 生成动态搜索表单配置(接收动态下拉选项)
+export function getSearchFormSchema(dynamicStatusOptions: Ref<{ label: string; value: string | number }[]>): FormSchema[] {
+  return [
+    {
+      field: 'mineCode',
+      label: '煤矿名称',
+      component: 'MineCascader',
+      colProps: { span: 6 },
+    },
+    {
+      field: 'mineNameAbbr',
+      label: '煤矿简称',
+      component: 'Input',
+      colProps: { span: 6 },
+      show: false,
+    },
+    {
+      field: 'productionStatus',
+      label: '生产状态',
+      component: 'Select',
+      componentProps: {
+        // 动态绑定下拉选项
+        options: dynamicStatusOptions,
+      },
+      colProps: { span: 6 },
+    },
+    {
+      field: 'accessStatus',
+      label: '接入状态',
+      component: 'Select',
+      componentProps: {
+        options: [
+          { label: '接入', value: 1 },
+          { label: '未接入', value: 0 },
+        ],
+      },
+      colProps: { span: 6 },
+    },
+    {
+      field: 'status',
+      label: '在线状态',
+      component: 'Select',
+      componentProps: {
+        options: [
+          { label: '离线', value: '0' },
+          { label: '在线', value: '1' },
+        ],
+      },
+      colProps: { span: 6 },
+    },
+    {
+      field: 'riskLevel',
+      label: '风险等级',
+      component: 'Select',
+      componentProps: {
+        options: [
+          { label: 'Ⅰ类容易自燃', value: '0' },
+          { label: 'Ⅱ类自燃', value: '1' },
+          { label: 'Ⅲ类不易自燃', value: '2' },
+        ],
+      },
+      colProps: { span: 6 },
+      show: false,
+    },
+  ];
+}

+ 13 - 11
src/views/monitor/sealedMonitor/components/HistoricalDetailsModal.vue

@@ -47,24 +47,30 @@
     </div>
   </Modal>
 </template>
-<script setup>
+<script lang="ts" setup>
   import { ref, computed } from 'vue';
   import { Modal, DatePicker, Button, message, Input } from 'ant-design-vue';
   import { BasicTree } from '/@/components/Tree/index';
   import CustomChart from '/@/components/Configurable/detail/CustomChart.vue';
-  import { treeData, historicalMockChartData } from '../monitor.data'; // 引入模拟数据
+  import { treeData } from '../monitor.data'; // 引入模拟数据
   import dayjs from 'dayjs';
-  import isBetween from 'dayjs/plugin/isBetween'; // 引入 isBetween 插件
+  // import isBetween from 'dayjs/plugin/isBetween'; // 引入 isBetween 插件
 
-  // 关键:使用 dayjs 插件
-  dayjs.extend(isBetween);
+  // // 关键:使用 dayjs 插件
+  // dayjs.extend(isBetween);
 
   // 组件注册
   const RangePicker = DatePicker.RangePicker;
 
   // 弹框控制
   const visible = ref(false);
-  const showModal = () => (visible.value = true);
+  const dataRef = ref<any>();
+
+  // 外部调用显示弹框
+  const showModal = (record: any) => {
+    visible.value = true;
+    dataRef.value = record;
+  };
   const hideModal = () => (visible.value = false);
   const handleOk = () => hideModal();
   const handleCancel = () => hideModal();
@@ -155,11 +161,7 @@
     const end = dayjs(dateRange.value[1]); // 转为 dayjs 实例
 
     // 1. 筛选时间范围内的模拟数据(修复核心漏洞)
-    const filteredData = historicalMockChartData.filter((item) => {
-      const itemTime = dayjs(item.time); // 解析 item.time 为 dayjs 实例
-      // 修复 isBetween 用法:明确指定 unit 为 'second',包容性为 '[]'
-      return itemTime.isBetween(start, end, 'second', '[]');
-    });
+    const filteredData = [];
 
     // 2. 构建图表数据结构(适配 CustomChart 的 line 类型)
     const timeMap = new Map();

+ 130 - 74
src/views/monitor/sealedMonitor/components/RealtimeDetailsModal.vue

@@ -1,18 +1,31 @@
 <template>
-  <Modal v-model:open="visible" title="密闭监测详情" width="1200px" @ok="handleOk" @cancel="handleCancel" prefixCls="custom-modal">
+  <BasicModal
+    v-bind="$attrs"
+    title="密闭监测详情"
+    width="1400px"
+    :bodyStyle="{ padding: `0 20px 0 20px` }"
+    @register="register"
+    @close="okHandler"
+    @ok="okHandler"
+  >
     <!-- 基础信息栏(修改布局:每行4列,共两行) -->
     <div class="base-info">
       <div v-for="(item, index) in modalDetailsData.basicInfo" :key="index" class="info-item">
         <span class="label">{{ item.label }}:</span>
-        <span class="value" :class="getBasicInfoTagClass(item.value)">
-          {{ item.value }}
-        </span>
+        <component :is="contextRender(item)"></component>
       </div>
     </div>
 
     <!-- 监测数据卡片 -->
     <div class="data-cards">
-      <MiniBoard v-for="(item, index) in modalDetailsData.board" :key="index" type="D" :label="item.label" :value="item.value" layout="val-top" />
+      <MiniBoard
+        v-for="(item, index) in modalDetailsData.board"
+        :key="index"
+        type="D"
+        :label="item.label"
+        :value="dataRef[item.value] || '-'"
+        layout="val-top"
+      />
     </div>
 
     <!-- 图表区域 -->
@@ -20,15 +33,20 @@
       <div class="chart-item">
         <div class="chart-title">爆炸三角形</div>
         <div class="chart-placeholder">
-          <BlastDelta :posMonitor="modalDetailsData.demoBlastData" canvasSize="{ width: 95%, height: 95% }" />
+          <BlastDelta :posMonitor="dataRef" :canvasSize="{ width: '95%', height: '95%' }" text-color="#000" />
         </div>
       </div>
       <div class="chart-item">
         <div class="chart-title">气体浓度曲线</div>
         <div class="chart-placeholder">
           <CustomChart
-            :chart-data="modalDetailsData.gasConcentrationData"
+            :chart-data="{ chartData: dataArray }"
             :chart-config="modalDetailsData.gasConcentrationConfig"
+            :chart-option="{
+              textStyle: {
+                color: '#000',
+              },
+            }"
             style="height: 100%; width: 100%"
           />
         </div>
@@ -37,76 +55,130 @@
         <div class="chart-title">内外压力及压差曲线</div>
         <div class="chart-placeholder">
           <CustomChart
-            :chart-data="modalDetailsData.pressureData"
+            :chart-data="{ chartData: dataArray }"
             :chart-config="modalDetailsData.pressureConfig"
+            :chart-option="{
+              textStyle: {
+                color: '#000',
+              },
+            }"
             style="height: 100%; width: 100%"
           />
         </div>
       </div>
     </div>
-  </Modal>
+  </BasicModal>
 </template>
-
-<script setup>
+<script lang="ts">
+  import { defineComponent } from 'vue';
+  import { BasicModal, useModalInner } from '/@/components/Modal';
   import { ref } from 'vue';
-  import { Modal } from 'ant-design-vue';
   import MiniBoard from '/@/components/Configurable/detail/MiniBoard.vue';
   import BlastDelta from '/@/components/Configurable/preset/BlastDelta.vue';
   import CustomChart from '/@/components/Configurable/detail/CustomChart.vue';
-  import { modalDetailsData } from '../monitor.data';
+  import { modalDetailsData, tagCellRender } from '../monitor.data';
+  import { concat, get, last, takeRight } from 'lodash-es';
+  import { h } from 'vue';
+  import { getGoafData } from '../monitor.api';
+  import { useIntervalFn } from '@vueuse/core';
+  import dayjs from 'dayjs';
+
+  export default defineComponent({
+    components: { BasicModal, MiniBoard, BlastDelta, CustomChart },
+    emits: ['close', 'register'],
+    setup(__, { emit }) {
+      const dataRef = ref<any>({});
+      const dataArray = ref<any[]>([]);
+
+      // 添加元素,数组最多15项,按队列排布
+      const push = (item) => {
+        item.readTime = dayjs().format('YYYY-MM-DD HH:mm:ss');
+        dataArray.value = takeRight(concat(dataArray.value, item), 15);
+      };
+
+      // const chartData = computed(() => {
+      //   return {
+      //     readTime: dataArray.value.map((item) => item.readTime),
+      //     sourcePressure: dataArray.value.map((item) => item.sourcePressure),
+      //     o2Val: dataArray.value.map((item) => item.o2Val),
+      //     coVal: dataArray.value.map((item) => item.coVal),
+      //   };
+      // });
+      function getTagType(level: string) {
+        switch (level) {
+          case '1':
+            return 'red';
+          case '2':
+            return 'volcano';
+          case '3':
+            return 'orange';
+          case '4':
+            return 'success';
+          default:
+            return 'default';
+        }
+      }
 
-  // 控制弹框显隐
-  const visible = ref(false);
-  // 外部调用显示弹框
-  const showModal = () => {
-    visible.value = true;
-  };
-  // 外部调用隐藏弹框
-  const hideModal = () => {
-    visible.value = false;
-  };
+      const [register] = useModalInner((d) => {
+        if (!d) return;
+        dataRef.value = d;
+        push(d);
+        resume();
+      });
 
-  // 确定按钮回调
-  const handleOk = () => {
-    visible.value = false;
-    // 可添加确定后的业务逻辑
-  };
-  // 取消按钮回调
-  const handleCancel = () => {
-    visible.value = false;
-  };
+      function contextRender({ value, tag }: any) {
+        if (tag) return tagCellRender(get(dataRef.value, value));
+        return h('span', get(dataRef.value, value));
+      }
 
-  // 获取基础信息value对应的标签样式类
-  const getBasicInfoTagClass = (value) => {
-    switch (value) {
-      case '闭内气体涌出':
-        return 'tag-danger';
-      case '低风险':
-        return 'tag-primary';
-      case '不可启封':
-        return 'tag-warning';
-      default:
-        return '';
-    }
-  };
-  // 暴露方法给父组件
-  defineExpose({
-    showModal,
-    hideModal,
+      function fetchDetailData() {
+        const { mineCode, goafId } = dataRef.value;
+        getGoafData({ mineCode, goafId }).then((r) => {
+          dataRef.value = last(r);
+          push(dataRef.value);
+          // push(dataRef.value)
+        });
+      }
+
+      const { pause, resume } = useIntervalFn(
+        () => {
+          fetchDetailData();
+        },
+        2000,
+        {
+          immediate: false,
+        }
+      );
+
+      function okHandler() {
+        pause();
+        emit('close');
+      }
+
+      return {
+        dataRef,
+        modalDetailsData,
+        dataArray,
+        get,
+        getTagType,
+        register,
+        contextRender,
+        okHandler,
+      };
+    },
   });
 </script>
-
-<style scoped>
+<style lang="less" scoped>
   .base-info {
     display: grid;
-    grid-template-columns: repeat(4, 1fr); /* 强制每行4列 */
+    grid-template-columns: repeat(3, 1fr); /* 强制每行4列 */
     grid-template-rows: auto auto; /* 两行自动高度 */
     gap: 16px 12px; /* 行列间距(行间距16px,列间距12px) */
     margin-bottom: 20px;
     padding: 20px;
-    border: 1px solid #f0f0f0;
+    border: 1px solid @border-color-base;
     border-radius: 10px;
-    background: #f8f9fc;
+    background: @card-bg-color;
   }
   .info-item {
     display: flex;
@@ -128,31 +200,15 @@
     overflow: hidden;
     text-overflow: ellipsis;
   }
-  .tag-danger {
-    color: #f5222d;
-    padding: 2px 6px;
-    border-radius: 4px;
-  }
-  .tag-primary {
-    color: #1890ff;
-    padding: 2px 6px;
-    border-radius: 4px;
-  }
-  .tag-warning {
-    color: #faad14;
-    padding: 2px 6px;
-    border-radius: 4px;
-  }
-
   .data-cards {
     display: grid;
     grid-template-columns: repeat(8, 1fr);
     gap: 16px;
     margin-bottom: 20px;
     padding: 20px;
-    border: 1px solid #f0f0f0;
+    border: 1px solid @border-color-base;
     border-radius: 10px;
-    background: #f8f9fc;
+    background: @card-bg-color;
   }
   .data-card {
     background: #fafafa;
@@ -176,10 +232,10 @@
     flex-wrap: wrap;
     gap: 16px;
     padding: 20px;
-    border: 1px solid #f0f0f0;
+    border: 1px solid @border-color-base;
     border-radius: 10px;
     /* background: black; */
-    background: #f8f9fc;
+    background: @card-bg-color;
   }
   .chart-item {
     flex: 1;

+ 44 - 0
src/views/monitor/sealedMonitor/hooks/form.ts

@@ -0,0 +1,44 @@
+import { last } from 'lodash';
+import { ref, computed } from 'vue';
+import { useRoute } from 'vue-router';
+import { getGoafSelectOption } from '../monitor.api';
+import { useMineStore } from '/@/store/modules/mine';
+import { findNodeAll, findPath } from '/@/utils/helper/treeHelper';
+
+export function useInitForm() {
+  const config = {
+    id: 'id',
+    pid: 'parentId',
+    children: 'childDepart',
+  };
+  const route = useRoute();
+  const mineStroe = useMineStore();
+  const mineCodes = ref<string[]>([]);
+  const getMineTree = computed(() => {
+    const id = last(route.fullPath.split('/'));
+    return findNodeAll(mineStroe.mineTree, (item) => item.id === id, config);
+  });
+  const paths = findPath(getMineTree.value, (item) => item.isLeaf, config);
+
+  mineCodes.value = paths.map((e) => e.id);
+
+  // 采空区选择器
+  const goafId = ref('');
+  const goafOptions = ref<any[]>([]);
+
+  function initGoafOptions() {
+    getGoafSelectOption({ mineCode: last(mineCodes.value) }).then(({ options, defaultValue }) => {
+      goafOptions.value = options;
+      goafId.value = defaultValue;
+    });
+  }
+  initGoafOptions();
+
+  return {
+    goafId,
+    goafOptions,
+    mineCodes,
+    getMineTree,
+    initGoafOptions,
+  };
+}

+ 108 - 78
src/views/monitor/sealedMonitor/index.vue

@@ -1,11 +1,29 @@
+<!-- eslint-disable vue/multi-word-component-names -->
 <template>
   <!-- 新增Tabs组件区分实时/历史数据 -->
-  <Tabs v-model:activeKey="activeTab" class="monitoring-page" type="line">
+  <Tabs v-model:activeKey="activeTab" class="common-page-tabs" type="line">
     <TabPane tab="实时数据监测" key="realtime">
       <!-- 实时数据表格 -->
       <BasicTable style="padding: 0" @register="registerRealtimeTable">
+        <template #form-mine-cascader>
+          <a-cascader
+            v-model:value="mineCodes"
+            :options="getMineTree"
+            :field-names="{
+              label: 'departName',
+              value: 'id',
+              children: 'childDepart',
+            }"
+            show-search
+            @change="initGoafOptions"
+          >
+            <template #displayRender="{ labels }">
+              {{ labels[labels.length - 1] }}
+            </template>
+          </a-cascader>
+        </template>
         <template #action="{ record }">
-          <button @click="openModal(record, 'realtime')" class="action-btn">
+          <button @click="openModal(record)" class="action-btn">
             <SvgIcon name="details" />
           </button>
         </template>
@@ -15,91 +33,120 @@
     <TabPane tab="历史数据监测" key="history">
       <!-- 历史数据表格 -->
       <BasicTable style="padding: 0" @register="registerHistoryTable">
+        <template #form-mine-cascader>
+          <a-cascader
+            v-model:value="mineCodes"
+            :options="getMineTree"
+            :field-names="{
+              label: 'departName',
+              value: 'id',
+              children: 'childDepart',
+            }"
+            show-search
+            @change="initGoafOptions"
+          >
+            <template #displayRender="{ labels }">
+              {{ labels[labels.length - 1] }}
+            </template>
+          </a-cascader>
+        </template>
+        <template #form-goaf-select>
+          <a-select v-model:value="goafId" :options="goafOptions" placeholder="请选择" />
+        </template>
         <template #afterReset>
           <a-button type="primary" @click="onExportXls">导出</a-button>
         </template>
-        <template #action="{ record }">
-          <button @click="openModal(record, 'history')" class="action-btn">
+        <!-- <template #action="{ record }">
+          <button @click="openModal(record)" class="action-btn">
             <SvgIcon name="details" />
           </button>
-        </template>
+        </template> -->
       </BasicTable>
     </TabPane>
   </Tabs>
 
   <!-- 实时数据详情弹框 -->
-  <realtimeDetailsModal ref="realtimeModalRef" />
+  <RealtimeDetailsModal @register="registerRealtimeModal" @close="resume" />
   <!-- 历史数据详情弹框 -->
-  <HistoricalDetailsModal ref="historyModalRef" />
+  <!-- <HistoricalDetailsModal @register="registerHistoryModal" @close="resume" /> -->
 </template>
 
 <script setup lang="ts">
-  import { onMounted, ref } from 'vue';
-  import { BasicTable, useTable } from '/@/components/Table';
+  import { ref } from 'vue';
+  import { BasicTable } from '/@/components/Table';
   import { Tabs, TabPane } from 'ant-design-vue';
   // 引入模拟数据
-  import { columns, searchFormSchema, minesData, historicalColumns, historicalFormSchema, historicalMinesData } from './monitor.data';
-  import realtimeDetailsModal from './components/RealtimeDetailsModal.vue';
-  import HistoricalDetailsModal from './components/HistoricalDetailsModal.vue';
+  import { columns, searchFormSchema, historicalColumns, historicalFormSchema } from './monitor.data';
+  import RealtimeDetailsModal from './components/RealtimeDetailsModal.vue';
+  // import HistoricalDetailsModal from './components/HistoricalDetailsModal.vue';
   import { SvgIcon } from '/@/components/Icon';
   import { getGoafData, getGoafHistory } from './monitor.api';
   import { useListPage } from '/@/hooks/system/useListPage';
+  import { last } from 'lodash-es';
+  import { useModal } from '/@/components/Modal';
+  import { useIntervalFn } from '@vueuse/core';
+  import { useInitForm } from './hooks/form';
+  // import { getGoafList } from '../../system/algorithm/algorithm.api';
 
   // 激活的Tab页签
+
+  // 处理矿名选择器相关的逻辑
+  const { goafId, goafOptions, mineCodes, getMineTree, initGoafOptions } = useInitForm();
   const activeTab = ref('realtime');
 
   // 注册实时数据表格
-  const [registerRealtimeTable, { getForm }] = useTable({
-    api: (params) =>
-      getGoafData(params).then((res) => {
-        if (res.length) return res;
-        return minesData;
-      }),
-    beforeFetch(params) {},
-    columns,
-    formConfig: {
-      labelWidth: 120,
-      schemas: searchFormSchema,
-      showAdvancedButton: false,
-      schemaGroupNames: ['常规查询'],
+  const { tableContext: ctxRealtime } = useListPage({
+    tableProps: {
+      // api: getGoafData,
+      // beforeFetch(params) {
+      //   params.mineCode = last(mineCodes.value);
+      // },
+      columns,
+      formConfig: {
+        schemas: searchFormSchema,
+        schemaGroupNames: ['常规查询'],
+        submitFunc: () => reloadRealtimeTable(true),
+      },
+      showIndexColumn: false,
+      scroll: { x: 'max-content' },
     },
     pagination: false,
-    useSearchForm: true,
-    showIndexColumn: false,
-    canResize: false,
-    scroll: { x: 'max-content' },
-    actionColumn: {
-      width: 60,
-      title: '操作',
-      dataIndex: 'action',
-      slots: { customRender: 'action' },
-    },
   });
+  const [registerRealtimeTable, { setTableData, setLoading }] = ctxRealtime;
+
+  function reloadRealtimeTable(showLoading: boolean = false) {
+    if (showLoading) {
+      setLoading(true);
+    }
+    return getGoafData({ mineCode: last(mineCodes.value) })
+      .then((res) => {
+        setTableData(res);
+      })
+      .finally(() => {
+        setLoading(false);
+      });
+  }
+
+  reloadRealtimeTable();
+  const { pause, resume } = useIntervalFn(reloadRealtimeTable, 10000);
 
   // 注册历史数据表格
-  const { tableContext, onExportXls } = useListPage({
+  const { tableContext: ctxHistory, onExportXls } = useListPage({
     tableProps: {
-      api: (params) =>
-        getGoafHistory(params)
-          .then((res) => {
-            return res;
-          })
-          .catch(() => {
-            return historicalMinesData;
-          }),
-      beforeFetch(params) {},
+      api: getGoafHistory,
+      beforeFetch(params) {
+        params.goafId = goafId.value;
+      },
       columns: historicalColumns,
       formConfig: {
-        labelWidth: 120,
         schemas: historicalFormSchema, // 使用历史数据的搜索配置
-        showAdvancedButton: false,
         schemaGroupNames: ['常规查询'],
       },
       useSearchForm: true,
       bordered: true,
       showIndexColumn: false,
-      canResize: false,
       scroll: { x: 'max-content' },
+      showActionColumn: false,
     },
     exportConfig: {
       url: '/province/alarm/exportProvinceAlarmHistory',
@@ -107,40 +154,23 @@
     },
     pagination: true,
   });
-  const [registerHistoryTable] = tableContext;
+  const [registerHistoryTable] = ctxHistory;
 
   // 弹窗引用
-  const realtimeModalRef = ref(null);
-  const historyModalRef = ref(null);
+  const [registerRealtimeModal, { openModal: openRealtimeModal }] = useModal();
+  // const [registerHistoryModal, { openModal: openHistoryModal }] = useModal();
 
   // 打开弹窗方法(区分实时/历史)
-  const openModal = (record, type) => {
-    if (type === 'realtime') {
-      // 可向实时弹窗传递当前记录数据
-      realtimeModalRef.value?.showModal(record);
-    } else {
-      // 可向历史弹窗传递当前记录数据
-      historyModalRef.value?.showModal(record);
-    }
+  const openModal = (record) => {
+    openRealtimeModal(true, record);
+    // if (type === 'realtime') {
+    //   // 可向实时弹窗传递当前记录数据
+    // } else {
+    //   // 可向历史弹窗传递当前记录数据
+    //   openHistoryModal(true, record);
+    // }
+    pause();
   };
 </script>
 
-<style lang="less" scoped>
-  .monitoring-page {
-    padding: 0 12px;
-    margin: 16px;
-    border: 1px solid @border-color-base;
-  }
-
-  .action-btn {
-    cursor: pointer;
-    border: none;
-    // background: transparent;
-    padding: 4px;
-  }
-
-  .action-icon {
-    width: 16px;
-    height: 16px;
-  }
-</style>
+<style lang="less" scoped></style>

+ 13 - 2
src/views/monitor/sealedMonitor/monitor.api.ts

@@ -3,11 +3,22 @@ import { defHttp } from '/@/utils/http/axios';
 enum Api {
   getGoafData = '/province/device/getGoafData',
   getGoafHistory = '/province/device/getGoafHistory',
+  getGoafList = '/province/device/getGoafList',
 }
 
 export function getGoafData(params: any) {
-  return defHttp.post({ url: Api.getGoafData, params });
+  return defHttp.post({ url: Api.getGoafData, params }, { joinParamsToUrl: true });
 }
 export function getGoafHistory(params: any) {
-  return defHttp.get({ url: Api.getGoafHistory, params }, { errorMessageMode: 'none' });
+  return defHttp.get({ url: Api.getGoafHistory, params }, { joinParamsToUrl: true });
+}
+
+export function getGoafSelectOption(params: any) {
+  return defHttp.post({ url: Api.getGoafList, params }, { joinParamsToUrl: true }).then((res) => {
+    const options = res.map((e) => ({ value: e.id, label: e.devicePos }));
+    return {
+      options,
+      defaultValue: options[0]?.value,
+    };
+  });
 }

+ 218 - 549
src/views/monitor/sealedMonitor/monitor.data.ts

@@ -1,79 +1,119 @@
 import dayjs from 'dayjs';
-import { getGoafList, getMineData } from '../../system/algorithm/algorithm.api';
 import { BasicColumn } from '/@/components/Table';
 import { FormSchema } from '/@/components/Table';
 import { TreeItem } from '/@/components/Tree/index';
-import { getGoafData } from './monitor.api';
+import { ModuleDataChart } from '/@/components/Configurable/types';
+import { h } from 'vue';
+import { Tag } from 'ant-design-vue';
 
 // 实时数据相关
 export const columns: BasicColumn[] = [
-  {
-    title: '序号',
-    dataIndex: 'orderNo',
-  },
-  {
-    title: '区域',
-    dataIndex: 'enforcement',
-  },
+  // {
+  //   title: '序号',
+  //   dataIndex: 'orderNo',
+  //   width: 60,
+  // },
+  // {
+  //   title: '区域',
+  //   dataIndex: 'coalSeamName',
+  //   width: 80,
+  // },
   {
     title: '煤矿名称',
     dataIndex: 'mineName',
+    width: 200,
   },
   {
     title: '密闭名称',
-    dataIndex: 'sealedName',
+    dataIndex: 'devicePos',
+    width: 100,
   },
   {
     title: '所属煤层',
-    dataIndex: 'coalSeam',
+    dataIndex: 'coalSeamName',
+    width: 100,
   },
   {
-    title: '自燃倾向性',
-    dataIndex: 'riskLevel',
+    title: 'CO(ppm)',
+    dataIndex: 'coVal',
+    width: 100,
   },
   {
-    title: 'CO(ppm)',
-    dataIndex: 'COVal',
+    title: 'CO2(%)',
+    dataIndex: 'co2Val',
+    width: 100,
   },
   {
     title: 'CH4(%)',
-    dataIndex: 'CH4Val',
+    dataIndex: 'ch4Val',
+    width: 100,
   },
   {
     title: 'C2H2(ppm)',
-    dataIndex: 'C2H2Val',
+    dataIndex: 'c2h2Val',
+    width: 100,
+  },
+  {
+    title: 'C2H4(%)',
+    dataIndex: 'c2h4Val',
+    width: 100,
   },
   {
     title: 'O2(%)',
-    dataIndex: 'O2Val',
+    dataIndex: 'o2Val',
+    width: 100,
   },
   {
     title: '温度(℃)',
     dataIndex: 'temperature',
+    width: 100,
   },
   {
     title: '压差(Pa)',
-    dataIndex: 'pressureDiff',
+    dataIndex: 'sourcePressure',
+    width: 100,
   },
   {
-    title: '是否漏风',
-    dataIndex: 'leakage',
+    title: '自然发火隐患等级',
+    dataIndex: 'fireAlarm',
+    width: 100,
+    customRender({ record }) {
+      return tagCellRender(record.fireAlarm);
+    },
   },
   {
-    title: '自然发火隐患',
-    dataIndex: 'fireHazard',
+    title: '是否漏风',
+    dataIndex: 'leakageAlarm',
+    width: 100,
+    customRender({ record }) {
+      return tagCellRender(record.leakageAlarm);
+    },
   },
   {
-    title: '密闭启封判定',
-    dataIndex: 'unsealing',
+    title: '压差隐患等级',
+    dataIndex: 'sourcePressureAlarm',
+    width: 100,
+    customRender({ record }) {
+      return tagCellRender(record.sourcePressureAlarm);
+    },
   },
   {
-    title: '爆炸危险性',
-    dataIndex: 'explosionHazard',
+    title: '密闭启封判定',
+    dataIndex: 'unsealAlarm',
+    width: 100,
+    customRender({ record }) {
+      return tagCellRender(record.unsealAlarm);
+    },
   },
+  // {
+  //   title: '爆炸危险性',
+  //   dataIndex: 'explosionHazard',
+  //   width: 80,
+  // },
   {
     title: '更新时间',
-    dataIndex: 'updateTime',
+    dataIndex: 'readTime',
+    width: 100,
   },
 ];
 
@@ -82,19 +122,8 @@ export const searchFormSchema: FormSchema[] = [
     field: 'mineCode',
     label: '煤矿名称',
     component: 'MineCascader',
+    slot: 'mine-cascader',
     colProps: { span: 6 },
-    // componentProps: {
-    //   //请求api,返回结果{ result: { records: [{'id':'1',name:'scott'},{'id':'2',name:'小张'}] }}
-    //   api: () => getMineData({ pageNo: 1, pageSize: 999 }),
-    //   //数值转成String
-    //   numberToString: false,
-    //   //标题字段
-    //   labelField: 'mineName',
-    //   //值字段
-    //   valueField: 'id',
-    //   //返回结果字段
-    //   resultField: 'records',
-    // },
   },
   {
     field: 'mineNameAbbr',
@@ -130,134 +159,101 @@ export const searchFormSchema: FormSchema[] = [
   },
 ];
 
-export const minesData = [
-  {
-    orderNo: 101, // 序号
-    enforcement: '执法一处', // 区域
-    mineName: '神木市三江', // 煤矿名称
-    sealedName: '采空区密闭', // 密闭名称
-    coalSeam: 'XX煤层', // 所属煤层
-    riskLevel: 'Ⅰ类容易自燃', // 自燃倾向性(与搜索框选项label一致)
-    COVal: 24, // CO浓度(ppm)
-    CH4Val: 0, // CH4浓度(%)
-    C2H2Val: 0, // C2H2浓度(ppm)
-    O2Val: 20, // O2浓度(%)
-    temperature: 35, // 温度(℃)
-    pressureDiff: 50, // 压差(Pa)
-    leakage: '气体涌出', // 是否漏风
-    fireHazard: '低风险', // 自然发火隐患
-    unsealing: '不可启封', // 密闭启封判定
-    explosionHazard: '低风险', // 爆炸危险性
-    updateTime: '2025-11-17 15:00:40', // 更新时间
-  },
-];
-
-export const modalDetailsData: {} = {
+export const modalDetailsData: {
+  basicInfo: Record<string, any>[];
+  board: Record<string, any>[];
+  gasConcentrationConfig: ModuleDataChart;
+  pressureConfig: ModuleDataChart;
+} = {
   basicInfo: [
     {
       label: '煤矿名称',
-      value: '神木市三江能源有限公司',
-    },
-    {
-      label: '密闭名称',
-      value: 'xxxx采空区密闭',
+      value: 'mineName',
+      tag: false,
     },
     {
-      label: '所属煤层',
-      value: 'xxxx煤层',
+      label: '设备位置',
+      value: 'devicePos',
+      tag: false,
     },
+    // {
+    //   label: '所属煤层',
+    //   value: 'coalSeamName',
+    // },
+    // {
+    //   label: '自燃情况',
+    //   value: 'Ⅰ类容易自燃',
+    // },
     {
-      label: '自燃情况',
-      value: 'Ⅰ类容易自燃',
+      label: '自然发火隐患等级',
+      value: 'fireAlarm',
+      tag: true,
     },
     {
       label: '是否漏风',
-      value: '闭内气体涌出',
+      value: 'leakageAlarm',
+      tag: true,
     },
     {
-      label: '自然发火隐患',
-      value: '低风险',
+      label: '压差隐患等级',
+      value: 'sourcePressureAlarm',
+      tag: true,
     },
     {
       label: '密闭启封判定',
-      value: '不可启封',
-    },
-    {
-      label: '爆炸危险性',
-      value: '低风险',
+      value: 'unsealAlarm',
+      tag: true,
     },
   ],
   board: [
     {
       label: 'CO(ppm)',
-      value: '21',
+      value: 'coVal',
     },
     {
       label: 'CO2(PPM)',
-      value: '21',
+      value: 'co2Val',
     },
     {
       label: 'O2(%)',
-      value: '24',
+      value: 'o2Val',
     },
     {
       label: 'CH4(%)',
-      value: '17',
+      value: 'ch4Val',
     },
     {
       label: 'C2H4(ppm)',
-      value: '23',
+      value: 'c2h4Val',
     },
     {
       label: 'C2H2(ppm)',
-      value: '14',
+      value: 'c2h2Val',
     },
     {
       label: '温度(℃)',
-      value: '14',
+      value: 'temperature',
     },
     {
       label: '压差(Pa)',
-      value: '14',
+      value: 'sourcePressure',
     },
   ],
-  demoBlastData: {
-    // 爆炸三角形顶点坐标数据(JSON字符串格式)
-    btTriBlast: JSON.stringify({
-      A_x: 0,
-      A_y: 21,
-      B_x: 50,
-      B_y: 0,
-      E_x: 10,
-      E_y: 15,
-      F_x: 30,
-      F_y: 5,
-      G_x: 5,
-      G_y: 18,
-    }),
-    o2val: '12.5',
-    coval: '2000',
-    gasval: '5.2',
-    ch2val: '1500',
-    chval: '800',
-  },
   gasConcentrationConfig: {
     type: 'line_smooth', // 使用光滑曲线类型
     legend: { show: true },
     xAxis: [
       {
-        type: 'category',
-        dataKey: 'time',
+        show: true,
         name: '时间',
         axisLabel: { color: '#000000' },
-        nameTextStyle: { color: '#000' },
       },
     ],
     yAxis: [
       {
-        type: 'value',
         show: true,
         name: '浓度(%)',
+        position: 'left',
         splitLine: { show: false },
         axisLine: {
           show: true,
@@ -269,118 +265,132 @@ export const modalDetailsData: {} = {
     ],
     series: [
       {
-        label: '气体浓度',
-        readFrom: 'gasData',
-        xprop: 'time',
-        yprop: 'value',
-        // color: '#000'
+        label: '氧气浓度',
+        readFrom: 'chartData',
+        xprop: 'readTime',
+        yprop: 'o2Val',
+      },
+      {
+        label: '一氧化碳浓度',
+        readFrom: 'chartData',
+        xprop: 'readTime',
+        yprop: 'coVal',
+      },
+      {
+        label: '二氧化碳浓度',
+        readFrom: 'chartData',
+        xprop: 'readTime',
+        yprop: 'co2Val',
       },
     ],
-  },
-  gasConcentrationData: {
-    gasData: [
-      // 示例数据,实际应从接口获取
-      { time: '00:00', value: 25.5 },
-      { time: '04:00', value: 26.3 },
-      { time: '08:00', value: 30.9 },
-      { time: '12:00', value: 27.8 },
-      { time: '16:00', value: 29.1 },
-      { time: '20:00', value: 25.5 },
-    ],
+    readFrom: '',
   },
   pressureConfig: {
     type: 'line', // 使用普通折线图类型
-    legend: { show: true, color: '#000000' },
-    xAxis: [{ type: 'category', dataKey: 'time', name: '时间', axisLabel: { color: '#000000' } }],
-    yAxis: [{ show: true, name: '压力(kPa)', axisLabel: { color: '#000000' } }],
-    series: [
-      { label: '内部压力', readFrom: 'chartdata', xprop: 'time', yprop: 'inner' },
-      { label: '外部压力', readFrom: 'chartdata', xprop: 'time', yprop: 'outer' },
-      { label: '压力差', readFrom: 'chartdata', xprop: 'time', yprop: 'diff' },
+    legend: { show: true },
+    xAxis: [
+      {
+        show: true,
+        name: '时间',
+        axisLabel: { color: '#000000' },
+      },
     ],
-  },
-  pressureData: {
-    chartdata: [
-      // 示例数据,实际应从接口获取
-      { time: '00:00', inner: 12, outer: 18, diff: 6 },
-      { time: '04:00', inner: 15, outer: 17, diff: 2 },
-      { time: '08:00', inner: 13, outer: 19, diff: 6 },
-      { time: '12:00', inner: 11, outer: 10, diff: 1 },
-      { time: '16:00', inner: 14, outer: 18, diff: 4 },
-      { time: '20:00', inner: 16, outer: 16, diff: 0 },
+    yAxis: [
+      {
+        show: true,
+        position: 'left',
+        name: '压力(kPa)',
+        axisLabel: { color: '#000000' },
+      },
     ],
+    series: [
+      {
+        label: '压差',
+        readFrom: 'chartData',
+        xprop: 'readTime',
+        yprop: 'sourcePressure',
+      },
+    ],
+    readFrom: '',
   },
 };
 
 // 历史数据相关
 export const historicalColumns: BasicColumn[] = [
-  {
-    title: '序号',
-    dataIndex: 'orderNo',
-  },
-  {
-    title: '区域',
-    dataIndex: 'enforcement',
-  },
+  // {
+  //   title: '序号',
+  //   dataIndex: 'orderNo',
+  //   width: 60,
+  // },
+  // {
+  //   title: '区域',
+  //   dataIndex: 'enforcement',
+  //   width: 100,
+  // },
   {
     title: '煤矿名称',
     dataIndex: 'mineName',
+    width: 200,
   },
   {
     title: '密闭名称',
-    dataIndex: 'sealedName',
+    dataIndex: 'devicePos',
+    width: 100,
   },
   {
     title: '所属煤层',
-    dataIndex: 'coalSeam',
+    dataIndex: 'coalSeamName',
+    width: 100,
   },
   {
-    title: '自燃倾向性',
-    dataIndex: 'riskLevel',
+    title: 'CO(ppm)',
+    dataIndex: 'coVal',
+    width: 100,
   },
   {
-    title: 'CO(ppm)',
-    dataIndex: 'COVal',
+    title: 'CO2(%)',
+    dataIndex: 'co2Val',
+    width: 100,
   },
   {
     title: 'CH4(%)',
-    dataIndex: 'CH4Val',
+    dataIndex: 'ch4Val',
+    width: 100,
   },
   {
     title: 'C2H2(ppm)',
-    dataIndex: 'C2H2Val',
+    dataIndex: 'c2h2Val',
+    width: 100,
+  },
+  {
+    title: 'C2H4(%)',
+    dataIndex: 'c2h4Val',
+    width: 100,
   },
   {
     title: 'O2(%)',
-    dataIndex: 'O2Val',
+    dataIndex: 'o2Val',
+    width: 100,
   },
   {
     title: '温度(℃)',
     dataIndex: 'temperature',
+    width: 100,
   },
   {
     title: '压差(Pa)',
-    dataIndex: 'pressureDiff',
-  },
-  {
-    title: '是否漏风',
-    dataIndex: 'leakage',
-  },
-  {
-    title: '自然发火隐患',
-    dataIndex: 'fireHazard',
-  },
-  {
-    title: '密闭启封判定',
-    dataIndex: 'unsealing',
-  },
-  {
-    title: '爆炸危险性',
-    dataIndex: 'explosionHazard',
+    dataIndex: 'sourcePressure',
+    width: 100,
   },
+  // {
+  //   title: '爆炸危险性',
+  //   dataIndex: 'explosionHazard',
+  //   width: 100,
+  // },
   {
     title: '更新时间',
-    dataIndex: 'updateTime',
+    dataIndex: 'createTime',
+    width: 100,
   },
 ];
 
@@ -389,14 +399,15 @@ export const historicalFormSchema: FormSchema[] = [
     field: 'mineCode',
     label: '煤矿名称',
     component: 'MineCascader',
+    slot: 'mine-cascader',
     colProps: { span: 6 },
   },
-  {
-    field: 'mineNameAbbr',
-    label: '煤矿简称',
-    component: 'Input',
-    colProps: { span: 6 },
-  },
+  // {
+  //   field: 'mineNameAbbr',
+  //   label: '煤矿简称',
+  //   component: 'Input',
+  //   colProps: { span: 6 },
+  // },
   // {
   //   field: 'productStatus',
   //   label: '生产状态',
@@ -440,18 +451,7 @@ export const historicalFormSchema: FormSchema[] = [
     field: 'goafId',
     label: '密闭名称',
     component: 'ApiSelect',
-    componentProps: {
-      api: getGoafList,
-      //标题字段
-      labelField: 'devicePos',
-      //值字段
-      valueField: 'id',
-      //请求参数
-      params: {},
-      //返回结果字段
-      resultField: 'records',
-    },
-    // required: true,
+    slot: 'goaf-select',
     colProps: { span: 6 },
   },
   {
@@ -464,7 +464,7 @@ export const historicalFormSchema: FormSchema[] = [
       //返回值格式化(绑定值的格式)
       valueFormat: 'YYYY-MM-DD hh:mm:ss',
     },
-    defaultValue: dayjs().add(-1, 'day').format('YYYY-MM-DD hh:mm:ss'),
+    defaultValue: dayjs().add(-7, 'day').format('YYYY-MM-DD hh:mm:ss'),
     colProps: { span: 6 },
   },
   {
@@ -482,28 +482,6 @@ export const historicalFormSchema: FormSchema[] = [
   },
 ];
 
-export const historicalMinesData = [
-  {
-    orderNo: 101, // 序号
-    enforcement: '执法一处', // 区域
-    mineName: '神木市三江', // 煤矿名称
-    sealedName: '采空区密闭', // 密闭名称
-    coalSeam: 'XX煤层', // 所属煤层
-    riskLevel: 'Ⅰ类容易自燃', // 自燃倾向性(与搜索框选项label一致)
-    COVal: 24, // CO浓度(ppm)
-    CH4Val: 0, // CH4浓度(%)
-    C2H2Val: 0, // C2H2浓度(ppm)
-    O2Val: 20, // O2浓度(%)
-    temperature: 35, // 温度(℃)
-    pressureDiff: 50, // 压差(Pa)
-    leakage: '气体涌出', // 是否漏风
-    fireHazard: '低风险', // 自然发火隐患
-    unsealing: '不可启封', // 密闭启封判定
-    explosionHazard: '低风险', // 爆炸危险性
-    updateTime: '2025-12-22 15:00:40', // 更新时间
-  },
-];
-
 export const treeData: TreeItem[] = [
   {
     title: '气体参数 ',
@@ -532,330 +510,21 @@ export const treeData: TreeItem[] = [
   },
 ];
 
-export const historicalMockChartData = [
-  {
-    time: '2025-12-22 00:00:00',
-    CO: 22.3,
-    CH4: 0.12,
-    C2H4: 0.35,
-    C2H2: 0.1,
-    CO2: 0.85,
-    O2: 19.5,
-    innerPressure: 101.32,
-    outerPressure: 101.1,
-    pressureDiff: 0.22,
-    temperature: 33.2,
-  },
-  {
-    time: '2025-12-22 01:00:00',
-    CO: 23.1,
-    CH4: 0.15,
-    C2H4: 0.42,
-    C2H2: 0.12,
-    CO2: 0.92,
-    O2: 19.7,
-    innerPressure: 101.38,
-    outerPressure: 101.15,
-    pressureDiff: 0.23,
-    temperature: 33.5,
-  },
-  {
-    time: '2025-12-22 02:00:00',
-    CO: 22.8,
-    CH4: 0.13,
-    C2H4: 0.38,
-    C2H2: 0.09,
-    CO2: 0.88,
-    O2: 19.6,
-    innerPressure: 101.41,
-    outerPressure: 101.18,
-    pressureDiff: 0.23,
-    temperature: 33.3,
-  },
-  {
-    time: '2025-12-22 03:00:00',
-    CO: 21.9,
-    CH4: 0.11,
-    C2H4: 0.31,
-    C2H2: 0.08,
-    CO2: 0.81,
-    O2: 19.4,
-    innerPressure: 101.35,
-    outerPressure: 101.12,
-    pressureDiff: 0.21,
-    temperature: 33.1,
-  },
-  {
-    time: '2025-12-22 04:00:00',
-    CO: 22.5,
-    CH4: 0.14,
-    C2H4: 0.36,
-    C2H2: 0.11,
-    CO2: 0.86,
-    O2: 19.5,
-    innerPressure: 101.39,
-    outerPressure: 101.16,
-    pressureDiff: 0.22,
-    temperature: 33.4,
-  },
-  {
-    time: '2025-12-22 05:00:00',
-    CO: 23.4,
-    CH4: 0.16,
-    C2H4: 0.45,
-    C2H2: 0.13,
-    CO2: 0.95,
-    O2: 19.8,
-    innerPressure: 101.43,
-    outerPressure: 101.2,
-    pressureDiff: 0.24,
-    temperature: 33.7,
-  },
-  {
-    time: '2025-12-22 06:00:00',
-    CO: 24.2,
-    CH4: 0.18,
-    C2H4: 0.51,
-    C2H2: 0.15,
-    CO2: 1.02,
-    O2: 20.0,
-    innerPressure: 101.47,
-    outerPressure: 101.23,
-    pressureDiff: 0.25,
-    temperature: 34.0,
-  },
-  {
-    time: '2025-12-22 07:00:00',
-    CO: 25.3,
-    CH4: 0.21,
-    C2H4: 0.58,
-    C2H2: 0.17,
-    CO2: 1.08,
-    O2: 20.2,
-    innerPressure: 101.52,
-    outerPressure: 101.27,
-    pressureDiff: 0.26,
-    temperature: 34.3,
-  },
-  {
-    time: '2025-12-22 08:00:00',
-    CO: 26.1,
-    CH4: 0.23,
-    C2H4: 0.65,
-    C2H2: 0.19,
-    CO2: 1.15,
-    O2: 20.4,
-    innerPressure: 101.56,
-    outerPressure: 101.3,
-    pressureDiff: 0.27,
-    temperature: 34.6,
-  },
-  {
-    time: '2025-12-22 09:00:00',
-    CO: 27.4,
-    CH4: 0.25,
-    C2H4: 0.72,
-    C2H2: 0.22,
-    CO2: 1.23,
-    O2: 20.6,
-    innerPressure: 101.6,
-    outerPressure: 101.33,
-    pressureDiff: 0.28,
-    temperature: 35.0,
-  },
-  {
-    time: '2025-12-22 10:00:00',
-    CO: 28.2,
-    CH4: 0.27,
-    C2H4: 0.78,
-    C2H2: 0.24,
-    CO2: 1.29,
-    O2: 20.8,
-    innerPressure: 101.63,
-    outerPressure: 101.35,
-    pressureDiff: 0.29,
-    temperature: 35.3,
-  },
-  {
-    time: '2025-12-22 11:00:00',
-    CO: 27.8,
-    CH4: 0.26,
-    C2H4: 0.75,
-    C2H2: 0.23,
-    CO2: 1.26,
-    O2: 20.7,
-    innerPressure: 101.61,
-    outerPressure: 101.34,
-    pressureDiff: 0.28,
-    temperature: 35.2,
-  },
-  {
-    time: '2025-12-22 12:00:00',
-    CO: 26.9,
-    CH4: 0.24,
-    C2H4: 0.69,
-    C2H2: 0.21,
-    CO2: 1.19,
-    O2: 20.5,
-    innerPressure: 101.58,
-    outerPressure: 101.32,
-    pressureDiff: 0.27,
-    temperature: 34.9,
-  },
-  {
-    time: '2025-12-22 13:00:00',
-    CO: 26.3,
-    CH4: 0.22,
-    C2H4: 0.64,
-    C2H2: 0.19,
-    CO2: 1.14,
-    O2: 20.3,
-    innerPressure: 101.55,
-    outerPressure: 101.3,
-    pressureDiff: 0.26,
-    temperature: 34.7,
-  },
-  {
-    time: '2025-12-22 14:00:00',
-    CO: 25.7,
-    CH4: 0.2,
-    C2H4: 0.59,
-    C2H2: 0.18,
-    CO2: 1.09,
-    O2: 20.1,
-    innerPressure: 101.53,
-    outerPressure: 101.28,
-    pressureDiff: 0.25,
-    temperature: 34.5,
-  },
-  {
-    time: '2025-12-22 15:00:00',
-    CO: 24.9,
-    CH4: 0.18,
-    C2H4: 0.53,
-    C2H2: 0.16,
-    CO2: 1.03,
-    O2: 19.9,
-    innerPressure: 101.49,
-    outerPressure: 101.25,
-    pressureDiff: 0.24,
-    temperature: 34.2,
-  },
-  {
-    time: '2025-12-22 16:00:00',
-    CO: 24.3,
-    CH4: 0.17,
-    C2H4: 0.49,
-    C2H2: 0.15,
-    CO2: 0.98,
-    O2: 19.8,
-    innerPressure: 101.46,
-    outerPressure: 101.22,
-    pressureDiff: 0.23,
-    temperature: 34.0,
-  },
-  {
-    time: '2025-12-22 17:00:00',
-    CO: 23.8,
-    CH4: 0.16,
-    C2H4: 0.46,
-    C2H2: 0.14,
-    CO2: 0.94,
-    O2: 19.7,
-    innerPressure: 101.44,
-    outerPressure: 101.21,
-    pressureDiff: 0.23,
-    temperature: 33.8,
-  },
-  {
-    time: '2025-12-22 18:00:00',
-    CO: 23.5,
-    CH4: 0.15,
-    C2H4: 0.43,
-    C2H2: 0.13,
-    CO2: 0.91,
-    O2: 19.6,
-    innerPressure: 101.42,
-    outerPressure: 101.19,
-    pressureDiff: 0.22,
-    temperature: 33.7,
-  },
-  {
-    time: '2025-12-22 19:00:00',
-    CO: 24.1,
-    CH4: 0.17,
-    C2H4: 0.48,
-    C2H2: 0.15,
-    CO2: 0.97,
-    O2: 19.8,
-    innerPressure: 101.45,
-    outerPressure: 101.22,
-    pressureDiff: 0.24,
-    temperature: 33.9,
-  },
-  {
-    time: '2025-12-22 20:00:00',
-    CO: 24.7,
-    CH4: 0.19,
-    C2H4: 0.52,
-    C2H2: 0.16,
-    CO2: 1.01,
-    O2: 20.0,
-    innerPressure: 101.48,
-    outerPressure: 101.24,
-    pressureDiff: 0.25,
-    temperature: 34.1,
-  },
-  {
-    time: '2025-12-22 21:00:00',
-    CO: 25.2,
-    CH4: 0.2,
-    C2H4: 0.56,
-    C2H2: 0.18,
-    CO2: 1.05,
-    O2: 20.1,
-    innerPressure: 101.51,
-    outerPressure: 101.26,
-    pressureDiff: 0.26,
-    temperature: 34.3,
-  },
-  {
-    time: '2025-12-22 22:00:00',
-    CO: 24.5,
-    CH4: 0.18,
-    C2H4: 0.5,
-    C2H2: 0.16,
-    CO2: 0.99,
-    O2: 19.9,
-    innerPressure: 101.47,
-    outerPressure: 101.23,
-    pressureDiff: 0.24,
-    temperature: 34.0,
-  },
-  {
-    time: '2025-12-22 23:00:00',
-    CO: 23.7,
-    CH4: 0.16,
-    C2H4: 0.45,
-    C2H2: 0.14,
-    CO2: 0.93,
-    O2: 19.7,
-    innerPressure: 101.43,
-    outerPressure: 101.2,
-    pressureDiff: 0.23,
-    temperature: 33.8,
-  },
-  {
-    time: '2025-11-18 00:00:00',
-    CO: 22.9,
-    CH4: 0.14,
-    C2H4: 0.39,
-    C2H2: 0.11,
-    CO2: 0.89,
-    O2: 19.6,
-    innerPressure: 101.37,
-    outerPressure: 101.17,
-    pressureDiff: 0.22,
-    temperature: 33.4,
-  },
-];
+function getTagType(level: string) {
+  switch (level) {
+    case '1':
+      return 'red';
+    case '2':
+      return 'volcano';
+    case '3':
+      return 'orange';
+    case '4':
+      return 'success';
+    default:
+      return 'default';
+  }
+}
+export function tagCellRender(record: any) {
+  if (!record) return h(Tag, { bordered: false, color: 'default' }, '-');
+  return h(Tag, { bordered: false, color: getTagType(record.alarmLevel) }, record.alarmName);
+}

+ 11 - 9
src/views/system/algorithm/algorithm.api.ts

@@ -21,36 +21,38 @@ export function getMineData(params: any) {
   return defHttp.post({ url: Api.getMineData, params });
 }
 export function getCoalSeam(params: any) {
-  return defHttp.post({ url: Api.getCoalSeam, params });
+  return defHttp.post({ url: Api.getCoalSeam, params }, { joinParamsToUrl: true });
 }
 export function getCoalSeamAlarmRule(params: any) {
   return defHttp.post({ url: Api.getCoalSeamAlarmRule, params });
 }
 export function updateCoalSeamAlarmRule(params: any) {
-  return defHttp.post({ url: Api.updateCoalSeamAlarmRule, params }).then(() => {
-    message.success('修改成功');
-  });
+  return defHttp.post({ url: Api.updateCoalSeamAlarmRule, params });
 }
 export function addCoalSeamAlarmRule(params: any) {
-  return defHttp.post({ url: Api.addCoalSeamAlarmRule, params });
+  return defHttp.post({ url: Api.addCoalSeamAlarmRule, params }).then(() => {
+    message.success('新增成功');
+  });
 }
 export function deleteCoalSeamAlarmRule(params: any) {
-  return defHttp.post({ url: Api.deleteCoalSeamAlarmRule, params });
+  return defHttp.post({ url: Api.deleteCoalSeamAlarmRule, params }, { joinParamsToUrl: true });
 }
 export function getGoafList(params: any) {
-  return defHttp.post({ url: Api.getGoafList, params });
+  return defHttp.post({ url: Api.getGoafList, params }, { joinParamsToUrl: true });
 }
 export function getGoafDataLimit(params: any) {
   return defHttp.post({ url: Api.getGoafDataLimit, params }, { joinParamsToUrl: true });
 }
 export function addGoafDataLimit(params: any) {
-  return defHttp.post({ url: Api.addGoafDataLimit, params });
+  return defHttp.post({ url: Api.addGoafDataLimit, params }).then(() => {
+    message.success('新增成功');
+  });
 }
 export function updateGoafDataLimit(params: any) {
   return defHttp.post({ url: Api.updateGoafDataLimit, params });
 }
 export function deleteGoafDataLimit(params: any) {
-  return defHttp.post({ url: Api.deleteGoafDataLimit, params });
+  return defHttp.post({ url: Api.deleteGoafDataLimit, params }, { joinParamsToUrl: true });
 }
 
 export function getMineTree(params: { searchValue: string }) {

+ 129 - 27
src/views/system/algorithm/algorithm.data.ts

@@ -2,18 +2,6 @@ import { h } from 'vue';
 import { FormSchema } from '/@/components/Form';
 import { BasicColumn } from '/@/components/Table';
 import { Tag } from 'ant-design-vue';
-import { options } from '../../monitor/mynews/XssWhiteList';
-
-const goafAlarmOptions = [
-  { value: 'ch4Val', label: '甲烷' },
-  { value: 'o2Val', label: '氧气' },
-  { value: 'coVal', label: '一氧化碳' },
-  { value: 'co2Val', label: '二氧化碳' },
-  { value: 'c2h4Val', label: '乙烯' },
-  { value: 'c2h2Val', label: '乙炔' },
-  { value: 'sourcePressure', label: '压差' },
-  { value: 'temperature', label: '温度' },
-];
 
 /** 煤层预警参数 表格配置 */
 export const columnsCoalAlarm: BasicColumn[] = [
@@ -25,10 +13,12 @@ export const columnsCoalAlarm: BasicColumn[] = [
   {
     title: '煤层名称',
     dataIndex: 'coalSeamName',
+    width: 400,
   },
   {
     title: '创建时间',
     dataIndex: 'createTime',
+    width: 400,
   },
   /*  {
     title: '职务',
@@ -48,14 +38,17 @@ export const columnsGoafLimit: BasicColumn[] = [
   {
     title: '气温',
     dataIndex: 'fireAirTemperature',
+    width: 200,
   },
   {
     title: '水温',
     dataIndex: 'fireWaterTemperature',
+    width: 200,
   },
   {
     title: '状态',
     dataIndex: 'status',
+    width: 200,
     customRender({ text }) {
       return h(
         Tag,
@@ -69,6 +62,7 @@ export const columnsGoafLimit: BasicColumn[] = [
   {
     title: '创建时间',
     dataIndex: 'createTime',
+    width: 300,
   },
 ];
 
@@ -468,29 +462,137 @@ export const schemasCoalAlarm: FormSchema[] = [
     colProps: { span: 12 },
   },
 ];
+
+export const goafAlarmModel = {
+  ch4Val: {
+    alarmField: 'ch4Val',
+    lowerLimit: undefined,
+    upperLimit: undefined,
+  },
+  o2Val: {
+    alarmField: 'o2Val',
+    lowerLimit: undefined,
+    upperLimit: undefined,
+  },
+  coVal: {
+    alarmField: 'coVal',
+    lowerLimit: undefined,
+    upperLimit: undefined,
+  },
+  co2Val: {
+    alarmField: 'co2Val',
+    lowerLimit: undefined,
+    upperLimit: undefined,
+  },
+  c2h4Val: {
+    alarmField: 'c2h4Val',
+    lowerLimit: undefined,
+    upperLimit: undefined,
+  },
+  c2h2Val: {
+    alarmField: 'c2h2Val',
+    lowerLimit: undefined,
+    upperLimit: undefined,
+  },
+  sourcePressure: {
+    alarmField: 'sourcePressure',
+    lowerLimit: undefined,
+    upperLimit: undefined,
+  },
+  temperature: {
+    alarmField: 'temperature',
+    lowerLimit: undefined,
+    upperLimit: undefined,
+  },
+};
+
 export const schemasGoafLimit: FormSchema[] = [
   {
-    label: 'ID',
-    field: 'id',
-    show: false,
+    field: 'ch4Val',
+    label: '甲烷',
+    labelWidth: 118,
     component: 'Input',
+    slot: 'InputRangeGoaf',
+    defaultValue: goafAlarmModel.ch4Val,
+    /** 借用 */
+    groupName: '下限 - 上限',
+    colProps: { span: 12 },
   },
   {
-    label: '监测值:',
-    field: 'alarmField',
-    component: 'Select',
-    componentProps: {
-      options: goafAlarmOptions,
-    },
+    field: 'o2Val',
+    label: '氧气',
+    labelWidth: 118,
+    component: 'Input',
+    slot: 'InputRangeGoaf',
+    defaultValue: goafAlarmModel.o2Val,
+    /** 借用 */
+    groupName: '下限 - 上限',
+    colProps: { span: 12 },
   },
   {
-    label: '下限值:',
-    field: 'lowerLimit',
-    component: 'InputNumber',
+    field: 'coVal',
+    label: '一氧化碳',
+    labelWidth: 118,
+    component: 'Input',
+    slot: 'InputRangeGoaf',
+    defaultValue: goafAlarmModel.coVal,
+    /** 借用 */
+    groupName: '下限 - 上限',
+    colProps: { span: 12 },
   },
   {
-    label: '上限值:',
-    field: 'upperLimit',
-    component: 'InputNumber',
+    field: 'co2Val',
+    label: '二氧化碳',
+    labelWidth: 118,
+    component: 'Input',
+    slot: 'InputRangeGoaf',
+    defaultValue: goafAlarmModel.co2Val,
+    /** 借用 */
+    groupName: '下限 - 上限',
+    colProps: { span: 12 },
+  },
+  {
+    field: 'c2h4Val',
+    label: '乙烯',
+    labelWidth: 118,
+    component: 'Input',
+    slot: 'InputRangeGoaf',
+    defaultValue: goafAlarmModel.c2h4Val,
+    /** 借用 */
+    groupName: '下限 - 上限',
+    colProps: { span: 12 },
+  },
+  {
+    field: 'c2h2Val',
+    label: '乙炔',
+    labelWidth: 118,
+    component: 'Input',
+    slot: 'InputRangeGoaf',
+    defaultValue: goafAlarmModel.c2h2Val,
+    /** 借用 */
+    groupName: '下限 - 上限',
+    colProps: { span: 12 },
+  },
+  {
+    field: 'sourcePressure',
+    label: '压差',
+    labelWidth: 118,
+    component: 'Input',
+    slot: 'InputRangeGoaf',
+    defaultValue: goafAlarmModel.sourcePressure,
+    /** 借用 */
+    groupName: '下限 - 上限',
+    colProps: { span: 12 },
+  },
+  {
+    field: 'temperature',
+    label: '温度',
+    labelWidth: 118,
+    component: 'Input',
+    slot: 'InputRangeGoaf',
+    defaultValue: goafAlarmModel.temperature,
+    /** 借用 */
+    groupName: '下限 - 上限',
+    colProps: { span: 12 },
   },
 ];

+ 65 - 28
src/views/system/algorithm/index.vue

@@ -14,12 +14,12 @@
       <template #expandedRowRender>
         <BasicTable @register="registerInnerTable">
           <template #action="{ record }">
-            <button @click="handleEdit({ goafId: record.id }, 'goaf')" class="action-btn">
+            <button @click="handleEdit({ goafId: record.id, mineCode: last(expandedRowKeys) }, 'goaf')" class="action-btn">
               <SvgIcon name="edit" />
             </button>
-            <button @click="handleAdd({ goafId: record.id }, 'goaf')" class="action-btn ml-1">
+            <!-- <button @click="handleAdd({ goafId: record.id, mineCode: last(expandedRowKeys) }, 'goaf')" class="action-btn ml-1">
               <PlusOutlined />
-            </button>
+            </button> -->
             <a-popconfirm title="确认删除?" @confirm="handleDelete(record, 'coal')">
               <button @click="handleDelete(record, 'goaf')" class="action-btn ml-1">
                 <SvgIcon name="delete" />
@@ -33,9 +33,9 @@
         <button @click="handleEdit({ coalSeamId: record.id, mineCode: record.mineCode }, 'coal')" class="action-btn">
           <SvgIcon name="edit" />
         </button>
-        <button @click="handleAdd({ coalSeamId: record.id, mineCode: record.mineCode }, 'coal')" class="action-btn ml-1">
+        <!-- <button @click="handleAdd({ coalSeamId: record.id, mineCode: record.mineCode }, 'coal')" class="action-btn ml-1">
           <PlusOutlined />
-        </button>
+        </button> -->
         <a-popconfirm title="确认删除?" @confirm="handleDelete(record, 'coal')">
           <button class="action-btn ml-1">
             <SvgIcon name="delete" />
@@ -73,6 +73,15 @@
           </a-input-group>
         </a-form-item>
       </template>
+      <template #InputRangeGoaf="{ model, field, schema }">
+        <a-form-item v-if="model[field]">
+          <a-input-group>
+            <a-input-number v-model:value="model[field][`lowerLimit`]" style="width: calc(50% - 100px)" placeholder="-" />
+            <a-input style="width: 200px; border-left: 0; pointer-events: none; color: inherit" :value="schema.groupName" disabled />
+            <a-input-number v-model:value="model[field][`upperLimit`]" style="width: calc(50% - 100px); border-left: 0" placeholder="-" />
+          </a-input-group>
+        </a-form-item>
+      </template>
     </BasicForm>
   </BasicModal>
 </template>
@@ -85,7 +94,7 @@
   import { useForm, BasicForm } from '/@/components/Form';
   import { BasicTable, useTable } from '/@/components/Table';
   import { useListPage } from '/@/hooks/system/useListPage';
-  import { columnsCoalAlarm, columnsGoafLimit, schemasCoalAlarm, schemasGoafLimit, searchFormSchema } from './algorithm.data';
+  import { columnsCoalAlarm, columnsGoafLimit, schemasCoalAlarm, schemasGoafLimit, searchFormSchema, goafAlarmModel } from './algorithm.data';
   import {
     addCoalSeamAlarmRule,
     deleteCoalSeamAlarmRule,
@@ -99,9 +108,9 @@
     getGoafDataLimit,
   } from './algorithm.api';
   import { Flex } from 'ant-design-vue';
-  import { PlusOutlined } from '@ant-design/icons-vue';
-  import { last } from 'lodash-es';
-
+  // import { PlusOutlined } from '@ant-design/icons-vue';
+  import { forEach, isNil, last, map } from 'lodash-es';
+  import { message } from 'ant-design-vue';
   import { SvgIcon } from '/@/components/Icon';
 
   const { prefixCls } = useDesign('algorithm-list');
@@ -146,6 +155,7 @@
       dataIndex: 'action',
       slots: { customRender: 'action' },
     },
+    immediate: false,
     beforeFetch(p) {
       p.coalSeamId = expandedRowKeys.value[0];
     },
@@ -164,8 +174,30 @@
       'goaf',
       {
         schemas: schemasGoafLimit,
-        submitFunc: (res) => (res.id ? updateGoafDataLimit(res) : addGoafDataLimit(res)),
-        fetchRecord: (params) => getGoafDataLimit(params).then((r) => last(r)),
+        submitFunc: (res) =>
+          Promise.all(
+            map(res, (item) => {
+              if (item.id) {
+                return updateGoafDataLimit(item);
+              }
+              if (!isNil(item.lowerLimit) || !isNil(item.upperLimit)) {
+                return addGoafDataLimit(item);
+              }
+              return Promise.resolve();
+            })
+          ),
+        fetchRecord: (params) =>
+          getGoafDataLimit(params).then((r) => {
+            const result: any = {};
+            forEach(goafAlarmModel, (item, key) => {
+              result[key] = { ...params, ...item };
+            });
+            forEach(r, (item) => {
+              result[item.alarmField] = item;
+            });
+
+            return result;
+          }),
       },
     ],
   ]);
@@ -173,7 +205,7 @@
     ['coal', { title: '预警参数设置', visible: true, loading: true }],
     ['goaf', { title: '超限预警设置', visible: true, loading: true }],
   ]);
-  const submitResolver = ref<(res: any) => Promise<void>>();
+  const submitResolver = ref<(res: any) => Promise<unknown>>();
   // 点击编辑后,获取对应的表单和弹窗配置
   async function handleEdit(record, sign: string) {
     if (!modalPropsMap.has(sign)) return;
@@ -195,25 +227,26 @@
 
     setModalProps({ loading: false });
   }
-  async function handleAdd(record, sign: string) {
-    if (!modalPropsMap.has(sign)) return;
-    if (!formPropsMap.has(sign)) return;
-    setModalProps(modalPropsMap.get(sign) as ModalProps);
-    const { schemas, submitFunc } = formPropsMap.get(sign)!;
-    await resetSchema(schemas);
+  // async function handleAdd(record, sign: string) {
+  //   if (!modalPropsMap.has(sign)) return;
+  //   if (!formPropsMap.has(sign)) return;
+  //   setModalProps(modalPropsMap.get(sign) as ModalProps);
+  //   const { schemas, submitFunc } = formPropsMap.get(sign)!;
+  //   await nextTick();
+  //   await resetSchema(schemas);
 
-    await nextTick();
+  //   await nextTick();
 
-    await resetFields();
+  //   await resetFields();
 
-    await nextTick();
+  //   await nextTick();
 
-    // 不要使用setFormProps因为它会错误的触发submit方法
-    // await setFormProps({ submitFunc });
-    submitResolver.value = (res) => submitFunc(Object.assign(res, record));
+  //   // 不要使用setFormProps因为它会错误的触发submit方法
+  //   // await setFormProps({ submitFunc });
+  //   submitResolver.value = (res) => submitFunc(Object.assign(res, record));
 
-    setModalProps({ loading: false });
-  }
+  //   setModalProps({ loading: false });
+  // }
 
   const deletionPropsMap = new Map<string, { api: (id: string) => Promise<void> }>([
     ['coal', { api: (id) => deleteCoalSeamAlarmRule({ id }) }],
@@ -226,7 +259,7 @@
   }
 
   const [registerModal, { setModalProps }] = useModal();
-  const [registerForm, { resetFields, setFieldsValue, validate, resetSchema }] = useForm({
+  const [registerForm, { setFieldsValue, validate, resetSchema }] = useForm({
     model: {},
     schemas: schemasCoalAlarm,
     showResetButton: false,
@@ -237,7 +270,11 @@
 
   function handleSubmit() {
     return validate().then((res) => {
-      submitResolver.value && submitResolver.value(res);
+      submitResolver.value &&
+        submitResolver.value(res).then(() => {
+          message.success('操作成功');
+          setModalProps({ visible: false });
+        });
     });
   }
 </script>

この差分においてかなりの量のファイルが変更されているため、一部のファイルを表示していません