浏览代码

[Wip 0000] 密闭监测页面数据对接及调整

houzekong 5 月之前
父节点
当前提交
980802fa1f

+ 279 - 305
src/views/monitor/sealedMonitor/components/HistoricalDetailsModal.vue

@@ -1,12 +1,5 @@
 <template>
-  <Modal
-    v-model:open="visible"
-    title="密闭监测详情"
-    width="1200px"
-    @ok="handleOk"
-    @cancel="handleCancel"
-    prefixCls="custom-modal"
-  >
+  <Modal v-model:open="visible" title="密闭监测详情" width="1200px" @ok="handleOk" @cancel="handleCancel" prefixCls="custom-modal">
     <div class="filter-area">
       <!-- 时间选择 -->
       <div class="filter-section">
@@ -14,7 +7,7 @@
         <RangePicker
           v-model="dateRange"
           format="YYYY-MM-DD HH:mm:ss"
-          :placeholder="['开始时间','结束时间']"
+          :placeholder="['开始时间', '结束时间']"
           style="width: 320px"
           :show-time="{ format: 'HH:mm:ss' }"
         />
@@ -23,22 +16,11 @@
       <div class="filter-section param-section">
         <span class="filter-label">参数选择:</span>
         <div class="param-selector">
-          <Input
-            v-model="selectedParamsText"
-            placeholder="请选择监测参数"
-            readonly
-            style="width: 300px"
-          />
+          <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>
@@ -49,14 +31,10 @@
     </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" 
-              style="height: 100%; width: 100%"
-            />
+            <CustomChart :chart-data="generatedChartData" :chart-config="generatedChartConfig" style="height: 100%; width: 100%" />
           </template>
           <template v-else-if="isChartGenerated">
             <div class="empty-chart">暂无匹配数据,请调整筛选条件</div>
@@ -70,305 +48,301 @@
   </Modal>
 </template>
 <script 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 '../monitorData.data'; // 引入模拟数据
-import dayjs from 'dayjs';
-import isBetween from 'dayjs/plugin/isBetween'; // 引入 isBetween 插件
+  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 dayjs from 'dayjs';
+  import isBetween from 'dayjs/plugin/isBetween'; // 引入 isBetween 插件
 
-// 关键:使用 dayjs 插件
-dayjs.extend(isBetween);
+  // 关键:使用 dayjs 插件
+  dayjs.extend(isBetween);
 
-// 组件注册
-const RangePicker = DatePicker.RangePicker;
+  // 组件注册
+  const RangePicker = DatePicker.RangePicker;
 
-// 弹框控制
-const visible = ref(false);
-const showModal = () => (visible.value = true);
-const hideModal = () => (visible.value = false);
-const handleOk = () => hideModal();
-const handleCancel = () => hideModal();
+  // 弹框控制
+  const visible = ref(false);
+  const showModal = () => (visible.value = true);
+  const hideModal = () => (visible.value = false);
+  const handleOk = () => hideModal();
+  const handleCancel = () => hideModal();
 
-// 筛选相关响应式数据
-const dateRange = ref([dayjs().subtract(1, 'day').toDate(), dayjs().toDate()]); // 默认时间范围(近1天)
-const selectedParams = ref([]); // 选中的参数(实际用于图表)
-const selectedParamsText = ref(''); // 参数选择框显示文本
-const showTree = ref(false); // 控制树形选择器显示/隐藏
-const checkedTreeKeys = ref([]); // 树形选中的key
-const generatedChartData = ref([]); // 生成的图表数据
-const generatedChartConfig = ref({}); // 生成的图表配置
-const isChartGenerated = ref(false); // 是否已点击生成
+  // 筛选相关响应式数据
+  const dateRange = ref([dayjs().subtract(1, 'day').toDate(), dayjs().toDate()]); // 默认时间范围(近1天)
+  const selectedParams = ref([]); // 选中的参数(实际用于图表)
+  const selectedParamsText = ref(''); // 参数选择框显示文本
+  const showTree = ref(false); // 控制树形选择器显示/隐藏
+  const checkedTreeKeys = ref([]); // 树形选中的key
+  const generatedChartData = ref([]); // 生成的图表数据
+  const generatedChartConfig = ref({}); // 生成的图表配置
+  const isChartGenerated = ref(false); // 是否已点击生成
 
-// Tree Key 与参数名映射(关键:关联树形节点和实际参数)
-const treeKeyToParamMap = computed(() => ({
-  '0-0-0': 'CO',
-  '0-0-1': 'CH4',
-  '0-0-2': 'C2H4',
-  '0-0-3': 'C2H2',
-  '0-0-4': 'CO2',
-  '0-0-5': 'O2',
-  '1-1-0': 'innerPressure',
-  '1-1-1': 'outerPressure',
-  '1-1-2': 'pressureDiff',
-  '2-2': 'temperature',
-}));
+  // Tree Key 与参数名映射(关键:关联树形节点和实际参数)
+  const treeKeyToParamMap = computed(() => ({
+    '0-0-0': 'CO',
+    '0-0-1': 'CH4',
+    '0-0-2': 'C2H4',
+    '0-0-3': 'C2H2',
+    '0-0-4': 'CO2',
+    '0-0-5': 'O2',
+    '1-1-0': 'innerPressure',
+    '1-1-1': 'outerPressure',
+    '1-1-2': 'pressureDiff',
+    '2-2': 'temperature',
+  }));
 
