he wei
5 天以前 3c3576d5792bfabcef84979757ee344712e71cd3
src/views/realtime/tabs/system.vue
@@ -1,11 +1,20 @@
<script setup>
import { nextTick, ref, watch, onMounted } 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 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 {
@@ -13,6 +22,11 @@
   getHalfHourPwrHisAcinData,
   getHalfHourPwrHisDcoutData,
} from "@/api/realtime";
import {
  stopDis,
  restart,
} from '@/api/control';
const props = defineProps({
   data: {
@@ -37,6 +51,66 @@
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,
   () => {
@@ -60,71 +134,444 @@
watch(
   () => props.powerId,
   (n) => {
    if (!n) return;
      if (!n) return;
      nextTick(() => {
         getAcinData();
         getDevData();
         getDcoutData();
         // 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秒一笔计
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() {
   // TODO
   if (chart0.value) {
      chart0.value.updateChart([1, 2, 3], [100, 200, 300]);
   }
   updateChart0();
}
function tabIdx1Change() {
   // TODO
   updateChart1();
}
async function getAcinData() {
   let { code, data, data2 } = await getHalfHourPwrHisAcinData(props.powerId, show_num.acin);
   let list = [];
   if (code && data) {
      list = data2;
   }
   return list;
}
async function getDevData() {
   let { code, data, data2 } = await getHalfHourBattDevData(props.battgroupId, show_num.dev);
   let list = [];
   if (code && data) {
      list = data2;
   }
   return list;
}
async function getDcoutData() {
   let { code, data, data2, data3 } = await getHalfHourPwrHisDcoutData(props.powerId, show_num.dcout);
   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;
   xLabels1.value.shift();
   xLabels1.value.push(devObj.recordDatetime);
   chartData['dev'].shift();
   chartData['dev'].push(devObj);
   updateChart2();
   // 蓄电池信息
   battInfo.value = props.data.sticRtdata;
}
// 取前半小时数据 更新图表
// 更新图表 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([1, 2, 3], [100, 200, 300]);
      chart1.value.updateChart(xLabels1.value, chartData1.value);
   }
}
async function getAcinData(granularity = 5) {
   let { code, data, data2 } = await getHalfHourPwrHisAcinData(props.powerId, granularity);
   let list = [];
   if (code && data) {
      list = data2;
function updateChart2() {
   if (chart2.value) {
      chart2.value.updateChart(xLabels2.value, chartData['dev']);
   }
   return list;
}
async function getDevData(granularity = 5) {
   let { code, data, data2 } = await getHalfHourBattDevData(props.battgroupId, granularity);
   let list = [];
   if (code && data) {
      list = data2;
   }
   return list;
function scrollHandler(data) {
   console.log('data', data, '=============');
   startIdx.value += data * 1;
   nextTick(() => {
      // updateChart1();
   })
}
async function getDcoutData(granularity = 5) {
   let { code, data, data2 } = await getHalfHourPwrHisDcoutData(props.powerId, granularity);
   let list = [];
   if (code && data) {
      list = data2;
   }
   return list;
const hrParamTitle = ref('核容测试');
const hrParamVisible = ref(false);
function startHrTest() {
   hrParamVisible.value = true;
}
onMounted(async () => {
   numChange('acin');
   numChange('dcout');
   numChange('dev');
   // await getAcinData();
   // await getDevData();
   // await getDcoutData();
   if (chart2.value) {
      chart2.value.updateChart(['04:12', '04:13', '04:14'], {
         '设备温度': [100, 200, 220],
         '组端电流': [100, 200, 220],
         '组端电压': [100, 200, 220],
         '负载电流': [100, 200, 220],
      });
   }
   // 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>
@@ -173,23 +620,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-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-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>
@@ -201,59 +648,181 @@
      <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"></svg-icon>
          </template>
          <line-chart
            ref="chart0"
            :type="['电流', '电压'][tabIdx0]"
          ></line-chart>
          <line-chart ref="chart0"></line-chart>
        </card>
      </div>
      <div class="card-item">
        <card title="直流输入">
        <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"></svg-icon>
          </template>
          <line-chart
          <line-chart3
            ref="chart1"
            :type="['电流', '电压'][tabIdx1]"
          ></line-chart>
            :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>
            <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> -->
          </template>
          <line-chart2
            ref="chart2"
            :type="['电流', '电压'][tabIdx1]"
          ></line-chart2>
          <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="hrParamVisible" :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">
      <dev-alarm-params :devId="devId" v-model:visible="devAlmVisible"></dev-alarm-params>
    </el-dialog>
  </div>
</template>
@@ -462,5 +1031,30 @@
      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>