he wei
2023-04-13 58c5441f7a98e2e14504474ddc619dc294e3a87d
UA 9149 4831修改
8个文件已修改
9个文件已添加
4748 ■■■■■ 已修改文件
src/assets/js/const/const_9141.js 10 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/js/const/const_9149.js 250 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/js/const/const_devType.js 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/js/tools/regEquipType.js 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/router/index.js 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/dataTest/components/bts9141DischargeParams.vue 15 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/dataTest/components/bts9149DischargeParams.vue 478 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/dataTest/components/bts9149ParamsItem.vue 470 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/dataTest/components/diagrams/parallelPower9149/index.vue 148 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/dataTest/components/diagrams/parallelPower9149/js/DiagramExtend.js 225 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/dataTest/components/diagrams/parallelPower9149/js/circuitDiagram.js 296 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/dataTest/components/diagrams/parallelPower9149/js/diagramStates.js 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/dataTest/components/selectGroup.vue 107 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/dataTest/js/realTime.js 35 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/dataTest/movingRingSystem/index.vue 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/dataTest/realTime9149.vue 2659 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/dataTest/realTimeFbo4831.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/js/const/const_9141.js
@@ -2,18 +2,22 @@
  paramsTypeList: [
    {
      label: '实时核容参数',
      type: 'discharge',
      value: 0
    },
    {
      label: '计划核容参数',
      type: 'plan',
      value: 1
    },
    {
      label: '活化参数',
      type: 'activate',
      value: 2
    },
    {
      label: '充电参数',
      type: 'charge',
      value: 3
    },
  ],
@@ -214,8 +218,8 @@
      onlineVolLowAction: 0,
      offLineYHOnceCycle: 0,
      monCapStd: 0,
      cProtectvol1: 0,
      cProtectvol2: 0,
      cprotectvol1: 0,
      cprotectvol2: 0,
      chargeCurrSet: 0,
      flowoverCharcurr1: 0,
      charTimeLong: 0,
@@ -235,7 +239,7 @@
      disCurr: 0,
      disTime: 0,
      devId: 0,
      hvMonUppernum1: 0,
      // hvMonUppernum1: 0,
    }
  }
};
src/assets/js/const/const_9149.js
New file
@@ -0,0 +1,250 @@
export default {
  paramsTypeList: [
    {
      label: '实时核容参数',
      type: 'discharge',
      value: 0
    },
    {
      label: '计划核容参数',
      type: 'plan',
      value: 1
    },
    {
      label: '活化参数',
      type: 'activate',
      value: 2
    },
    {
      label: '充电参数',
      type: 'charge',
      value: 3
    },
  ],
  battManageList: [
    {
      label: '自动',
      value: 0
    },
    {
      label: '手动',
      value: 1
    },
  ],
  JCList: [
    {
      label: '开启',
      value: 0
    },
    {
      label: '关闭',
      value: 1
    },
  ],
  CharTimeList: [0, 1, 2, 3, 4, 5],
  switchTempList: [
    {
      label: '开启',
      value: 0
    },
    {
      label: '关闭',
      value: 1
    },
  ],
  CharWaitTimeList: [
    {
      label: '开启',
      value: 0
    },
    {
      label: '关闭',
      value: 1
    },
  ],
  DisWaitTimeList: [
    {
      label: '开启',
      value: 0
    },
    {
      label: '关闭',
      value: 1
    },
  ],
  OnlineTestFlagList: [
    {
      label: '远程',
      value: 0
    },
    {
      label: '本地',
      value: 1
    },
  ],
  groupIndexList: [
    { value: 0, label: '组1' },
    { value: 1, label: '组2' },
    { value: 2, label: '组3' },
    { value: 3, label: '组4' },
  ],
  cmd: {
    get: 0xB4,
    set: 0xB5,
    start: 81,
    stop: 83
  },
  testCmd: {
    discharge: 37,
    charge: 64,
  },
  dischargeRules: {
    battnominalcap: {  // 标称容量
      pattern: /^[0-9]{2,3}$/,
      regVal: true,
      min: 50,
      max: 200,
      msg: '取值范围50~200'
    },
    battfloatvol: {
      pattern: /^[0-9]{2}(\.[0-9]{1})?$/,
      regVal: true,
      min: 20,
      max: 30,
      msg: '取值范围20~30(保留一位小数)'
    },
    battchargevol: {
      pattern: /^[0-9]{2}(\.[0-9]{1})?$/,
      regVal: true,
      min: 20,
      max: 30,
      msg: '取值范围20~30(保留一位小数)'
    },
    battchargecurr1: {
      pattern: /^[0-9]{1,3}(\.[0-9]{1,2})?$/,
      regVal: true,
      min: 0,
      max: 100,
      msg: '取值范围0~100(保留两位小数)'
    },
    battchargecurr2: {
      pattern: /^[0-9]{1,3}(\.[0-9]{1,2})?$/,
      regVal: true,
      min: 0,
      max: 100,
      msg: '取值范围0~100(保留两位小数)'
    },
    battchargecurr3: {
      pattern: /^[0-9]{1,3}(\.[0-9]{1,2})?$/,
      regVal: true,
      min: 0,
      max: 100,
      msg: '取值范围0~100(保留两位小数)'
    },
    timerchargeperiod: {
      pattern: /^[0-9]{2,3}$/,
      regVal: true,
      min: 30,
      max: 180,
      msg: '取值范围30~180'
    },
    maxchargetimehour: {
      pattern: /^[0-9]{1,2}$/,
      regVal: true,
      min: 1,
      max: 30,
      msg: '取值范围1~30'
    },
    batthightemp: {
      pattern: /^[0-9]{2}$/,
      regVal: true,
      min: 20,
      max: 80,
      msg: '取值范围20~80'
    },
    battlowtemp: {
      pattern: /^-?[0-9]{1,2}$/,
      regVal: true,
      min: -40,
      max: 10,
      msg: '取值范围-40~10'
    },
    compensatedtemp: {
      pattern: /^[0-9]{2}$/,
      regVal: true,
      min: 10,
      max: 40,
      msg: '取值范围10~40'
    },
    tempcompensatedcoe: {
      pattern: /^[0-9]{1,2}$/,
      regVal: true,
      min: 0,
      max: 50,
      msg: '取值范围0~50'
    },
    battdischargelowvol: {
      pattern: /^[0-9]{2}(\.[0-9]{1})?$/,
      regVal: true,
      min: 20,
      max: 30,
      msg: '取值范围20~30(保留一位小数)'
    },
    mondischargelowvol: {
      pattern: /^[0-9]{1,2}(\.[0-9]{1})?$/,
      regVal: true,
      min: 1.6,
      max: 15,
      msg: '取值范围1.6~15(保留一位小数)'
    },
    herongcurr: {
      pattern: /^[0-9]{1,3}(\.[0-9]{1,2})?$/,
      regVal: true,
      min: 0,
      max: 100,
      msg: '取值范围0~100(保留两位小数)'
    },
    herongtimehour: {
      pattern: /^[0-9]+$/,
      regVal: true,
      min: 0,
      max: 20,
      msg: '取值范围0~20'
    },
    monvollow: {
      pattern: /^[0-9]{1,2}(\.[0-9]{1})?$/,
      regVal: true,
      min: 1.6,
      max: 13.6,
      msg: '取值范围1.6~13.6(保留一位小数)'
    },
  },
  getInitParams() {
    return {
      battauto: 0,
      timerchargeable: 0,
      battnominalcap: 0,
      battfloatvol: 0,
      battchargevol: 0,
      battchargecurr1: 0,
      battchargecurr2: 0,
      battchargecurr3: 0,
      tailcurrchargetime: 0,
      timerchargeperiod: 0,
      maxchargetimehour: 0,
      tempcompensatedable: 0,
      batthightemp: 0,
      battlowtemp: 0,
      compensatedtemp: 0,
      tempcompensatedcoe: 0,
      battdischargelowvol: 0,
      mondischargelowvol: 0,
      localremoteset: 0,
      battchrgctrl: 0,
      battdisctrl: 0,
      herongcurr: 0,
      herongtimehour: 0,
      monvollow: 0,
    }
  }
};
src/assets/js/const/const_devType.js
@@ -13,6 +13,14 @@
      label: "并联BTS"
    },
    {
      value: 9141,
      label: "直流并联BTS"
    },
    {
      value: 9149,
      label: "交流并联BTS"
    },
    {
      value: 9110,
      label: '假负载BTS'
    },
@@ -76,6 +84,10 @@
      value: 4815,
      label: "FBO-4815NT"
    },
    {
      value: 4831,
      label: "FBC300NT"
    },
  ],
  power: [
    {
src/assets/js/tools/regEquipType.js
@@ -36,6 +36,7 @@
        storage: /^3100/,
        BTS9140:/^9140/,//并联BTS
        BTS9141:/^9141/,//并联BTS 新
        BTS9149:/^9149/,//并联BTS 交流9路
        remoteRestartDevice: /^61851/,  // 远程重启装置
        eleOperation: /^60870/,         // 电操核容产品
    };
src/router/index.js
@@ -605,6 +605,16 @@
      },
      component: () => import('@/views/dataTest/realTime9141')
    }, {
      // 新的并联电源
      path: 'real-time-9149/:battGroupId',
      name: 'movingRingSystem',
      meta: {
        title: '实时监控',
        icon: '',
        url: '/dataTest/realTime9149'
      },
      component: () => import('@/views/dataTest/realTime9149')
    }, {
      path: 'lithium-battery/:battGroupId',
      name: 'movingRingSystem',
      meta: {
src/views/dataTest/components/bts9141DischargeParams.vue
@@ -26,14 +26,14 @@
          <el-input v-model="otherParams.groupInfo" readonly></el-input>
        </el-form-item>
      </el-col>
      <el-col :span="row.span">
      <!-- <el-col :span="row.span">
        <el-form-item label="参数类型">
          <el-select v-model="params.hvMonUppernum1" :disabled="readOnly" placeholder="请选择">
            <el-option v-for="item in paramsTypeList" :key="'params_' + item.value" :label="item.label"
              :value="item.value"></el-option>
          </el-select>
        </el-form-item>
      </el-col>
      </el-col> -->
      <el-col :span="row.span">
        <el-form-item label="电池管理方式">
          <el-select v-model="params.onlineVolLowAction" :disabled="readOnly" placeholder="请选择">
@@ -482,10 +482,11 @@
      }
      // 启动按钮不可点击
      this.startTestFlag = false;
      //
      let {
        hvMonUppernum1,
      } = this.params;
      // TODO 参数类型 来自于启动时的类型 type
      // let {
      //   hvMonUppernum1,
      // } = this.params;
      let hvMonUppernum1 = const_9141.paramsTypeList.filter((v) => v.type == this.type)[0].value;
      let parms = {
        opCmd: this.cmd.get,
        devId: this.batt.fbsdeviceId,
@@ -742,7 +743,7 @@
    } else {
      this.getParams(true);
    }
    console.log(this.batt, this.readOnly, this.paramData);
    // console.log(this.batt, this.readOnly, this.paramData);
  },
};
</script>
src/views/dataTest/components/bts9149DischargeParams.vue
New file
@@ -0,0 +1,478 @@
<template>
  <div class="params-dialog">
    <el-form size="mini" label-position="top">
      <el-row :gutter="row.gutter">
        <el-col>
          <el-form-item label="电池组名称">
            <el-input v-model="otherParams.groupName" readonly></el-input>
          </el-form-item>
        </el-col>
      </el-row>
      <el-row :gutter="row.gutter">
        <el-col :span="row.span">
          <el-form-item label="设备ID">
            <el-input v-model="otherParams.fbsdeviceId" readonly></el-input>
          </el-form-item>
        </el-col>
        <el-col :span="12">
          <el-form-item label="电池组信息">
            <el-input v-model="otherParams.groupInfo" readonly></el-input>
          </el-form-item>
        </el-col>
      </el-row>
    </el-form>
    <el-tabs v-model="acTabs" type="border-card" class="params-tabs flex-layout noborder" @tab-click="tabClick">
      <el-tab-pane ref="tabs" v-for="idx in 9" :key="'list_' + idx" :name="'tab_' + (idx - 1)" :label="'组' + idx">
        <param-item :ref="'params' + (idx - 1)" :params="params[idx - 1]"></param-item>
      </el-tab-pane>
    </el-tabs>
    <div class="form-footer">
      <!-- <three-btn>清除告警</three-btn> -->
      <template v-if="!readOnly">
        <span v-if="copyedIdx > -1" class="msg-copy">{{ '组' + (copyedIdx + 1) + '参数已复制' }}</span>
        <three-btn @click="copy">复制</three-btn>
        <three-btn :disabled="copyedIdx < 0" @click="paste">粘贴</three-btn>
        <three-btn :disabled="!startTestFlag" @click="selectGroup">启动</three-btn>
        <three-btn @click="getParams(true)">读取</three-btn>
        <three-btn :disabled="!setTestFlag" @click="submitFrom">设定</three-btn>
      </template>
      <three-btn @click="$emit('close')">关闭</three-btn>
    </div>
    <el-dialog title="人脸校验" width="480px" :visible.sync="setFaceShow" :close-on-click-modal="false" top="0" :modal="false"
      class="dialog-center" :modal-append-to-body="false" :destroy-on-close="true">
      <check-face v-if="setFaceShow" @checkSuccess="setFaceSuccess"></check-face>
    </el-dialog>
    <el-dialog title="人脸校验" width="480px" :visible.sync="startFaceShow" :close-on-click-modal="false" top="0"
      :modal="false" class="dialog-center" :modal-append-to-body="false" :destroy-on-close="true">
      <check-face v-if="startFaceShow" @checkSuccess="startFaceSuccess"></check-face>
    </el-dialog>
    <el-dialog title="选择要启动测试的电池组" width="480px" :visible.sync="selectGroupVisible" :close-on-click-modal="false" top="0"
      :modal="false" class="dialog-center" :modal-append-to-body="false" :destroy-on-close="true">
      <select-group @ok="startTestCheck" @cancel="selectGroupVisible = false"></select-group>
      <div class="mask"></div>
    </el-dialog>
  </div>