-// 参数名反向映射到 Tree Key
-const paramToTreeKeyMap = computed(() => {
-  return Object.fromEntries(
-    Object.entries(treeKeyToParamMap.value).map(([key, val]) => [val, key])
-  );
-});
+  // 参数名反向映射到 Tree Key
+  const paramToTreeKeyMap = computed(() => {
+    return Object.fromEntries(Object.entries(treeKeyToParamMap.value).map(([key, val]) => [val, key]));
+  });
 
-// 树形选择事件处理
-const handleTreeCheck = (checkedKeys) => {
-  checkedTreeKeys.value = checkedKeys;
-  // 转换为实际参数名
-  const params = checkedKeys
-    .map(key => treeKeyToParamMap.value[key])
-    .filter(param => param); // 过滤无效参数
-  selectedParams.value = params;
-  
-  // 更新输入框显示文本
-  const paramLabels = params.map(param => paramLabelMap.value[param]);
-  selectedParamsText.value = paramLabels.join('、');
-};
+  // 树形选择事件处理
+  const handleTreeCheck = (checkedKeys) => {
+    checkedTreeKeys.value = checkedKeys;
+    // 转换为实际参数名
+    const params = checkedKeys.map((key) => treeKeyToParamMap.value[key]).filter((param) => param); // 过滤无效参数
+    selectedParams.value = params;
 
-// 参数颜色映射
-const paramColorMap = computed(() => ({
-  'CO': '#f5222d',    // 红色
-  'CH4': '#1890ff',   // 蓝色
-  'C2H4': '#faad14',  // 橙色
-  'C2H2': '#52c41a',  // 绿色
-  'CO2': '#722ed1',   // 紫色
-  'O2': '#13c2c2',    // 青色
-  'innerPressure': '#ff4d4f', // 浅红
-  'outerPressure': '#40a9ff',// 浅蓝
-  'pressureDiff': '#fa8c16', // 浅橙
-  'temperature': '#9254de',  // 浅紫
-}));
+    // 更新输入框显示文本
+    const paramLabels = params.map((param) => paramLabelMap.value[param]);
+    selectedParamsText.value = paramLabels.join('、');
+  };
 
-// 参数标签映射(图表系列名称)
-const paramLabelMap = computed(() => ({
-  'CO': 'CO浓度(ppm)',
-  'CH4': 'CH4浓度(%)',
-  'C2H4': 'C2H4浓度(ppm)',
-  'C2H2': 'C2H2浓度(ppm)',
-  'CO2': 'CO2浓度(%)',
-  'O2': 'O2浓度(%)',
-  'innerPressure': '内压力(kPa)',
-  'outerPressure': '外压力(kPa)',
-  'pressureDiff': '压差(kPa)',
-  'temperature': '温度(℃)',
-}));
+  // 参数颜色映射
+  const paramColorMap = computed(() => ({
+    CO: '#f5222d', // 红色
+    CH4: '#1890ff', // 蓝色
+    C2H4: '#faad14', // 橙色
+    C2H2: '#52c41a', // 绿色
+    CO2: '#722ed1', // 紫色
+    O2: '#13c2c2', // 青色
+    innerPressure: '#ff4d4f', // 浅红
+    outerPressure: '#40a9ff', // 浅蓝
+    pressureDiff: '#fa8c16', // 浅橙
+    temperature: '#9254de', // 浅紫
+  }));
 
-// 生成折线图核心逻辑
-const generateChart = () => {
-  // 校验筛选条件
-  if (!dateRange.value[0] || !dateRange.value[1]) {
-    message.warning('请选择完整的时间范围');
-    return;
-  }
-  if (selectedParams.value.length === 0) {
-    message.warning('请至少选择一个监测参数');
-    return;
-  }
+  // 参数标签映射(图表系列名称)
+  const paramLabelMap = computed(() => ({
+    CO: 'CO浓度(ppm)',
+    CH4: 'CH4浓度(%)',
+    C2H4: 'C2H4浓度(ppm)',
+    C2H2: 'C2H2浓度(ppm)',
+    CO2: 'CO2浓度(%)',
+    O2: 'O2浓度(%)',
+    innerPressure: '内压力(kPa)',
+    outerPressure: '外压力(kPa)',
+    pressureDiff: '压差(kPa)',
+    temperature: '温度(℃)',
+  }));
+
+  // 生成折线图核心逻辑
+  const generateChart = () => {
+    // 校验筛选条件
+    if (!dateRange.value[0] || !dateRange.value[1]) {
+      message.warning('请选择完整的时间范围');
+      return;
+    }
+    if (selectedParams.value.length === 0) {
+      message.warning('请至少选择一个监测参数');
+      return;
+    }
 
-  isChartGenerated.value = true;
-  const start = dayjs(dateRange.value[0]); // 转为 dayjs 实例
-  const end = dayjs(dateRange.value[1]);   // 转为 dayjs 实例
+    isChartGenerated.value = true;
+    const start = dayjs(dateRange.value[0]); // 转为 dayjs 实例
+    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', '[]');
-  });
+    // 1. 筛选时间范围内的模拟数据(修复核心漏洞)
+    const filteredData = historicalMockChartData.filter((item) => {
+      const itemTime = dayjs(item.time); // 解析 item.time 为 dayjs 实例
+      // 修复 isBetween 用法:明确指定 unit 为 'second',包容性为 '[]'
+      return itemTime.isBetween(start, end, 'second', '[]');
+    });
 
