487cc9bad146b1bcd86910746a341ef3455fb579..c353554427f56eeda8a7cb75cc12bfa572dd1c85
12 小时以前 he wei
U 大小写问题
c35355 对比 | 目录
12 小时以前 he wei
U 整理提交
011aab 对比 | 目录
12个文件已修改
2个文件已添加
2684 ■■■■ 已修改文件
package-lock.json 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
package.json 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/alarm.js 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/realtime.js 38 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/echarts/BaseChart.vue 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/echarts/line-scroll.vue 57 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/echarts/line-yj.vue 173 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/echarts/line1.vue 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/echarts/line2.vue 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/alarm/earlyWarningAnalysis.vue 1605 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/history/index.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/realtime/index.vue 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/realtime/tabs/system.vue 190 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/statistics/battCompare0_.vue 546 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
package-lock.json
@@ -24,6 +24,7 @@
        "path-browserify": "^1.0.1",
        "pinia": "^2.1.7",
        "pinyin-match": "^1.2.8",
        "tree-transfer-vue3": "^1.2.2",
        "vue": "^3.5.13",
        "vue-router": "^4.3.3",
        "xlsx": "^0.18.5"
@@ -5847,6 +5848,16 @@
        "url": "https://github.com/sponsors/ljharb"
      }
    },
    "node_modules/tree-transfer-vue3": {
      "version": "1.2.2",
      "resolved": "https://registry.npmmirror.com/tree-transfer-vue3/-/tree-transfer-vue3-1.2.2.tgz",
      "integrity": "sha512-+jBDjXeHSay9PcKJqVwluHWaM6dlnLDtJGhsZ9bp7FKTYA7hNV13/amDjlsHY8OO675/ysrvBm1wJBtNvfKQVQ==",
      "license": "ISC",
      "dependencies": {
        "element-plus": "^2.8.7",
        "vue": "^3.5.12"
      }
    },
    "node_modules/tslib": {
      "version": "2.3.0",
      "resolved": "https://registry.npmmirror.com/tslib/-/tslib-2.3.0.tgz",
package.json
@@ -25,6 +25,7 @@
    "path-browserify": "^1.0.1",
    "pinia": "^2.1.7",
    "pinyin-match": "^1.2.8",
    "tree-transfer-vue3": "^1.2.2",
    "vue": "^3.5.13",
    "vue-router": "^4.3.3",
    "xlsx": "^0.18.5"
src/api/alarm.js
@@ -207,3 +207,26 @@
    params
  });
}
/**
 * 预警分析管理-查询时间间隔
 */
export function getAlarmAnalysisCycle() {
  return request({
    url: "analysis/getAlarmAnalysisCycle",
    method: "GET"
  });
}
/**
 * 预警分析管理-设置时间间隔
 */
export function updateAlarmAnalysisCycle(intervalTime) {
  return request({
    url: "analysis/updateAlarmAnalysisCycle",
    method: "GET",
    params: {
      intervalTime
    }
  });
}
src/api/realtime.js
@@ -1,40 +1,37 @@
import request from '@/utils/request';
/**
 * 系统概览获取半小时核容设备信息
 * 系统概览获取核容设备信息 前100笔
 * battgroupId
 * granularity
 */
export function getHalfHourBattDevData(battgroupId, granularity) {
export function getBattDevData100(battgroupId, powerId) {
  return request({
    url: 'real/getHalfHourBattDevData',
    url: 'real/getBattDevData100',
    method: 'GET',
    params: { battgroupId, granularity }
    params: { battgroupId, powerId }
  });
}
/**
 * 系统概览获取半小时交流输入统计
 * 系统概览获取交流输入统计 前100笔
 * powerId
 * granularity
 */
export function getHalfHourPwrHisAcinData(powerId, granularity) {
export function getPwrHisAcinData100(powerId) {
  return request({
    url: 'real/getHalfHourPwrHisAcinData',
    url: 'real/getPwrHisAcinData100',
    method: 'GET',
    params: { powerId, granularity }
    params: { powerId }
  });
}
/** 系统概览获取半小时直流输出统计
/** 系统概览获取直流输出统计 前100笔
 * powerId
 * granularity
 */
export function getHalfHourPwrHisDcoutData(powerId, granularity) {
export function getPwrHisDcoutData100(powerId) {
  return request({
    url: 'real/getHalfHourPwrHisDcoutData',
    url: 'real/getPwrHisDcoutData100',
    method: 'GET',
    params: { powerId, granularity }
    params: { powerId }
  });
}
@@ -69,4 +66,15 @@
    method: 'GET',
    params: { battgroupId }
  });
}
/**
 * 电源心跳参数
 */
export function getPwrHeartParam(powerId) {
  return request({
    url: 'pwrHeart/getPwrHeartParam',
    method: 'GET',
    params: { powerId }
  });
}
src/components/echarts/BaseChart.vue
@@ -21,6 +21,13 @@
const fullScreenFlag = ref(props.fullFlag);
function busHandler() {
  setTimeout(() => {
    resize();
    // 因为过渡设置了0.5s,所以需要等待0.5s后再resize
  }, 580);
}
  onMounted(() => {
    console.log('base mounted',chart.value, '=============');
@@ -34,20 +41,13 @@
    });
    window.addEventListener("resize", resize);
    eventBus.on("toggleSiteList", () => {
      console.log('toggleSiteList', '=============');
      setTimeout(() => {
        resize();
        // 因为过渡设置了0.5s,所以需要等待0.5s后再resize
      }, 500);
    });
    eventBus.on("toggleSiteList", busHandler);
  });
  onBeforeUnmount(() => {
    window.removeEventListener("resize", resize);
    eventBus.off("toggleSiteList");
    eventBus.off("toggleSiteList", busHandler);
    dispose();
  });
@@ -97,6 +97,8 @@
  }
  function resize() {
    console.log('resize', chart_instance, '=============');
    if (chart_instance) {
      chart_instance.resize();
    }
@@ -149,6 +151,7 @@
/* chart wrapper css */
.e-chart-root,
.e-chart {
  width: 100%;
  height: 100%;
  box-sizing: border-box;
}
src/components/echarts/line-scroll.vue
@@ -80,8 +80,9 @@
    function makeGrid(top, opt) {
        let res = echarts.util.merge({
            top: top + '%',
            height: gridHeight + '%',
            left: 60,
            height: gridHeight - 0.5 + '%',
      bottom: top + gridHeight - 0.5 + '%',
            left: 90,
            right: 14,
        }, opt || {}, true);
    return JSON.parse(JSON.stringify(res));
@@ -98,18 +99,26 @@
                smooth: true,
                symbol: 'circle',
                symbolSize: 5,
                showSymbol: false,
                showSymbol: true,
        xAxisIndex: idx,
        yAxisIndex: idx,
        gridIndex: idx,
        seriesIndex: idx,
        // 禁用动画,确保立即渲染
        animation: false,
        // silent: true,
                lineStyle: {
                    width: 1
                },
                data: datas[idx],
        tooltip: {
          show: true,
        },
                data: datas[idx].map(v => v + 3),
            });
        });
        return JSON.parse(JSON.stringify(res));
        // return JSON.parse(JSON.stringify(res));
    return res;
    }
  let lastXLabels = [];