</template>
<script>
import const_9149 from "@/assets/js/const/const_9149";
import config from "@/assets/js/config";
import checkFace from "@/components/checkFace";
import selectGroup from './selectGroup';
import {
  updateParalleParam9149 as setParams,
  searchParalleParam9149 as getParams,
  controllerParalle9149 as start,
} from "../js/realTime";
import { checkUserPwd } from "@/views/login/js/api";
import toFixed from "@/assets/js/tools/toFixed";
import paramItem from './bts9149ParamsItem';
export default {
  name: "BtsDischargeParams",
  components: {
    checkFace,
    paramItem,
    selectGroup,
  },
  props: {
    batt: {
      type: Object,
      default() {
        return {};
      },
    },
    // 只读模式 显示参数用
    readOnly: {
      type: Boolean,
      default: false
    },
    paramData: {
      type: Object,
      default() {
        return {}
      }
    },
    type: {
      type: String,
      default: 'charge'
    },
  },
  data() {
    let {
      cmd,
      testCmd,
      CharWaitTimeList,
      DisWaitTimeList,
      OnlineTestFlagList,
      switchTempList,
      CharTimeList,
      JCList,
      paramsTypeList,
      battManageList,
      groupIndexList,
      getInitParams,
    } = const_9149;
    return {
      testList: [],
      selectGroupVisible: false,
      copyedParams: null,
      copyedIdx: -1,
      acTabs: 'tab_0',
      row: {
        gutter: 16,
        span: 6,
      },
      CharWaitTimeList,
      DisWaitTimeList,
      OnlineTestFlagList,
      switchTempList,
      CharTimeList,
      JCList,
      paramsTypeList,
      battManageList,
      setFaceShow: false,
      startFaceShow: false,
      cmd: cmd, // 操作命令
      testCmd,
      startTestFlag: false, // 启动测试的状态
      setTestFlag: false, // 设置参数的状态
      params: [],
      groupIndexList,
    };
  },
  watch: {
  },
  methods: {
    tabClick(tab) {
      this.acTabs = tab.name;
    },
    initParams() {
      // 初始化参数
      this.params = [0, 1, 2, 3, 4, 5, 6, 7, 8].map((v) => {
        let obj = const_9149.getInitParams();
        obj.groupnum = v;
        return obj;
      });
    },
    // 获取参数
    getParams(showLoad) {
      // 定义等待框
      let loading;
      if (showLoad) {
        loading = this.$layer.loading(1);
      }
      // 启动按钮不可点击
      this.startTestFlag = false;
      // TODO 参数类型 来自于启动时的类型 type
      // let {
      //   hvMonUppernum1,
      // } = this.params;
      let paramtype = const_9149.paramsTypeList.filter((v) => v.type == this.type)[0].value;
      let parms = {
        opCmd: this.cmd.get,
        devId: this.batt.fbsdeviceId,
        paramtype,
      };
      // 查询后台
      getParams(parms)
        .then((res) => {
          res = res.data;
          if (res.code && res.data) {
            this.params = res.data2;
            console.log(res.data2, '===data2')
            this.$layer.msg("读取成功!");
            // 设置按钮可点击
            this.setTestFlag = true;
          } else {
            // 初始化参数
            this.initParams();
            // 设置按钮不可点击
            this.setTestFlag = false;
            this.$layer.msg("读取失败!");
          }
          // 关闭等待框
          this.$layer.close(loading);
          this.reset();
        })
        .catch((error) => {
          console.log(error);
          // 初始化参数
          this.initParams();
          // 设置按钮不可点击
          this.setTestFlag = false;
          // 关闭等待框
          this.$layer.close(loading);
          this.reset();
          this.$layer.msg("读取失败,读取请求异常!");
        });
    },
    // 提交表单设置参数
    submitFrom() {
      let list = [0, 1, 2, 3, 4, 5, 6, 7, 8].map((v) => this.$refs['params' + v][0].$children[0].validate());
      Promise.all(list).then((res) => {
        // console.log(res, '===p res');
        // 设置参数
        this.setParamsCheck();
      }).catch(e => {
        let r = [];
        list.forEach((v, i) => {
          v.then(a => console.log(a, i)).catch(e => {
            if (!r.length) {
              this.acTabs = 'tab_' + i;
              this.$layer.msg("存在校验未通过的数据!");
            }
            r.push(i);
          });
        })
        // if (e === false) {
        //   this.acTabs = 'tab_' + r[0];
        //   this.$layer.msg("存在校验未通过的数据!");
        // }
      });
    },
    setParamsCheck() {
      if (config.dischargeByFace.value) {
        this.setFaceShow = true;
      } else {
        this.setParams(true);
      }
    },
    // 设置参数
    setParams() {
      // 等待框
      let loading = this.$layer.loading(1);
      // let params = {
      //   ...this.params,
      //   opCmd: const_9149.cmd.set,
      // }
      let params = this.params.map((v) => {
        v.opCmd = const_9149.cmd.set;
        return v;
      });
      // 请求后台
      setParams(params)
        .then((res) => {
          res = res.data;
          if (res.code && res.data) {
            // 启动按钮可点击
            this.startTestFlag = true;
            // 提示信息
            this.$layer.msg("设置成功");
          } else {
            // 启动按钮不可点击
            this.startTestFlag = false;
            // 提示信息
            this.$layer.msg("设置失败!");
          }
          // 关闭等待框
          this.$layer.close(loading);
        })
        .catch((error) => {
          console.log(error);
          // 关闭等待框
          this.$layer.close(loading);
          // 启动按钮不可点击
          this.startTestFlag = false;
          // 提示信息
          this.$layer.msg("设置失败,设置请求异常!");
        });
    },
    startTestCheck(list) {
      this.testList = list;
      if (config.dischargeByFace.value) {
        this.startFaceShow = true;
      } else {
        this.confirmStartTest();
      }
    },
    // 确认框
    confirmStartTest() {
      this.$layer.prompt(
        {
          title: "输入启动口令,并确认",
          formType: 2,
          area: ["300px", "180px"],
        },
        (pass, index) => {
          // 请求后台校验密码
          checkUserPwd(pass)
            .then((res) => {
              res = res.data;
              if (res.code) {
                // 关闭弹出框
                this.$layer.close(index);
                this.$layer.msg("密码检测通过,启动测试");
                this.selectGroupVisible = false;
                // 启动测试
                this.startTest();
              } else {
                this.$layer.msg("启动口令错误!");
              }
            })
            .catch((error) => {
              console.log(error);
              this.$layer.msg("网络请求异常");
            });
        }
      );
    },
    // 启动
    startTest() {
      // 等待框
      let loading = this.$layer.loading(1);
      let params = {
        battGroupNums: this.testList.join(','),
        opCmd: this.cmd.start,
        devId: this.batt.fbsdeviceId,
        testCmd: this.testCmd[this.type],
      }
      // 请求后台
      start(params)
        .then((res) => {
          res = res.data;
          if (res.code && res.data[Object.keys(res.data)[0]]) {
            // 提示信息
            this.$layer.msg("启动测试成功");
            // 关闭弹出框
            this.$emit("close");
          } else {
            // 提示信息
            this.$layer.msg("启动测试失败!");
          }
          // 关闭等待框
          this.$layer.close(loading);
        })
        .catch((error) => {
          console.log(error);
          // 关闭等待框
          this.$layer.close(loading);
          // 提示信息
          this.$layer.msg("启动测试失败,启动测试请求异常!");
        });
    },
    checkValIsInObjects(val, objects) {
      let rs = false;
      for (let i = 0; i < objects.length; i++) {
        let obj = objects[i];
        if (obj.value === val) {
          rs = true;
          break;
        }
      }
      return false;
    },
    setFaceSuccess() {
      this.setFaceShow = false;
      this.setParams();
    },
    startFaceSuccess() {
      this.startFaceShow = false;
      this.startTest();
    },
    copy() {
      let idx = this.acTabs.split('_')[1] * 1;
      // 后面可以加上验证
      this.copyedParams = this.params[idx];
      this.copyedIdx = idx;
    },
    reset() {
      this.copyedIdx = -1;
      this.copyedParams = null;
    },
    paste() {
      let idx = this.acTabs.split('_')[1] * 1;
      // this.params[idx] = { ...this.copyedParams, groupnum: idx };
      this.$set(this.params, idx, { ...this.copyedParams, groupnum: idx });
    },
    // 选择要启动的电池组
    selectGroup() {
      this.selectGroupVisible = true;
    },
  },
  computed: {
    otherParams() {
      let batt = this.batt;
      let groupInfo =
        "单体数量:" +
        this.batt.monCount +
        ";电压(V):" +
        this.batt.monVolStd;
      return {
        groupName: batt.stationName + "-" + batt.battGroupName,
        fbsdeviceId: batt.fbsdeviceId,
        groupInfo: groupInfo
      };
    },
    // 0.1C-0.5C  //核容限流(A)
    disCurrRange() {
      let { monCapStd } = this.params;
      let r0 = toFixed(0.1 * monCapStd, 2);
      let r1 = toFixed(0.5 * monCapStd, 2);
      return `${r0}~${r1}`;
    },
    // 0.01-0.10C  //均充转浮充电流(A)
    charSotpCurrRange() {
      let { monCapStd } = this.params;
      let r0 = toFixed(0.01 * monCapStd, 2);
      let r1 = toFixed(0.1 * monCapStd, 2);
      return `${r0}~${r1}`;
    },
    // 0.01-0.10C   //浮充转均充电流(A)
    flowoverCharcurr1Range() {
      let { monCapStd } = this.params;
      let r0 = toFixed(0.01 * monCapStd, 2);
      let r1 = toFixed(0.1 * monCapStd, 2);
      return `${r0}~${r1}`;
    },
    // 0.05-0.20 C   //电池充电限流(A)
    chargeCurrSetRange() {
      let { monCapStd } = this.params;
      let r0 = toFixed(0.05 * monCapStd, 2);
      let r1 = toFixed(0.2 * monCapStd, 2);
      return `${r0}~${r1}`;
    },
  },
  mounted() {
    // 获取数据
    if (this.readOnly) {
      // this.initParams();
      this.params = [
        ...this.paramData
      ];
    } else {
      this.getParams(true);
    }
    // console.log(this.batt, this.readOnly, this.paramData);
  },
};
</script>
<style scoped>
.params-tabs /deep/ .el-tabs__content .el-tab-pane {
  padding: 0 0 10px;
}
.form-footer {
  margin-top: 16px;
  margin-bottom: 16px;
  text-align: right;
}
.form-footer .three-btn {
  margin-left: 12px;
}
.mask {
  position: fixed;
  left: 0;
  top: 0;
  right: 0;
  bottom: 0;
  z-index: -1;
  background: rgba(0, 0, 0, 0.3);
}
</style>
src/views/dataTest/components/bts9149ParamsItem.vue
New file
@@ -0,0 +1,470 @@
<template>
  <el-form ref="ruleForm" size="mini" label-position="top" :model="params" :rules="rules" class="params-dialog">
    <el-row :gutter="row.gutter">
      <el-col :span="row.span">
        <el-form-item label="电池管理方式">
          <el-select v-model="params.battauto" :disabled="readOnly" placeholder="请选择">
            <el-option v-for="item in battManageList" :key="'battm_' + item.value" :label="item.label"
              :value="item.value"></el-option>
          </el-select>
        </el-form-item>
      </el-col>
      <el-col :span="row.span">
        <el-form-item label="定时均充功能">
          <el-select v-model="params.timerchargeable" :disabled="readOnly" placeholder="请选择">
            <el-option v-for="item in JCList" :key="'jc_' + item.value" :label="item.label"
              :value="item.value"></el-option>
          </el-select>
        </el-form-item>
      </el-col>
      <el-col :span="row.span">
        <el-form-item label="电池标称容量(50~200AH)" prop="battnominalcap">
          <el-input v-model="params.battnominalcap" :readonly="readOnly"></el-input>
        </el-form-item>
      </el-col>
      <el-col :span="row.span">
        <el-form-item label="电池浮充电压(20~30V)" prop="battfloatvol">
          <el-input v-model="params.battfloatvol" :readonly="readOnly"></el-input>
        </el-form-item>
      </el-col>
      <el-col :span="row.span">
        <el-form-item label="电池均充电压(20~30V)" prop="battchargevol">
          <el-input v-model="params.battchargevol" :readonly="readOnly"></el-input>
        </el-form-item>
      </el-col>
      <el-col :span="row.span">
        <el-form-item :label="`电池充电限流(${battchargecurr1Range}A)`" prop="battchargecurr1">
          <el-input v-model="params.battchargecurr1" :readonly="readOnly"></el-input>
        </el-form-item>
      </el-col>
      <el-col :span="row.span">
        <el-form-item :label="`浮充转均充电流(${battchargecurr2Range}A)`" prop="battchargecurr2">
          <el-input v-model="params.battchargecurr2" :readonly="readOnly"></el-input>
        </el-form-item>
      </el-col>
      <el-col :span="row.span">
        <el-form-item :label="`均充转浮充电流(${battchargecurr3Range}A)`" prop="battchargecurr3">
          <el-input v-model="params.battchargecurr3" :readonly="readOnly"></el-input>
        </el-form-item>
      </el-col>
      <el-col :span="row.span">
        <el-form-item label="尾电流充电时间(H)">
          <el-select v-model="params.tailcurrchargetime" :disabled="readOnly" placeholder="请选择">
            <el-option v-for="item in CharTimeList" :key="'charTime_' + item" :label="item + '(H)'"
              :value="item"></el-option>
          </el-select>
        </el-form-item>
      </el-col>
      <el-col :span="row.span">
        <el-form-item label="定时均充周期(30~180天)" prop="timerchargeperiod">
          <el-input v-model="params.timerchargeperiod" :readonly="readOnly"></el-input>
        </el-form-item>
      </el-col>
      <el-col :span="row.span">
        <el-form-item label="最长均充时间(1~30H)" prop="maxchargetimehour">
          <el-input v-model="params.maxchargetimehour" :readonly="readOnly"></el-input>
        </el-form-item>
      </el-col>
      <el-col :span="row.span">
        <el-form-item label="温度补偿开关">
          <el-select v-model="params.tempcompensatedable" :disabled="readOnly" placeholder="请选择">
            <el-option v-for="item in switchTempList" :key="'temp_' + item.value" :label="item.label"
              :value="item.value"></el-option>
          </el-select>
        </el-form-item>
      </el-col>
      <el-col :span="row.span">
        <el-form-item label="电池过温点(20~80℃)" prop="batthightemp">
          <el-input v-model="params.batthightemp" :readonly="readOnly"></el-input>
        </el-form-item>
      </el-col>
      <el-col :span="row.span">
        <el-form-item label="电池欠温点(-40~10℃)" prop="battlowtemp">
          <el-input v-model="params.battlowtemp" :readonly="readOnly"></el-input>
        </el-form-item>
      </el-col>
      <el-col :span="row.span">
        <el-form-item label="温补中心点(10~40℃)" prop="compensatedtemp">
          <el-input v-model="params.compensatedtemp" :readonly="readOnly"></el-input>
        </el-form-item>
      </el-col>
      <el-col :span="row.span">
        <el-form-item label="温补系数(0~50mV/℃)" prop="tempcompensatedcoe">
          <el-input v-model="params.tempcompensatedcoe" :readonly="readOnly"></el-input>
        </el-form-item>
      </el-col>
      <el-col :span="row.span">
        <el-form-item label="电池放电终止电压(20~30V)" prop="battdischargelowvol">
          <el-input v-model="params.battdischargelowvol" :readonly="readOnly"></el-input>
        </el-form-item>
      </el-col>
      <el-col :span="row.span">
        <el-form-item label="单节放电终止电压(1.6~15V)" prop="mondischargelowvol">
          <el-input v-model="params.mondischargelowvol" :readonly="readOnly"></el-input>
        </el-form-item>
      </el-col>
      <el-col :span="row.span">
        <el-form-item label="本地远程设置">
          <el-select v-model="params.localremoteset" :disabled="readOnly" placeholder="请选择">
            <el-option v-for="item in OnlineTestFlagList" :key="'OnlineTestFlag_' + item.value" :label="item.label"
              :value="item.value"></el-option>
          </el-select>
        </el-form-item>
      </el-col>
      <el-col :span="row.span">
        <el-form-item label="电池充电控制">
          <el-select v-model="params.battchrgctrl" :disabled="readOnly" placeholder="请选择">
            <el-option v-for="item in CharWaitTimeList" :key="'CharWaitTime_' + item.value" :label="item.label"
              :value="item.value"></el-option>
          </el-select>
        </el-form-item>
      </el-col>
      <el-col :span="row.span">
        <el-form-item label="电池放电控制">
          <el-select v-model="params.battdisctrl" :disabled="readOnly" placeholder="请选择">
            <el-option v-for="item in DisWaitTimeList" :key="'DisWaitTime_' + item.value" :label="item.label"
              :value="item.value"></el-option>
          </el-select>
        </el-form-item>
      </el-col>
      <el-col :span="row.span">
        <el-form-item :label="`核容限流(${herongcurrRange}A)`" prop="herongcurr">
          <el-input v-model="params.herongcurr" :readonly="readOnly"></el-input>
        </el-form-item>
      </el-col>
      <el-col :span="row.span">
        <el-form-item label="核容时限(0~20H)" prop="herongtimehour">
          <el-input v-model="params.herongtimehour" :readonly="readOnly"></el-input>
        </el-form-item>
      </el-col>
      <el-col :span="row.span">
        <el-form-item label="内部单体下限值(1.6~13.6V)" prop="monvollow">
          <el-input v-model="params.monvollow" :readonly="readOnly"></el-input>
        </el-form-item>
      </el-col>
    </el-row>
  </el-form>