-  // 2. 构建图表数据结构(适配 CustomChart 的 line 类型)
-  const timeMap = new Map();
-  // 修复变量名:filteredRawData → filteredData(之前未定义)
-  filteredData.forEach((item) => {
-    const timeStr = dayjs(item.time).format('YYYY-MM-DD HH:mm:ss');
-    if (!timeMap.has(timeStr)) {
-      timeMap.set(timeStr, { time: timeStr });
-    }
-    // 只保留选中的参数数据
-    selectedParams.value.forEach(param => {
-      if (item[param] !== undefined) {
-        timeMap.get(timeStr)[param] = item[param];
+    // 2. 构建图表数据结构(适配 CustomChart 的 line 类型)
+    const timeMap = new Map();
+    // 修复变量名:filteredRawData → filteredData(之前未定义)
+    filteredData.forEach((item) => {
+      const timeStr = dayjs(item.time).format('YYYY-MM-DD HH:mm:ss');
+      if (!timeMap.has(timeStr)) {
+        timeMap.set(timeStr, { time: timeStr });
       }
+      // 只保留选中的参数数据
+      selectedParams.value.forEach((param) => {
+        if (item[param] !== undefined) {
+          timeMap.get(timeStr)[param] = item[param];
+        }
+      });
     });
-  });
 
-  // 转换为数组并按时间排序
-  const chartData = Array.from(timeMap.values()).sort((a, b) => {
-    return dayjs(a.time).valueOf() - dayjs(b.time).valueOf();
-  });
-  generatedChartData.value = chartData;
+    // 转换为数组并按时间排序
+    const chartData = Array.from(timeMap.values()).sort((a, b) => {
+      return dayjs(a.time).valueOf() - dayjs(b.time).valueOf();
+    });
+    generatedChartData.value = chartData;
 
-  // 3. 构建图表配置(折线图类型,完善适配逻辑)
-  generatedChartConfig.value = {
-    type: 'line', // 折线图
-    clear: true, // 每次生成清空之前的图表
-    legend: { show: true, top: 10, right: 10 },
-    xAxis: [
-      {
-        type: 'category',
-        axisLabel: {
-          rotate: 30,
-          formatter: (value) => dayjs(value).format('HH:mm:ss'),
-          interval: Math.max(1, Math.floor(chartData.length / 10)) // 控制x轴标签密度
-        }
-      }
-    ],
-    yAxis: selectedParams.value.map(param => ({
-      type: 'value',
-      name: paramLabelMap.value[param].split('(')[1].replace(')', ''), // 显示单位
-      nameTextStyle: { color: paramColorMap.value[param] },
-      axisLine: { lineStyle: { color: paramColorMap.value[param] } },
-      splitLine: { lineStyle: { opacity: 0.1 } }
-    })),
-    series: selectedParams.value.map((param, index) => ({
-      name: paramLabelMap.value[param],
-      type: 'line',
-      readFrom: '', // 适配 CustomChart 的 baseSeries 读取逻辑
-      label: paramLabelMap.value[param],
-      xprop: 'time', // 对应图表数据的 x 字段(时间)
-      yprop: param, // 对应图表数据的 y 字段(参数值)
-      color: paramColorMap.value[param],
-      smooth: true,
-      symbol: 'circle',
-      symbolSize: 4,
-      yAxisIndex: index,
-    })),
-    tooltip: {
-      trigger: 'axis',
-      axisPointer: { type: 'cross' },
-      formatter: (params) => {
-        let tooltipHtml = `<div>${dayjs(params[0].axisValue).format('YYYY-MM-DD HH:mm:ss')}</div>`;
-        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 }
-  };
+    // 3. 构建图表配置(折线图类型,完善适配逻辑)
+    generatedChartConfig.value = {
+      type: 'line', // 折线图
+      clear: true, // 每次生成清空之前的图表
+      legend: { show: true, top: 10, right: 10 },
+      xAxis: [
+        {
+          type: 'category',
+          axisLabel: {
+            rotate: 30,
+            formatter: (value) => dayjs(value).format('HH:mm:ss'),
+            interval: Math.max(1, Math.floor(chartData.length / 10)), // 控制x轴标签密度
+          },
+        },
+      ],
+      yAxis: selectedParams.value.map((param) => ({
+        type: 'value',
+        name: paramLabelMap.value[param].split('(')[1].replace(')', ''), // 显示单位
+        nameTextStyle: { color: paramColorMap.value[param] },
+        axisLine: { lineStyle: { color: paramColorMap.value[param] } },
+        splitLine: { lineStyle: { opacity: 0.1 } },
+      })),
+      series: selectedParams.value.map((param, index) => ({
+        name: paramLabelMap.value[param],
+        type: 'line',
+        readFrom: '', // 适配 CustomChart 的 baseSeries 读取逻辑
+        label: paramLabelMap.value[param],
+        xprop: 'time', // 对应图表数据的 x 字段(时间)
+        yprop: param, // 对应图表数据的 y 字段(参数值)
+        color: paramColorMap.value[param],
+        smooth: true,
+        symbol: 'circle',
+        symbolSize: 4,
+        yAxisIndex: index,
+      })),
+      tooltip: {
+        trigger: 'axis',
+        axisPointer: { type: 'cross' },
+        formatter: (params) => {
+          let tooltipHtml = `<div>${dayjs(params[0].axisValue).format('YYYY-MM-DD HH:mm:ss')}</div>`;
+          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 },
+    };
 
-  // 无数据提示
-  if (chartData.length === 0) {
-    message.info('当前筛选条件下无数据');
-  }
-};
+    // 无数据提示
+    if (chartData.length === 0) {
+      message.info('当前筛选条件下无数据');
+    }
+  };
 
-// 暴露方法给父组件
-defineExpose({
-  showModal,
-  hideModal
-});
+  // 暴露方法给父组件
+  defineExpose({
+    showModal,
+    hideModal,
+  });
 </script>
 <style scoped>
-.param-selector {
-  display: flex;
-  align-items: center;
-  gap: 8px;
-  position: relative;
-}
-.tree-popup {
-  position: absolute;
-  top: 100%;
-  left: 0;
-  margin-top: 8px;
-  width: 300px;
-  max-height: 300px;
-  overflow-y: auto;
-  background: #fff;
-  border: 1px solid #e8e8e8;
-  border-radius: 4px;
-  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
-  z-index: 100;
-  padding: 8px;
-}
-.filter-area {
-  display: flex;
-  flex-wrap: wrap;
-  gap: 16px;
-  margin-bottom: 20px;
-  padding: 20px;
-  border: 1px solid #f0f0f0;
-  border-radius: 10px;
-  background: #f8f9fc;
-  align-items: center;
-}
-.filter-section {
-  display: flex;
-  align-items: center;
-  gap: 8px;
-}
-.filter-label {
-  color: #666;
-  min-width: 80px;
-  flex-shrink: 0;
-  font-weight: 500;
-}
-.param-section {
-  flex: 1;
-  min-width: 300px;
-}
-.chart-area {
-  display: flex;
-  flex-wrap: wrap;
-  gap: 16px;
-  padding: 20px;
-  border: 1px solid #f0f0f0;
-  border-radius: 10px;
-  background: #f8f9fc;
-}
-.chart-item {
-  flex: 1;
-  min-width: 200px;
-}
-.chart-title {
-  font-size: 16px;
-  font-weight: 500;
-  margin-bottom: 12px;
-  color: #333;
-  display: flex;
-  align-items: center;
-  gap: 8px;
-}
-.chart-desc {
-  font-size: 12px;
-  color: #666;
-  font-weight: normal;
-}
-.chart-placeholder {
-  width: 100%;
-  height: 300px;
-  border-radius: 4px;
-  overflow: hidden;
-  background: #333;
-  border: 1px solid #eee;
-}
-.empty-chart {
-  width: 100%;
-  height: 100%;
-  display: flex;
-  align-items: center;
-  justify-content: center;
-  color: #999;
-  font-size: 14px;
-}
-@media (max-width: 1200px) {
-  .param-section {
-    min-width: 100%;
+  .param-selector {
+    display: flex;
+    align-items: center;
+    gap: 8px;
+    position: relative;
+  }
+  .tree-popup {
+    position: absolute;
+    top: 100%;
+    left: 0;
     margin-top: 8px;
+    width: 300px;
+    max-height: 300px;
+    overflow-y: auto;
+    background: #fff;
+    border: 1px solid #e8e8e8;
+    border-radius: 4px;
+    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
+    z-index: 100;
+    padding: 8px;
   }
   .filter-area {
-    gap: 12px;
+    display: flex;
+    flex-wrap: wrap;
+    gap: 16px;
+    margin-bottom: 20px;
+    padding: 20px;
+    border: 1px solid #f0f0f0;
+    border-radius: 10px;
+    background: #f8f9fc;
+    align-items: center;
+  }
+  .filter-section {
+    display: flex;
+    align-items: center;
+    gap: 8px;
+  }
+  .filter-label {
+    color: #666;
+    min-width: 80px;
+    flex-shrink: 0;
+    font-weight: 500;
+  }
+  .param-section {
+    flex: 1;
+    min-width: 300px;
+  }
+  .chart-area {
+    display: flex;
+    flex-wrap: wrap;
+    gap: 16px;
+    padding: 20px;
+    border: 1px solid #f0f0f0;
+    border-radius: 10px;
+    background: #f8f9fc;
+  }
+  .chart-item {
+    flex: 1;
+    min-width: 200px;
+  }
+  .chart-title {
+    font-size: 16px;
+    font-weight: 500;
+    margin-bottom: 12px;
+    color: #333;
+    display: flex;
+    align-items: center;
+    gap: 8px;
+  }
+  .chart-desc {
+    font-size: 12px;
+    color: #666;
+    font-weight: normal;
+  }
+  .chart-placeholder {
+    width: 100%;
+    height: 300px;
+    border-radius: 4px;
+    overflow: hidden;
+    background: #333;
+    border: 1px solid #eee;
+  }
+  .empty-chart {
+    width: 100%;
+    height: 100%;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    color: #999;
+    font-size: 14px;
+  }
+  @media (max-width: 1200px) {
+    .param-section {
+      min-width: 100%;
+      margin-top: 8px;
+    }
+    .filter-area {
+      gap: 12px;
+    }
   }
-}
-</style>
+</style>

+ 160 - 185
src/views/monitor/sealedMonitor/components/RealtimeDetailsModal.vue

@@ -1,24 +1,10 @@
 <template>
-  <Modal
-    v-model:open="visible"
-    title="密闭监测详情"
-    width="1200px"
-    @ok="handleOk"
-    @cancel="handleCancel"
-    prefixCls="custom-modal"
-  >
+  <Modal v-model:open="visible" title="密闭监测详情" width="1200px" @ok="handleOk" @cancel="handleCancel" prefixCls="custom-modal">
     <!-- 基础信息栏(修改布局:每行4列,共两行) -->
     <div class="base-info">
-      <div 
-        v-for="(item, index) in modalDetailsData.basicInfo" 
-        :key="index" 
-        class="info-item"
-      >
+      <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)"
-        >
+        <span class="value" :class="getBasicInfoTagClass(item.value)">
           {{ item.value }}
         </span>
       </div>
@@ -26,14 +12,7 @@
 
     <!-- 监测数据卡片 -->
     <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="item.value" layout="val-top" />
     </div>
 
     <!-- 图表区域 -->
@@ -41,18 +20,15 @@
       <div class="chart-item">
         <div class="chart-title">爆炸三角形</div>
         <div class="chart-placeholder">
-          <BlastDelta 
-            :posMonitor="modalDetailsData.demoBlastData"
-            canvasSize="{ width: 95%, height: 95% }" />
-          
+          <BlastDelta :posMonitor="modalDetailsData.demoBlastData" canvasSize="{ width: 95%, height: 95% }" />
         </div>
       </div>
       <div class="chart-item">
         <div class="chart-title">气体浓度曲线</div>
         <div class="chart-placeholder">
-          <CustomChart 
-            :chart-data="modalDetailsData.gasConcentrationData" 
-            :chart-config="modalDetailsData.gasConcentrationConfig" 
+          <CustomChart
+            :chart-data="modalDetailsData.gasConcentrationData"
+            :chart-config="modalDetailsData.gasConcentrationConfig"
             style="height: 100%; width: 100%"
           />
         </div>
@@ -60,11 +36,11 @@
       <div class="chart-item">
         <div class="chart-title">内外压力及压差曲线</div>
         <div class="chart-placeholder">
-          <CustomChart 
-          :chart-data="modalDetailsData.pressureData" 
-          :chart-config="modalDetailsData.pressureConfig" 
-          style="height: 100%; width: 100%"
-        />
+          <CustomChart
+            :chart-data="modalDetailsData.pressureData"
+            :chart-config="modalDetailsData.pressureConfig"
+            style="height: 100%; width: 100%"
+          />
         </div>
       </div>
     </div>
@@ -72,159 +48,158 @@
 </template>
 
 <script setup>
-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 '../monitorData.data'
+  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';
 
-// 控制弹框显隐
-const visible = ref(false);
-// 外部调用显示弹框
-const showModal = () => {
-  visible.value = true;
-};
-// 外部调用隐藏弹框
-const hideModal = () => {
-  visible.value = false;
-};
+  // 控制弹框显隐
+  const visible = ref(false);
+  // 外部调用显示弹框
+  const showModal = () => {
+    visible.value = true;
+  };
+  // 外部调用隐藏弹框
+  const hideModal = () => {
+    visible.value = false;
+  };
 
-// 确定按钮回调
-const handleOk = () => {
-  visible.value = false;
-  // 可添加确定后的业务逻辑
-};
-// 取消按钮回调
-const handleCancel = () => {
-  visible.value = false;
-};
+  // 确定按钮回调
+  const handleOk = () => {
+    visible.value = false;
+    // 可添加确定后的业务逻辑
+  };
+  // 取消按钮回调
+  const handleCancel = () => {
+    visible.value = false;
+  };
 
-// 获取基础信息value对应的标签样式类
-const getBasicInfoTagClass = (value) => {
-  switch (value) {
-    case '闭内气体涌出':
-      return 'tag-danger';
-    case '低风险':
-      return 'tag-primary';
-    case '不可启封':
-      return 'tag-warning';
-    default:
-      return '';
-  }
-};
-// 暴露方法给父组件
-defineExpose({
-  showModal,
-  hideModal
-});
+  // 获取基础信息value对应的标签样式类
+  const getBasicInfoTagClass = (value) => {
+    switch (value) {
+      case '闭内气体涌出':
+        return 'tag-danger';
+      case '低风险':
+        return 'tag-primary';
+      case '不可启封':
+        return 'tag-warning';
+      default:
+        return '';
+    }
+  };
+  // 暴露方法给父组件
+  defineExpose({
+    showModal,
+    hideModal,
+  });
 </script>
 
 <style scoped>
+  .base-info {
+    display: grid;
+    grid-template-columns: repeat(4, 1fr); /* 强制每行4列 */
+    grid-template-rows: auto auto; /* 两行自动高度 */
+    gap: 16px 12px; /* 行列间距(行间距16px,列间距12px) */
+    margin-bottom: 20px;
+    padding: 20px;
+    border: 1px solid #f0f0f0;
+    border-radius: 10px;
+    background: #f8f9fc;
+  }
+  .info-item {
+    display: flex;
+    align-items: center;
+    /* 适配文字过长的情况 */
+    white-space: nowrap;
+    overflow: hidden;
+    text-overflow: ellipsis;
+  }
+  .label {
+    color: #666;
+    margin-right: 8px;
+    min-width: 80px;
+    flex-shrink: 0; /* 标签宽度不收缩 */
+  }
+  .value {
+    color: #333;
+    flex: 1;
+    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;
+  }
 
-.base-info {
-  display: grid;
-  grid-template-columns: repeat(4, 1fr); /* 强制每行4列 */
-  grid-template-rows: auto auto; /* 两行自动高度 */
-  gap: 16px 12px; /* 行列间距(行间距16px,列间距12px) */
-  margin-bottom: 20px;
-  padding: 20px;
-  border: 1px solid #f0f0f0;
-  border-radius: 10px;
-  background: #f8f9fc;
-}
-.info-item {
-  display: flex;
-  align-items: center;
-  /* 适配文字过长的情况 */
-  white-space: nowrap;
-  overflow: hidden;
-  text-overflow: ellipsis;
-}
-.label {
-  color: #666;
-  margin-right: 8px;
-  min-width: 80px;
-  flex-shrink: 0; /* 标签宽度不收缩 */
-}
-.value {
-  color: #333;
-  flex: 1;
-  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-radius: 10px;
-  background: #f8f9fc;
-}
-.data-card {
-  background: #fafafa;
-  border-radius: 8px;
-  padding: 12px;
-  text-align: center;
-}
-.card-value {
-  font-size: 20px;
-  font-weight: bold;
-  color: #1890ff;
-  margin-bottom: 4px;
-}
-.card-label {
-  font-size: 14px;
-  color: #666;
-}
+  .data-cards {
+    display: grid;
+    grid-template-columns: repeat(8, 1fr);
+    gap: 16px;
+    margin-bottom: 20px;
+    padding: 20px;
+    border: 1px solid #f0f0f0;
+    border-radius: 10px;
+    background: #f8f9fc;
+  }
+  .data-card {
+    background: #fafafa;
+    border-radius: 8px;
+    padding: 12px;
+    text-align: center;
+  }
+  .card-value {
+    font-size: 20px;
+    font-weight: bold;
+    color: #1890ff;
+    margin-bottom: 4px;
+  }
+  .card-label {
+    font-size: 14px;
+    color: #666;
+  }
 
-.chart-area {
-  display: flex;
-  flex-wrap: wrap;
-  gap: 16px;
-  padding: 20px;
-  border: 1px solid #f0f0f0;
-  border-radius: 10px;
-  /* background: black; */
-  background: #f8f9fc;
-}
-.chart-item {
-  flex: 1;
-  min-width: 200px;
-}
-.chart-title {
-  font-size: 14px;
-  font-weight: 500;
-  margin-bottom: 8px;
-  color: #333;
-}
-.chart-placeholder {
-  width: 100%;
-  height: 150px;
-  border-radius: 4px;
-  overflow: hidden;
-}
-.chart-placeholder img {
-  width: 100%;
-  height: 100%;
-  object-fit: cover;
-}
-</style>
+  .chart-area {
+    display: flex;
+    flex-wrap: wrap;
+    gap: 16px;
+    padding: 20px;
+    border: 1px solid #f0f0f0;
+    border-radius: 10px;
+    /* background: black; */
+    background: #f8f9fc;
+  }
+  .chart-item {
+    flex: 1;
+    min-width: 200px;
+  }
+  .chart-title {
+    font-size: 14px;
+    font-weight: 500;
+    margin-bottom: 8px;
+    color: #333;
+  }
+  .chart-placeholder {
+    width: 100%;
+    height: 150px;
+    border-radius: 4px;
+    overflow: hidden;
+  }
+  .chart-placeholder img {
+    width: 100%;
+    height: 100%;
+    object-fit: cover;
+  }
+</style>

+ 62 - 55
src/views/monitor/sealedMonitor/index.vue

@@ -1,35 +1,36 @@
 <template>
-  <div class="monitoring-page">
-    <!-- 新增Tabs组件区分实时/历史数据 -->
-    <Tabs v-model:activeKey="activeTab" type="card" style="margin-bottom: 16px">
-      <TabPane tab="实时数据监测" key="realtime">
-        <!-- 实时数据表格 -->
-        <BasicTable @register="registerRealtimeTable" :scroll="{ x: 'max-content' }">
-          <template #action="{ record }">
-            <button @click="openModal(record, 'realtime')" class="action-btn">
-              <SvgIcon name="details" />
-            </button>
-          </template>
-        </BasicTable>
-      </TabPane>
+  <!-- 新增Tabs组件区分实时/历史数据 -->
+  <Tabs v-model:activeKey="activeTab" class="monitoring-page" type="line">
+    <TabPane tab="实时数据监测" key="realtime">
+      <!-- 实时数据表格 -->
+      <BasicTable style="padding: 0" @register="registerRealtimeTable">
+        <template #action="{ record }">
+          <button @click="openModal(record, 'realtime')" class="action-btn">
+            <SvgIcon name="details" />
+          </button>
+        </template>
+      </BasicTable>
+    </TabPane>
 
-      <TabPane tab="历史数据监测" key="history">
-        <!-- 历史数据表格 -->
-        <BasicTable @register="registerHistoryTable" :scroll="{ x: 'max-content' }">
-          <template #action="{ record }">
-            <button @click="openModal(record, 'history')" class="action-btn">
-              <SvgIcon name="details" />
-            </button>
-          </template>
-        </BasicTable>
-      </TabPane>
-    </Tabs>
+    <TabPane tab="历史数据监测" key="history">
+      <!-- 历史数据表格 -->
+      <BasicTable style="padding: 0" @register="registerHistoryTable">
+        <template #afterReset>
+          <a-button type="primary" @click="onExportXls">导出</a-button>
+        </template>
+        <template #action="{ record }">
+          <button @click="openModal(record, 'history')" class="action-btn">
+            <SvgIcon name="details" />
+          </button>
+        </template>
+      </BasicTable>
+    </TabPane>
+  </Tabs>
 
-    <!-- 实时数据详情弹框 -->
-    <realtimeDetailsModal ref="realtimeModalRef" />
-    <!-- 历史数据详情弹框 -->
-    <HistoricalDetailsModal ref="historyModalRef" />
-  </div>
+  <!-- 实时数据详情弹框 -->
+  <realtimeDetailsModal ref="realtimeModalRef" />
+  <!-- 历史数据详情弹框 -->
+  <HistoricalDetailsModal ref="historyModalRef" />
 </template>
 
 <script setup lang="ts">
@@ -37,61 +38,65 @@
   import { BasicTable, useTable } from '/@/components/Table';
   import { Tabs, TabPane } from 'ant-design-vue';
   // 引入模拟数据
-  import { columns, searchFormSchema, minesData, historicalColumns, historicalFormSchema, historicalMinesData } from './monitorData.data';
+  import { columns, searchFormSchema, minesData, historicalColumns, historicalFormSchema, historicalMinesData } 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';
 
   // 激活的Tab页签
   const activeTab = ref('realtime');
 
   // 注册实时数据表格
-  const [registerRealtimeTable] = useTable({
-    dataSource: minesData,
+  const [registerRealtimeTable, { getForm }] = useTable({
+    api: getGoafData,
+    beforeFetch(params) {},
     columns,
     formConfig: {
       labelWidth: 120,
       schemas: searchFormSchema,
       showAdvancedButton: false,
+      schemaGroupNames: ['常规查询'],
     },
     pagination: false,
-    striped: false,
     useSearchForm: true,
-    bordered: true,
     showIndexColumn: false,
     canResize: false,
+    scroll: { x: 'max-content' },
     actionColumn: {
       width: 60,
       title: '操作',
       dataIndex: 'action',
       slots: { customRender: 'action' },
-      fixed: undefined,
     },
   });
 
   // 注册历史数据表格
-  const [registerHistoryTable] = useTable({
-    dataSource: historicalMinesData,
-    columns: historicalColumns,
-    formConfig: {
-      labelWidth: 120,
-      schemas: historicalFormSchema, // 使用历史数据的搜索配置
-      showAdvancedButton: false,
+  const { tableContext, onExportXls } = useListPage({
+    tableProps: {
+      api: getGoafHistory,
+      beforeFetch(params) {},
+      columns: historicalColumns,
+      formConfig: {
+        labelWidth: 120,
+        schemas: historicalFormSchema, // 使用历史数据的搜索配置
+        showAdvancedButton: false,
+        schemaGroupNames: ['常规查询'],
+      },
+      useSearchForm: true,
+      bordered: true,
+      showIndexColumn: false,
+      canResize: false,
+      scroll: { x: 'max-content' },
     },
-    pagination: false,
-    striped: false,
-    useSearchForm: true,
-    bordered: true,
-    showIndexColumn: false,
-    canResize: false,
-    actionColumn: {
-      width: 60,
-      title: '操作',
-      dataIndex: 'action',
-      slots: { customRender: 'action' },
-      fixed: undefined,
+    exportConfig: {
+      url: '/province/alarm/exportProvinceAlarmHistory',
+      name: '历史数据',
     },
+    pagination: true,
   });
+  const [registerHistoryTable] = tableContext;
 
   // 弹窗引用
   const realtimeModalRef = ref(null);
@@ -111,7 +116,9 @@
 
 <style lang="less" scoped>
   .monitoring-page {
-    padding: 16px;
+    padding: 0 12px;
+    margin: 16px;
+    border: 1px solid @border-color-base;
   }
 
   .action-btn {

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

@@ -0,0 +1,13 @@
+import { defHttp } from '/@/utils/http/axios';
+
+enum Api {
+  getGoafData = '/province/device/getGoafData',
+  getGoafHistory = '/province/device/getGoafHistory',
+}
+
+export function getGoafData(params: any) {
+  return defHttp.post({ url: Api.getGoafData, params });
+}
+export function getGoafHistory(params: any) {
+  return defHttp.get({ url: Api.getGoafHistory, params });
+}

+ 428 - 85
src/views/monitor/sealedMonitor/monitorData.data.ts → src/views/monitor/sealedMonitor/monitor.data.ts

@@ -1,3 +1,5 @@
+import dayjs from 'dayjs';
+import { getMineData } from '../../system/algorithm/algorithm.api';
 import { BasicColumn } from '/@/components/Table';
 import { FormSchema } from '/@/components/Table';
 import { TreeItem } from '/@/components/Tree/index';
@@ -76,10 +78,22 @@ export const columns: BasicColumn[] = [
 
 export const searchFormSchema: FormSchema[] = [
   {
-    field: 'mineName',
+    field: 'mineCode',
     label: '煤矿名称',
-    component: 'Input',
+    component: 'ApiSelect',
     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',
@@ -173,10 +187,10 @@ export const minesData = [
     explosionHazard: '低风险', // 爆炸危险性
     updateTime: '2025-11-17 15:00:40', // 更新时间
   },
-]
+];
 
-export const modalDetailsData:{} = {
-  basicInfo:[
+export const modalDetailsData: {} = {
+  basicInfo: [
     {
       label: '煤矿名称',
       value: '神木市三江能源有限公司',
@@ -244,42 +258,52 @@ export const modalDetailsData:{} = {
       value: '14',
     },
   ],
-  demoBlastData:{
+  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 :{
+      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', 
-      name: '时间', 
-      axisLabel: {color: '#000000'}, 
-      nameTextStyle: { color: '#000' },
-    }],
-    yAxis: [{ 
-      type: 'value',
-      show: true, 
-      name: '浓度(%)',
-      splitLine: { show: false },
-      axisLine: {
+    xAxis: [
+      {
+        type: 'category',
+        dataKey: 'time',
+        name: '时间',
+        axisLabel: { color: '#000000' },
+        nameTextStyle: { color: '#000' },
+      },
+    ],
+    yAxis: [
+      {
+        type: 'value',
         show: true,
-        lineStyle: { color: '#333' }
+        name: '浓度(%)',
+        splitLine: { show: false },
+        axisLine: {
+          show: true,
+          lineStyle: { color: '#333' },
+        },
+        axisLabel: { color: '#000000' },
+        nameTextStyle: { color: '#000' },
       },
-      axisLabel: {color: '#000000'}, 
-      nameTextStyle: { color: '#000' },    }],
+    ],
     series: [
       {
         label: '气体浓度',
@@ -290,19 +314,20 @@ export const modalDetailsData:{} = {
       },
     ],
   },
-  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 },
-  ]},
-  pressureConfig:{
+  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 },
+    ],
+  },
+  pressureConfig: {
     type: 'line', // 使用普通折线图类型
-    legend: { show: true,color:'#000000' },
+    legend: { show: true, color: '#000000' },
     xAxis: [{ type: 'category', dataKey: 'time', name: '时间', axisLabel: { color: '#000000' } }],
     yAxis: [{ show: true, name: '压力(kPa)', axisLabel: { color: '#000000' } }],
     series: [
@@ -311,18 +336,18 @@ export const modalDetailsData:{} = {
       { label: '压力差', readFrom: 'chartdata', xprop: 'time', yprop: 'diff' },
     ],
   },
-  pressureData:{
+  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},
-    ]
-  }
-}
+      { 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 },
+    ],
+  },
+};
 
 // 历史数据相关
 export const historicalColumns: BasicColumn[] = [
@@ -398,7 +423,7 @@ export const historicalColumns: BasicColumn[] = [
 
 export const historicalFormSchema: FormSchema[] = [
   {
-    field: 'mineName',
+    field: 'mineCode',
     label: '煤矿名称',
     component: 'Input',
     colProps: { span: 6 },
@@ -449,7 +474,7 @@ export const historicalFormSchema: FormSchema[] = [
     colProps: { span: 6 },
   },
   {
-    field: 'sealedName',
+    field: 'goafId',
     label: '密闭名称',
     component: 'Select',
     componentProps: {
@@ -461,6 +486,24 @@ export const historicalFormSchema: FormSchema[] = [
     },
     colProps: { span: 6 },
   },
+  {
+    field: 'startTime ',
+    label: '起始日期',
+    component: 'DatePicker',
+    componentProps: {
+      defaultPickerValue: dayjs().add(-1, 'day'),
+    },
+    colProps: { span: 6 },
+  },
+  {
+    field: 'endTime ',
+    label: '结束日期',
+    component: 'DatePicker',
+    componentProps: {
+      defaultPickerValue: dayjs(),
+    },
+    colProps: { span: 6 },
+  },
 ];
 
 export const historicalMinesData = [
@@ -521,7 +564,7 @@ export const historicalMinesData = [
     explosionHazard: '低风险', // 爆炸危险性
     updateTime: '2025-12-22 15:00:40', // 更新时间
   },
-]
+];
 
 export const treeData: TreeItem[] = [
   {
@@ -552,29 +595,329 @@ 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.10, CO2: 0.85, O2: 19.5, innerPressure: 101.32, outerPressure: 101.10, 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.20, 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.30, 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.60, 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.30, pressureDiff: 0.26, temperature: 34.7 },
-  { time: '2025-12-22 14:00:00', CO: 25.7, CH4: 0.20, 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.20, 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.50, 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.20, 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 },
+  {
+    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,
+  },
 ];