@@ -121,8 +130,8 @@
      nextTick(() => {
        chart.value.setOption(getOptions(lastXLabels, lastDatas));
      });
    }
  )
    },
  );
    function getOptions(xLabels, datas) {
@@ -152,23 +161,29 @@
              color: '#fff'
            }
          },
      } : { show: false };
      } : { axisLine: { show: false }};
      xAxis.push(makeXAxis(i, xAxisOption));
      yAxis.push(makeYAxis(i, {
                    name: props.yLabels.length ? props.yLabels[i].replace(/(#)/g, '$1\n').replace(/\n$/, '') : '',
                }));
        name: props.yLabels.length ? props.yLabels[i] : '',
      }));
    }
        const option = {
      animation: false,
      color: ['#1186ce', '#e5c619', '#1d1dfd', '#2dbfae'],
            tooltip: {
                trigger: 'axis',
        // 强制显示所有系列
        alwaysShowContent: true,
                axisPointer: {
          snap: true,
                    lineStyle: {
                        color: '#fff'
                    }
                },
        formatter: function (params) {
          // console.log('params:', params);
          // console.log('捕获的seriesIndex:', params.map(p => p.seriesIndex));
                    if (params.length) {
            // params.unshift({ seriesName: 'time', value: params[0].name, color: '#5193f2' })
            let _label = '';
@@ -187,7 +202,7 @@
                        });
            res.push('<span style="color: #000">' + _label + '</span>');
            res = res.join('<br>');
            // console.log('res', res, '=============');
            // console.log('res', res, params, '=====tooltip========', series, datas, xLabels[xLabels.length - 1]);
            return res;
            
                    }
@@ -206,12 +221,15 @@
            series
        };
    console.log('option', option, '=============');
    // console.log('option', option, '=======dcout======');
    
        return option;
    }
  let myChart = null;
  const startIndex = computed(() => {
    return Math.floor(props.startIdx);
  });
    function initChart() {
        if (chart.value) {
@@ -227,18 +245,25 @@
            let option = getOptions(xLabels, datas);
      // chart.value.setOption(option, {notMerge: true});
      chart.value.setOption(option);
      // tooltip Bug 重新渲染了一下 就没问题了
      if (props.startIdx == 0) {
        nextTick(() => {
          emit('scroll', 0.1);
        });
      }
        }
    }
  function scrollToTop() {
    if (props.startIdx > 0) {
    if (startIndex.value > 0) {
      emit('scroll', -1);      
    }
    
  }
  function scrollToBottom() {
    if (props.startIdx < props.modeCount - 4) {
    if (startIndex.value < props.modeCount - 4) {
      nextTick(() => {
        emit('scroll', 1);
      });
@@ -261,10 +286,10 @@
    <base-chart ref="chart" v-model:fullFlag="fullFlag" :key="startIdx">
      <template #tools v-if="modeCount > 4">
        <div class="t-contain">
          <div :class="['btn', 'btn-top', {disabled: startIdx == 0}]" @click="scrollToTop">
          <div :class="['btn', 'btn-top', {disabled: startIndex <= 0}]" @click="scrollToTop">
            <svg-icon icon-class="arrow-right" ></svg-icon>
          </div>
          <div :class="['btn', 'btn-bottom', {disabled: startIdx == modeCount - 4}]" @click="scrollToBottom">
          <div :class="['btn', 'btn-bottom', {disabled: startIndex == modeCount - 4}]" @click="scrollToBottom">
            <svg-icon icon-class="arrow-right" ></svg-icon>
          </div>
        </div>
src/components/echarts/line-yj.vue
New file
@@ -0,0 +1,173 @@
<script setup>
    import { onMounted, ref, watchEffect, nextTick, onBeforeUnmount } from "vue";
    import * as echarts from 'echarts';
  import baseChart from "./BaseChart.vue";
  import { toFixed } from '@/utils/toFixed.js';
  const chart = ref(null);
  const props = defineProps({
    title: {
      type: String,
      default: ''
    },
    unit: {
      type: String,
      default: ''
    }
  });
  function getMax(data) {
    let max = Math.max.apply(null, data) * 1.2;
    return toFixed(max, 1) || 1;
  }
 function getOptions(xLabels, datas, mark) {
    xLabels = xLabels || [];
    datas = datas || [];
    mark = mark || '';
        const option = {
      animation: false,
            // title: {
            //     text: props.title,
            //     textStyle: {
            //         fontWeight: 'normal',
            //         fontSize: 14,
            //         color: '#fff'
            //     },
            //     left: '6%'
            // },
            tooltip: {
                trigger: 'axis',
                axisPointer: {
                    lineStyle: {
                        color: '#fff'
                    }
                }
            },
            grid: {
                left: '3%',
                right: '4%',
                bottom: '3%',
        top: 30,
                containLabel: true
            },
            xAxis: [{
                type: 'category',
                // boundaryGap: false,
                axisLine: {
                    lineStyle: {
                        color: '#fff'
                    }
                },
                data: xLabels
            }],
            yAxis: [{
                type: 'value',
                name: props.unit,
                axisTick: {
                    show: true,
                },
                axisLine: {
          show: true,
                    lineStyle: {
                        color: '#fff'
                    }
                },
                axisLabel: {
                    margin: 10,
                    fontSize: 12,
          color: '#fff'
                },
                splitLine: {
                    lineStyle: {
                        color: 'rgba(255,255,255,0.2)'
                    }
                },
        max: getMax(datas),
            }],
            series: [{
                // name: props.type,
                type: 'line',
                smooth: true,
                symbol: 'circle',
                symbolSize: 5,
                showSymbol: false,
                lineStyle: {
          width: 1
                },
         // 添加标记线
        markLine: {
          data: [
            {
              name: '告警分界线',
              xAxis: mark,
              lineStyle: {
                color: 'red',
                type: 'dashed'
              },
              label: {
                position: 'end',
                formatter: '告警分界线',
                color: 'red'
              },
              animation: false,
            }
          ]
        },
                data: datas
            }]
        };
        return option;
    }
  let myChart = null;
  let chart_instance = null;
    function initChart() {
        if (chart.value) {
            // myChart = chart.value.getChart();
            let option = getOptions();
      chart.value.setOption(option);
      chart_instance = chart.value.getChart();
        }
    }
    function updateChart(xLabels, datas, mark) {
    if (chart.value) {
            let option = getOptions(xLabels, datas, mark);
      chart.value.setOption(option);
        }
    }
  function getChart() {
    return chart_instance;
  }
  defineExpose({
    getChart,
    updateChart
  });
    onMounted(() => {
    // console.log('line mounted', '=============');
        initChart();
    });
</script>
<template>
  <div class="line-chart">
    <base-chart ref="chart"></base-chart>
  </div>
</template>
<style scoped>
.line-chart {
  width: 100%;
  height: 100%;
}
</style>
src/components/echarts/line1.vue
@@ -51,6 +51,7 @@
        return [series, xlabels];
    }
 function getOptions(labels, datas) {
    labels = labels || [];
    datas = datas || [];
src/components/echarts/line2.vue
@@ -62,7 +62,8 @@
        return echarts.util.merge({
            top: top + '%',
            height: gridHeight + '%',
            left: '15%',
            // left: '15%',
            left: 80,
            right: 14,
        }, opt || {}, true);
    }
@@ -203,16 +204,17 @@
            // }],
            yAxis: [
                makeYAxis(0, {
                    name: typeList[0].replace(/(.{2})/g, '$1\n').replace(/\n$/, ''),
                    // name: typeList[0].replace(/(.{2})/g, '$1\n').replace(/\n$/, ''),
                    name: typeList[0],
                }),
                makeYAxis(1, {
                    name: typeList[1].replace(/(.{2})/g, '$1\n').replace(/\n$/, ''),
                    name: typeList[1],
                }),
                makeYAxis(2, {
                    name: typeList[2].replace(/(.{2})/g, '$1\n').replace(/\n$/, ''),
                    name: typeList[2],
                }),
                makeYAxis(3, {
                    name: typeList[3].replace(/(.{2})/g, '$1\n').replace(/\n$/, ''),
                    name: typeList[3],
                })
            ],
            series
src/views/alarm/earlyWarningAnalysis.vue
@@ -10,6 +10,9 @@
import getQueryString from "@/utils/getQueryString";
import alarmParams from '@/components/pwrAlarmParams.vue';
import lineChart from '@/components/echarts/line-yj.vue';
import treeTransfer from 'tree-transfer-vue3';
import useStation from "@/hooks/useStationList.js";
const { provice, city, country, stationName, stationId, powerId,
@@ -34,6 +37,9 @@
  getBattAlmAnalyse,
  getHisRealInAlm,
  getAlmSummaryParam,
  getHisRealWithChage,
  getAlarmAnalysisCycle,
  updateAlarmAnalysisCycle,
} from "@/api/alarm.js";
import {
@@ -43,6 +49,7 @@
const { $loading, $message, $confirm } = useElement();
const flag = ref(Math.random());
const chart0 = ref(null);
const headers0 = [
@@ -73,12 +80,84 @@
  },
];
const headers1 = [
  {
    prop: "fullName",
    label: "机房名称",
    width: "220",
  },
  {
    prop: "devName",
    label: "设备名称",
    width: "80",
  },
  {
    prop: "almName",
    label: "告警名称",
    width: "160",
  },
  {
    prop: "almLevelStr",
    label: "告警等级",
    width: "120",
  },
  {
    prop: "almStartTime",
    label: "告警开始时间",
    width: "120",
  },
];
const headers2 = [
  {
    prop: "fullName",
    label: "机房名称",
    width: "220",
  },
  {
    prop: "battgroupName",
    label: "电池组名称",
    width: "80",
  },
  {
    prop: "almName",
    label: "告警名称",
    width: "160",
  },
  {
    prop: "almLevelStr",
    label: "告警等级",
    width: "120",
  },
  {
    prop: "almStartTime",
    label: "告警开始时间",
    width: "120",
  },
];
const pageNum0 = ref(1);
const pageSize0 = ref(10);
const total0 = ref(0);
const addEditVisible = ref(false);
const timeVisible = ref(false);
const dialogTitle = ref("");
const datas0 = reactive({
  tableData: [],
  rowData: {},
});
const pageNum1 = ref(1);
const pageSize1 = ref(10);
const total1 = ref(0);
const datas1 = reactive({
  tableData: [],
  rowData: {},
});
const pageNum2 = ref(1);
const pageSize2 = ref(10);
const total2 = ref(0);
const datas2 = reactive({
  tableData: [],
  rowData: {},
});
@@ -88,6 +167,8 @@
const alarmTypeList = ref([]);
const alarmId = ref('');
// 电源告警列表
function getList0() {
@@ -107,23 +188,118 @@
  getPwrtAlmAnalyse(params).then((res) => {
    let { code, data, data2 } = res;
    let list = [];
    // let _total0 = 0;
    let _total0 = 0;
    loading.close();
    if (code && data) {
      // console.log(data);
      list = data2.list.map(v => ({
        ...v,
        almLevelStr: ['', '一级告警', '二级告警', '三级告警', '四级告警'][v.almLevel],
      }));
      // _total0 = data2.total0;
      _total0 = data2.total;
    }
    datas0.tableData = list;
    // total0.value = _total0;
    total0.value = _total0;
  })
    .catch((err) => {
      console.log(err);
    });
}
// 设备告警列表
function getList1() {
  let params = {
    almIdList: alarmId.value ? [alarmId.value] : undefined,
    provice: provice.value || undefined,
    city: city.value || undefined,
    country: country.value || undefined,
    stationId: stationId.value || undefined,
    powerId: powerId.value || undefined,
    almLevel: alarmLevel.value,
    pageNum: pageNum1.value,
    pageSize: pageSize1.value,
  };
  let loading = $loading();
  getDevAlmAnalyse(params).then((res) => {
    let { code, data, data2 } = res;
    let list = [];
    let _total0 = 0;
    loading.close();
    if (code && data) {
      // console.log(data);
      list = data2.list.map(v => ({
        ...v,
        almLevelStr: ['', '一级告警', '二级告警', '三级告警', '四级告警'][v.almLevel],
      }));
      _total0 = data2.total;
    }
    datas1.tableData = list;
    console.log('list', list, '=============');
    total1.value = _total0;
  })
    .catch((err) => {
      console.log(err);
    });
}
// 电池告警列表
function getList2() {
  let params = {
    almIdList: alarmId.value ? [alarmId.value] : undefined,
    provice: provice.value || undefined,
    city: city.value || undefined,
    country: country.value || undefined,
    stationId: stationId.value || undefined,
    powerId: powerId.value || undefined,
    almLevel: alarmLevel.value,
    pageNum: pageNum2.value,
    pageSize: pageSize2.value,
  };
  let loading = $loading();
  getBattAlmAnalyse(params).then((res) => {
    let { code, data, data2 } = res;
    let list = [];
    let _total0 = 0;
    loading.close();
    if (code && data) {
      // console.log(data);
      list = data2.list.map(v => ({
        ...v,
        almLevelStr: ['', '一级告警', '二级告警', '三级告警', '四级告警'][v.almLevel],
      }));
      _total0 = data2.total;
    }
    datas2.tableData = list;
    console.log('list', list, '=============');
    total2.value = _total0;
  })
    .catch((err) => {
      console.log(err);
    });
}
async function acTabChange() {
  await nextTick();
  switch (acTab.value) {
    case 'power':
      getList0();
      break;
    case 'dev':
      getList1();
      break;
    case 'batt':
      getList2();
      break;
  }
}
const allProps = ref([]);
@@ -136,6 +312,7 @@
      list = data2;
    }
    allProps.value = list;
    formatProp(list);
}
// 查询告警类型
@@ -157,19 +334,155 @@
}
const chartRefs = ref({});
function setComponentRef (prop, el) {
  if (el) {
    chartRefs.value[prop] = el;
  } else {
    // 组件卸载时移除引用
    delete chartRefs.value[prop];
  }
};
const alarmType = ref(0);
const acTab = ref('power');
const alarmLevel = ref(1);
const currAlm = ref({});
// 当前告警的告警开始时间
const startTime = ref('');
const battList = ref([]);
const battId = ref('');
async function view(record) {
  currAlm.value = record;
  battList.value = record.binfList;
  battId.value = acTab.value == 'batt'
      ? record.battgroupId
      : record.binfList.length
      ? record.binfList[0].battgroupId
      : 0;
  getRtData();
}
const propInfo = ref({});
async function getRtData() {
  let params = {
    powerId: record.powerId,
    almId: record.almId,
    startTime: record.almStartTime,
    battgroupId: record.battgroupIdList.length ? record.battgroupIdList[0] : 0,
    powerId: currAlm.value.powerId,
    almId: currAlm.value.almId,
    startTime: currAlm.value.almStartTime,
    battgroupId: battId.value,
  }
  let res = await getHisRealInAlm(params);
  let { code, data, data2, data3, data4 } = res;
  let list = [];
  let mainProps = '主属性曲线';
  let subs = [];
  if (code && data) {
    let { batt, pwr } = data2;
    // 取出主属性 和 副属性  及对应的中文名称
    mainProps = data2[data3.main][0].dataName1;
    if (data3.main == 'pwr') {
      // batt 个数表示全部的副属性
      // pwr 要去掉第一个主属性 剩下的为副属性
      for(let i = 0, len = data3.batt; i < len; i++) {
        let idx = i + 1;
        let prop = batt[0][`dataName${idx}`];
        subs.push({prop, name: getPropName(prop), data: [], xLabels: [], valueProp: `dataValue${idx}`, from: 'batt'});
      }
      for (let j = 0, len = data3.pwr - 1; j < len; j++) {
        let idx = j + 2;
        let prop = pwr[0][`dataName${idx}`];
        subs.push({prop, name: getPropName(prop), data: [], xLabels: [], valueProp: `dataValue${idx}`, from: 'pwr'});
      }
    } else {
      for(let i = 0, len = data3.batt - 1; i < len; i++) {
        let idx = i + 2;
        let prop = batt[0][`dataName${idx}`];
        subs.push({prop, name: getPropName(prop), data: [], xLabels: [], valueProp: `dataValue${idx}`, from: 'batt'});
      }
      for (let j = 0, len = data3.pwr; j < len; j++) {
        let idx = j + 1;
        let prop = pwr[0][`dataName${idx}`];
        subs.push({prop, name: getPropName(prop), data: [], xLabels: [], valueProp: `dataValue${idx}`, from: 'pwr'});
      }
    }
    // 格式化数据
    formatData(data2, data3, subs);
    propInfo.value = data4;
  }
  subProp.value = subs;
  startTime.value = currAlm.value.almStartTime;
  name0.value = getPropName(mainProps);
  nextTick(() => {
    // 更新图表
    updateChart();
  });
}
function findClosestTime(timeArray, targetTime, format = 'YYYY-MM-DD HH:mm:ss') {
    if (!timeArray || timeArray.length === 0) return '';
    // 将目标时间转换为Moment对象
    const targetMoment = moment(targetTime, format);
    // 找出所有大于或等于目标时间的元素
    const timesAfterTarget = timeArray.filter(time =>
        moment(time, format).isSameOrAfter(targetMoment)
    );
    // 如果存在这样的元素,返回第一个
    if (timesAfterTarget.length > 0) {
        return timesAfterTarget[0];
    }
    // 若没有找到大于或等于目标时间的元素,则返回整个数组中的最后一个元素(即最接近但小于目标时间的元素)
    return timeArray[timeArray.length - 1];
}
const mainData = ref([]);
// const xLabels0 = ref([]);
// const xLabels1 = ref([]);
function formatData(data2, data3, subs) {
  let _mainData = [];
  let recordTimes = [];
  for (let i = 0, len = data2[data3.main].length; i < len; i++) {
    let item = data2[data3.main][i];
    let recordTime = item.recordTime;
    _mainData.push(item.dataValue1);
    recordTimes.push(recordTime);
    for (let j = 0, len = subs.length; j < len; j++) {
      let sub = subs[j];
      // 取属性对应的index
      let { prop, from, valueProp } = sub;
      sub.data.push(data2[from][i][valueProp]);
      sub.xLabels.push(data2[from][i].recordTime);
    }
  }
  mainData.value = {labels: recordTimes, data: _mainData};
  // xlabels.value = recordTimes;
}
function updateChart() {
  console.log('xlabels.value, mainData.value', mainData.value, '=============');
  chart0.value.updateChart(mainData.value.labels, mainData.value.data, findClosestTime(mainData.value.labels, startTime.value));
  subProp.value.forEach((v, i) => {
    chartRefs.value[v.prop].updateChart(v.xLabels, v.data, findClosestTime(v.xLabels, startTime.value));
  });
}
@@ -197,6 +510,28 @@
function handleCurrentChange0(val) {
  pageNum0.value = val;
  getList0();
}
// 展示数据数量
function handleSizeChange1(val) {
  pageSize1.value = val;
  getList1();
}
// 翻页
function handleCurrentChange1(val) {
  pageNum1.value = val;
  getList1();
}
// 展示数据数量
function handleSizeChange2(val) {
  pageSize2.value = val;
  getList2();
}
// 翻页
function handleCurrentChange2(val) {
  pageNum2.value = val;
  getList2();
}
async function exportExcelAll() {
@@ -231,26 +566,240 @@
  return name;
}
// 获取类型名称
function getTypeName(type) {
  let name = '';
  let obj = allTypes.value.filter(v => v.id == type);
  if (obj.length) {
    name = obj[0].label;
  }
  return name;
}
const name0 = ref('主属性曲线');
const subProp = ref([]);
const timeLong = ref(0);
async function getTimeSettings() {
  let res = await getAlarmAnalysisCycle();
  let { code, data, data2 } = res;
  let _time = 30;
  if (code && data) {
    _time = data2.paramValue;
  }
  timeLong.value = _time;
}
subProp.value = [1];
// subProp.value = [1, 2];
// subProp.value = [1, 2, 3];
// subProp.value = [1, 2, 3, 4];
const layout = {
  gutter: 20,
  span: 24,
};
let obj = [[1], [1, 2], [1, 2, 3], [1, 2, 3, 4]];
let i = 0;
const form1 = reactive({
  time: 0,
});
const validatorTime = (rule, value, callback) => {
    const reg = /^\d+$/;
    if (reg.test(value)) {
      if (value < 1 || value > 1440) {
        callback(new Error('范围1~1440'));
      } else {
        callback();
      }
    } else {
      callback(new Error('请输入整数'));
    }
  }
