he wei
19 小时以前 011aab07af85ba820b9f96a02c249b7ba26c8d26
src/views/realtime/tabs/system.vue
@@ -1,22 +1,644 @@
<script setup>
import { ref } from "vue";
<script setup name="tabSystem">
import { nextTick, ref, reactive, computed, watch, onMounted } from "vue";
import svgDiagram from '@/components/svgDiagram.vue';
import info from '@/components/info.vue';
// import lineChart from '@/components/echarts/line1.vue';
import lineChart from '@/components/echarts/BaseChart.vue';
import lineChart from '@/components/echarts/line1.vue';
import lineChart2 from '@/components/echarts/line2.vue';
import hrParams from '@/components/hrParams.vue';
import devAlarmParams from '../devAlarmParams.vue';
import lineChart3 from '@/components/echarts/line-scroll.vue';
// import lineChart from '@/components/echarts/BaseChart.vue';
// import lineChart from '../bar8.vue';
import moment from 'moment';
import getBinaryDigits from '@/utils/getBinaryDigits.js';
import useElement from "@/hooks/useElement.js";
   const { $loading, $message, $confirm } = useElement();
import {
   getBattDevData100,
   getPwrHisAcinData100,
   getPwrHisDcoutData100,
  getPwrHeartParam,
} from "@/api/realtime";
import {
  stopDis,
  restart,
} from '@/api/control';
const props = defineProps({
  data: {
    type: Object,
    default: {},
  },
   data: {
      type: Object,
      default: {},
   },
   powerId: {
      type: [Number, String],
   },
   devId: {
      type: [Number, String],
   },
   battgroupId: {
      type: [Number, String],
   },
});
const tabIdx0 = ref(0);
const tabIdx1 = ref(0);
const chart0 = ref(null);
const chart1 = ref(null);
const chart2 = ref(null);
const labels_0 = [
   [
      ['一路A相电流', 'acin1Curra'],
      ['一路B相电流', 'acin1Currb'],
      ['一路C相电流', 'acin1Currc'],
      ['二路A相电流', 'acin2Curra'],
      ['二路B相电流', 'acin2Currb'],
      ['二路C相电流', 'acin2Currc'],
   ],
   [
      ['一路A相电压', 'acin1Vola'],
      ['一路B相电压', 'acin1Volb'],
      ['一路C相电压', 'acin1Volc'],
      ['二路A相电压', 'acin2Vola'],
      ['二路B相电压', 'acin2Volb'],
      ['二路C相电压', 'acin2Volc'],
   ]
];
const labels_1 = reactive([[], []]);
const devRt = ref({
  devIp: "127.0.0.0",
  devVersion: "1",
  devId: 0,
  devOnline: 0,
  recordDatetime: "",
  devTesttype: 0,
  devTestgroupnum: 0,
  devWorkstate: -1,
  devAlarmstate: 0,
  devTemp: 0.0,
  devResTestState: 0,
  devOnlinevollow: 0,
  devEachgroupBattsum: 0,
  devCaptestOnlinevol: 0.0,
  devCaptestGroupvol: 0.0,
  devCaptestCurr: 0.0,
  devCaptestCap: 0.0,
  devCaptestTimelong: 0,
  devRestestCount: 0,
  devCommcount: 0,
  devErrcommcount: 0,
  devRxnullerrcount: 0,
  devLastCaptestStopType: 0,
  devCondvoldp: 0.0,
  devConresist: 0.0,
  devConresist1: 0.0,
  dev61850alarms: "",
  devCondvoldp1: 0.0,
  groupVol1: 0.0,
  groupVol2: 0.0,
  groupCurr1: 0.0,
  groupCurr2: 0.0,
});
const battRt = ref({
  groupCurr: 0,
});
watch(
   () => tabIdx0.value,
   () => {
      nextTick(() => {
         tabIdx0Change();
      });
   },
   { immediate: true }
);
watch(
   () => tabIdx1.value,
   () => {
      nextTick(() => {
         tabIdx1Change();
      });
   },
   { immediate: true }
);
watch(
   () => props.powerId,
   (n) => {
      if (!n) return;
      nextTick(() => {
      getHeartParam();
         // getAcinData();
         // getDevData();
         // getDcoutData();
         numChange('acin');
         numChange('dcout');
         numChange('dev');
      });
   },
   { immediate: true }
);
watch(
   () => props.data,
   (n) => {
      if (!n) return;
      nextTick(() => {
         updateRt();
      if (n.deviceState) {
        devRt.value = n.deviceState;
      }
      if (n.battRtstate) {
        battRt.value = n.battRtstate;
      }
      });
   },
   { immediate: true, deep: true }
);
const show_num = reactive({
   acin: 5,
   dcout: 5,
   dev: 5,
});
// 用来绘图的数据
const chartData = reactive({
   acin: [],
   dcout: [],
   dev: [],
});
const modelCfg = ref([]);
const startIdx = ref(0);
// 半小时的数据条数 1秒一笔计
// 改为100笔 可配置 三个属性可以设置不同
const counter = 30 * 60;
let xLabels1 = ref([]);
let xLabels2 = ref([]);
// 根据粒度 和查询结果 补全数据
function completeData(type) {
   // 根据粒度 计算出需要的条数
   let num = Math.ceil(counter / show_num[type]);
   let _num = num - chartData[type].length;
   let obj = null;
   let res = [...chartData[type]];
   switch (type) {
      case 'acin':
         obj = {
            acin1Vola: 0,
            acin1Volb: 0,
            acin1Volc: 0,
            acin2Vola: 0,
            acin2Volb: 0,
            acin2Volc: 0,
            acin1Curra: 0,
            acin1Currb: 0,
            acin1Currc: 0,
            acin2Curra: 0,
            acin2Currb: 0,
            acin2Currc: 0,
         };
         break;
      case 'dcout':
         obj = {
            m1Outcurr: 0.0,
            m2Outcurr: 0.0,
            m3Outcurr: 0.0,
            m4Outcurr: 0.0,
            m5Outcurr: 0.0,
            m6Outcurr: 0.0,
            m7Outcurr: 0.0,
            m8Outcurr: 0.0,
            m9Outcurr: 0.0,
            m10Outcurr: 0.0,
            m11Outcurr: 0.0,
            m12Outcurr: 0.0,
            m13Outcurr: 0.0,
            m14Outcurr: 0.0,
            m15Outcurr: 0.0,
            m16Outcurr: 0.0,
            m1OutVol: 0.0,
            m2OutVol: 0.0,
            m3OutVol: 0.0,
            m4OutVol: 0.0,
            m5OutVol: 0.0,
            m6OutVol: 0.0,
            m7OutVol: 0.0,
            m8OutVol: 0.0,
            m9OutVol: 0.0,
            m10OutVol: 0.0,
            m11OutVol: 0.0,
            m12OutVol: 0.0,
            m13OutVol: 0.0,
            m14OutVol: 0.0,
            m15OutVol: 0.0,
            m16OutVol: 0.0,
            moutputvol: 0.0,
         };
         break;
      case 'dev':
         obj = {
            groupVol: 0.0,
            onlineVol: 0.0,
            groupCurr: 0.0,
            groupTmp: 0.0,
            loadCurr: 0.0,
         };
         break;
   }
   let _xLabels1 = chartData['dcout'].map(item => item.recordDatetime);
   let _xLabels2 = chartData['dev'].map(item => item.recordDatetime);
   // 数据最小时间
   let minTime = chartData[type].length ? chartData[type][0].recordDatetime : moment().format('YYYY-MM-DD HH:mm:ss');
   if (_num > 0) {
      for (let i = _num; i--;) {
         minTime = moment(minTime).subtract(show_num[type], 'seconds').format('YYYY-MM-DD HH:mm:ss');
         res.unshift({
            recordDatetime: minTime,
            ...obj,
         });
         _xLabels1.unshift(minTime);
         _xLabels2.unshift(minTime);
      }
   }
   switch (type) {
      case 'acin':
         break;
      case 'dcout':
         xLabels1.value = yLabels.value.length ? _xLabels1 : [];
         break;
      case 'dev':
         xLabels2.value = _xLabels2;
         break;
   }
   chartData[type] = res;
}
function tabIdx0Change() {
   updateChart0();
}
function tabIdx1Change() {
   updateChart1();
}
async function getAcinData() {
   let { code, data, data2 } = await getPwrHisAcinData100(props.powerId);
   let list = [];
   if (code && data) {
      list = data2;
   }
   return list;
}
async function getDevData() {
   let { code, data, data2 } = await getBattDevData100(props.battgroupId, props.powerId);
   let list = [];
   if (code && data) {
      list = data2;
   }
   return list;
}
async function getDcoutData() {
   let { code, data, data2, data3 } = await getPwrHisDcoutData100(props.powerId);
   let list = [];
   let cfg = [];
   if (code && data) {
      list = data2;
      cfg = getBinaryDigits(data3).map((v, i) => ({ value: v, label: i + 1 })).filter(vv => vv.value).map(v => v.label);
   }
   console.log('cfg', cfg, '=============', data3);
   modelCfg.value = cfg;
   if (cfg.length < 4) {
      startIdx.value = 0;
   }
   // setLabel1();
   return list;
}
const yLabels = computed(() => {
   let res = modelCfg.value.map((idx) => `${idx}#整流器`);
   if (modelCfg.value.length > 4) {
      res = res.slice(startIdx.value, startIdx.value + 4);
   }
   return res;
});
// function setLabel1() {
//   // console.log('??', modelCfg.value, '=============');
//   if (modelCfg.value.length <= 4) {
//     yLabels.value = modelCfg.value.map((idx) => `${idx}#整流器`);
//   } else {
//     yLabels.value = modelCfg.value.slice(startIdx.value, startIdx.value + 4).map((idx) => `${idx}#整流器`);
//   }
// }
const chartData1 = ref([]);
function formatData1() {
   let res = [];
   for (let i = 0, len = chartData['dcout'].length; i < len; i++) {
      yLabels.value.forEach((item, idx) => {
         res[idx] = res[idx] || [];
         let type = ['curr', 'Vol'][tabIdx1.value];
         let _prop = `m${idx + 1}Out${type}`;
         res[idx].push(chartData['dcout'][i][_prop]);
      });
   }
   // console.log('res format', res, yLabels.value, '=============');
   chartData1.value = res;
}
function stopHrTest() {
  $confirm("停止核容测试", async () => {
    let loading = $loading();
    let res = await stopDis(props.powerId, props.battgroupId);
    loading.close();
    let { code, data } = res;
    if (code && data) {
      $message.success('操作成功');
    } else {
      $message.error('操作失败');
    }
  });
}
function remoteRestart() {
  $confirm("远程重启", async () => {
    let loading = $loading();
    let res = await restart(props.powerId, props.battgroupId);
    loading.close();
    let { code, data } = res;
    if (code && data) {
      $message.success('操作成功');
    } else {
      $message.error('操作失败');
    }
  });
}
const devAlmVisible = ref(false);
function showDevAlarmParam() {
  devAlmVisible.value = true;
}
async function numChange(type) {
   switch (type) {
      case 'acin':
         chartData.acin = await getAcinData();
         completeData('acin');
         updateChart0();
         break;
      case 'dcout':
         chartData.dcout = await getDcoutData();
         // setLabel1();
         completeData('dcout');
         formatData1();
         updateChart1();
         break;
      case 'dev':
         chartData.dev = await getDevData();
         completeData('dev');
         updateChart2();
         break;
   }
}
const battInfo = ref({});
// 更新实时数据
function updateRt() {
   let pwrData = props.data.pwrdevAcdcdata;
   if (!pwrData) {
      return false;
   }
   // 修改三个图表的数据
   // chart0  chartData['acin']
   // 根据粒度 计算出需要的条数
   // let num = Math.ceil(counter / show_num['acin']);
   chartData['acin'].shift();
   chartData['acin'].push(pwrData);
   updateChart0();
   // chart1  chartData['dcout']
   // 根据粒度 计算出需要的条数
   if (!chartData1.value.length) {
      modelCfg.value = getBinaryDigits(props.data.powerInf.modelCfg).map((v, i) => ({ value: v, label: i + 1 })).filter(vv => vv.value).map(v => v.label);
      pwrData.recordDatetime
      let minTime = pwrData.recordDatetime;
      let num = Math.ceil(counter / show_num['dcout']);
      let _label = [];
      let list = [];
      for (let i = num; i--;) {
         minTime = moment(minTime).subtract(show_num['dcout'], 'seconds').format('YYYY-MM-DD HH:mm:ss');
         list.unshift({
            recordDatetime: minTime,
            m1Outcurr: 0.0,
            m2Outcurr: 0.0,
            m3Outcurr: 0.0,
            m4Outcurr: 0.0,
            m5Outcurr: 0.0,
            m6Outcurr: 0.0,
            m7Outcurr: 0.0,
            m8Outcurr: 0.0,
            m9Outcurr: 0.0,
            m10Outcurr: 0.0,
            m11Outcurr: 0.0,
            m12Outcurr: 0.0,
            m13Outcurr: 0.0,
            m14Outcurr: 0.0,
            m15Outcurr: 0.0,
            m16Outcurr: 0.0,
            m1OutVol: 0.0,
            m2OutVol: 0.0,
            m3OutVol: 0.0,
            m4OutVol: 0.0,
            m5OutVol: 0.0,
            m6OutVol: 0.0,
            m7OutVol: 0.0,
            m8OutVol: 0.0,
            m9OutVol: 0.0,
            m10OutVol: 0.0,
            m11OutVol: 0.0,
            m12OutVol: 0.0,
            m13OutVol: 0.0,
            m14OutVol: 0.0,
            m15OutVol: 0.0,
            m16OutVol: 0.0,
            moutputvol: 0.0,
         });
         _label.unshift(minTime);
      }
      xLabels1.value = _label;
      chartData['dcout'] = list;
   }
   xLabels1.value.shift();
   xLabels1.value.push(pwrData.recordDatetime);
   chartData['dcout'].shift();
   chartData['dcout'].push(pwrData);
   nextTick(() => {
      formatData1();
      updateChart1();
   });
   // chart2  chartData['dev']
   // 根据粒度 计算出需要的条数
   // let num = Math.ceil(counter / show_num['dev']);
   // TODO battRtstate 缺少loadCurr
   let devObj = props.data.battRtstate;
   xLabels2.value.shift();
   xLabels2.value.push(devObj.recDatetime);
   chartData['dev'].shift();
   chartData['dev'].push(devObj);
   updateChart2();
   // 蓄电池信息
   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'] },
  ],
};
// 取前半小时数据 更新图表
// 更新图表 1 2 3
function updateChart0() {
   if (chart0.value) {
      chart0.value.updateChart(labels_0[tabIdx0.value], chartData['acin']);
   }
}
function updateChart1() {
   if (chart1.value) {
      chart1.value.updateChart(xLabels1.value, chartData1.value);
   }
}
function updateChart2() {
   if (chart2.value) {
      chart2.value.updateChart(xLabels2.value, chartData['dev']);
   }
}
function scrollHandler(data) {
   console.log('data', data, '=============');
   startIdx.value += data * 1;
   nextTick(() => {
      // updateChart1();
   })
}
const hrParamTitle = ref('核容测试');
const hrParamVisible = ref(false);
function startHrTest() {
   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 () => {
});
</script>
<template>
@@ -64,19 +686,23 @@
          </div>
        </div>
        <div class="p-main">
          <svg-diagram class="svg-diagram"></svg-diagram>
          <svg-diagram :data="devRt" :battRt="battRt" class="svg-diagram"></svg-diagram>
        </div>
        <div class="p-right">
          <div class="control-contain">
            <div class="control-title"><svg-icon icon-class="controls"></svg-icon><span>控制管理</span></div>
            <div class="control-btn">核容测试</div>
            <div class="control-btn">停止核容测试</div>
            <div class="control-title">
              <svg-icon icon-class="controls"></svg-icon><span>控制管理</span>
            </div>
            <div class="control-btn" @click="startHrTest">核容测试</div>
            <div class="control-btn" @click="stopHrTest">停止核容测试</div>
          </div>
          <div class="control-contain">
            <div class="control-title"><svg-icon icon-class="dev"></svg-icon><span>设备管理</span></div>
            <div class="control-btn">远程重启</div>
            <div class="control-title">
              <svg-icon icon-class="dev"></svg-icon><span>设备管理</span>
            </div>
            <div class="control-btn" @click="remoteRestart">远程重启</div>
            <div class="control-btn">系统参数设置</div>
            <div class="control-btn">告警参数设置</div>
            <div class="control-btn" @click="showDevAlarmParam">告警参数设置</div>
          </div>
          <div class="control-contain no-wrap">
            <div class="control-btn">放电申请</div>