</template>
<script>
import { testVal } from "@/assets/js/tools";
import const_9149 from "@/assets/js/const/const_9149";
import toFixed from "@/assets/js/tools/toFixed";
const rules = const_9149.dischargeRules;
export default {
  name: "BtsDischargeParams",
  props: {
    batt: {
      type: Object,
      default() {
        return {};
      },
    },
    // 只读模式 显示参数用
    readOnly: {
      type: Boolean,
      default: false
    },
    params: {
      type: Object,
      required: true,
      default() {
        return {}
      }
    },
    type: {
      type: String,
      default: 'charge'
    },
  },
  data() {
    let {
      cmd,
      testCmd,
      dischargeRules: rules,
      CharWaitTimeList,
      DisWaitTimeList,
      OnlineTestFlagList,
      switchTempList,
      CharTimeList,
      JCList,
      paramsTypeList,
      battManageList,
      groupIndexList,
      getInitParams,
    } = const_9149;
    return {
      row: {
        gutter: 16,
        span: 6,
      },
      cacheParams: {
        0: null,
        1: null,
        2: null,
        3: null
      },
      startNum: 0,
      battGroupNum: 0,
      CharWaitTimeList,
      DisWaitTimeList,
      OnlineTestFlagList,
      switchTempList,
      CharTimeList,
      JCList,
      paramsTypeList,
      battManageList,
      setFaceShow: false,
      startFaceShow: false,
      cmd: cmd, // 操作命令
      testCmd,
      startTestFlag: false, // 启动测试的状态
      setTestFlag: false, // 设置参数的状态
      groupIndexList,
      rules: {
        battnominalcap: [
          {
            validator(rule, value, callback) {
              testVal(rule, value, callback, rules.battnominalcap);
            },
            trigger: "change",
          },
        ],
        battfloatvol: [
          {
            validator(rule, value, callback) {
              testVal(rule, value, callback, rules.battfloatvol);
            },
            trigger: "change",
          },
        ],
        battchargevol: [
          {
            validator(rule, value, callback) {
              testVal(rule, value, callback, rules.battchargevol);
            },
            trigger: "change",
          },
        ],
        battchargecurr1: [
          {
            validator(rule, value, callback) {
              testVal(rule, value, callback, rules.battchargecurr1);
            },
            trigger: "change",
          },
        ],
        battchargecurr2: [
          {
            validator(rule, value, callback) {
              testVal(rule, value, callback, rules.battchargecurr2);
            },
            trigger: "change",
          },
        ],
        battchargecurr3: [
          {
            validator(rule, value, callback) {
              testVal(rule, value, callback, rules.battchargecurr3);
            },
            trigger: "change",
          },
        ],
        timerchargeperiod: [
          {
            validator(rule, value, callback) {
              testVal(rule, value, callback, rules.timerchargeperiod);
            },
            trigger: "change",
          },
        ],
        maxchargetimehour: [
          {
            validator(rule, value, callback) {
              testVal(rule, value, callback, rules.maxchargetimehour);
            },
            trigger: "change",
          },
        ],
        batthightemp: [
          {
            validator(rule, value, callback) {
              testVal(rule, value, callback, rules.batthightemp);
            },
            trigger: "change",
          },
        ],
        battlowtemp: [
          {
            validator(rule, value, callback) {
              testVal(rule, value, callback, rules.battlowtemp);
            },
            trigger: "change",
          },
        ],
        compensatedtemp: [
          {
            validator(rule, value, callback) {
              testVal(rule, value, callback, rules.compensatedtemp);
            },
            trigger: "change",
          },
        ],
        tempcompensatedcoe: [
          {
            validator(rule, value, callback) {
              testVal(rule, value, callback, rules.tempcompensatedcoe);
            },
            trigger: "change",
          },
        ],
        battdischargelowvol: [
          {
            validator(rule, value, callback) {
              testVal(rule, value, callback, rules.battdischargelowvol);
            },
            trigger: "change",
          },
        ],
        mondischargelowvol: [
          {
            validator(rule, value, callback) {
              testVal(rule, value, callback, rules.mondischargelowvol);
            },
            trigger: "change",
          },
        ],
        herongcurr: [
          {
            validator(rule, value, callback) {
              testVal(rule, value, callback, rules.herongcurr);
            },
            trigger: "change",
          },
        ],
        herongtimehour: [
          {
            validator(rule, value, callback) {
              testVal(rule, value, callback, rules.herongtimehour);
            },
            trigger: "change",
          },
        ],
        monvollow: [
          {
            validator(rule, value, callback) {
              testVal(rule, value, callback, rules.monvollow);
            },
            trigger: "change",
          },
        ]
      },
    };
  },
  watch: {
    'params.battnominalcap': {
      handler(num) {
        // 计算rules
        let names = ['herongcurr', 'battchargecurr3', 'battchargecurr2', 'battchargecurr1'];
        this.upDateRules(names, num);
      },
      immediate: true
    }
  },
  methods: {
    battNumChanged() {
      let num = this.battGroupNum;
      let cache = this.cacheParams[num];
      if (cache) {
        this.params = cache;
        this.startTestFlag = true;
      } else {
        this.initParams();
        this.startTestFlag = false;
      }
    },
    upDateRules(names, num) {
      let range = [0, 1];
      names.forEach((v) => {
        switch (v) {
          case 'herongcurr':
            range = [0.1, 0.5];
            break;
          case 'battchargecurr3':
            range = [0.01, 0.1];
            break;
          case 'battchargecurr2':
            range = [0.01, 0.1];
            break;
          case 'battchargecurr1':
            range = [0.05, 0.2];
            break;
        }
        // 修改取值范围
        rules[v].min = toFixed(range[0] * num, 2);
        rules[v].max = toFixed(range[1] * num, 2);
        rules[v].msg =
          "取值范围" +
          rules[v].min +
          "~" +
          rules[v].max +
          "(保留两位小数)";
        this.rules[v] = [
          {
            validator(rule, value, callback) {
              testVal(rule, value, callback, rules[v]);
            },
            trigger: "change",
          },
        ];
        let value = this.params[v];
        this.params[v] = '';
        this.$nextTick(() => {
          this.params[v] = value;
        })
      });
    },
  },
  computed: {
    // 0.1C-0.5C  //核容限流(A)
    herongcurrRange() {
      let { battnominalcap } = this.params;
      let r0 = toFixed(0.1 * battnominalcap, 2);
      let r1 = toFixed(0.5 * battnominalcap, 2);
      return `${r0}~${r1}`;
    },
    // 0.01-0.10C  //均充转浮充电流(A)
    battchargecurr3Range() {
      let { battnominalcap } = this.params;
      let r0 = toFixed(0.01 * battnominalcap, 2);
      let r1 = toFixed(0.1 * battnominalcap, 2);
      return `${r0}~${r1}`;
    },
    // 0.01-0.10C   //浮充转均充电流(A)
    battchargecurr2Range() {
      let { battnominalcap } = this.params;
      let r0 = toFixed(0.01 * battnominalcap, 2);
      let r1 = toFixed(0.1 * battnominalcap, 2);
      return `${r0}~${r1}`;
    },
    // 0.05-0.20 C   //电池充电限流(A)
    battchargecurr1Range() {
      let { battnominalcap } = this.params;
      let r0 = toFixed(0.05 * battnominalcap, 2);
      let r1 = toFixed(0.2 * battnominalcap, 2);
      return `${r0}~${r1}`;
    },
  },
  mounted() {
  },
};
</script>
<style scoped>
</style>
src/views/dataTest/components/diagrams/parallelPower9149/index.vue
New file
@@ -0,0 +1,148 @@
<template>
  <div class="diagram-content">
    <div class="diagram-stc" ref="static"></div>
    <div class="diagram-flush" ref="flush"></div>
  </div>
</template>
<script>
import circuitDiagram from "./js/circuitDiagram";
import diagramStates from "./js/diagramStates";
export default {
  diagram: "",
  props: {
    type: {
      type: Number,
      default: -1,
    },
    update: {
      type: Boolean,
      default: true,
    },
    rtData: {
      type: Object,
      default() {
        return {}
      }
    }
  },
  watch: {
    type() {
      this.setDiagramByType();
    },
    update(val) {
      let diagram = this.$options.diagram;
      if (val) {
        diagram.start(true);
      } else {
        diagram.stop();
      }
    },
    rtData: {
      handler(n) {
        if (Object.keys(n).length) {
          this.updateDiagram(n);
        }
      },
      deep: true
    },
  },
  methods: {
    init() {
      // 设置更新状态
      if (!this.update) {
        this.$options.diagram.stop();
      }
    },
    // setDiagramByType() {
    //   let type = this.type;
    //   let diagram = this.$options.diagram;
    //   switch (type) {
    //     case -1: // 设备断开
    //       diagramStates(diagram, "break");
    //       break;
    //     case 0: // 浮充
    //       diagramStates(diagram, "float");
    //       break;
    //     case 1: // 放电
    //       diagramStates(diagram, "discharge");
    //       break;
    //     case 2: // 充电
    //       diagramStates(diagram, "charge");
    //       break;
    //     case 3: // KD测试
    //       diagramStates(diagram, "kd");
    //       break;
    //     case 4: // 离线养护测试
    //       diagramStates(diagram, "yh");
    //       break;
    //     case 5: // 停电放电
    //       diagramStates(diagram, "powerCutDischarge");
    //       break;
    //     default:
    //       diagramStates(diagram, "");
    //       break;
    //   }
    // },
    updateDiagram(data) {
      let diagram = this.$options.diagram;
      let {
        acua1,
        acub1,
        acuc1,
        acua2,
        acub2,
        acuc2,
        totalCurr,
        onlinevol,
        accurrrindex,
      } = data;
      if (!diagram) {
        return false;
      }
      const state = ['浮充', '均充', '供电', '核容', '尾充'];
      // 1#交流信息
      diagram.setOption("Ua1", "text", acua1);
      diagram.setOption("Ub1", "text", acub1);
      diagram.setOption("Uc1", "text", acuc1);
      // 2#交流信息
      diagram.setOption("Ua2", "text", acua2);
      diagram.setOption("Ub2", "text", acub2);
      diagram.setOption("Uc2", "text", acuc2);
      // 在线电压
      diagram.setOption("onlineVol", "text", onlinevol + 'V');
      // 总电流
      diagram.setOption('totalCurr', 'text', totalCurr + 'A');
      // ac来源
      diagram.setOption("AcInput", "text", [1, 2][accurrrindex] + '#');
      for (let i = 1, j = 9; i <= j; i++) {
        // 电池组状态
        diagram.setOption("battState" + i, "text", state[data['battState' + i]] || '未知');
        // 电池电压
        diagram.setOption("groupVol" + i, "text", data['modOutvol' + i] + 'V');
        // 电池电流
        diagram.setOption("groupCurr" + i, "text", data['modOutcurr' + i] + 'A');
        // 使能开关
        diagram.setOption("switchBox" + i, "isOn", data['modEnable' + i]);
      }
    },
  },
  mounted() {
    this.$options.diagram = circuitDiagram(this.$refs.static, this.$refs.flush);
    // 初始化数据
    this.init();
    // 设置充放电的类型
    // this.setDiagramByType();
  },
  destroyed() {
    if (this.$options.diagram) {
      this.$options.diagram.stop();
    }
  },
};
</script>
src/views/dataTest/components/diagrams/parallelPower9149/js/DiagramExtend.js
New file
@@ -0,0 +1,225 @@
import Diagram from '@/views/dataTest/diagram';
function extend(child, parent) {
  let prototype = Object.create(parent.prototype);
  prototype.constructor = child;
  child.prototype = prototype;
}
function DiagramExtend(width, height) {
  Diagram.call(this);
  if (width) {
    this.width = width;
  }
  if (height) {
    this.height = height;
  }
}
// 继承
extend(DiagramExtend, Diagram);
// 画AcDc
DiagramExtend.prototype.acdc = function (option) {
  // 默认参数
  let defaults = {
    lineWidth: 2,
    strokeStyle: '#fff',
    boxWidth: 80,
    // 方块的中心
    center: [200, 200],
    lineLength: 50,
    method: 'acdc',
  };
  option = Object.assign({}, defaults, option);
  let ctx = option.flush ? this.f_ctx : this.s_ctx; // 获取上下文
  let {
    center,
    lineWidth,
    strokeStyle,
    boxWidth,
    lineLength,
  } = option;
  ctx.save();
  ctx.beginPath();
  ctx.lineWidth = lineWidth;
  ctx.strokeStyle = strokeStyle;
  let start = [center[0] - boxWidth / 2, center[1] - boxWidth / 2];
  ctx.moveTo(...start);
  ctx.lineTo(start[0] + boxWidth, start[1]);
  ctx.lineTo(start[0] + boxWidth, start[1] + boxWidth);
  ctx.lineTo(start[0], start[1] + boxWidth);
  ctx.lineTo(...start);
  ctx.lineTo(start[0] + boxWidth, start[1] + boxWidth);
  ctx.moveTo(...center);
  ctx.lineTo(start[0], start[1] + boxWidth);
  ctx.moveTo(start[0], center[1]);
  ctx.lineTo(start[0] - lineLength, center[1]);
  ctx.stroke();
  // 文字
  ctx.fillStyle = '#fff';
  ctx.font = "16px Arial";
  ctx.textBaseline = 'middle';
  ctx.textAlign = 'center';
  ctx.fillText('AC', center[0] - boxWidth * 2 / 7, center[1]);
  ctx.fillText('DC', center[0] + boxWidth / 5, center[1] - boxWidth / 5);
  ctx.fillText('DC', center[0], center[1] + boxWidth / 3);
  ctx.restore();
  option.leftP = [start[0] - lineLength, center[1]];
  // 添加配置项
  this.addOptions(option);
  return {
    topP: [center[0], start[1]],
    bottomP: [center[0], start[1] + boxWidth],
    center: [...center]
  };
}
// 开关盒
DiagramExtend.prototype.switchBox = function (option) {
  // 默认参数
  let defaults = {
    flush: true,
    lineWidth: 2,
    strokeStyle: '#fff',
    fillStyle: '#fff',
    boxWidth: 40,
    boxHeight: 100,
    r: 4,
    isOn: true,
    // 方块的中心
    center: [200, 200],
    method: 'switchBox',
  };
  option = Object.assign({}, defaults, option);
  let ctx = option.flush ? this.f_ctx : this.s_ctx; // 获取上下文
  let {
    center,
    lineWidth,
    strokeStyle,
    boxWidth,
    boxHeight,
    fillStyle,
    r,
    isOn,
  } = option;
  ctx.save();
  ctx.beginPath();
  ctx.lineWidth = lineWidth;
  ctx.strokeStyle = strokeStyle;
  let start = [center[0] - boxWidth / 2, center[1] - boxHeight / 2];
  ctx.moveTo(...start);
  ctx.lineTo(start[0] + boxWidth, start[1]);
  ctx.lineTo(start[0] + boxWidth, start[1] + boxHeight);
  ctx.lineTo(start[0], start[1] + boxHeight);
  ctx.lineTo(...start);
  ctx.stroke();
  ctx.beginPath();
  ctx.fillStyle = fillStyle;
  ctx.arc(center[0], start[1], r, 0, Math.PI * 2);
  ctx.arc(center[0], start[1] + boxHeight, r, 0, Math.PI * 2);
  ctx.arc(...center, r, 0, Math.PI * 2);
  ctx.fill();
  let ang = isOn ? 3 * Math.PI / 180 : 20 * Math.PI / 180;
  ctx.save();
  ctx.translate(center[0], start[1]);
  ctx.beginPath();
  ctx.moveTo(0, 0);
  ctx.rotate(ang);
  ctx.lineTo(0, boxHeight / 2);
  ctx.stroke();
  ctx.restore();
  ctx.save();
  ctx.translate(center[0], start[1] + boxHeight);
  ctx.beginPath();
  ctx.moveTo(0, 0);
  ctx.rotate(ang);
  ctx.lineTo(0, - boxHeight / 2);
  ctx.stroke();
  ctx.restore();
  ctx.restore();
  // 添加配置项
  this.addOptions(option);
  return {
    topP: [center[0], start[1]],
    bottomP: [center[0], start[1] + boxHeight],
    center: [...center]
  };
}
// 交流电源 数据面板
DiagramExtend.prototype.powerInfo = function (option) {
  // 默认参数
  let defaults = {
    flush: true,
    lineWidth: 2,
    strokeStyle: '#fff',
    fillStyle: '#fff',
    boxWidth: 160,
    boxHeight: 160,
    // 方块的中心
    center: [200, 200],
    lineLen: 60,
    font: '24px Arial',
    idx: 1,
    method: 'powerInfo',
  };
  option = Object.assign({}, defaults, option);
  let ctx = option.flush ? this.f_ctx : this.s_ctx; // 获取上下文
  let {
    center,
    lineWidth,
    strokeStyle,
    boxWidth,
    boxHeight,
    fillStyle,
    lineLen,
    font,
    idx,
  } = option;
  ctx.save();
  // ctx.translate(center);
  ctx.beginPath();
  ctx.lineWidth = lineWidth;
  ctx.strokeStyle = strokeStyle;
  let start = [center[0] - boxWidth / 2, center[1] - boxHeight / 2];
  ctx.moveTo(...start);
  ctx.lineTo(start[0] + boxWidth, start[1]);
  ctx.lineTo(start[0] + boxWidth, start[1] + boxHeight);
  ctx.lineTo(start[0], start[1] + boxHeight);
  ctx.lineTo(...start);
  ctx.moveTo(center[0] + boxWidth / 2, center[1]);
  ctx.lineTo(center[0] + boxWidth / 2 + lineLen, center[1]);
  ctx.stroke();
  let arr = [`${idx}#交流`, 'Ua:', 'Ub:', 'Uc:'];
  // 中心在Y轴上基数
  let _center = (arr.length - 1) / 2;
  ctx.fillStyle = fillStyle;
  ctx.font = font;
  ctx.textAlign = 'left';
  ctx.textBaseline = 'middle';
  let textPoints = [];
  arr.forEach((v, i) => {
    let x = center[0] - boxWidth / 2 + 10,
        y = center[1] + (i - _center) * (boxHeight / 4);
    textPoints.push([x, y]);
    ctx.fillText(v, x, y);
  });
  ctx.textAlign = 'end';
  ctx.fillText(`${idx}#`, start[0] + boxWidth + lineLen, center[1] - 20);
  ctx.restore();
  option.textPoints = textPoints;
  // 添加配置项
  this.addOptions(option);
  return {
    center: [...center]
  };
}
export default DiagramExtend;
src/views/dataTest/components/diagrams/parallelPower9149/js/circuitDiagram.js
New file
@@ -0,0 +1,296 @@
import DiagramExtend from './DiagramExtend';
import eleGroupImage from '@/views/dataTest/diagram/images/elegroup.png'
// 基础配置
const strokeStyle = '#fff';
//  顶上等长的横线长度
const lineLen = 150;
// 竖线长度
const lineVLen1 = 40;
const lineVLen2 = 100;
const lineVLen3 = 120;
const textFont = 20;
const offsetLeft = 46;
const font_power = 24;
const ROUTECOUNT = 9;
// 绘制电路图
function circuitDiagram(stc, flush) {
  // let diagram = new DiagramExtend(1450, 630);
  let diagram = new DiagramExtend(1740, 630);
  diagram.setCanvas(stc, flush);
  // let start = [240, 40];
  // if (startPoint) {
  //   start = startPoint;
  // }
  let line1 = diagram.line({
    id: 'line1',
    points: [
      [20, 36],
      [430, 36]
    ],
    strokeStyle,
  });
  // 循环画九条支路
  for (let i = 0; i < ROUTECOUNT; i++) {
    drawItem(i, diagram);
  }
  let powerInfo1 = diagram.powerInfo({
    id: 'powerInfo1',
    center: [line1[0][0] + 100, line1[0][1] + 120],
  });
  diagram.powerInfo({
    id: 'powerInfo2',
    center: [powerInfo1.center[0], powerInfo1.center[1] + 180],
    idx: 2,
  });
  setDiagramTexts(diagram);
  return diagram;
}
function setDiagramTexts(diagram) {
  const fontColor = '#ff0';
  // 在线电压
  let line1 = diagram.getOption('line1').points;
  diagram.text({
    id: 'onlineVol',
    flush: true,
    baseline: 'bottom',
    align: 'center',
    fontSize: textFont,
    fillStyle: fontColor,
    point: [line1[0][0] + 150, line1[0][1] - 10],
    text: '48.1V'
  });
  // 总电流
  diagram.text({
    id: 'totalCurr',
    flush: true,
    baseline: 'bottom',
    align: 'center',
    fontSize: textFont,
    fillStyle: fontColor,
    point: [line1[0][0] + 320, line1[0][1] - 10],
    text: '0A'
  });
  // 交流来源
  let acdc1 = diagram.getOption('acdc1').leftP;
  diagram.text({
    id: 'AcInput',
    flush: true,
    baseline: 'middle',
    align: 'right',
    fontSize: textFont,
    fillStyle: fontColor,
    point: [acdc1[0] - 6, acdc1[1]],
    text: '#1'
  });
  for (let i = 1, j = 9; i <= j; i++) {
    // 组工作状态
    let line2vObj = diagram.getOption('line2v' + i).points;
    diagram.text({
      id: 'battState' + i,
      flush: true,
      baseline: 'top',
      align: 'left',
      fontSize: textFont,
      fillStyle: fontColor,
      point: [line2vObj[0][0] + 10, line2vObj[0][1] + 20],
      text: '浮充'
    });
    // 组电压 电流
    let line3vObj = diagram.getOption('line3v' + i).points;
    diagram.text({
      id: 'groupVol' + i,
      flush: true,
      baseline: 'top',
      align: 'left',
      fontSize: textFont,
      fillStyle: fontColor,
      point: [line3vObj[0][0] + 10, line3vObj[0][1] + 20],
      text: '0V'
    });
    diagram.text({
      id: 'groupCurr' + i,
      flush: true,
      baseline: 'top',
      align: 'left',
      fontSize: textFont,
      fillStyle: fontColor,
      point: [line3vObj[0][0] + 10, line3vObj[0][1] + 70],
      text: '0A'
    });
  }
  // 交流1数据
  let powerInfo1 = diagram.getOption('powerInfo1').textPoints;
  diagram.text({
    id: 'Ua1',
    flush: true,
    baseline: 'middle',
    align: 'left',
    fontSize: font_power,
    fillStyle: fontColor,
    point: [powerInfo1[1][0] + offsetLeft, powerInfo1[1][1]],
    text: '0.0'
  });
  diagram.text({
    id: 'Ub1',
    flush: true,
    baseline: 'middle',
    align: 'left',
    fontSize: font_power,
    fillStyle: fontColor,
    point: [powerInfo1[2][0] + offsetLeft, powerInfo1[2][1]],
    text: '0.0'
  });
  diagram.text({
    id: 'Uc1',
    flush: true,
    baseline: 'middle',
    align: 'left',
    fontSize: font_power,
    fillStyle: fontColor,
    point: [powerInfo1[3][0] + offsetLeft, powerInfo1[3][1]],
    text: '0.0'
  });
  // 交流2数据
  let powerInfo2 = diagram.getOption('powerInfo2').textPoints;
  diagram.text({
    id: 'Ua2',
    flush: true,
    baseline: 'middle',
    align: 'left',
    fontSize: font_power,
    fillStyle: fontColor,
    point: [powerInfo2[1][0] + offsetLeft, powerInfo2[1][1]],
    text: '0.0'
  });
  diagram.text({
    id: 'Ub2',
    flush: true,
    baseline: 'middle',
    align: 'left',
    fontSize: font_power,
    fillStyle: fontColor,
    point: [powerInfo2[2][0] + offsetLeft, powerInfo2[2][1]],
    text: '0.0'
  });
  diagram.text({
    id: 'Uc2',
    flush: true,
    baseline: 'middle',
    align: 'left',
    fontSize: font_power,
    fillStyle: fontColor,
    point: [powerInfo2[3][0] + offsetLeft, powerInfo2[3][1]],
    text: '0.0'
  });
}
function drawItem(idx, diagram) {
  const IDX = idx + 1;
  let lineName = 'line' + IDX;
  let lineV1Name = 'linev' + IDX;
  let lineName_next = 'line' + (IDX + 1);
  let _lineLen = idx == ROUTECOUNT - 1 ? 100 : lineLen;
  let point = diagram.getOption(lineName).points;
  let acdcName = 'acdc' + IDX;
  diagram.line({
    id: lineV1Name,
    points: [
      point[1],
      [point[1][0], point[1][1] + lineVLen1]
    ],
    strokeStyle,
  });
  let point1 = diagram.getOption(lineV1Name).points;
  let acdcObj = diagram.acdc({
    id: acdcName,
    center: [point1[1][0], point1[1][1] + 40]
  });
  let lineV2Name = 'line2v' + IDX;
  let lineV2Obj = diagram.line({
    id: lineV2Name,
    points: [
      acdcObj.bottomP,
      [acdcObj.bottomP[0], acdcObj.bottomP[1] + lineVLen2]
    ],
    strokeStyle,
  });
  let switchBoxName = 'switchBox' + IDX;
  let switchBoxObj = diagram.switchBox({
    id: switchBoxName,
    center: [lineV2Obj[1][0], lineV2Obj[1][1] + 50]
  });
  let line3vName = 'line3v' + IDX;
  let line3vObj = diagram.line({
    id: line3vName,
    points: [
      switchBoxObj.bottomP,
      [switchBoxObj.bottomP[0], switchBoxObj.bottomP[1] + lineVLen3]
    ],
    strokeStyle
  });
  // 绘制电池组1
  let width1 = 37;
  let height1 = 61;
  let springGreen = "#50cef5";
  let eleGroup_1 = diagram.drawImage({
    point: [line3vObj[1][0] - width1 / 2, line3vObj[1][1]],
    url: eleGroupImage,
    width: width1,
    height: height1,
  });
  // 绘制虚线
  let dashLine1 = diagram.dashLine({
    strokeStyle: springGreen,
    lineWidth: 4,
    points: [
      eleGroup_1.bottom,
      [eleGroup_1.bottom[0], eleGroup_1.bottom[1] + 20]
    ],
  });
  let eleGroup1_2 = diagram.drawImage({
    point: [dashLine1[1][0] - width1 / 2, dashLine1[1][1]],
    url: eleGroupImage,
    width: width1,
    height: height1,
  });
  diagram.text({
    text: '组&' + IDX,
    point: [dashLine1[0][0] + 37, dashLine1[0][1] - 6],
    baseline: 'middle',
    align: 'center',
    fontSize: textFont,
  });
  diagram.line({
    id: lineName_next,
    points: [
      point[1],
      [point[1][0] + _lineLen, point[1][1]]
    ],
    strokeStyle,
  });
}
export default circuitDiagram;
src/views/dataTest/components/diagrams/parallelPower9149/js/diagramStates.js
New file
@@ -0,0 +1,25 @@
// 基础配置
let springGreen = "#50cef5";
let scalcRadius = 9;
// 放电状态
function diagramStates(diagram, type) {
  // 清除电流
  diagram.del(/^line.*dot$/);
  switch(type) {
    default:
      console.log('默认状态');
    break;
  }
  // // 更新文本数据
  // diagram.setOption('type', 'text', '设备状态未知');
  // diagram.setOption('switchBox1', 'isOn', true);
  // diagram.setOption('switchBox2', 'isOn', false);
  // diagram.setOption('switchBox3', 'isOn', false);
  // diagram.setOption('switchBox4', 'isOn', false);
}
export default diagramStates;
src/views/dataTest/components/selectGroup.vue
New file
@@ -0,0 +1,107 @@
<template>
  <div class="select-group params-dialog">
    <div class="select-content">
      <el-checkbox :indeterminate="isIndeterminate" v-model="checkAll" @change="handleCheckAllChange">全选</el-checkbox>
      <el-button class="btn-reverse" size="mini" type="primary" @click="reverse">反选</el-button>
      <div style="margin: 15px 0;"></div>
      <el-checkbox-group v-model="testList">
        <el-checkbox v-for="idx in 9" :label="idx - 1" :key="'select_' + idx">{{ '组' + idx }}</el-checkbox>
      </el-checkbox-group>
    </div>
    <div class="select-footer">
      <three-btn @click="cancel">取消</three-btn>
      <three-btn @click="ok">{{ 'start' == type ? '启动' : '停止' }}测试</three-btn>
    </div>
  </div>