const rules = reactive({
  time: [{ required: true, message: "不能为空", trigger: ["blur", "change"] },
    { validator: validatorTime, trigger: ["blur", "change"] },
  ],
});
function setTime() {
  form1.time = timeLong.value;
  dialogTitle.value = '设置时间周期';
  timeVisible.value = true;
}
const formRef = ref();
async function timeSetOk() {
  let valid = await formRef.value.validate(() => { });
  // console.log('valid', valid, '=============');
  if (!valid) {
    $message.error("表单验证失败");
    return false;
  }
  let loading = $loading();
  let res = await updateAlarmAnalysisCycle(form1.time);
  let { code, data } = res;
  loading.close();
  if (code && data) {
    $message.success("设置成功");
    timeLong.value = form1.time;
    timeVisible.value = false;
  } else {
    $message.error("设置失败");
  }
}
const transferRef = ref();
const fromData = ref([]);
const propVisible = ref(false);
const toData = ref([]);
function setProp () {
  dialogTitle.value = '设置关注属性';
  propVisible.value = true;
  nextTick(() => {
    initSubProp(propInfo.value);
  });
}
function initSubProp (data) {
  let {
    almId,
    minorField1,
    minorField1Type,
    minorField2,
    minorField2Type,
    minorField3,
    minorField3Type,
    minorField4,
    minorField4Type,
  } = data;
  let arr = [];
  let obj = {};
  [1, 2, 3, 4].forEach((v) => {
    let prop = `minorField${v}`;
    let type = `${prop}Type`;
    if (data[prop]) {
      obj[data[type]] = obj[data[type]] || [];
      obj[data[type]].push({
        pid: data[type] + '',
        id: data[prop],
        label: getPropName(data[prop]),
        prop: data[prop],
        type: data[type],
      });
      // arr.push({
      //   pid: data[type] + '',
      //   id: data[prop],
      //   label: getPropName(data[prop]),
      //   prop: data[prop],
      //   type: data[type],
      // });
    }
  });
  Object.keys(obj).forEach((key) => {
    arr.push({
      pid: 0,
      id: key,
      label: getTypeName(key),
      children: obj[key],
    });
  });
  transferRef.value.removeToSource(false);
  transferRef.value.addToAims(false);
  toData.value = arr;
}
function propSetOk() {
}
async function add (_fromData,_toData,{ checkedKeys, checkedNodes, harfKeys, harfNodes }) {
  console.log('fromData,toData,obj', _fromData,_toData, checkedKeys, checkedNodes, harfKeys, harfNodes , '=============');
  let params = {
    battgroupId: battId.value,
    powerId: currAlm.value.powerId,
    startTime: currAlm.value.almStartTime,
  }
  let arr = [];
  _toData.forEach((v) => {
    arr.push(...v.children);
  });
  let len = arr.length;
  if (len > 4) {
    $message.error('最多设置4个属性');
    console.log('toData', _toData, toData, '=============');
    toData.value = toData.value.map(v => ({
      ...v,
      children: v.children.filter(vv => !checkedKeys.includes(vv.id))
    }));
    return false;
  }
  let i = 0;
  _toData.forEach((item) => {
    item.children.forEach((v) => {
      i++;
      params[`dataName${i}`] = v.id;
      params[`dataType${i}`] = v.pid;
    });
  });
  console.log('params', params, '=============');
  let res = await getHisRealWithChage(params);
}
function remove(fromData,toData,obj) {
  console.log('fromData,toData,obj', fromData,toData,obj, '=============');
}
const allTypes = ref([]);
function formatProp(data) {
  let obj = {};
  let res = [];
  let types = [];
  data.forEach((v) => {
    obj[v.fieldType] = obj[v.fieldType] || [];
    obj[v.fieldType].push(v);
  });
  Object.keys(obj).forEach((key) => {
    types.push({
      id: key,
      label: obj[key][0].fieldTypeName
    });
    res.push({
      id: key,
      pid: 0,
      label: obj[key][0].fieldTypeName,
      children: obj[key].map(vv => {
        return {
          ...vv,
          id: vv.fieldName,
          label: vv.fieldNameZh,
          pid: key,
        }
      })
    })
  });
  fromData.value = res;
  allTypes.value = types;
  return res;
}
onMounted(async () => {
  await getAlarmType();
  getAllProps();
  getTimeSettings();
  getList0();
  setInterval(() => {
    i++;
    i%=4;
    subProp.value.length = obj[i];
  }, 5000);
});
// onActivated(async () => {
@@ -258,10 +807,10 @@
//   // console.log('pageFlag', pageFlag, flag.value, '=============');
//   await nextTick();
//   await whenLoaded();
//   if (pageFlag && pageFlag != flag.value) {
//     // let provice, city, country, stationName, battId;
//     if (getQueryString('stationId')) {
//       let statId = getQueryString('stationId');
//       let stat = stationList.value.find(v => v.stationId == statId);
@@ -286,267 +835,736 @@
    <!-- <div class="page-header">
      </div> -->
    <div class="page-content">
      <el-tabs tab-position="left" v-model="acTab" type="card" class="main-tabs">
      <el-tabs
        tab-position="left"
        v-model="acTab"
        @tab-change="acTabChange"
        type="card"
        class="main-tabs"
      >
        <el-tab-pane name="power" class="tab-pane" label="电源告警">
          <div class="page-content-wrapper">
          <div class="page-content-tools page-filter">
            <div class="grid-container" :style="{'--counter': 9}">
              <div class="grid-item">
                <div class="label">省</div>
                <div class="value">
                  <el-select
                    v-model="provice"
                    size="small"
                    clearable
                    placeholder="请选择省"
                  >
                    <el-option
                      v-for="item in proviceList"
                      :key="'l0_' + item"
                      :label="item"
                      :value="item"
            <div class="page-content-tools page-filter">
              <div class="grid-container" :style="{'--counter': 9}">
                <div class="grid-item">
                  <div class="label">省</div>
                  <div class="value">
                    <el-select
                      v-model="provice"
                      size="small"
                      clearable
                      placeholder="请选择省"
                    >
                    </el-option>
                  </el-select>
                </div>
              </div>
              <div class="grid-item">
                <div class="label">市</div>
                <div class="value">
                  <el-select
                    v-model="city"
                    size="small"
                    clearable
                    placeholder="请选择市"
                  >
                    <el-option
                      v-for="item in cityList"
                      :key="'l1_' + item"
                      :label="item"
                      :value="item"
                    >
                    </el-option>
                  </el-select>
                </div>
              </div>
              <div class="grid-item">
                <div class="label">区县</div>
                <div class="value">
                  <el-select
                    v-model="country"
                    clearable
                    size="small"
                    placeholder="请选择区县"
                  >
                    <el-option
                      v-for="item in countryList"
                      :key="'l2_' + item"
                      :label="item"
                      :value="item"
                    >
                    </el-option>
                  </el-select>
                </div>
              </div>
              <div class="grid-item">
                <div class="label">站点</div>
                <div class="value">
                  <el-select
                    v-model="stationName"
                    clearable
                    size="small"
                    placeholder="请选择站点"
                  >
                    <el-option
                      v-for="item in stationList"
                      :key="'l3_' + item.stationId"
                      :label="item.stationName"
                      :value="item.stationName"
                    >
                    </el-option>
                  </el-select>
                </div>
              </div>
              <div class="grid-item">
                <div class="label">电源名称</div>
                <div class="value">
                  <el-select
                    v-model="powerId"
                    clearable
                    size="small"
                    placeholder="请选择电源"
                  >
                    <el-option
                      v-for="item in powerList"
                      :key="'l4_' + item.powerId"
                      :label="`${item.stationName}-${item.powerName}`"
                      :value="item.powerId"
                    >
                    </el-option>
                  </el-select>
                </div>
              </div>
              <div class="grid-item">
                <div class="label">告警名称</div>
                <div class="value">
                  <el-select
                    v-model="alarmId"
                    size="small"
                    clearable
                    filterable
                    placeholder="请选择告警名称"
                  >
                    <el-option
                      v-for="item in alarmTypeList"
                      :key="item.value"
                      :label="item.label"
                      :value="item.value"
                    >
                    </el-option>
                  </el-select>
                </div>
              </div>
              <div class="grid-item">
                <!-- <div class="label">一级告警</div>
                <div class="label">二级告警</div>
                <div class="label">三级告警</div>
                <div class="label">四级告警</div> -->
                <el-radio-group v-model="alarmLevel" size="small" style="grid-column: span 6;">
                  <el-radio-button :label="1">一级告警</el-radio-button>
                  <el-radio-button :label="2">二级告警</el-radio-button>
                  <el-radio-button :label="3">三级告警</el-radio-button>
                  <el-radio-button :label="4">四级告警</el-radio-button>
                </el-radio-group>
              </div>
            </div>
          </div>
          <div class="page-content-table">
            <div class="pos-rel">
              <div class="pos-abs">
                <el-table
                  class="yc-table"
                  stripe
                  height="100%"
                  size="small"
                  :data="datas0.tableData"
                  style="width: 100%"
                >
                  <el-table-column
                    type="index"
                    fixed="left"
                    label="序号"
                    width="60"
                  ></el-table-column>
                  <el-table-column
                    v-for="header in headers0"
                    :key="header.prop"
                    :prop="header.prop"
                    :label="header.label"
                    :min-width="header.width"
                    align="center"
                  >
                    <template #default="scope">
                      <template v-if="header.prop == 'almIsConfirmed'">
                        <el-checkbox
                          disabled
                          :checked="scope.row[header.prop] == 1"
                        ></el-checkbox>
                      </template>
                      <template v-else>
                        {{ scope.row[header.prop] || '--' }}
                      </template>
                    </template>
                  </el-table-column>
                  <el-table-column
                    label="操作"
                    fixed="right"
                    width="120"
                    align="center"
                  >
                    <template #default="scope">
                      <el-button
                        type="warning"
                        size="small"
                        @click="view(scope.row)"
                        >查看详情</el-button
                      <el-option
                        v-for="item in proviceList"
                        :key="'l0_' + item"
                        :label="item"
                        :value="item"
                      >
                    </template>
                  </el-table-column>
                </el-table>
                      </el-option>
                    </el-select>
                  </div>
                </div>
                <div class="grid-item">
                  <div class="label">市</div>
                  <div class="value">
                    <el-select
                      v-model="city"
                      size="small"
                      clearable
                      placeholder="请选择市"
                    >
                      <el-option
                        v-for="item in cityList"
                        :key="'l1_' + item"
                        :label="item"
                        :value="item"
                      >
                      </el-option>
                    </el-select>
                  </div>
                </div>
                <div class="grid-item">
                  <div class="label">区县</div>
                  <div class="value">
                    <el-select
                      v-model="country"
                      clearable
                      size="small"
                      placeholder="请选择区县"
                    >
                      <el-option
                        v-for="item in countryList"
                        :key="'l2_' + item"
                        :label="item"
                        :value="item"
                      >
                      </el-option>
                    </el-select>
                  </div>
                </div>
                <div class="grid-item">
                  <div class="label">站点</div>
                  <div class="value">
                    <el-select
                      v-model="stationName"
                      clearable
                      size="small"
                      placeholder="请选择站点"
                    >
                      <el-option
                        v-for="item in stationList"
                        :key="'l3_' + item.stationId"
                        :label="item.stationName"
                        :value="item.stationName"
                      >
                      </el-option>
                    </el-select>
                  </div>
                </div>
                <div class="grid-item">
                  <div class="label">电源名称</div>
                  <div class="value">
                    <el-select
                      v-model="powerId"
                      clearable
                      size="small"
                      placeholder="请选择电源"
                    >
                      <el-option
                        v-for="item in powerList"
                        :key="'l4_' + item.powerId"
                        :label="`${item.stationName}-${item.powerName}`"
                        :value="item.powerId"
                      >
                      </el-option>
                    </el-select>
                  </div>
                </div>
                <div class="grid-item">
                  <div class="label">告警名称</div>
                  <div class="value">
                    <el-select
                      v-model="alarmId"
                      size="small"
                      clearable
                      filterable
                      placeholder="请选择告警名称"
                    >
                      <el-option
                        v-for="item in alarmTypeList"
                        :key="item.value"
                        :label="item.label"
                        :value="item.value"
                      >
                      </el-option>
                    </el-select>
                  </div>
                </div>
                <div class="grid-item">
                  <el-radio-group
                    v-model="alarmLevel"
                    size="small"
                    style="grid-column: span 6;"
                  >
                    <el-radio-button :value="1">一级告警</el-radio-button>
                    <el-radio-button :value="2">二级告警</el-radio-button>
                    <el-radio-button :value="3">三级告警</el-radio-button>
                    <el-radio-button :value="4">四级告警</el-radio-button>
                  </el-radio-group>
                </div>
              </div>
            </div>
          </div>
          <div class="page-content-page">
            <div class="page-tool">
              <el-button
                type="primary"
                round
                size="small"
                @click="getList0"
                :icon="Search"
                >查询</el-button
              >
            <div class="page-content-table">
              <div class="pos-rel">
                <div class="pos-abs">
                  <el-table
                    class="yc-table"
                    stripe
                    height="100%"
                    size="small"
                    :data="datas0.tableData"
                    style="width: 100%"
                  >
                    <el-table-column
                      type="index"
                      fixed="left"
                      label="序号"
                      width="60"
                    ></el-table-column>
                    <el-table-column
                      v-for="header in headers0"
                      :key="header.prop"
                      :prop="header.prop"
                      :label="header.label"
                      :min-width="header.width"
                      align="center"
                    >
                      <template #default="scope">
                        <template v-if="header.prop == 'almIsConfirmed'">
                          <el-checkbox
                            disabled
                            :checked="scope.row[header.prop] == 1"
                          ></el-checkbox>
                        </template>
                        <template v-else>
                          {{ scope.row[header.prop] || '--' }}
                        </template>
                      </template>
                    </el-table-column>
                    <el-table-column
                      label="操作"
                      fixed="right"
                      width="120"
                      align="center"
                    >
                      <template #default="scope">
                        <el-button
                          type="warning"
                          size="small"
                          @click="view(scope.row)"
                          >查看详情</el-button
                        >
                      </template>
                    </el-table-column>
                  </el-table>
                </div>
              </div>
            </div>
            <div class="el-page-container">
              <el-pagination v-model:current-page="pageNum0" v-model:page-size="pageSize0"
                :page-sizes="[20, 40, 60, 80, 100, 200, 300, 400]" size="small" layout="total, sizes, prev, pager, next, jumper" :total="total0"
                @size-change="handleSizeChange0" @current-change="handleCurrentChange0" />
            </div>
            <div class="page-tool">
              <!-- <el-button type="primary" round size="small" @click="exportExcel"
            <div class="page-content-page">
              <div class="page-tool">
                <el-button
                  type="primary"
                  round
                  size="small"
                  @click="getList0"
                  :icon="Search"
                  >查询</el-button
                >
              </div>
              <div class="el-page-container">
                <el-pagination
                  v-model:current-page="pageNum0"
                  v-model:page-size="pageSize0"
                  :page-sizes="[20, 40, 60, 80, 100, 200, 300, 400]"
                  size="small"
                  layout="total, sizes, prev, pager, next, jumper"
                  :total="total0"
                  @size-change="handleSizeChange0"
                  @current-change="handleCurrentChange0"
                />
              </div>
              <div class="page-tool">
                <!-- <el-button type="primary" round size="small" @click="exportExcel"
                >导出</el-button
              >
              <el-button type="primary" round size="small" @click="exportExcelAll"
                >导出全部</el-button
              > -->
              </div>
            </div>
          </div>
        </div>
        </el-tab-pane>
        <el-tab-pane name="dev" label="设备告警">设备告警</el-tab-pane>
        <el-tab-pane name="batt" label="电池告警">电池告警</el-tab-pane>
        <el-tab-pane name="dev" class="tab-pane" label="设备告警">
          <div class="page-content-wrapper">
            <div class="page-content-tools page-filter">
              <div class="grid-container" :style="{'--counter': 9}">
                <div class="grid-item">
                  <div class="label">省</div>
                  <div class="value">
                    <el-select
                      v-model="provice"
                      size="small"
                      clearable
                      placeholder="请选择省"
                    >
                      <el-option
                        v-for="item in proviceList"
                        :key="'l0_' + item"
                        :label="item"
                        :value="item"
                      >
                      </el-option>
                    </el-select>
                  </div>
                </div>
                <div class="grid-item">
                  <div class="label">市</div>
                  <div class="value">
                    <el-select
                      v-model="city"
                      size="small"
                      clearable
                      placeholder="请选择市"
                    >
                      <el-option
                        v-for="item in cityList"
                        :key="'l1_' + item"
                        :label="item"
                        :value="item"
                      >
                      </el-option>
                    </el-select>
                  </div>
                </div>
                <div class="grid-item">
                  <div class="label">区县</div>
                  <div class="value">
                    <el-select
                      v-model="country"
                      clearable
                      size="small"
                      placeholder="请选择区县"
                    >
                      <el-option
                        v-for="item in countryList"
                        :key="'l2_' + item"
                        :label="item"
                        :value="item"
                      >
                      </el-option>
                    </el-select>
                  </div>
                </div>
                <div class="grid-item">
                  <div class="label">站点</div>
                  <div class="value">
                    <el-select
                      v-model="stationName"
                      clearable
                      size="small"
                      placeholder="请选择站点"
                    >
                      <el-option
                        v-for="item in stationList"
                        :key="'l3_' + item.stationId"
                        :label="item.stationName"
                        :value="item.stationName"
                      >
                      </el-option>
                    </el-select>
                  </div>
                </div>
                <div class="grid-item">
                  <div class="label">电源名称</div>
                  <div class="value">
                    <el-select
                      v-model="powerId"
                      clearable
                      size="small"
                      placeholder="请选择电源"
                    >
                      <el-option
                        v-for="item in powerList"
                        :key="'l4_' + item.powerId"
                        :label="`${item.stationName}-${item.powerName}`"
                        :value="item.powerId"
                      >
                      </el-option>
                    </el-select>
                  </div>
                </div>
                <div class="grid-item">
                  <div class="label">告警名称</div>
                  <div class="value">
                    <el-select
                      v-model="alarmId"
                      size="small"
                      clearable
                      filterable
                      placeholder="请选择告警名称"
                    >
                      <el-option
                        v-for="item in alarmTypeList"
                        :key="item.value"
                        :label="item.label"
                        :value="item.value"
                      >
                      </el-option>
                    </el-select>
                  </div>
                </div>
                <div class="grid-item">
                  <el-radio-group
                    v-model="alarmLevel"
                    size="small"
                    style="grid-column: span 6;"
                  >
                    <el-radio-button :value="1">一级告警</el-radio-button>
                    <el-radio-button :value="2">二级告警</el-radio-button>
                    <el-radio-button :value="3">三级告警</el-radio-button>
                    <el-radio-button :value="4">四级告警</el-radio-button>
                  </el-radio-group>
                </div>
              </div>
            </div>
            <div class="page-content-table">
              <div class="pos-rel">
                <div class="pos-abs">
                  <el-table
                    class="yc-table"
                    stripe
                    height="100%"
                    size="small"
                    :data="datas1.tableData"
                    style="width: 100%"
                  >
                    <el-table-column
                      type="index"
                      fixed="left"
                      label="序号"
                      width="60"
                    ></el-table-column>
                    <el-table-column
                      v-for="header in headers1"
                      :key="header.prop"
                      :prop="header.prop"
                      :label="header.label"
                      :min-width="header.width"
                      align="center"
                    >
                      <template #default="scope">
                        <template v-if="header.prop == 'almIsConfirmed'">
                          <el-checkbox
                            disabled
                            :checked="scope.row[header.prop] == 1"
                          ></el-checkbox>
                        </template>
                        <template v-else>
                          {{ scope.row[header.prop] || '--' }}
                        </template>
                      </template>
                    </el-table-column>
                    <el-table-column
                      label="操作"
                      fixed="right"
                      width="120"
                      align="center"
                    >
                      <template #default="scope">
                        <el-button
                          type="warning"
                          size="small"
                          @click="view(scope.row)"
                          >查看详情</el-button
                        >
                      </template>
                    </el-table-column>
                  </el-table>
                </div>
              </div>
            </div>
            <div class="page-content-page">
              <div class="page-tool">
                <el-button
                  type="primary"
                  round
                  size="small"
                  @click="getList1"
                  :icon="Search"
                  >查询</el-button
                >
              </div>
              <div class="el-page-container">
                <el-pagination
                  v-model:current-page="pageNum1"
                  v-model:page-size="pageSize1"
                  :page-sizes="[20, 40, 60, 80, 100, 200, 300, 400]"
                  size="small"
                  layout="total, sizes, prev, pager, next, jumper"
                  :total="total1"
                  @size-change="handleSizeChange1"
                  @current-change="handleCurrentChange1"
                />
              </div>
              <div class="page-tool">
                <!-- <el-button type="primary" round size="small" @click="exportExcel"
                  >导出</el-button
                >
                <el-button type="primary" round size="small" @click="exportExcelAll"
                  >导出全部</el-button
                > -->
              </div>
            </div>
          </div>
        </el-tab-pane>
        <el-tab-pane name="batt" class="tab-pane" label="电池告警">
          <div class="page-content-wrapper">
            <div class="page-content-tools page-filter">
              <div class="grid-container" :style="{'--counter': 9}">
                <div class="grid-item">
                  <div class="label">省</div>
                  <div class="value">
                    <el-select
                      v-model="provice"
                      size="small"
                      clearable
                      placeholder="请选择省"
                    >
                      <el-option
                        v-for="item in proviceList"
                        :key="'l0_' + item"
                        :label="item"
                        :value="item"
                      >
                      </el-option>
                    </el-select>
                  </div>
                </div>
                <div class="grid-item">
                  <div class="label">市</div>
                  <div class="value">
                    <el-select
                      v-model="city"
                      size="small"
                      clearable
                      placeholder="请选择市"
                    >
                      <el-option
                        v-for="item in cityList"
                        :key="'l1_' + item"
                        :label="item"
                        :value="item"
                      >
                      </el-option>
                    </el-select>
                  </div>
                </div>
                <div class="grid-item">
                  <div class="label">区县</div>
                  <div class="value">
                    <el-select
                      v-model="country"
                      clearable
                      size="small"
                      placeholder="请选择区县"
                    >
                      <el-option
                        v-for="item in countryList"
                        :key="'l2_' + item"
                        :label="item"
                        :value="item"
                      >
                      </el-option>
                    </el-select>
                  </div>
                </div>
                <div class="grid-item">
                  <div class="label">站点</div>
                  <div class="value">
                    <el-select
                      v-model="stationName"
                      clearable
                      size="small"
                      placeholder="请选择站点"
                    >
                      <el-option
                        v-for="item in stationList"
                        :key="'l3_' + item.stationId"
                        :label="item.stationName"
                        :value="item.stationName"
                      >
                      </el-option>
                    </el-select>
                  </div>
                </div>
                <div class="grid-item">
                  <div class="label">电源名称</div>
                  <div class="value">
                    <el-select
                      v-model="powerId"
                      clearable
                      size="small"
                      placeholder="请选择电源"
                    >
                      <el-option
                        v-for="item in powerList"
                        :key="'l4_' + item.powerId"
                        :label="`${item.stationName}-${item.powerName}`"
                        :value="item.powerId"
                      >
                      </el-option>
                    </el-select>
                  </div>
                </div>
                <div class="grid-item">
                  <div class="label">告警名称</div>
                  <div class="value">
                    <el-select
                      v-model="alarmId"
                      size="small"
                      clearable
                      filterable
                      placeholder="请选择告警名称"
                    >
                      <el-option
                        v-for="item in alarmTypeList"
                        :key="item.value"
                        :label="item.label"
                        :value="item.value"
                      >
                      </el-option>
                    </el-select>
                  </div>
                </div>
                <div class="grid-item">
                  <el-radio-group
                    v-model="alarmLevel"
                    size="small"
                    style="grid-column: span 6;"
                  >
                    <el-radio-button :value="1">一级告警</el-radio-button>
                    <el-radio-button :value="2">二级告警</el-radio-button>
                    <el-radio-button :value="3">三级告警</el-radio-button>
                    <el-radio-button :value="4">四级告警</el-radio-button>
                  </el-radio-group>
                </div>
              </div>
            </div>
            <div class="page-content-table">
              <div class="pos-rel">
                <div class="pos-abs">
                  <el-table
                    class="yc-table"
                    stripe
                    height="100%"
                    size="small"
                    :data="datas2.tableData"
                    style="width: 100%"
                  >
                    <el-table-column
                      type="index"
                      fixed="left"
                      label="序号"
                      width="60"
                    ></el-table-column>
                    <el-table-column
                      v-for="header in headers2"
                      :key="header.prop"
                      :prop="header.prop"
                      :label="header.label"
                      :min-width="header.width"
                      align="center"
                    >
                      <template #default="scope">
                        <template v-if="header.prop == 'almIsConfirmed'">
                          <el-checkbox
                            disabled
                            :checked="scope.row[header.prop] == 1"
                          ></el-checkbox>
                        </template>
                        <template v-else>
                          {{ scope.row[header.prop] || '--' }}
                        </template>
                      </template>
                    </el-table-column>
                    <el-table-column
                      label="操作"
                      fixed="right"
                      width="120"
                      align="center"
                    >
                      <template #default="scope">
                        <el-button
                          type="warning"
                          size="small"
                          @click="view(scope.row)"
                          >查看详情</el-button
                        >
                      </template>
                    </el-table-column>
                  </el-table>
                </div>
              </div>
            </div>
            <div class="page-content-page">
              <div class="page-tool">
                <el-button
                  type="primary"
                  round
                  size="small"
                  @click="getList2"
                  :icon="Search"
                  >查询</el-button
                >
              </div>
              <div class="el-page-container">
                <el-pagination
                  v-model:current-page="pageNum2"
                  v-model:page-size="pageSize2"
                  :page-sizes="[20, 40, 60, 80, 100, 200, 300, 400]"
                  size="small"
                  layout="total, sizes, prev, pager, next, jumper"
                  :total="total2"
                  @size-change="handleSizeChange2"
                  @current-change="handleCurrentChange2"
                />
              </div>
              <div class="page-tool">
                <!-- <el-button type="primary" round size="small" @click="exportExcel"
                  >导出</el-button
                >
                <el-button type="primary" round size="small" @click="exportExcelAll"
                  >导出全部</el-button
                > -->
              </div>
            </div>
          </div>
        </el-tab-pane>
      </el-tabs>
    </div>
    <div class="page-footer">
      <div class="left">
        <card :title="name0"></card>
        <card :title="name0">
          <line-chart ref="chart0"></line-chart>
        </card>
      </div>
      <div class="right">
        <div class="btn-grp">
          <!-- <div class="item">
          <div class="item">
            <div class="label">选择电池组</div>
            <div class="value">
              <el-select
                v-model="battId"
                size="small"
                clearable
                @change="getRtData"
                placeholder="请选择电池组"
              >
                <el-option
                  v-for="item in battList"
                  :key="'l5_' + item.powerId"
                  :label="`${item.stationName}-${item.powerName}`"
                  :value="item.powerId"
                  :key="'l5_' + item.battgroupId"
                  :label="`${item.devName}-${item.battgroupName}`"
                  :value="item.battgroupId"
                >
                </el-option>
              </el-select>
            </div>
          </div>
          <div class="item">
            <div class="label">设置时间周期</div>
            <div class="label">设置时间周期(分钟)</div>
            <div class="value">
              {{ 132 }}
              <div class="input">{{ timeLong }}</div>
            </div>
            <el-button type="primary" size="small" @click="setTime"
              >设置</el-button
            >
          </div>
          <div class="item">
            <div class="label">关注属性</div>
          </div> -->
            <el-button type="primary" size="small" @click="setProp"
              >关注属性</el-button
            >
          </div>
        </div>
        <!-- 一个就分一块 两个就分两列一行 两个以上就两列两行 -->
        <div :class="['contain', { 'grid1': subProp.length == 1, 'grid2': subProp.length == 2, 'grid3': subProp.length > 2}]">
        <div
          :class="['contain', { 'grid1': subProp.length == 1, 'grid2': subProp.length == 2, 'grid3': subProp.length > 2}]"
        >
          <template v-for="(sub, idx) in subProp" :key="'sub_' + idx">
            <card :title="'次属性' + (idx + 1)">
              <line-chart :ref="() => chartRefs[idx]"></line-chart>
            <card :title="sub.name">
              <line-chart
                :ref="(el) => setComponentRef(sub.prop, el)"
              ></line-chart>
            </card>
          </template>
        </div>