@@ -92,68 +718,141 @@
              <el-radio-button label="电流" :value="0" />
              <el-radio-button label="电压" :value="1" />
            </el-radio-group>
            <svg-icon class-name="btn-setting" icon-class="setting"></svg-icon>
            <svg-icon class-name="btn-setting" icon-class="setting" @click="setConfig(0)"></svg-icon>
          </template>
          <line-chart></line-chart>
          <line-chart ref="chart0"></line-chart>
        </card>
      </div>
      <div class="card-item">
        <card title="直流输入">
        <card title="直流输出">
          <template #tools>
            <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"></svg-icon>
            <svg-icon class-name="btn-setting" icon-class="setting" @click="setConfig(1)"></svg-icon>
          </template>
          <line-chart3
            ref="chart1"
            :type="['电流', '电压'][tabIdx1]"
            :yLabels="yLabels"
            :start-idx="startIdx"
            :mode-count="modelCfg.length"
            @scroll="scrollHandler"
          ></line-chart3>
        </card>
      </div>
      <div class="card-item">
        <card title="核容设备信息">
          <template #tools>
            <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>
      </div>
      <div class="card-item">
        <card title="蓄电池信息">
          <div class="batt grid">
            <info
              label="最大容量"
              value="#3 8Ah"
            ></info>
            <info
              label="最小容量"
              value="100"
            ></info>
            <info
              label="最高内阻"
              value="100"
            ></info>
            <info
              label="最低内阻"
              value="100"
            ></info>
            <info
              label="最高电压"
              value="100"
            ></info>
            <info
              label="最低电压"
              value="100"
            ></info>
            <info
              label="最高温度"
              value="100"
            ></info>
            <info
              label="最低温度"
              value="100"
            ></info>
            <info label="最大容量">
              <template
                #value
                v-if="battInfo.maxCapNumList && battInfo.maxCapNumList.length"
              >
                <span class="mon-num">#{{ battInfo.maxCapNumList[0] }}</span>
                <span class="val">{{ battInfo.maxCap }}Ah</span>
              </template>
            </info>
            <info label="最小容量">
              <template
                #value
                v-if="battInfo.minCapNumList && battInfo.minCapNumList.length"
              >
                <span class="mon-num">#{{ battInfo.minCapNumList[0] }}</span>
                <span class="val">{{ battInfo.minCap }}Ah</span>
              </template>
            </info>
            <info label="最高内阻">
              <template
                #value
                v-if="battInfo.maxResNumList && battInfo.maxResNumList.length"
              >
                <span class="mon-num">#{{ battInfo.maxResNumList[0] }}</span>
                <span class="val">{{ battInfo.maxRes }}mΩ</span>
              </template>
            </info>
            <info label="最低内阻">
              <template
                #value
                v-if="battInfo.minResNumList && battInfo.minResNumList.length"
              >
                <span class="mon-num">#{{ battInfo.minResNumList[0] }}</span>
                <span class="val">{{ battInfo.minRes }}mΩ</span>
              </template>
            </info>
            <info label="最高电压">
              <template
                #value
                v-if="battInfo.maxVolNumList && battInfo.maxVolNumList.length"
              >
                <span class="mon-num">#{{ battInfo.maxVolNumList[0] }}</span>
                <span class="val">{{ battInfo.maxVol }}V</span>
              </template>
            </info>
            <info label="最低电压">
              <template
                #value
                v-if="battInfo.minVolNumList && battInfo.minVolNumList.length"
              >
                <span class="mon-num">#{{ battInfo.minVolNumList[0] }}</span>
                <span class="val">{{ battInfo.minVol }}V</span>
              </template>
            </info>
            <info label="最高温度">
              <template
                #value
                v-if="battInfo.maxTmpNumList && battInfo.maxTmpNumList.length"
              >
                <span class="mon-num">#{{ battInfo.maxTmpNumList[0] }}</span>
                <span class="val">{{ battInfo.maxTmp }}℃</span>
              </template>
            </info>
            <info label="最低温度">
              <template
                #value
                v-if="battInfo.minTmpNumList && battInfo.minTmpNumList.length"
              >
                <span class="mon-num">#{{ battInfo.minTmpNumList[0] }}</span>
                <span class="val">{{ battInfo.minTmp }}℃</span>
              </template>
            </info>
          </div>
        </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" draggable :title="hrParamTitle" width="960">
      <hr-params :devId="devId" v-model:visible="hrParamVisible" :battgroupId="battgroupId"></hr-params>
    </el-dialog>
    <!-- 设置设备告警参数 -->
    <el-dialog v-model="devAlmVisible" draggable title="设备告警参数" width="960">
      <dev-alarm-params :devId="devId" v-model:visible="devAlmVisible"></dev-alarm-params>
    </el-dialog>
  </div>