</template>
<script>
export default {
  props: {
    type: {
      type: String,
      default: 'start'
    },
  },
  data() {
    const list = [0, 1, 2, 3, 4, 5, 6, 7, 8];
    return {
      list,
      isIndeterminate: false,
      checkAll: false,
      testList: [],
    };
  },
  watch: {
  },
  methods: {
    reverse() {
      let list = this.testList;
      let res = this.list.filter((v) => !list.some(vv => vv == v));
      this.testList = res;
      this.checkAll = res.length === 9;
      this.isIndeterminate = res.length > 0 && res.length < 9;
    },
    handleCheckAllChange(val) {
      this.testList = val ? this.list : [];
      this.isIndeterminate = false;
    },
    handleCheckedChange(value) {
      let checkedCount = value.length;
      this.checkAll = checkedCount === 9;
      this.isIndeterminate = checkedCount > 0 && checkedCount < 9;
    },
    ok() {
      if (!this.testList.length) {
        this.$message.error('请选择电池组');
        return false;
      }
      this.$emit('ok', this.testList);
    },
    cancel() {
      this.$emit('cancel');
    }
  },
  computed: {
  },
  mounted() {
  },
};
</script>
<style scoped>
.select-content {
  padding: 0 10px 10px;
}
.select-content label {
  color: #153953;
  font-weight: bold;
  margin-bottom: 0.8em;
}
.select-content /deep/ .el-checkbox__input.is-checked+.el-checkbox__label {
  color: #409EFF;
}
.select-content /deep/ .el-checkbox__input.is-checked .el-checkbox__inner,
.select-content /deep/ .el-checkbox__input.is-indeterminate .el-checkbox__inner {
  background-color: #409EFF;
  border-color: #409EFF;
}
.select-footer {
  text-align: right;
}
.select-footer .three-btn {
  margin-left: 1em;
}
.btn-reverse {
  margin-left: 1em;
}
</style>
src/views/dataTest/js/realTime.js
@@ -867,4 +867,39 @@
    url: "Fbs9100_setparamAction/controllerParalle",
    params
  });
}
/**
 * 读取并联电源9149放电参数
 * {devId, opCmd, paramtype}
 */
export const searchParalleParam9149 = (params) => {
  return axios({
    method: "GET",
    url: "fbs9149Setparam/searchParalleParam9149",
    params
  });
}
/**
 * 设置并联电源9149放电参数
 * 对象数组 参数
 */
export const updateParalleParam9149 = (data) => {
  return axios({
    method: "POST",
    url: "fbs9149Setparam/updateParalleParam9149",
    data
  });
}
/**
 * 控制并联电源9149充放电停止
 * {battGroupNums, devId, opCmd, testCmd}
 */