@@ -555,21 +1573,60 @@
    <!-- 弹窗 -->
    <el-dialog
      :title="dialogTitle"
      v-model="addEditVisible"
      v-model="timeVisible"
      top="0"
      draggable
      :close-on-click-modal="false"
      class="dialog-center"
      width="860px"
      width="460px"
      center
    >
      <alarm-params
        v-if="addEditVisible"
        :type="alarmType"
        :info="currentRow"
        @change="getList"
        v-model:visible="addEditVisible"
      ></alarm-params>
      <el-form ref="formRef" :model="form1" :rules="rules" label-width="10em">
        <el-row :gutter="layout.gutter">
          <el-col :span="layout.span">
            <el-form-item label="时间周期(分钟)" prop="time">
              <el-input v-model="form1.time"></el-input>
            </el-form-item>
          </el-col>
        </el-row>
      </el-form>
      <template #footer>
        <span class="dialog-footer">
          <el-button @click="timeVisible = false">取 消</el-button>
          <el-button type="primary" @click="timeSetOk">确 定</el-button>
        </span>
      </template>
    </el-dialog>
    <!-- 弹窗 -->
    <el-dialog
      :title="dialogTitle"
      v-model="propVisible"
      top="0"
      draggable
      :close-on-click-modal="false"
      class="dialog-center transfer-dialog"
      width="940px"
      center
    >
      <tree-transfer
        v-model:fromData="fromData"
        :titleList="['未关注属性', '已关注属性']"
        ref="transferRef"
        :showBtnTxt="true"
        :btnTitleList="['添加', '移除']"
        rootPid="0"
        v-model:toData="toData"
        :defaultProps="{label:'label', id: 'id', parentId: 'pid', children: 'children'}"
        @add="add"
        @remove="remove"
      >
      </tree-transfer>
      <template #footer>
        <span class="dialog-footer">
          <el-button @click="propVisible = false">取 消</el-button>
          <el-button type="primary" @click="propSetOk">确 定</el-button>
        </span>
      </template>
    </el-dialog>
  </div>