</template>
@@ -164,24 +863,30 @@
  padding-right: 8px;
  display: flex;
  flex-direction: column;
  .row {
    flex: 1.52;
    .row-content {
      display: flex;
      flex-direction: row;
      height: 100%;
    }
    .p-left {
      width: 240px;
      display: flex;
      flex-direction: column;
      .p-item {
        margin: 8px;
        display: flex;
        flex-direction: column;
        .panel-title {
          font-size: 24px;
        }
        .panel {
          border: 1px solid #5FA9CF;
          background: #073451;
@@ -192,18 +897,22 @@
          font-size: 12px;
          display: flex;
          flex-direction: column;
          .panel-row {
            display: flex;
            flex-direction: row;
            margin-bottom: 4px;
            .label {
              flex: 0 0 6em;
              margin-right: 0.6em;
              text-align: right;
              &::after {
                content: ":";
              }
            }
            .value {
              flex: 1;
            }
@@ -211,9 +920,11 @@
        }
      }
    }
    .p-main {
      flex: 1;
    }
    .p-right {
      width: 160px;
      margin-left: 20px;
@@ -221,6 +932,7 @@
      padding-top: 20px;
      display: flex;
      flex-direction: column;
      .control-contain {
        display: flex;
        flex-direction: column;
@@ -231,6 +943,7 @@
        padding-bottom: 4px;
        overflow: hidden;
        font-size: 12px;
        .control-title {
          background: #0B415D;
          font-size: 20px;
@@ -238,10 +951,12 @@
          text-align: center;
          font-weight: 700;
          margin-bottom: 4px;
          span {
            margin-left: 0.6em;
          }
        }
        .control-btn {
          margin: 2px 4px;
          cursor: pointer;
@@ -250,14 +965,17 @@
          padding: 6px 0;
          text-align: center;
          border-radius: 4px;
          &:hover {
            color: #FDFE01;
            border: 1px solid #DF7B26;
            box-shadow: inset 0 0 10px 4px #DF7B26;
          }
        }
        &.no-wrap {
          background: transparent;
          .control-btn {
            flex: 1;
            border: 1px solid #0BF9FE;
@@ -265,6 +983,7 @@
            font-weight: bold;
            font-size: 14px;
            box-shadow: inset 0 0 10px 4px #0BF9FE;
            &:hover {
              color: #FDFE01;
              border: 1px solid #DF7B26;
@@ -274,26 +993,28 @@
        }
      }
    }
    &.row2 {
      flex: 1;
      margin-top: 4px;
      display: flex;
      flex-direction: row;
      .card-item {
        flex: 1;
        margin: 4px;
      }
    }
  }
  .svg-diagram {
  }
  .svg-diagram {}
  .btn-setting {
    display: inline-block;
    cursor: pointer;
    margin-left: 0.4em;
    transition: all 1.3s ease;
    &:hover {
      transform: rotate(360deg);
      color: #FDFE01;
@@ -317,26 +1038,53 @@
      border-radius: 0;
      box-shadow: none !important;
    }
    // .el-radio-button--small .el-radio-button__inner {
    //     border-radius: 0;
    //     font-size: 12px;
    //     padding: 5px 11px;
    // }
    :deep(.el-radio-button__inner) {
        background: #183A55;
        border: 1px solid #4D81BA;
        border-left: 0;
        border-radius: 0;
        color: #fff;
        font-weight: 500;
        padding: 4px 10px;
      background: #183A55;
      border: 1px solid #4D81BA;
      border-left: 0;
      border-radius: 0;
      color: #fff;
      font-weight: 500;
      padding: 4px 10px;
    }
    :deep(.el-radio-button.is-active .el-radio-button__original-radio:not(:disabled)+.el-radio-button__inner) {
        background: linear-gradient(69deg, #6EABE4, #6EABE4 25%,  #0A3E77 75%, #0A3E77);
        // border: 0 none;
        box-shadow: none;
        color: #fff;
      background: linear-gradient(69deg, #6EABE4, #6EABE4 25%, #0A3E77 75%, #0A3E77);
      // border: 0 none;
      box-shadow: none;
      color: #fff;
    }
  }
  .page-filter {
    display: flex;
    flex-direction: row;
    align-items: center;
    margin-right: 6px;
    margin-top: 0;
    margin-bottom: 0;
    padding: 0;
    background: transparent;
    border: 0 none;
    .label {
      font-size: 12px;
      margin-right: 6px;
      &::after {
        content: ":";
      }
    }
  }
  .mon-num {
    margin-right: 1em;
  }
}
</style>
</style>