export const controllerParalle9149 = (params) => {
  return axios({
    method: "GET",
    url: "fbs9149Setparam/controllerParalle9149",
    params
  });
}
src/views/dataTest/movingRingSystem/index.vue
@@ -90,6 +90,11 @@
              path:
                "/dataTest/movingRingSystem/real-time-9141/" + data.battGroupId,
            });
             } else if (regEquipType(dev_id1, "BTS9149")) {
            this.$router.push({
              path:
                "/dataTest/movingRingSystem/real-time-9149/" + data.battGroupId,
            });
          } else {
            this.$router.push({
              path: "/dataTest/movingRingSystem/real-time/" + data.battGroupId,
src/views/dataTest/realTime9149.vue
New file
@@ -0,0 +1,2659 @@
<template>
  <flex-layout direction="row" class="page-real-time" :no-bg="true">
    <home-list v-if="homeListShow" slot="header" @toggleChange="toggleChange" @leaf-click="leafClick"></home-list>
    <content-box style="margin-left: 4px; margin-right: 4px" :title="battFullName">
      <div slot="box-tools" class="box-tools">
        <el-tooltip class="item" effect="dark" content="历史数据" placement="bottom">
          <i class="iconfont el-icon-jinru" @click="syncPage"></i>
        </el-tooltip>
      </div>
      <div slot="box-tools" class="box-tools" style="right: 40px">
        <el-tooltip class="item" effect="dark" content="历史实时数据" placement="bottom">
          <i class="el-iconfont el-icon-s-marketing" @click="historyRealTimeDataDialog.show = true"></i>
        </el-tooltip>
      </div>
      <div slot="box-tools" class="box-tools" style="right: 72px" v-if="esVideoSn">
        <el-tooltip class="item" effect="dark" content="视频监控" placement="bottom">
          <i class="el-iconfont el-icon-video-camera-solid" @click="esVideoDialog = true"></i>
        </el-tooltip>
      </div>
      <div style="right: 72px" slot="box-tools" class="box-tools">
        <el-tooltip class="item" effect="dark" content="通讯状态" placement="bottom">
          <hdw-light :type="isLink"></hdw-light>
        </el-tooltip>
      </div>
      <div slot="box-tools" class="box-tools" style="right: 106px">
        <el-tooltip class="item" effect="dark" content="3D机房" placement="bottom">
          <i class="el-iconfont el-icon-office-building" @click="station.show = true"></i>
        </el-tooltip>
      </div>
      <div slot="box-tools" class="box-tools" style="right: 140px">
        <el-tooltip class="item" effect="dark" content="机房环境图集" placement="bottom">
          <i class="el-iconfont el-icon-picture" @click="homeImageDialog = true"></i>
        </el-tooltip>
      </div>
      <flex-layout :no-bg="true">
        <div class="content-header" slot="header" :model="inputs">
          <div class="table-layout">
            <div class="table-row">
              <div class="table-cell text-right w80">电池状态:</div>
              <div class="table-cell">
                <el-input :value="backInputs.battState" size="small" :disabled="true"></el-input>
              </div>
              <div class="table-cell text-right w80">端电压:</div>
              <div class="table-cell">
                <el-input :value="backInputs.group_online_vol" size="small" :disabled="true"></el-input>
              </div>
              <div class="table-cell text-right w80">电池电流:</div>
              <div class="table-cell">
                <el-input :value="backInputs.groupCurr" size="small" :disabled="true"></el-input>
              </div>
              <div class="table-cell text-right w80">更新日期:</div>
              <div class="table-cell">
                <el-input :value="backInputs.recDatetime" size="small" :disabled="true"></el-input>
              </div>
            </div>
            <div class="table-row">
              <div class="table-cell text-right w80">测试时长:</div>
              <div class="table-cell">
                <el-input :value="backInputs.battTestTlong" size="small" :disabled="true"></el-input>
              </div>
              <div class="table-cell text-right w80">测试容量:</div>
              <div class="table-cell">
                <el-input :value="backInputs.battTestCap" size="small" :disabled="true"></el-input>
              </div>
              <div class="table-cell text-right w80">剩余容量:</div>
              <div class="table-cell">
                <el-input :value="backInputs.batt_syrl_cap" size="small" :disabled="true"></el-input>
              </div>
              <div class="table-cell text-right w80">续航时长:</div>
              <div class="table-cell">
                <el-input :value="backInputs.sysc" size="small" :disabled="true"></el-input>
              </div>
            </div>
          </div>
        </div>
        <div class="page-content">
          <div class="page-content-tools" v-if="control.show && isCanTest">
            <el-popover placement="bottom" trigger="hover">
              <div class="hdw-menu-list">
                <ul>
                  <li class="hdw-menu-item">
                    <a @click="startTest(0)" href="javascript:void(0);">启动充电</a>
                  </li>
                  <li class="hdw-menu-item">
                    <a @click="stopTest(0)" href="javascript:void(0);">停止充电</a>
                  </li>
                  <li class="hdw-menu-item">
                    <a @click="startTest(1)" href="javascript:void(0);">启动放电</a>
                  </li>
                  <li class="hdw-menu-item">
                    <a @click="stopTest(1)" href="javascript:void(0);">停止放电</a>
                  </li>
                </ul>
              </div>
              <button class="hdw-btn transparentBtn" slot="reference">
                <span class="light-color">远程管理</span>
                <i class="hdw-icon el-icon-caret-bottom"></i>
              </button>
            </el-popover>
          </div>
          <el-tabs v-model="acTabs" type="border-card" class="flex-layout noborder" @tab-click="tabClick">
            <el-tab-pane key="eleLine" label="电路拓扑图" class="tab-eleLine" name="eleLine" v-if="pageConfig.eleLine">
              <!-- <div style="position: absolute; top: 8px; left: 8px"> -->
              <div class="left">
                <science-box style="position: relative" no-header v-show="batt.fbsdeviceId">
                  <div class="hdw-state-list table-layout">
                    <div class="table-row">
                      <div class="table-cell text-right">设备工作状态:
                      </div>
                      <div class="table-cell">{{ workState }}</div>
                    </div>
                  </div>
                </science-box>
                <!-- 上次核容测试信息 -->
                <science-box style="position: relative; margin-top: 8px" title="上一次核容测试信息" v-show="batt.fbsdeviceId">
                  <div class="hdw-state-list table-layout">
                    <div v-for="state in lastCapacityTest.filter(
                      (item) => item.show
                    )" :key="state.text" class="table-row" :class="state.type">
                      <div class="table-cell text-right">
                        <i v-if="state.icon" class="iconfont" :class="state.icon"></i>{{ state.text }}
                      </div>
                      <div class="table-cell">
                        {{ state.value }}{{ state.unit }}
                      </div>
                    </div>
                  </div>
                </science-box>
              </div>
              <circuit-diagram v-show="batt.fbsdeviceId" :batt="batt" :rt-data="diagromData"></circuit-diagram>
            </el-tab-pane>
            <el-tab-pane key="vol" label="电压" name="vol" v-if="tabsConfig.vol && pageConfig.vol">
              <bar-chart ref="vol" id="vol" unit="V" :show-tools="true" @right-click="chartRightCLick"></bar-chart>
            </el-tab-pane>
            <el-tab-pane key="res" label="内阻" name="res" v-if="tabsConfig.res && pageConfig.res">
              <bar-chart ref="res" id="res" unit="mΩ" :show-tools="true" max-color="red" min-color="green"
                @right-click="chartRightCLick"></bar-chart>
            </el-tab-pane>
            <el-tab-pane key="temp" label="温度" name="temp" v-if="tabsConfig.temp && pageConfig.temp">
              <bar-chart ref="temp" id="temp" unit="℃" :show-tools="true" max-color="red" min-color="green"
                @right-click="chartRightCLick"></bar-chart>
            </el-tab-pane>
            <el-tab-pane key="conduct" label="电导" name="conduct" v-if="tabsConfig.conduct && pageConfig.conduct">
              <bar-chart ref="conduct" id="conduct" :show-tools="true" @right-click="chartRightCLick"></bar-chart>
            </el-tab-pane>
            <el-tab-pane key="monConnRes" label="链接条阻值" name="monConnRes"
              v-if="tabsConfig.monConnRes && pageConfig.monConnRes">
              <bar-chart ref="monConnRes" id="monConnRes" unit="mΩ" :show-tools="true"
                @right-click="chartRightCLick"></bar-chart>
            </el-tab-pane>
            <el-tab-pane key="curr" label="均衡电流" name="curr" v-if="tabsConfig.curr && pageConfig.curr">
              <bar-chart ref="curr" id="curr" unit="A" :show-tools="true" @right-click="chartRightCLick">
              </bar-chart>
            </el-tab-pane>
            <el-tab-pane key="leakVol" label="漏液电压" name="leakVol" v-if="tabsConfig.leakVol && pageConfig.leakVol">
              <bar-chart ref="leakVol" id="leakVol" unit="V" :show-tools="true"
                @right-click="chartRightCLick"></bar-chart>
            </el-tab-pane>
            <el-tab-pane key="tblData" label="数据表格" name="tblData" class="el-table-wrapper" v-if="pageConfig.tblData">
              <div class="tbl-data-container">
                <div class="tbl-data-body">
                  <el-table stripe size="small" :data="table.datas" :row-class-name="setTableRowClass" height="100%">
                    <el-table-column v-for="header in dataHeaders" :key="header.prop" :prop="header.prop"
                      :label="header.label" :width="header.width" align="center"></el-table-column>
                  </el-table>
                </div>
                <div class="tbl-data-footer">
                  <el-button type="primary" size="mini" round @click="exportFile">导出</el-button>
                </div>
              </div>
            </el-tab-pane>
            <el-tab-pane key="dianchigaojing" label="电池告警" name="dianchigaojing" class="el-table-wrapper"
              v-if="tabsConfig.dianchigaojing && pageConfig.dianchigaojing">
              <div class="dianchigaojing">
                <div class="borderBox box1">
                  <el-table stripe size="small" :data="table1.datas" height="100%">
                    <el-table-column prop="battGroupId" align="center" label="电池组ID">
                    </el-table-column>
                    <el-table-column prop="recordTime" align="center" label="记录时间">
                    </el-table-column>
                    <el-table-column prop="groupVolAlarm" align="center" label="组电压告警">
                      <template slot-scope="scope">
                        <hdw-light :type="scope.row.groupVolAlarm"></hdw-light>
                      </template>
                    </el-table-column>
                    <el-table-column prop="testEndVol" align="center" label="测试终止电压">
                    </el-table-column>
                    <el-table-column prop="testEndCap" align="center" label="测试终止剩余容量">
                    </el-table-column>
                    <el-table-column prop="testTimelong" align="center" label="测试终止时间(秒)">
                    </el-table-column>
                  </el-table>
                </div>
                <div class="borderBox box2">
                  <el-table stripe size="small" :data="table2.datas" height="100%">
                    <el-table-column prop="battGroupId" align="center" label="电池组ID">
                    </el-table-column>
                    <el-table-column prop="recordTime" align="center" label="记录时间">
                    </el-table-column>
                    <el-table-column prop="monNum" align="center" label="单体编号">
                    </el-table-column>
                    <el-table-column prop="monVolAlarm" align="center" label="单体电压告警">
                      <template slot-scope="scope">
                        <hdw-light :type="scope.row.monVolAlarm"></hdw-light>
                      </template>
                    </el-table-column>
                    <el-table-column prop="monTempAlarm" align="center" label="单体温度告警">
                      <template slot-scope="scope">
                        <hdw-light :type="scope.row.monTempAlarm"></hdw-light>
                      </template>
                    </el-table-column>
                    <el-table-column prop="monResAlarm" align="center" label="单体内阻告警">
                      <template slot-scope="scope">
                        <hdw-light :type="scope.row.monResAlarm"></hdw-light>
                      </template>
                    </el-table-column>
                    <el-table-column prop="monRestCapAlarm" align="center" label="单体预估容量告警">
                      <template slot-scope="scope">
                        <hdw-light :type="scope.row.monRestCapAlarm"></hdw-light>
                      </template>
                    </el-table-column>
                  </el-table>
                </div>
              </div>
            </el-tab-pane>
          </el-tabs>
        </div>
      </flex-layout>
    </content-box>
    <!-- 参数设置 -->
    <el-dialog :title="dischargeDialogTitle" width="900px" :visible.sync="dischargeDialog.show"
      :close-on-click-modal="false" top="0" class="dialog-center dialog-params" :modal-append-to-body="false">
      <discharge-dialog-content v-if="dischargeDialog.show" :type="paramsType" :batt="batt" @close="closeDisChargeDialog">
      </discharge-dialog-content>
    </el-dialog>
    <!-- 停止 -->
    <el-dialog :title="dischargeDialogTitle" width="500px" :visible.sync="stopTestVisible" :close-on-click-modal="false"
      top="0" class="dialog-center dialog-params" :modal-append-to-body="false">
      <select-group v-if="stopTestVisible" type="stop" @ok="(data) => stop(data, stopType)" @cancel="stopTestVisible = false"></select-group>
    </el-dialog>
    <!-- 实时历史数据 -->
    <el-dialog :title="histroyDataTitle" width="1200px" :visible.sync="historyRealTimeDataDialog.show"
      :close-on-click-modal="false" top="0" class="dialog-center no-bg" :modal-append-to-body="false">
      <history-realtime-data :batt="batt" v-if="historyRealTimeDataDialog.show"></history-realtime-data>
    </el-dialog>
    <el-dialog title="视频监控" width="600px" :visible.sync="esVideoDialog" :close-on-click-modal="false" top="0"
      class="dialog-center" :modal-append-to-body="false">
      <ez-video v-if="esVideoDialog" :sn="esVideoSn"></ez-video>
    </el-dialog>
    <el-dialog title="历史内阻数据" width="1200px" :visible.sync="hisResDialog" :close-on-click-modal="false" top="0"
      class="dialog-center" :modal-append-to-body="false">
      <history-res v-if="hisResDialog" :batt="batt"></history-res>
    </el-dialog>
    <right-menu :visible.sync="rightMenu.show" :x="rightMenu.x" :y="rightMenu.y">
      <div class="right-menu-list">
        <ul>
          <li>
            <a href="javascript:;" @click="payAttentionMon">添加关注单体</a>
          </li>
          <li>
            <a href="javascript:;" @click="hisResDialog = true">导出历史内阻数据</a>
          </li>
        </ul>
      </div>
    </right-menu>
    <!-- 3d机房 -->
    <el-dialog title="3d机房" class="threeD-dialog" :visible.sync="station.show" :close-on-click-modal="false">
      <div class="station-contain">
        <three-station :data="station.data"></three-station>
      </div>
      <!-- <div slot="footer">
          v-if="station.data.stationId"
        <el-button @click="station.show = false">关闭</el-button>
      </div> -->
    </el-dialog>
    <!-- 机房环境图集 -->
    <el-dialog title="机房环境图集" width="auto" :visible.sync="homeImageDialog" :close-on-click-modal="false" top="0"
      class="dialog-center" :modal-append-to-body="false">
      <home-image-list v-if="homeImageDialog" :batt="batt" :images="stationImages"
        @success="getStationPic"></home-image-list>
    </el-dialog>
    <stop-outline-curing :dev-id="batt.fbsdeviceId" :stop-time="stopTime"></stop-outline-curing>
  </flex-layout>
</template>
<script>
import ContentBox from "@/components/ContentBox";
import BarChart from "@/components/chart/BarChart";
import ScienceBox from "@/components/ScienceBox";
import HdwLight from "@/components/HdwLight.vue";
import stopOutlineCuring from "./components/stopOutlineCuring";
import HomeList from "./movingRingSystem/HomeList";
import DischargeDialogContent from "./components/bts9149DischargeParams";
import SystemParams from "./components/SystemParams";
import CuringParams from "./components/CuringParams";
import OutlineCuringParams from "./components/OutlineCuringParams";
import HistoryRealtimeData from "./components/HistoryRealtimeData";
import StopCuring from "./components/StopCuring";
import NiBianInfoTab from "./components/NiBianInfoTab";
import dcWorkParams from "./components/dcdc/workParams";
import CircuitDiagram from "./components/diagrams/parallelPower9149";
import RightMenu from "./components/RightMenu";
import historyRes from "./components/historyRes";
import BalanceSupplyModule from "./components/balance-supply-module.vue";
import BalanceControlParams from "./components/balance-control-params.vue";
import ezVideo from "@/components/ezVideo";
import workPlan from "./components/dcdc/workPlan";
import ElePriceTpl from "./components/elePriceTpl";
import BmsInfo from "./components/bmsInfo";
import LithiumPackTab from "./components/lithiumPackTab";
import qrCode from "@/assets/js/outside/qrCode";
import sysConfig from "@/assets/js/config";
import selectGroup from './components/selectGroup';
import {
  realTimeNot,
  realTimeAdd,
  realTimeAlarm,
  clearWarn,
  searchInfo,
  outlineControl as restart,
  getStationPic,
  getGuidesData,
  controllerParalle9149,
} from "./js/realTime";
import {
  getBattGroupInfo,
  getStationBattInfo,
} from "../dataMager/js/battGroupMager";
import {
  formatSeconds,
  sethoubeiTime,
  regEquipType,
  getBarNum,
  GetMonomerCap,
  GetHourRate,
  isHasPermit,
  getConduct,
  lithium as lithiumInfo,
  getDevType,
} from "@/assets/js/tools";
import {
  const_61850,
  const_9100,
  const_system,
} from "@/assets/js/const";
import const_9149 from "@/assets/js/const/const_9149";
import getMarkLineData from "@/components/chart/js/getMarkLineData";
import getTblHeader from "./js/getTblHeader";
import ThreeStation from "@/components/threeStation";
import createWs from "@/assets/js/websocket";
import HomeImageList from "@/components/homeImageList";
import JcParams from "@/views/dataTest/components/JcParams";
import { ExportFile } from "@/assets/js/tools/exportFile";
const WSMixin = createWs("RealTime");
/* import moment from "moment"; */
let vol, resChart, temp, conduct, currChart, leakVol, monConnRes;
let tblData = [];
export default {
  name: "movingRingSysteRrealTime",
  mixins: [WSMixin],
  components: {
    JcParams,
    HomeImageList,
    stopOutlineCuring,
    BmsInfo,
    ElePriceTpl,
    ezVideo,
    ContentBox,
    HomeList,
    BarChart,
    CircuitDiagram,
    ScienceBox,
    DischargeDialogContent,
    SystemParams,
    CuringParams,
    OutlineCuringParams,
    HistoryRealtimeData,
    RightMenu,
    StopCuring,
    NiBianInfoTab,
    HdwLight,
    historyRes,
    BalanceSupplyModule,
    BalanceControlParams,
    dcWorkParams,
    workPlan,
    ThreeStation,
    LithiumPackTab,
    selectGroup,
  },
  watch: {
    "$route.params.BattGroupId"(battGroupId) {
      this.$nextTick(() => {
        this.getBattGroupInfo(battGroupId);
      });
    },
    "$store.state.theme.collapse"() {
      this.$nextTick(() => {
        this.resize();
      });
    },
  },
  data() {
    let permits = this.$store.state.user.permits;
    let isCanTest = isHasPermit("batt_test_op_permit", permits);
    let stateList = const_61850.stateList;
    let historyStateList = const_61850.historyStateList;
    let lastCapacityTest = const_61850.lastCapacityTest;
    let pageConfig = this.$store.getters["user/realTabsConfig"];
    return {
      diagromData: {},
      paramsType: 'charge',
      stopTestVisible: false,
      dischargeDialogTitle: '',
      workState: "",
      guidesVal: "",
      guidesData: {},
      homeImageDialog: false,
      hisResDialog: false,
      esVideoDialog: false,
      esVideoSn: "",
      maskShow: false,
      isCanTest: isCanTest,
      homeListShow: true,
      devVersion: "",
      username: sessionStorage.getItem("username"),
      pageConfig: pageConfig,
      stopTime: 0,
      stationImages: [],
      rightMenu: {
        show: false,
        x: 0,
        y: 0,
        xIndex: 0,
      },
      /* 电池状态 模块 组端展示 */
      inputs: {
        groupVol: 0 /* 端电压-组端电压 */,
        onlineVol: 0 /* 端电压-在线电压 */,
        groupCurr: 0 /* 电池电流 */,
        battTestTlong: "0:00:00" /* 测试时长 */,
        recDatetime: 0 /* 更新日期 */,
        battTestCap: 0 /* 测试容量 */,
        battRestCap: 0, // 剩余容量
        battState: 0 /* 电池状态 */,
        devTemperature: 0, // 环境温度
        devHumidity: 0, // 环境湿度
      },
      chargeMon: "",
      dischargeMon: "",
      acTabs: "eleLine",
      table: {
        headers: [
          {
            prop: "num1",
            label: "单体编号",
            width: "",
            key1: "",
          },
          {
            prop: "vol1",
            label: "电压(V)",
            width: "",
            key1: "vol",
          },
          {
            prop: "res1",
            label: "内阻(mΩ)",
            width: "",
            key1: "res",
          },
          {
            prop: "temp1",
            label: "温度(℃)",
            width: "",
            key1: "temp",
          },
          {
            prop: "conduct1",
            label: "电导",
            width: "",
            key1: "conduct",
          },
          {
            prop: "monConnRes",
            label: "链接条阻值",
            width: "",
            key1: "monConnRes",
          },
          {
            prop: "curr1",
            label: "均衡电流(A)",
            width: "",
            key1: "curr",
          },
          {
            prop: "leakVol1",
            label: "漏液电压(V)",
            width: "",
            key1: "leakVol",
          },
        ],
        datas: [],
      },
      table1: {
        datas: [
          {
            battGroupId: 0,
            recordTime: 0,
            groupVolAlarm: 0,
            testEndVol: 0,
            testEndCap: 0,
            testTimeLong: 0,
          },
        ],
      },
      table2: {
        datas: [
          {
            battGroupId: 0,
            recordTime: 0,
            monNum: 0,
            monVolAlarm: 0,
            monTempAlarm: 0,
            monResAlarm: 0,
            monRestCapAlarm: 0,
          },
        ],
      },
      batt: {},
      stateListShow: false,
      stateList: stateList,
      historyStateList: historyStateList,
      lastCapacityTest: lastCapacityTest,
      diagram: {
        update: true,
        type: -1,
        desc: "",
        powerCut: 1,
        temp: 0, // 设备温度
        contactRes: 0, // 接触器阻抗
        dropVol: 0, // 导通压降
        devType: 0, // 设备类型
      },
      dischargeDialog: {
        show: false,
      },
      historyRealTimeDataDialog: {
        show: false,
      },
      control: {
        show: false,
        data: {
          startTest: {
            // 启动核容测试
            show: true,
            typeShow: false,
            id: 11,
          },
          stopTest: {
            // 停止测试
            show: true,
            typeShow: false,
            id: 12,
          },
          setSystemParams: {
            // 系统参数设置
            show: true,
            typeShow: false,
            id: 13,
          },
          clearWarn: {
            // 清理告警
            show: true,
            typeShow: false,
            id: 14,
          },
          startYH: {
            // 启动养护/除硫
            show: true,
            typeShow: false,
            id: 15,
          },
          stopYH: {
            // 停止养护/除硫
            show: true,
            typeShow: false,
            id: 16,
          },
          startOutlineYH: {
            // 启动离线养护/除硫
            show: true,
            typeShow: false,
            id: 17,
          },
          stopOutlineYH: {
            // 停止离线养护/除硫
            show: true,
            typeShow: false,
            id: 18,
          },
          circleRestart: {
            // 定期重启
            show: true,
            typeShow: false,
            id: 19,
          },
          restart: {
            // 重启
            show: true,
            typeShow: false,
            id: 20,
          },
          juheng: {
            // 均衡控制参数设置
            show: true,
            typeShow: false,
            id: 21,
          },
        },
      },
      powerChart: {
        ACVol: [
          {
            id: "ACVolA",
            name: "三项交流电压",
            number: "A",
            min: 0,
            max: 250,
            unit: "伏特(V)",
            color: [
              [0.2, "#FA62E8"],
              [0.8, "#00FFFF"],
              [1, "#DCFD00"],
            ],
          },
          {
            id: "ACVolB",
            name: "三项交流电压",
            number: "B",
            min: 0,
            max: 250,
            unit: "伏特(V)",
            color: [
              [0.2, "#FA62E8"],
              [0.8, "#00FFFF"],
              [1, "#DCFD00"],
            ],
          },
          {
            id: "ACVolC",
            name: "三项交流电压",
            number: "C",
            min: 0,
            max: 250,
            unit: "伏特(V)",
            color: [
              [0.2, "#FA62E8"],
              [0.8, "#00FFFF"],
              [1, "#DCFD00"],
            ],
          },
        ],
        ACCurr: [
          {
            id: "ACCurrA",
            name: "三项交流电流",
            number: "A",
            min: 0,
            max: 100,
            unit: "安培(A)",
            color: [
              [0.2, "#0081FF"],
              [0.8, "#90EC7D"],
              [1, "#E5357E"],
            ],
          },
          {
            id: "ACCurrB",
            name: "三项交流电流",
            number: "B",
            min: 0,
            max: 100,
            unit: "安培(A)",
            color: [
              [0.2, "#0081FF"],
              [0.8, "#90EC7D"],
              [1, "#E5357E"],
            ],
          },
          {
            id: "ACCurrC",
            name: "三项交流电流",
            number: "C",
            min: 0,
            max: 100,
            unit: "安培(A)",
            color: [
              [0.2, "#0081FF"],
              [0.8, "#90EC7D"],
              [1, "#E5357E"],
            ],
          },
        ],
        ACPower: [
          {
            id: "ACPowerA",
            name: "三项交流频率",
            number: "A",
            min: 40,
            max: 80,
            unit: "赫兹(Hz)",
            color: [
              [0.2, "#F8BD45"],
              [0.8, "#00FFFF"],
              [1, "#F3535F"],
            ],
          },
          {
            id: "ACPowerB",
            name: "三项交流频率",
            number: "B",
            min: 40,
            max: 80,
            unit: "赫兹(Hz)",
            color: [
              [0.2, "#F8BD45"],
              [0.8, "#00FFFF"],
              [1, "#F3535F"],
            ],
          },
          {
            id: "ACPowerC",
            name: "三项交流频率",
            number: "C",
            min: 40,
            max: 80,
            unit: "赫兹(Hz)",
            color: [
              [0.2, "#F8BD45"],
              [0.8, "#00FFFF"],
              [1, "#F3535F"],
            ],
          },
        ],
        Cos: [
          {
            id: "CosA",
            name: "三项功率因数",
            number: "A",
            min: 0,
            max: 0.2,
            unit: "",
            color: [
              [0.2, "#F8BD45"],
              [0.8, "#00FFFF"],
              [1, "#F3535F"],
            ],
          },
          {
            id: "CosB",
            name: "三项功率因数",
            number: "B",
            min: 0,
            max: 0.2,
            unit: "",
            color: [
              [0.2, "#F8BD45"],
              [0.8, "#00FFFF"],
              [1, "#F3535F"],
            ],
          },
          {
            id: "CosC",
            name: "三项功率因数",
            number: "C",
            min: 0,
            max: 0.2,
            unit: "",
            color: [
              [0.2, "#F8BD45"],
              [0.8, "#00FFFF"],
              [1, "#F3535F"],
            ],
          },
        ],
        apparentPower: [
          {
            id: "apparentPowerA",
            name: "三项视在功率",
            number: "A",
            min: 0,
            max: 1000,
            unit: "千伏安(KVA)",
            color: [
              [0.2, "#6042FA"],
              [0.8, "#F8BD45"],
              [1, "#00FFFF"],
            ],
          },
          {
            id: "apparentPowerB",
            name: "三项视在功率",
            number: "B",
            min: 0,
            max: 1000,
            unit: "千伏安(KVA)",
            color: [
              [0.2, "#6042FA"],
              [0.8, "#F8BD45"],
              [1, "#00FFFF"],
            ],
          },
          {
            id: "apparentPowerC",
            name: "三项视在功率",
            number: "C",
            min: 0,
            max: 1000,
            unit: "千伏安(KVA)",
            color: [
              [0.2, "#6042FA"],
              [0.8, "#F8BD45"],
              [1, "#00FFFF"],
            ],
          },
        ],
        direct: [
          {
            id: "directVol",
            name: "输出直流电压",
            number: "电压",
            min: 0,
            max: 60,
            unit: "伏特(V)",
            color: [
              [0.2, "#FA62E8"],
              [0.8, "#00FFFF"],
              [1, "#DCFD00"],
            ],
          },
          {
            id: "directCurr",
            name: "输出直流电流",
            number: "电流",
            min: 0,
            max: 100,
            unit: "安培(A)",
            color: [
              [0.2, "#0081FF"],
              [0.8, "#90EC7D"],
              [1, "#E5357E"],
            ],
          },
          {
            id: "directPower",
            name: "输出直流功率",
            number: "功率",
            min: 0,
            max: 100,
            unit: "千瓦(KW)",
            color: [
              [0.2, "#F8BD45"],
              [0.8, "#00FFFF"],
              [1, "#F3535F"],
            ],
          },
        ],
      },
      fodHeaders: [],
      fodData: [],
      lithiumParams: {
        analog: lithiumInfo.analog().params,
      },
      // 空开状态 0-断开 1-闭合
      buscoupleSwitch: 0,
      // 数据更新标识
      dataChangeFlag: 0,
      // 单体电压信息
      monVols: [],
      // 单体温度信息
      monTemps: [],
      // 包电压
      packVols: [],
      packCurrs: [],
      station: {
        show: false,
        data: {
          stationId: 0,
          info: null,
        },
      },
    };
  },
  methods: {
    tabClick(tab) {
      this.acTabs = tab.name;
      // 根据tab更新电路图
      if (this.acTabs === "eleLine") {
        this.diagram.update = true;
      } else {
        this.diagram.update = false;
      }
      // 更新图表
      this.setChart();
      // 重置图表的大小
      this.$nextTick(() => {
        this.resize();
        // 设置表格的数据
        if (this.acTabs == "tblData") {
          this.table.datas = tblData;
        }
        //  else if (this.acTabs == "dianchigaojing") {
        //   this.loadDevAla();
        // }
      });
    },
    loadDevAla(rtalarm, rsalarm) {
      if (rtalarm) {
        let res = rtalarm;
        let list = [];
        if (res.code && res.data) {
          list = res.data2.list.map((v) => {
            return {
              ...v,
              battGroupId: v.BattGroupId,
            };
          });
        }
        this.table2.datas = list;
      }
      if (rsalarm) {
        let res = rsalarm;
        let list = [];
        if (res.code && res.data) {
          list = res.data2.list.map((v) => {
            return {
              ...v,
              battGroupId: v.BattGroupId,
            };
          });
        }
        this.table1.datas = list;
      }
    },
    toggleChange() {
      this.resize();
    },
    resize() {
      if (this.acTabs == "elePrice") {
        // 锂电池显示电价分析图
        this.$refs.elePriceTpl.resize();
      } else {
        this.$G.chartManage.resize(this.acTabs);
      }
      // if (isToggleChange) {
      const acTabs = this.acTabs;
      this.acTabs = "";
      this.$nextTick(() => {
        this.acTabs = acTabs;
      });
      // }
    },
    powerInfoChartResize() {
      // 三项交流电压
      this.powerChart.ACVol.forEach((item) => {
        this.$refs[item.id][0].resize();
      });
      // 三项交流电流
      this.powerChart.ACCurr.forEach((item) => {
        this.$refs[item.id][0].resize();
      });
      // 三项交流频率
      this.powerChart.ACPower.forEach((item) => {
        this.$refs[item.id][0].resize();
      });
      // 三项功率因数
      this.powerChart.Cos.forEach((item) => {
        this.$refs[item.id][0].resize();
      });
      // 三项视在功率
      this.powerChart.apparentPower.forEach((item) => {
        this.$refs[item.id][0].resize();
      });
      // 输出直流
      this.powerChart.direct.forEach((item) => {
        this.$refs[item.id][0].resize();
      });
    },
    initChart() {
      // 电压
      vol = {
        title: {
          show: true,
          text: "最大值=0V;最小值=0V;平均值=0V",
          x: "center",
          textStyle: {
            fontSize: "14",
          },
        },
        series: [
          {
            name: "电压",
            type: "bar",
            data: [],
            markLine: {
              data: getMarkLineData(),
            },
          },
        ],
      };
      // 漏液电压
      leakVol = {
        title: {
          show: true,
          text: "最大值=0V;最小值=0V;平均值=0V",
          x: "center",
          textStyle: {
            fontSize: "14",
          },
        },
        series: [
          {
            name: "漏液电压",
            type: "bar",
            data: [],
            markLine: {
              data: getMarkLineData(),
            },
          },
        ],
      };
      // 内阻
      resChart = {
        title: {
          show: true,
          text: "最大值=0mΩ;最小值=mΩ;平均值=0mΩ",
          x: "center",
          textStyle: {
            fontSize: "14",
          },
        },
        series: [
          {
            name: "内阻",
            type: "bar",
            data: [],
            markLine: {
              data: getMarkLineData(),
            },
          },
        ],
      };
      // 温度
      temp = {
        title: {
          show: true,
          text: "最大值=0℃;最小值=0℃;平均值=0℃",
          x: "center",
          textStyle: {
            fontSize: "14",
          },
        },
        series: [
          {
            name: "温度",
            type: "bar",
            data: [],
            markLine: {
              data: getMarkLineData(),
            },
          },
        ],
      };
      // 电导
      conduct = {
        title: {
          show: true,
          text: "最大值=0;最小值=0;平均值=0",
          x: "center",
          textStyle: {
            fontSize: "14",
          },
        },
        series: [
          {
            name: "电导",
            type: "bar",
            data: [],
            markLine: {
              data: getMarkLineData(),
            },
          },
        ],
      };
      // 均衡电流
      currChart = {
        title: {
          show: true,
          text: "最大值=0A;最小值=0A;平均值=0A",
          x: "center",
          textStyle: {
            fontSize: "14",
          },
        },
        series: [
          {
            name: "均衡电流",
            type: "bar",
            data: [],
          },
        ],
      };
      // 链接条阻值
      monConnRes = {
        title: {
          show: true,
          text: "最大值=0mΩ;最小值=0mΩ;平均值=0mΩ",
          x: "center",
          textStyle: {
            fontSize: "14",
          },
        },
        series: [
          {
            name: "链接条阻值",
            type: "bar",
            data: [],
          },
        ],
      };
      // 设置配置项
      this.setChart();
    },
    setChart() {
      let acTabs = this.acTabs;
      if (!this.$refs[acTabs]) {
        return;
      }
      switch (acTabs) {
        case "vol":
          this.$refs.vol.setOption(vol);
          break;
        case "res":
          this.$refs.res.setOption(resChart);
          break;
        case "temp":
          this.$refs.temp.setOption(temp);
          break;
        case "conduct":
          this.$refs.conduct.setOption(conduct);
          break;
        case "curr":
          this.$refs.curr.setOption(currChart);
          break;
        case "leakVol":
          this.$refs.leakVol.setOption(leakVol);
          break;
        case "monConnRes":
          this.$refs.monConnRes.setOption(monConnRes);
          break;
      }
    },
    onWSOpen() {
      this.$nextTick(() => {
        this.sendMessage();
      });
    },
    sendMessage() {
      let batt = this.batt;
      // console.log(batt, '=====batt');
      // if (!batt.battGroupId || this.SOCKET.readyState != 1) {
      if (!batt.battGroupId || !this.isWSOpen) {
        return false;
      }
      let params = {
        battGroupId: batt.battGroupId,
        devId: batt.fbsdeviceId,
        powerDeviceId: 0,
        groupNum: batt.groupIndexInFBSDevice,
        pageType: "paralle9149",
      };
      console.log("=====9=", params, JSON.stringify(params));
      this.SOCKET.send(JSON.stringify(params));
    },
    onWSMessage(res) {
      res = JSON.parse(res.data);
      let data = res.data.data;
      // console.log(data, "=====111data");
      this.realTimePowerOffs(data.f9100state);
      this.realTimeSearch(data.rtdata);
      this.realTimeGroupss(data.rtstate, res.data.data2);
      this.loadDevAla(data.rtalarm, data.rsalarm);
      this.pologystateRes(data.pologystateRes);
      // 最后一次核容数据
      this.getLastCapacityTest(data.tinfdata);
      this.dataChangeFlag = Math.random(); // 数据更新
    },
    pologystateRes(res) {
      if (res) {
        let { code, data, data2 } = res;
        if (code && data) {
          this.diagromData = data2;
        }
      }
    },
    getBattGroupInfo(battGroupId) {
      this.homeListShow = false;
      getBattGroupInfo(battGroupId)
        .then((res) => {
          res = res.data;
          if (res.code) {
            this.leafClick(res.data[0]);
          } else {
            this.$layer.msg("未获取到电池组的信息");
          }
        })
        .catch((error) => {
          console.log(error);
        });
    },
    leafClick(data) {
      this.batt = data;
      this.diagram.desc = "";
      // 查询机房电池组信息(3D用)
      this.getStationBattInfo(data.stationId);
      this.realTimeAlarmss();
      // this.realTimeXuHang();    // 预估续航时长
      this.diagram.devType = getDevType(data.chargeType, data.buscoupleState);
      this.esVideoSn = data.videoUrl;
      this.table.headers = getTblHeader(data.fbsdeviceId);
      this.$nextTick(() => {
        this.changeTabsName();
        // 开启循环请求
        this.sendMessage();
        // 获取机房的图片
        this.getStationPic();
      });
    },
    getStationBattInfo(id) {
      getStationBattInfo(id).then((res) => {
        res = res.data;
        // console.log(res, '======res?a');
        if (res.code && res.data.length) {
          this.station.data.stationId = res.data[0].stationId;
          this.station.data.info = res.data;
        }
      });
    },
    /**
     * 根据设备类型修改Tabs选中状态
     */
    changeTabsName() {
      this.$nextTick(() => {
        this.resize();
      });
    },
    /* 查询电池告警参数 */
    realTimeAlarmss() {
      var batt = this.batt;
      realTimeAlarm({
        devId: batt.fbsdeviceId,
      }).then((res) => {
        res = res.data;
        // 初始化查询参考线
        this.setLin(res);
      });
    },
    // 设置高低线参考线
    setLin: function (res) {
      if (res.code) {
        let list = res.data.list;
        // 单体电压
        this.setChartMarkLine(vol, "Voltage", "Batt_Alarm_Type_MonVol", list);
        // 单体温度
        this.setChartMarkLine(
          temp,
          "Temperature",
          "Batt_Alarm_Type_MonTmp",
          list
        );
        // 单体内阻
        this.setChartMarkLine(
          resChart,
          "Resistance",
          "Batt_Alarm_Type_MonRes",
          list
        );
        // 单体电导
        this.setChartMarkLine(
          conduct,
          "Conductance",
          "Batt_Alarm_Type_MonRes",
          list
        );
        // 漏液电压
        this.setChartMarkLine(
          leakVol,
          "leakVol",
          "Batt_Alarm_Type_MonLYVol",
          list
        );
      }
    },
    setChartMarkLine(chartData, name, almName, list) {
      let batt = this.batt;
      // 遍历list
      for (let i = 0; i < list.length; i++) {
        let item = list[i];
        if (item.almName == almName) {
          let high = 0;
          let low = 0;
          let guides = 0;
          switch (name) {
            case "Voltage": // 电压告警
              //单体电压
              let std_mon_vol = batt.monVolStd;
              high = parseFloat(std_mon_vol * item.almHighCoe).toHold(3);
              low = parseFloat(std_mon_vol * item.almLowCoe).toHold(3);
              break;
            case "Temperature":
              //单体温度
              let std_mon_tmp = 25;
              high = parseFloat(std_mon_tmp * item.almHighCoe).toHold(1);
              low = parseFloat(std_mon_tmp * item.almLowCoe).toHold(1);
              break;
            case "Resistance":
              // 单体电阻
              let std_mon_res =
                (1 * (batt.monVolStd / 2)) / (batt.monCapStd / 100);
              high = parseFloat(std_mon_res * item.almHighCoe).toHold(3);
              low = parseFloat(std_mon_res * item.almLowCoe).toHold(3);
              break;
            case "Conductance":
              // 单体电导
              let std_mon_ser = batt.monSerStd;
              high = parseFloat(std_mon_ser * item.almHighCoe).toHold(0);
              low = parseFloat(std_mon_ser * item.almLowCoe).toHold(0);
              break;
            case "leakVol":
              // 漏液电压
              high = parseFloat(item.almHighCoe);
              low = parseFloat(item.almLowCoe);
              break;
          }
          // debugger
          // 低告警
          chartData.series[0].markLine.data[0].yAxis = low;
          // 高告警
          chartData.series[0].markLine.data[1].yAxis = high;
          break;
        }
      }
    },
    // 获取电池组参考线
    getGuides: function (resdata) {
      let vm = this;
      let batt = this.batt;
      let obj = {
        battGroupId: batt.battGroupId,
      };
      getGuidesData(obj).then((res) => {
        let rs = res.data;
        if (rs.code == 1) {
          vm.guidesData = rs.data;
          console.log(vm.guidesData);
          vm.setLin(resdata);
        }
        console.log(vm.guidesData);
      });
    },
    /* 实时组端信息 */
    realTimeGroupss(res, res2) {
      let vm = this;
      if (res) {
        // res = res.data;
        if (res.code && res.data) {
          vm.inputs = res.data2;
        }
      }
    },
    /* 查询电路图开关状态和信息 */
    realTimePowerOffs(res) {
      let batt = this.batt;
      this.stateListShow = false;
      // 查询后台数据
      if (res) {
        // res = res.data;
        let outTime = 2 * 60; //设备超时时间(2分钟)
        if (res.code && res.data) {
          let data = res.data2;
          // 设置版本号
          this.devVersion = data.devVersion;
          // 基础信息
          this.setEquipBase(data);
          // 判断是否超时
          var nowTime = new Date(data.note).getTime(); //当前时间
          var record = new Date(data.recordDatetime).getTime();
          if (Math.abs(nowTime - record) / 1000 > outTime) {
            this.disconnect();
          } else {
            // 未超时执行逻辑
            let devId = batt.fbsdeviceId;
            this.diagram.powerCut = 0;
            this.setEquipBTS(data);
          }
        } else {
          // 设置版本号
          this.devVersion = "";
          // 设备处于未连接
          this.disconnect();
        }
      }
    },
    disconnect() {
      // 设备未连接
      this.diagram.type = -1;
      this.setStateList("workState", "未连接");
      this.workState = "未连接";
      this.diagram.temp = 0;
      // 通讯状态
      this.setStateList("connect", "异常", "table-row-error");
      // 温度
      this.setStateList("devTemp", "未知", "table-row-warn");
      // 干接点
      this.setStateList("contact", "未知", "table-row-warn");
      // 核容终止原因
      // this.setStateList("stopReason", "未知");
      // 操作失败原因
      this.setStateList("failReason", "未知");
      // 预估续航时长
      //this.setStateList("xuHang", "???");
      // 显示遮罩层
      this.maskShow = true;
    },
    // 基础信息
    setEquipBase(data) {
      let groupIndex = this.batt.groupIndexInFBSDevice;
      // 设备的温度
      this.diagram.temp = data.devTemp;
      let contactRes = (
        groupIndex != 0 ? data.devConresist1 : data.devConresist
      ).toHold(2);
      let dropVol = (
        groupIndex != 0 ? data.devCondvoldp1 : data.devCondvoldp
      ).toHold(2);
      let alarms = data.dev61850alarms.split(",");
      if (alarms.length) {
        this.diagram.contactRes = alarms[0] == "true" ? "k1异常" : contactRes;
        this.diagram.dropVol = alarms[3] == "true" ? "D1异常" : dropVol;
      } else {
        this.diagram.contactRes = contactRes;
        this.diagram.dropVol = dropVol;
      }
    },
    // BTS设备信息
    setEquipBTS(data) {
      let batt = this.batt;
      // 关闭遮罩层
      this.maskShow = false;
      //  电路图类型
      let workstatus = parseInt(data.devWorkstate); //[0:'在线监测',1:'放电测试',2:'充电测试',3:'内阻测试',4:'未知'];
      this.workState = const_9100.workstates[data.devWorkstate];
      this.diagram.desc = "";
      let battstate = this.inputs.battState;
      let alarmstatus = data.devAlarmstate;
      // 设置停电放电状态
      if (data.devOnlinevollow) {
        this.inputs.battState = 5;
        this.diagram.type = 5;
        this.diagram.desc = "(开关闭合)";
        this.diagram.powerCut = 1;
        this.workState = '停电放电';
        // 当前设备是BTS设备
        if (workstatus === 0 && data.devResTestState !== 0) {
          this.diagram.desc += "(内阻测试)";
        }
        return;
      }
      // 判断workstatus
      switch (workstatus) {
        case 0:
          this.diagram.type = 0;
          this.diagram.desc = "(开关闭合)";
          // 当前设备是BTS设备
          if (data.devResTestState !== 0) {
            this.diagram.desc += "(内阻测试)";
          }
          break;
        case 1:
          if (
            data.devTestgroupnum > 0 &&
            data.devTestgroupnum === batt.groupIndexInFBSDevice + 1
          ) {
            this.diagram.type = 1;
            this.diagram.desc = "(开关断开)";
          } else {
            if (battstate === 3) {
              this.diagram.type = 1;
              this.diagram.desc = "(开关断开)";
            } else {
              this.diagram.type = 0;
              this.diagram.desc = "(开关闭合)";
            }
          }
          // 当前设备是BTS设备
          if (data.devTesttype == 209) {
            this.diagram.desc += "(KD测试)";
            this.diagram.type = 3;
          }
          break;
        case 2:
          //辨别当前电池组是否在充电
          if (
            this.diagram.type == 2 ||
            (data.devTestgroupnum > 0 &&
              data.devTestgroupnum === batt.groupIndexInFBSDevice + 1)
          ) {
            //充电
            if (
              alarmstatus === 1 ||
              alarmstatus === 2 ||
              alarmstatus === 3 ||
              alarmstatus === 4 ||
              alarmstatus === 6
            ) {
              //限流充电      -->常闭接触器断开
              this.diagram.type = 2;
              this.diagram.desc = "(开关断开)";
            } else {
              //直流充电     -->常闭接触器闭合
              this.diagram.type = 2;
              this.diagram.desc = "(开关闭合)";
            }
          } else {
            this.diagram.type = 0;
            this.diagram.desc = "(开关闭合)";
          }
          break;
        default:
          this.diagram.type = -1;
          this.maskShow = true;
          break;
      }
    },
    // 设置stateList的值
    setStateList(name, value, type) {
      let stateList = this.stateList;
      for (let i = 0; i < stateList.length; i++) {
        let state = stateList[i];
        if (state.name == name) {
          state.value = value;
          state.type = type ? type : "";
        }
      }
      let historyStateList = this.historyStateList;
      for (let i = 0; i < historyStateList.length; i++) {
        let state = historyStateList[i];
        if (state.name == name) {
          state.value = value;
          state.type = type ? type : "";
        }
      }
      for (
        let i = 0, list = this.lastCapacityTest, j = list.length;
        i < j;
        i++
      ) {
        let state = list[i];
        if (state.name == name) {
          state.value = value;
          state.type = type || "";
        }
      }
    },
    setTableRowClass({ row }) {
      if (row.monState == 1) {
        return "red-row";
      } else if (row.monState == 2) {
        return "green-row";
      }
      return "";
    },
    /* echars图表 */
    realTimeSearch(res) {
      if (res) {
        let diagramType = this.diagram.type;
        // res = res.data;
        let data = [];
        let chargeMon = "";
        let dischargeMon = "";
        if (res.code && res.data && diagramType != -1) {
          data = res.data2.list.map((item) => {
            if (item.monState == 1) {
              dischargeMon += (dischargeMon == "" ? "#" : ",#") + item.monNum;
            } else if (item.monState == 2) {
              chargeMon += (chargeMon == "" ? "#" : ",#") + item.monNum;
            }
            return {
              num1: "#" + item.monNum,
              vol1: item.monVol,
              res1: item.monRes,
              temp1: item.monTmp,
              conduct1: item.monRes ? ((1 / item.monRes) * 1000).toFixed(0) : 0,
              curr1: item.monJhCurr,
              leakVol1: item.monLyVol,
              monConnRes: item.monConnRes,
              monCap: item.monCap,
              monTestCap:
                diagramType == 1 || diagramType == 2 || diagramType == 6
                  ? item.monTestCap
                  : "---",
              monResCap:
                diagramType == 1 || diagramType == 2 || diagramType == 6
                  ? item.monRestCap
                  : "---",
              monDisTimeLong:
                diagramType == 1 || diagramType == 2 || diagramType == 6
                  ? Math.floor(item.monDisTimelong / 60) +
                  "时" +
                  (item.monDisTimelong % 60) +
                  "分"
                  : "---",
              monState: item.monState,
            };
          });
        }
        // 添加正在测试的单体
        this.chargeMon = chargeMon;
        this.dischargeMon = dischargeMon;
        // 更新表格
        if (this.acTabs == "tblData") {
          this.table.datas = data;
        } else {
          tblData = data;
        }
        // 电压值
        let volTempVol = [];
        if (res.code && res.data) {
          volTempVol = res.data2.list.map((item) => {
            let value = diagramType == -1 ? 0 : item.monVol.toFixed(3);
            return ["#" + item.monNum, value];
          });
        }
        // 设置电压值
        this.monVols = volTempVol.map((item) => {
          return item[1];
        });
        let volBarNum = getBarNum(volTempVol);
        vol.title.text =
          "最大值=" +
          volBarNum.max.toFixed(3) +
          "V  最小值=" +
          volBarNum.min.toFixed(3) +
          "V  平均值=" +
          volBarNum.avg.toFixed(3) +
          "V";
        vol.series[0].data = volTempVol;
        // 内阻
        let volTempres = [];
        if (res.code && res.data) {
          volTempres = res.data2.list.map((item) => {
            let value = diagramType == -1 ? 0 : item.monRes;
            return ["#" + item.monNum, value];
          });
        }
        let resBarNum = getBarNum(volTempres);
        resChart.title.text =
          "最大值=" +
          resBarNum.max.toFixed(3) +
          "mΩ  最小值=" +
          resBarNum.min.toFixed(3) +
          "mΩ  平均值=" +
          resBarNum.avg.toFixed(3) +
          "mΩ";
        resChart.series[0].data = volTempres;
        // 温度
        let volTempte = [];
        if (res.code && res.data) {
          volTempte = res.data2.list.map((item) => {
            let value = diagramType == -1 ? 0 : item.monTmp;
            return ["#" + item.monNum, value];
          });
        }
        this.monTemps = volTempte.map((item) => {
          return item[1];
        });
        let tempBarNum = getBarNum(volTempte);
        temp.title.text =
          "最大值=" +
          tempBarNum.max.toFixed(1) +
          "℃  最小值=" +
          tempBarNum.min.toFixed(1) +
          "℃  平均值=" +
          tempBarNum.avg.toFixed(1) +
          "℃";
        temp.series[0].data = volTempte;
        // 电导
        let conductTemp = [];
        if (res.code && res.data) {
          conductTemp = res.data2.list.map((item) => {
            let value =
              diagramType == -1 ? 0 : getConduct(item.monRes, item.monVol);
            return ["#" + item.monNum, value];
          });
        }
        let conductBarNum = getBarNum(conductTemp);
        conduct.title.text =
          "最大值=" +
          conductBarNum.max.toFixed(0) +
          "  最小值=" +
          conductBarNum.min.toFixed(0) +
          "  平均值=" +
          conductBarNum.avg.toFixed(0);
        conduct.series[0].data = conductTemp;
        // 均衡电流
        let currTemp = [];
        if (res.code && res.data) {
          currTemp = res.data2.list.map((item) => {
            let value = diagramType == -1 ? 0 : item.monJhCurr;
            return ["#" + item.monNum, value];
          });
        }
        let currBarNum = getBarNum(currTemp);
        currChart.title.text =
          "最大值=" +
          currBarNum.max.toFixed(1) +
          "A  最小值=" +
          currBarNum.min.toFixed(1) +
          "A  平均值=" +
          currBarNum.avg.toFixed(1) +
          "A";
        currChart.series[0].data = currTemp;
        // 漏液电压
        let leakVolTemp = [];
        if (res.code && res.data) {
          leakVolTemp = res.data2.list.map((item) => {
            let value = diagramType == -1 ? 0 : item.monLyVol;
            return ["#" + item.monNum, value];
          });
        }
        let leakVolNum = getBarNum(leakVolTemp);
        leakVol.title.text =
          "最大值=" +
          leakVolNum.max.toFixed(1) +
          "V  最小值=" +
          leakVolNum.min.toFixed(1) +
          "V  平均值=" +
          leakVolNum.avg.toFixed(1) +
          "V";
        leakVol.series[0].data = leakVolTemp;
        // 链接条阻值
        let monConnResData = [];
        if (res.code && res.data) {
          monConnResData = res.data2.list.map((item) => {
            let value = diagramType == -1 ? 0 : item.monConnRes;
            return ["#" + item.monNum, value];
          });
        }
        let connResBarNum = getBarNum(monConnResData);
        monConnRes.title.text =
          "最大值=" +
          connResBarNum.max.toFixed(1) +
          "mΩ  最小值=" +
          connResBarNum.min.toFixed(1) +
          "mΩ  平均值=" +
          connResBarNum.avg.toFixed(1) +
          "mΩ";
        monConnRes.series[0].data = monConnResData;
        // 更新电压图表
        this.setChart();
      }
    },
    // 向父级发送同步页面的指令
    syncPage() {
      let batt = this.batt;
      let search =
        "?province=" +
        batt.stationName1 +
        "&city=" +
        batt.stationName2 +
        "&county=" +
        batt.stationName5 +
        "&home=" +
        batt.stationName3 +
        "&batt=" +
        batt.battGroupId;
      let url = "/dataTest/history";
      if (regEquipType(batt.fbsdeviceId, "LD9")) {
        url = "/dataTest/historyLD9";
      }
      this.$router.push(url + search);
    },
    // 开始测试
    startTest(type) {
      switch (type) {
        case 0:
          // 充电
          this.dischargeDialogTitle = '充电参数设置';
          this.paramsType = 'charge';
          break;
        case 1:
          // 放电
          this.dischargeDialogTitle = '放电参数设置';
          this.paramsType = 'discharge';
          break;
      }
      this.dischargeDialog.show = true;
    },
    // 停止测试
    stopTest(type) {
      switch (type) {
        case 0:
          // 停止充电
          this.dischargeDialogTitle = '停止充电';
          this.stopType = 'charge';
          break;
        case 1:
          // 停止放电
          this.dischargeDialogTitle = '停止放电';
          this.stopType = 'discharge';
          break;
      }
      this.stopTestVisible = true;
    },
    // 查询拓扑图状态的显示
    searchStatus() {
      searchInfo({ categoryId: 1 })
        .then((res) => {
          res = res.data;
          if (res.code) {
            let data = res.data.list;
            this.stateList.forEach((item) => {
              item.show = this.getStateById(item.id, data);
            });
            this.historyStateList.forEach((item) => {
              item.show = this.getStateById(item.id, data);
            });
          }
          // 设置养护除硫信息
          this.setFodHeaders(this.stateList);
        })
        .catch((error) => {
          console.log(error);
        });
    },
    setFodHeaders(stateList) {
      let result = [];
      result.push({
        prop: "num",
        label: "编号",
      });
      // 剩余天数
      let resDay = const_61850.getItemByName("resDay", stateList);
      if (resDay && resDay.show) {
        result.push({
          prop: "RestTime_",
          label: "天数",
        });
      }
      // 工作状态
      let workModel = const_61850.getItemByName("workMode", stateList);
      if (workModel && workModel.show) {
        result.push({
          prop: "workstate",
          label: "模式",
        });
      }
      // 组端电压
      let groupVol = const_61850.getItemByName("groupVol", stateList);
      if (groupVol && groupVol.show) {
        result.push({
          prop: "vgroupvol",
          label: "组压",
        });
      }
      // 峰值电压
      let peakVol = const_61850.getItemByName("peakVol", stateList);
      if (peakVol && peakVol.show) {
        result.push({
          prop: "vpeakvol",
          label: "峰压",
        });
      }
      this.fodHeaders = result;
    },
    // 查询控制按钮的内容
    searchControl() {
      searchInfo({ categoryId: 2 })
        .then((res) => {
          res = res.data;
          let control = false; // 控制整体的显示
          if (res.code) {
            let data = res.data.list;
            Object.keys(this.control.data).forEach((key) => {
              let item = this.control.data[key];
              item.show = this.getStateById(item.id, data); // 根据id设置按钮的状态
              // 存在控制
              if (item.show) {
                control = item.show;
              }
            });
          }
          this.control.show = control; // 设置整体显示的状态
        })
        .catch((error) => {
          console.log(error);
        });
    },
    getStateById(id, list) {
      let result = true;
      for (let i = 0; i < list.length; i++) {
        let item = list[i];
        if (id == item.id) {
          result = item.status ? true : false;
          break;
        }
      }
      return result;
    },
    clearWarn() {
      // 清除告警
      this.$layer.confirm(
        "清除设备告警",
        {
          icon: 3,
          title: "系统提示",
        },
        (index) => {
          // 关闭弹出框
          this.$layer.close(index);
          // 开启加载等待
          let load = this.$layer.loading(1);
          // 执行清除告警
          let batt = this.batt;
          clearWarn({
            devId: batt.fbsdeviceId,
            num: const_system.cmd.clear,
          })
            .then((res) => {
              res = res.data;
              if (res.code && res.data) {
                this.$layer.msg("清除设备告警成功!");
              } else {
                this.$layer.msg("清除设备告警失败!");
              }
              // 关闭等待
              this.$layer.close(load);
            })
            .catch((error) => {
              console.log(error);
              // 关闭等待
              this.$layer.close(load);
            });
        }
      );
    },
    // 初始化时lifeFlag传true 页面销毁时传false
    monitorPage(lifeFlag) {
      if (!lifeFlag) {
        return;
      }
      let url = this.$route.meta.url || "";
      if (url == "/dataTest/realTime9141" && this.acTabs === "eleLine") {
        this.diagram.update = true;
      } else {
        this.diagram.update = false;
      }
      // 启动监控
      requestAnimationFrame(() => {
        this.monitorPage(true);
      });
    },
    setRightMenuPos(x, y) {
      this.rightMenu.show = true;
      this.rightMenu.x = x;
      this.rightMenu.y = y;
    },
    chartRightCLick(params) {
      this.rightMenu.show = true;
      this.rightMenu.x = params.x;
      this.rightMenu.y = params.y;
      this.rightMenu.xIndex = params.xIndex;
    },
    payAttentionMon() {
      let searchParams = {
        battGroupId: this.batt.battGroupId,
        monNum: this.rightMenu.xIndex + 1,
      };
      // 查询
      realTimeNot(searchParams)
        .then((res) => {
          res = res.data;
          if (res.code && res.data) {
            this.$layer.msg("单体#" + searchParams.monNum + "已被关注");
          } else {
            this.addAttentionMon(searchParams);
          }
        })
        .catch((error) => {
          console.log(error);
        });
    },
    addAttentionMon(params) {
      let loading = this.$layer.loading(1);
      // 请求后台添加
      realTimeAdd(params)
        .then((res) => {
          res = res.data;
          if (res.code && res.data) {
            this.$layer.msg("成功关注单体#" + params.monNum);
          } else {
            this.$layer.msg("添加失败");
          }
          this.$layer.close(loading);
        })
        .catch((error) => {
          this.$layer.close(loading);
          console.log(error);
        });
    },
    closeDisChargeDialog() {
      this.dischargeDialog.show = false;
    },
    restartSystem() {
      let self = this;
      let batt = this.batt;
      let resetPwd = "restart123456";
      this.$prompt("请输入重启密码", "提示", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        inputType: "password",
      })
        .then(({ value }) => {
          if (value == resetPwd) {
            let loading = this.$layer.loading();
            restart({
              devId: batt.fbsdeviceId,
              opCmd: 16
            }).then((res) => {
              res = res.data;
              if (res.code) {
                this.$alert("发送重启命令成功", "系统提示");
              } else {
                this.$alert("发送重启命令失败!", "系统提示");
              }
              this.$layer.close(loading);
            })
              .catch((error) => { });
          } else {
            this.$layer.msg("密码不正确");
          }
        })
        .catch(() => { });
    },
    getLastCapacityTest(res) {
      if (res) {
        let batt = this.batt;
        // res = res.data;
        if (res.code && res.data) {
          let data = res.data2;
          // 上次核容停止原因
          this.setStateList("stopReason", data.testStoptypeReason);
          // 核容测试的最后一笔数据
          let datalist = data.batttestdataList;
          // 上次核容开始时间
          this.setStateList("test_starttime", data.testStarttime);
          // 上次核容测试容量
          this.setStateList("test_cap", data.testCap.toFixed(1) + "AH");
          // 上次核容测试时长
          this.setStateList("test_timelong", formatSeconds(data.testTimelong));
          let volArr = [];
          datalist.forEach((v) => {
            volArr.push(["#" + v.monNum, v.monVol]);
          });
          let batNum = getBarNum(volArr);
          let avg_curr =
            data.testTimelong > 0
              ? (data.testCap * 3600) / data.testTimelong
              : data.testCurr;
          let over_cap = GetMonomerCap(
            batt.monCapStd,
            GetHourRate(batt.monCapStd, avg_curr),
            data.testCap,
            batNum.max,
            batNum.min,
            batt.monVolStd,
            0
          );
          let real_cap = GetMonomerCap(
            batt.monCapStd,
            GetHourRate(batt.monCapStd, avg_curr),
            data.testCap,
            batNum.max,
            batNum.min,
            batt.monVolStd,
            1
          );
          let xuhang = batt.loadCurr ? real_cap / batt.loadCurr : 0;
          // 剩余容量
          this.setStateList("re_cap", over_cap.toFixed(1) + "AH");
          // 续航时长
          this.setStateList(
            "endurance_time",
            xuhang ? sethoubeiTime(xuhang) : "---"
          );
        }
      }
    },
    stopOutLineCuring() {
      this.stopTime = new Date().getTime();
      console.log(this.stopTime);
    },
    getStationPic() {
      let batt = this.batt;
      if (sysConfig.clientName.name == "sxty") {
        this.getQRStationPic();
      } else {
        getStationPic(batt.stationId)
          .then((res) => {
            let rs = res.data;
            let data = [];
            if (rs.code == 1) {
              data = rs.data ? rs.data : [];
            }
            this.stationImages = data;
          })
          .catch((error) => {
            console.log(error);
          });
      }
    },
    getQRStationPic() {
      let mId = this.batt.mid;
      qrCode
        .battery(mId)
        .then((res) => {
          let rs = res.data;
          let pics = "";
          if (rs.code == 200) {
            pics = rs.data.pics;
          }
          this.stationImages = pics ? pics.split(",") : [];
        })
        .catch((error) => {
          this.stationImages = [];
        });
    },
    // 导出表格
    exportFile() {
      let batt = this.batt;
      let time = new Date().getTime();
      if (this.table.datas.length === 0) {
        this.$message.warning("暂无数据,无需导出");
        return false;
      }
      ExportFile(this.dataHeaders, this.table.datas, batt.stationName + "-电池实时数据(" + time + ")");
    },
    // 停止
    stop(list, type) {
     // 等待框
     let loading = this.$layer.loading(1);
     let {cmd, testCmd} = const_9149;
      let params = {
        battGroupNums: list.join(','),
        opCmd: cmd.stop,
        devId: this.batt.fbsdeviceId,
        testCmd: testCmd[type],
      }
      // 请求后台
      controllerParalle9149(params)
        .then((res) => {
          res = res.data;
          if (res.code && res.data[Object.keys(res.data)[0]]) {
            // 提示信息
            this.$layer.msg("操作成功");
            // 关闭弹出框
            this.$emit("close");
          } else {
            // 提示信息
            this.$layer.msg("操作失败!");
          }
          // 关闭等待框
          this.$layer.close(loading);
        })
        .catch((error) => {
          console.log(error);
          // 关闭等待框
          this.$layer.close(loading);
          // 提示信息
          this.$layer.msg("操作失败,请求异常!");
        });
    },
  },
  computed: {
    battFullName() {
      let batt = this.batt;
      if (batt.stationName && batt.battGroupName) {
        return batt.stationName + "-" + batt.battGroupName;
      }
      return "电池组全称";
    },
    backInputs() {
      let batt = this.batt;
      const obj = {
        0: "未知",
        1: "浮充",
        2: "充电",
        3: "放电",
        4: "均充",
        5: "内阻测试",
      },
        list = {
          battState: "未知",
          group_online_vol: "在线:0.000V;组端:0.000V",
          groupCurr: "0.00A",
          recDatetime: "1982-01-01 00:00:00",
          battTestTlong: formatSeconds(0),
          battTestCap: "0Ah",
          batt_syrl_cap: "---",
          sysc: "------",
        };
      if (this.diagram.type == -1) {
        return list;
      }
      let batt_state_text =
        this.diagram.powerCut
          ? "停电放电"
          : obj[this.inputs.battState];
      list.battState = batt_state_text + this.diagram.desc;
      if (regEquipType(batt.fbsdeviceId, "BTS9605")) {
        list.group_online_vol = `组端:${this.inputs.groupVol.toFixed(2)}V`;
      } else {
        list.group_online_vol = `在线:${this.inputs.onlineVol.toFixed(
          2
        )}V;组端:${this.inputs.groupVol.toFixed(2)}V`;
      }
      list.groupCurr = this.inputs.groupCurr.toFixed(2) + "A";
      list.recDatetime = this.inputs.recDatetime;
      list.battTestTlong = formatSeconds(this.inputs.battTestTlong);
      list.battTestCap = this.inputs.battTestCap.toFixed(1) + "AH";
      if (this.inputs.battState === 3) {
        // 为0是不更新剩余容量
        if (this.inputs.battRestCap != 0) {
          list.batt_syrl_cap = this.inputs.battRestCap.toFixed(1);
        }
      } else {
        list.batt_syrl_cap = "---";
      }
      if (this.inputs.battState === 3) {
        // 为0是不更新续航时长
        if (this.inputs.battRestCap != 0) {
          list.sysc = sethoubeiTime(
            parseFloat(this.inputs.battRestCap) /
            parseFloat(this.inputs.groupCurr)
          );
        }
      } else {
        list.sysc = "------";
      }
      return list;
    },
    showStateList() {
      return this.stateList.filter((item) => {
        if (item.show) {
          return item;
        }
      });
    },
    showHistoryStateList() {
      return this.historyStateList.filter((item) => {
        if (item.show) {
          return item;
        }
      });
    },
    stateListState() {
      return this.stateListShow && this.showStateList.length;
    },
    historyStateListState() {
      return this.stateListShow && this.showHistoryStateList.length;
    },
    histroyDataTitle() {
      return this.batt.stationName + "-历史实时数据";
    },
    fodShow() {
      return this.fodHeaders.length === 1 || this.fodData.length === 0
        ? false
        : true;
    },
    tabsConfig() {
      let batt = this.batt;
      if (!batt.fbsdeviceId) {
        return {
          vol: false,
          res: false,
          temp: false,
          conduct: false,
          curr: false,
          leakVol: false,
          dianchigaojing: false,
          monConnRes: false,
        };
      } else {
        return {
          vol: true,
          res: true,
          temp: true,
          conduct: true,
          curr: true,
          leakVol: true,
          dianchigaojing: true,
          monConnRes: true,
        };
      }
    },
    // 设备连接状态1为未连接 0正常
    isLink() {
      return this.diagram.type == -1 ? 1 : 0;
    },
    dataHeaders() {
      let headers = this.table.headers;
      let tabConfig = this.pageConfig;
      let batt = this.batt;
      return headers.filter((item) => {
        let isShow = item.key1 ? tabConfig[item.key1] : true;
        if (item.type) {
          isShow = regEquipType(batt.fbsdeviceId, item.type);
        }
        return isShow;
      });
    },
  },
  mounted() {
    let battGroupId = this.$route.params.battGroupId;
    // console.log("mounted======", battGroupId);
    if (battGroupId) {
      this.getBattGroupInfo(battGroupId);
    }
    // 查询拓扑图状态的显示
    this.searchStatus();
    // 查询控制按钮的配置
    this.searchControl();
    // 初始化图表
    this.initChart();
    this.$nextTick(() => {
      this.$G.chartManage.resize(this.acTabs);
    });
    // 屏幕缩放时触发
    window.addEventListener("resize", this.resize);
    // 监控是否已经切换到当前页面
    this.monitorPage(true);
    // 监听点击事件
    // this.$G.chartManage.get("vol").getZr().on('contextmenu', params=>{
    //     let pointInPixel= [params.offsetX, params.offsetY];
    //     console.log(this.$G.chartManage.get("vol").containPixel('grid',pointInPixel));
    //     this.setRightMenuPos(params.event.clientX, params.event.clientY);
    // });
  },
  destroyed() {
    window.removeEventListener("resize", this.resize);
    this.monitorPage(false);
  },
};
</script>
<style scoped>
.page-real-time {
  color: #ffffff;
}
.table-cell.text-right {
  font-size: 14px;
}
.table-cell.text-right .iconfont {
  margin-right: 4px;
}
.table-row.table-row-error {
  color: #ff0000;
}
.table-row.table-row-warn {
  color: #e6a23c;
}
.table-row .table-cell {
  padding-top: 8px;
}
.page-content {
  position: relative;
  padding-top: 8px;
  padding-bottom: 2px;
  box-sizing: border-box;
  height: 100%;
}
.box-tools {
  position: static;
  line-height: 32px;
  margin-left: 6px;
}
.box-tools .iconfont,
.box-tools .el-iconfont {
  font-size: 24px;
}
.box-tools .iconfont:hover,
.box-tools .el-iconfont:hover {
  cursor: pointer;
  color: #cfcfcf;
}
.box-tools .iconfont:active,
.box-tools .el-iconfont:active {
  color: #ff0000;
}
.page-content-tools {
  position: absolute;
  top: 14px;
  right: 8px;
  z-index: 99;
}
.hdw-btn {
  display: inline-block;
  color: #fff;
  background-color: #409eff;
  border-color: #409eff;
  line-height: 1;
  white-space: nowrap;
  cursor: pointer;
  -webkit-appearance: none;
  text-align: center;
  box-sizing: border-box;
  outline: none;
  margin: 0;
  transition: 0.1s;
  font-weight: 500;
  -webkit-user-select: none;
  -moz-user-select: none;
  -ms-user-select: none;
  user-select: none;
  padding: 6px 10px;
  font-size: 14px;
  border-radius: 4px;
}
.hdw-btn:hover {
  background-color: #3c91e6;
}
.hdw-menu-list {
  border: 1px solid #409eff;
}
.hdw-menu-list .hdw-menu-item {
  border-top: 1px solid #0e5194;
}
.hdw-menu-list .hdw-menu-item:first-child {
  border-top: none;
}
.hdw-menu-item a {
  display: block;
  text-align: center;
  padding: 8px;
  color: #ffffff;
  cursor: pointer;
  background-color: rgba(30, 125, 219, 0.767);
}
.hdw-menu-item a:hover {
  background-color: rgb(60, 135, 211);
}
.hdw-menu-item a:active {
  background-color: rgb(34, 100, 167);
}
.hdw-state-list {
  box-sizing: border-box;
  font-size: 14px;
  padding-bottom: 8px;
}
.table-info-list {
  width: 100%;
  font-size: 14px;
}
.table-info-list td {
  padding: 4px;
  text-align: center;
}
.noborder {
  border: none;
}
.el-table-wrapper {
  background-color: #052272;
}
.flex-box-list,
.flex-box-list-full {
  display: flex;
  flex-direction: row;
  height: 50%;
  box-sizing: border-box;
}
.flex-box-list-full {
  height: 100%;
}
.flex-box-mgr {
  margin: 16px;
}
.page-content .flex-box {
  flex: 1;
  overflow: hidden;
}
.dianchigaojing {
  padding: 5px;
  height: 100%;
}
.dianchigaojing .borderBox {
  border: 1px solid #00fefe;
  padding: 5px;
}
.dianchigaojing .borderBox.box1 {
  margin-bottom: 5px;
  height: 110px;
}
.dianchigaojing .borderBox.box2 {
  height: calc(100% - 140px);
}
.lampImg {
  height: 28px;
}
.box-header {
  font-size: 14px;
  padding: 0;
}
.threeD-dialog>>>.el-dialog {
  width: 960px;
}
.station-contain {
  height: 600px;
}
.wx_guides {
  height: 150px;
  text-align: center;
  background-color: #ffffff;
  padding-top: 15%;
}
.wx_guides p {
  display: inline-block;
  margin-right: 10px;
}
.wx_guides p /deep/.el-input__inner {
  color: #000;
}
.tbl-data-container {
  display: flex;
  flex-direction: column;
  height: 100%;
}
.tbl-data-body {
  flex: 1;
  overflow: hidden;
}
.tbl-data-footer {
  text-align: center;
}
.dialog-params /deep/ .el-dialog__body {
  background: #ececec;
  padding: 0.4rem;
}
.tab-eleLine {
  display: flex;
}
.left {
  display: inline-block;
}
</style>
src/views/dataTest/realTimeFbo4831.vue
@@ -1084,7 +1084,7 @@
      //  电路图类型
      let workstatus = parseInt(data.devWorkstate); //[0:'在线监测',1:'放电测试',2:'充电测试',3:'内阻测试',4:'未知'];
      this.workState = (const_fbo4831.workstates[data.devWorkstate] || "未知") + (data.a059AcvolLowFlag ? '(急停)' : '');
      this.devTesttype = ['放电', '充电', '活化', '在线监测'][data.devTesttype] || '未知';
      this.devTesttype = { 0: '放电', 1: '充电', 2: '活化', 3: '在线监测', 255: '停止态' }[data.devTesttype] || '未知';
      this.diagram.desc = "";
      let battstate = this.inputs.battState;
      let alarmstatus = data.devAlarmstate;