</template>
@@ -710,6 +1767,54 @@
    height: 100%;
  }
}
.btn-grp {
  .item {
    font-size: 14px;
    color: #439bc4;
    margin-left: 12px;
    display: flex;
    align-items: center;
    .label {
      &::after {
        content: ':';
      }
    }
    .value {
      margin-left: 8px;
      margin-right: 8px;
      :deep(.el-select) {
        width: 120px;
      }
    }
    .input {
      display: flex;
      align-items: center;
      padding-left: 6px;
      color: #fff;
      background: #439bc4;
      border-radius: 4px;
      min-width: 86px;
      height: 28px;
    }
  }
}
.item-setting {
  display: flex;
  align-items: center;
  .label {
    &::after {
      content: ':';
    }
  }
  .value {
    margin-left: 8px;
  }
}
.dialog-footer {
  display: flex;
  justify-content: flex-end;
}
.tools-filter {
  display: inline-block;
@@ -728,4 +1833,10 @@
    }
  }
}
:deep(.transfer-dialog) {
  .el-tree {
    max-height: 500px;
    overflow-y: auto;
  }
}
</style>
src/views/history/index.vue
@@ -7,7 +7,7 @@
import hisReal from "./hisReal.vue";
import { useRoute, useRouter } from "vue-router";
import useWebsocket from "@/hooks/useWebsocket";
import useWebSocket from "@/hooks/useWebSocket";
const route = useRoute();
const router = useRouter();
src/views/realtime/index.vue
@@ -15,12 +15,12 @@
import { useRoute, useRouter } from "vue-router";
import useWebsocket from "@/hooks/useWebsocket";
import useWebSocket from "@/hooks/useWebSocket";
const route = useRoute();
const router = useRouter();
const { message, sendData } = useWebsocket('real');
const { message, sendData } = useWebSocket('real');
const curStationId = ref(
  getQueryString("stationId") || ''
src/views/realtime/tabs/system.vue
@@ -18,15 +18,17 @@
import {
    getHalfHourBattDevData,
    getHalfHourPwrHisAcinData,
    getHalfHourPwrHisDcoutData,
    getBattDevData100,
    getPwrHisAcinData100,
    getPwrHisDcoutData100,
  getPwrHeartParam,
} from "@/api/realtime";
import {
  stopDis,
  restart,
} from '@/api/control';
const props = defineProps({
    data: {
@@ -137,6 +139,7 @@
        if (!n) return;
        nextTick(() => {
      getHeartParam();
            // getAcinData();
            // getDevData();
            // getDcoutData();
@@ -182,6 +185,7 @@
const startIdx = ref(0);
// 半小时的数据条数 1秒一笔计
// 改为100笔 可配置 三个属性可以设置不同
const counter = 30 * 60;
let xLabels1 = ref([]);
@@ -296,7 +300,7 @@
}
async function getAcinData() {
    let { code, data, data2 } = await getHalfHourPwrHisAcinData(props.powerId, show_num.acin);
    let { code, data, data2 } = await getPwrHisAcinData100(props.powerId);
    let list = [];
    if (code && data) {
        list = data2;
@@ -305,7 +309,7 @@
}
async function getDevData() {
    let { code, data, data2 } = await getHalfHourBattDevData(props.battgroupId, show_num.dev);
    let { code, data, data2 } = await getBattDevData100(props.battgroupId, props.powerId);
    let list = [];
    if (code && data) {
        list = data2;
@@ -314,7 +318,7 @@
}
async function getDcoutData() {
    let { code, data, data2, data3 } = await getHalfHourPwrHisDcoutData(props.powerId, show_num.dcout);
    let { code, data, data2, data3 } = await getPwrHisDcoutData100(props.powerId);
    let list = [];
    let cfg = [];
    if (code && data) {
@@ -508,8 +512,8 @@
    // let num = Math.ceil(counter / show_num['dev']);
    // TODO battRtstate 缺少loadCurr
    let devObj = props.data.battRtstate;
    xLabels1.value.shift();
    xLabels1.value.push(devObj.recordDatetime);
    xLabels2.value.shift();
    xLabels2.value.push(devObj.recDatetime);
    chartData['dev'].shift();
    chartData['dev'].push(devObj);
    updateChart2();
@@ -517,6 +521,46 @@
    // 蓄电池信息
    battInfo.value = props.data.sticRtdata;
}
const configVisible = ref(false);
const formRef = ref();
const form1 = reactive({
  time: 5,
  count: 100,
});
function validatorTime(rule, value, callback) {
  if(/^\d+$/.test(value)) {
    if(value<1 || value>30) {
      callback(new Error('范围1~30'));
    } else {
      callback();
    }
  }else {
    callback(new Error('请输入整数'));
  }
}
function validatorCount(rule, value, callback) {
  if(/^\d+$/.test(value)) {
    if (value<50 || value>200) {
      callback(new Error('范围50~200'));
    } else {
      callback();
    }
  }else {
    callback(new Error('请输入整数'));
  }
}
const rules = {
  time: [{ required: true, message: '请输入时间', trigger: ['blur', 'change'] },
    { validator: validatorTime, trigger: ['blur', 'change'] },
  ],
  count: [{ required: true, message: '请输入条数', trigger: ['blur', 'change'] },
    { validator: validatorCount, trigger: ['blur', 'change'] },
  ],
};
// 取前半小时数据 更新图表
@@ -554,24 +598,46 @@
    hrParamVisible.value = true;
}
const config = ref({});
async function getHeartParam() {
  let res = await getPwrHeartParam(props.powerId);
  let { code, data, data2 } = res.data;
  let cfg = {};
  if (code && data) {
    cfg = data2;
  }
  config.value = cfg;
}
const configTitle = ref('');
function setConfig(type) {
  switch(type) {
    case 0:
      configTitle.value = '设置交流输入采集参数';
      form1.time = config.value.acinInterverCfg || 5;
      form1.count = config.value.acinCountCfg || 100;
      break;
    case 1:
      configTitle.value = '设置直流输出采集参数';
      form1.time = config.value.acoutInterverCfg || 5;
      form1.count = config.value.acoutCountCfg || 100;
      break;
    case 2:
      configTitle.value = '设置核容设备采集参数';
      form1.time = config.value.hrInterverCfg || 5;
      form1.count = config.value.hrCountCfg || 100;
      break;
  }
  configVisible.value = true;
}
function updateConfig() {
  configVisible.value = false;
}
onMounted(async () => {
    numChange('acin');
    numChange('dcout');
    numChange('dev');
    // await getAcinData();
    // await getDevData();
    // await getDcoutData();
    // if (chart1.value) {
    //     chart1.value.updateChart(['04:12', '04:13', '04:14'], {
    //         '设备温度': [100, 200, 220],
    //         '组端电流': [100, 200, 220],
    //         '组端电压': [100, 200, 220],
    //         '负载电流': [100, 200, 220],
    //     });
    // }
});
</script>
@@ -648,28 +714,11 @@
      <div class="card-item">
        <card title="交流输入">
          <template #tools>
            <div class="page-filter">
              <div class="label">粒度</div>
              <div class="value">
                <el-select
                  v-model="show_num['acin']"
                  size="small"
                  style="width: 50px"
                  @change="numChange('acin')"
                >
                  <el-option
                    v-for="(n, i) in 10"
                    :key="'list0_' + i"
                    :label="'x' + n"
                    :value="n"
                  />
                </el-select>
              </div>
            </div>
            <el-radio-group class="tab-idx" v-model="tabIdx0" size="small">
              <el-radio-button label="电流" :value="0" />
              <el-radio-button label="电压" :value="1" />
            </el-radio-group>
            <svg-icon class-name="btn-setting" icon-class="setting" @click="setConfig(0)"></svg-icon>
          </template>
          <line-chart ref="chart0"></line-chart>
        </card>
@@ -677,28 +726,11 @@
      <div class="card-item">
        <card title="直流输出">
          <template #tools>
            <div class="page-filter">
              <div class="label">粒度</div>
              <div class="value">
                <el-select
                  v-model="show_num['dcout']"
                  size="small"
                  style="width: 50px"
                  @change="numChange('dcout')"
                >
                  <el-option
                    v-for="(n, i) in 10"
                    :key="'list0_' + i"
                    :label="'x' + n"
                    :value="n"
                  />
                </el-select>
              </div>
            </div>
            <el-radio-group class="tab-idx" v-model="tabIdx1" size="small">
              <el-radio-button label="电流" :value="0" />
              <el-radio-button label="电压" :value="1" />
            </el-radio-group>
            <svg-icon class-name="btn-setting" icon-class="setting" @click="setConfig(1)"></svg-icon>
          </template>
          <line-chart3
            ref="chart1"
@@ -713,25 +745,7 @@
      <div class="card-item">
        <card title="核容设备信息">
          <template #tools>
            <div class="page-filter">
              <div class="label">粒度</div>
              <div class="value">
                <el-select
                  v-model="show_num['dev']"
                  size="small"
                  style="width: 50px"
                  @change="numChange('dev')"
                >
                  <el-option
                    v-for="(n, i) in 10"
                    :key="'list0_' + i"
                    :label="'x' + n"
                    :value="n"
                  />
                </el-select>
              </div>
            </div>
            <!-- <svg-icon class-name="btn-setting" icon-class="setting"></svg-icon> -->
            <svg-icon class-name="btn-setting" icon-class="setting" @click="setConfig(2)"></svg-icon>
          </template>
          <line-chart2 ref="chart2"></line-chart2>
        </card>
@@ -815,12 +829,28 @@
        </card>
      </div>
    </div>
    <!-- 设置间隔参数 -->
    <el-dialog v-model="configVisible" draggable :title="configTitle" width="560">
      <el-form ref="formRef" :model="form1" :rules="rules" label-width="10em">
        <el-form-item label="间隔时间(分)" prop="time">
          <el-input v-model="form1.time"></el-input>
        </el-form-item>
        <el-form-item label="数据笔数" prop="count">
          <el-input v-model="form1.count"></el-input>
        </el-form-item>
      </el-form>
      <template #footer>
        <el-button @click="configVisible = false">关闭</el-button>
        <!-- <el-button type="primary" @click="getConfig">读取</el-button> -->
        <el-button type="primary" @click="updateConfig">设定</el-button>
      </template>
    </el-dialog>
    <!-- 设置核容参数 -->
    <el-dialog v-model="hrParamVisible" :title="hrParamTitle" width="960">
    <el-dialog v-model="hrParamVisible" draggable :title="hrParamTitle" width="960">
      <hr-params :devId="devId" v-model:visible="hrParamVisible" :battgroupId="battgroupId"></hr-params>
    </el-dialog>
    <!-- 设置设备告警参数 -->
    <el-dialog v-model="devAlmVisible" title="设备告警参数" width="960">
    <el-dialog v-model="devAlmVisible" draggable title="设备告警参数" width="960">
      <dev-alarm-params :devId="devId" v-model:visible="devAlmVisible"></dev-alarm-params>
    </el-dialog>
  </div>
src/views/statistics/battCompare0_.vue
New file
@@ -0,0 +1,546 @@
<script setup name="battCompare0">
    import { ref, reactive, onMounted, computed, nextTick } from "vue";
    import { storeToRefs } from "pinia";
    import { Search, Plus } from "@element-plus/icons-vue";
    import ycCard from "@/components/ycCard/index.vue";
    import addEdit from "../datas/addEdit.vue";
    import { ElMessage } from "element-plus";
    import useElement from "@/hooks/useElement.js";
  import { useUserStore } from '@/store/user';
  import useStation from "@/hooks/useStationList.js";
  const { provice, city, country, stationName,
    proviceList, cityList, countryList, stationList,
  } = useStation();
  import { useRouter } from "vue-router";
  const router = useRouter();
  import { ExportFile } from '@/utils/exportFile.js';
  import powerTypes from '@/utils/const/const_powerType.js';
  import hrTypes from '@/utils/const/const_hrTestType.js';
  import {
    getBattPerformance,
    getBatteryBrand,
  } from "@/api/station";
  const userStore = useUserStore();
  const { uid, uname } = storeToRefs(userStore);
  import moment from 'moment';
  import formatSeconds from '@/utils/formatSeconds';
  import {
    toFixed,
    digits,
  } from '@/utils/toFixed';
  import {
    getBattCompare15,
  } from "@/api/statistic.js";
    const { $loading, $message, $confirm } = useElement();
    const headers = [
    {
      prop: "stationName",
      label: "站点名称",
      width: "160",
    },
    {
      prop: "devName",
      label: "设备名称",
      width: "80",
    },
    {
      prop: "battgroupName",
      label: "电池组名称",
      width: "80",
    },
    {
      prop: "product",
      label: "电池品牌",
      width: "100",
    },
    {
      prop: "inuseTime",
      label: "投运时间",
      width: "100",
    },
    {
      prop: "monvolstd",
      label: "电池规格",
      width: "100",
    },
    {
      prop: "monNumsStr",
      label: "落后单体编号",
      width: "160",
    },
    {
      prop: "realCap",
      label: "预估容量",
      width: "80",
    },
    {
      prop: "precentCapStr",
      label: "容量百分比",
      width: "80",
    },
    {
      prop: "capperformance",
      label: "电池性能",
      width: "80",
    },
  ];
   const testType = ref('');
  const hrTypeList = computed(() => {
    return Object.keys(hrTypes).map(v => {
      return {
        value: v,
        label: hrTypes[v],
      };
    });
  });
    const background = ref(true);
    const disabled = ref(false);
    const pageCurr = ref(1);
    const pageSize = ref(10);
    const total = ref(0);
    const addEditVisible = ref(false);
    const dialogTitle = ref("");
    const currentAreaId = ref();
    const currentAreaIds = ref([]);
  const testStartDate = ref('');
  const testEndDate = ref('');
    const datas = reactive({
        tableData: [],
        rowData: {},
    });
  // 计算属性生成 picker-options(更简洁)
  const startDisabledDate = (time) =>  testEndDate.value ? moment(testEndDate.value).isBefore(time) || moment().isBefore(time) : moment().isBefore(time);
  const endDisabledDate = (time) => testStartDate.value ? moment(time).isBefore(testStartDate.value) || moment().isBefore(time) : moment().isBefore(time);
  const performance = ref('');
  const performanceList = ref([]);
  function getPerformancList() {
    getBattPerformance()
      .then((res) => {
        let { code, data, data2 } = res;
        let list = [];
        if (code && data) {
          // console.log(data);
          list = Object.keys(data2).map((key) => ({ value: key, label: data2[key] }));
        }
        performanceList.value = list;
      })
      .catch((err) => {
        console.log(err);
      });
  }
  const product = ref('');
  const productList = ref([]);
  function getProductList() {
    getBatteryBrand().then((res) => {
      let { code, data, data2 } = res;
      let list = [];
      if (code && data) {
        list = data2;
      }
      productList.value = list;
    });
  }
    function getList() {
        let loading = $loading();
    let params = {
      provice: provice.value || undefined,
      city: city.value || undefined,
      country: country.value || undefined,
      stationName: stationName.value || undefined,
      pageNum: pageCurr.value,
      pageSize: pageSize.value,
      performance: performance.value || undefined,
      product: product.value || undefined,
      testStartTime: testStartDate.value ? testStartDate.value + ' 00:00:00' : undefined,
      testEndTime: testEndDate.value ? testEndDate.value + ' 23:59:59' : undefined,
    };
        getBattCompare15(params)
            .then((res) => {
                let { code, data, data2 } = res;
                let list = [];
                let _total = 0;
                if (code && data) {
                    // console.log(data);
                    list = data2.list.map(v => ({
            ...v,
            monNumsStr: v.monNums.map(v => `#${v}`).join(',') || '--',
            precentCapStr: toFixed(v.precentCap, digits.PREC) + '%',
          }));
                    _total = data2.total;
                }
                loading.close();
                // tableData.length = 0;
                // tableData.push(...list);
                datas.tableData = list;
                total.value = _total;
            })
            .catch((err) => {
                console.log(err);
                loading.close();
            });
    }
    // 展示数据数量
    function handleSizeChange(val) {
        pageSize.value = val;
        getList();
    }
    // 翻页
    function handleCurrentChange(val) {
        pageCurr.value = val;
        getList();
    }
  function filterChange() {
    nextTick(() => {
      pageCurr.value = 1;
      getList();
    });
  }
  function goRt (row) {
    router.push({
      path: '/datas/realtime',
      query: {
        stationId: row.stationId || undefined,
        powerId: row.powerId || undefined,
        devId: row.devId || undefined,
        battgroupId: row.battgroupId || undefined,
        pageFlag: Math.random(),
      }
    });
  }
  function goHis (row) {
    router.push({
      path: '/datas/history',
      query: {
        stationId: row.stationId || undefined,
        powerId: row.powerId || undefined,
        devId: row.devId || undefined,
        battgroupId: row.battgroupId || undefined,
        pageTab: 'his-real',
        pageFlag: Math.random(),
      }
    });
  }
  function exportExcel() {
    ExportFile(headers, datas.tableData, "蓄电池组对比分析--同一品牌同一时间");
  }
    onMounted(() => {
    getPerformancList();
    getProductList();
        getList();
    });
</script>
<template>
  <div class="page-wrapper">
    <!-- <div class="page-header">
    </div> -->
    <div class="page-content">
      <yc-card is-full>
        <div class="page-content-wrapper">
          <div class="page-content-tools page-filter">
            <div class="grid-container" :style="{'--counter': 10}">
              <div class="grid-item">
                <div class="label">省</div>
                <div class="value">
                  <el-select
                    v-model="provice"
                    size="small"
                    clearable
                    @change="filterChange"
                    placeholder="请选择省"
                  >
                    <el-option
                      v-for="item in proviceList"
                      :key="'l0_' + item"
                      :label="item"
                      :value="item"
                    >
                    </el-option>
                  </el-select>
                </div>
              </div>
              <div class="grid-item">
                <div class="label">市</div>
                <div class="value">
                  <el-select
                    v-model="city"
                    size="small"
                    clearable
                    @change="filterChange"
                    placeholder="请选择市"
                  >
                    <el-option
                      v-for="item in cityList"
                      :key="'l1_' + item"
                      :label="item"
                      :value="item"
                    >
                    </el-option>
                  </el-select>
                </div>
              </div>
              <div class="grid-item">
                <div class="label">区县</div>
                <div class="value">
                  <el-select
                    v-model="country"
                    clearable
                    @change="filterChange"
                    size="small"
                    placeholder="请选择区县"
                  >
                    <el-option
                      v-for="item in countryList"
                      :key="'l2_' + item"
                      :label="item"
                      :value="item"
                    >
                    </el-option>
                  </el-select>
                </div>
              </div>
              <div class="grid-item">
                <div class="label">站点</div>
                <div class="value">
                  <el-select
                    v-model="stationName"
                    clearable
                    @change="filterChange"
                    size="small"
                    placeholder="请选择站点"
                  >
                    <el-option
                      v-for="item in stationList"
                      :key="'l3_' + item.stationId"
                      :label="item.stationName"
                      :value="item.stationName"
                    >
                    </el-option>
                  </el-select>
                </div>
              </div>
              <div class="grid-item">
                <div class="label">电池性能</div>
                <div class="value">
                  <el-select
                    v-model="performance"
                    filterable
                    clearable
                    size="small"
                    @change="filterChange"
                    placeholder="请选择"
                  >
                    <el-option
                      v-for="(item, idx) in performanceList"
                      :key="'list7_' + idx"
                      :label="item.label"
                      :value="item.value"
                    />
                  </el-select>
                </div>
              </div>
              <div class="grid-item">
                <div class="label">电池品牌</div>
                <div class="value">
                  <el-select
                    v-model="product"
                    filterable
                    clearable
                    size="small"
                    @change="filterChange"
                    placeholder="请选择"
                  >
                    <el-option
                      v-for="(item, idx) in productList"
                      :key="'list6_' + idx"
                      :label="item"
                      :value="item"
                    />
                  </el-select>
                </div>
              </div>
              <div class="grid-item">
                <div class="label">统计时间段</div>
                <div class="value" style="grid-column: span 7;">
                  <el-date-picker
                    v-model="testStartDate"
                    type="date"
                    size="small"
                    placeholder="选择日期"
                    format="YYYY-MM-DD"
                    value-format="YYYY-MM-DD"
                    :disabled-date="startDisabledDate"
                  />
                  -
                  <el-date-picker
                    v-model="testEndDate"
                    size="small"
                    type="date"
                    placeholder="选择日期"
                    format="YYYY-MM-DD"
                    value-format="YYYY-MM-DD"
                    :disabled-date="endDisabledDate"
                  />
                </div>
              </div>
            </div>
          </div>
          <div class="page-content-table">
            <div class="pos-rel">
              <div class="pos-abs">
                <el-table class="yc-table" stripe height="100%" size="small" :data="datas.tableData" style="width: 100%">
                  <el-table-column type="index" fixed="left" label="序号" width="60"></el-table-column>
                  <el-table-column v-for="header in headers" :key="header.prop" :prop="header.prop" :label="header.label"
                    :min-width="header.width" align="center">
                    <template #default="scope">{{ scope.row[header.prop] }}</template>
                  </el-table-column>
                  <el-table-column label="操作" fixed="right" width="240" align="center">
                    <template #default="scope">
                      <el-button type="warning" size="small" @click="goRt(scope.row)">实时监测</el-button>
                      <el-button type="primary" size="small" @click="goHis(scope.row)">历史数据</el-button>
                    </template>
                  </el-table-column>
                </el-table>
              </div>
            </div>
          </div>
          <div class="page-content-page">
            <div class="page-tool">
              <el-button type="primary" round size="small" @click="getList" :icon="Search">查询</el-button>
            </div>
            <div class="el-page-container">
              <el-pagination v-model:current-page="pageCurr" v-model:page-size="pageSize"
                :page-sizes="[20, 40, 60, 80, 100, 200, 300, 400]" size="small" :disabled="disabled"
                :background="background" layout="total, sizes, prev, pager, next, jumper" :total="total"
                @size-change="handleSizeChange" @current-change="handleCurrentChange" />
            </div>
            <div class="page-tool">
              <el-button type="primary" round size="small" @click="exportExcel">导出</el-button>
            </div>
          </div>
        </div>
      </yc-card>
    </div>
    <div class="page-footer"></div>
  </div>
</template>
<style scoped lang="less">
.page-wrapper {
  display: flex;
  flex-direction: row;
  // padding: 8px;
  height: 100%;
  .page-content {
    flex: 1;
  }
}
.page-content-wrapper {
  display: flex;
  flex-direction: column;
  height: 100%;
  .page-content-tools {
    padding-bottom: 8px;
  }
  .page-content-table {
    // border-top: 1px solid var(--border-light-color);
    box-sizing: border-box;
    flex: 1;
    margin-left: 26px;
    margin-right: 26px;
  }
  .page-content-page {
    padding: 8px 8px 0 8px;
    text-align: center;
    .el-page-container {
      display: inline-block;
      padding: 0 16px;
    }
    .page-tool {
      display: inline-block;
    }
  }
}
.hdw-card-container {
  width: 240px;
  padding-right: 8px;
  height: 100%;
}
.pos-rel {
  position: relative;
  width: 100%;
  height: 100%;
  .pos-abs {
    position: absolute;
    top: 0;
    bottom: 0;
    left: 0;
    right: 0;
    width: 100%;
    height: 100%;
  }
}
.tools-filter {
  display: inline-block;
  font-size: 14px;
  .tools-filter-item {
    display: inline-block;
    margin-right: 8px;
    .filter-label {
      display: inline-block;
    }
    .filter-content {
      display: inline-block;
    }
  }
}
.max-width {
  max-width: 200px;
}
</style>