he wei
2023-11-29 baaee5d47dd0e1ec4e9519a4858418cc36bdc0ab
UA ipInput修改
9个文件已修改
22个文件已添加
3729 ■■■■ 已修改文件
public/images/ac.png 补丁 | 查看 | 原始文档 | blame | 历史
public/images/ac1.png 补丁 | 查看 | 原始文档 | blame | 历史
public/images/batt.png 补丁 | 查看 | 原始文档 | blame | 历史
public/images/dc.png 补丁 | 查看 | 原始文档 | blame | 历史
public/images/dc1.png 补丁 | 查看 | 原始文档 | blame | 历史
public/images/header-bg.png 补丁 | 查看 | 原始文档 | blame | 历史
src/App.vue 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/images/gantan.png 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/js/getBinaryDigits.js 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/alarmCard.vue 95 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/alarmCardPop.vue 159 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/gauge3.vue 64 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/gradientBtn.vue 99 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/instrumentBoard.vue 338 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/ipInput.vue 233 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/listCard.vue 21 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/panel.vue 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/ycGrid.vue 70 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/router/routes.js 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/home/index.vue 67 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/powerCabinetControl/components/card.vue 133 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/powerCabinetControl/components/card2.vue 124 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/powerCabinetControl/components/ipCard.vue 148 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/powerCabinetControl/index.vue 375 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/realTime/index.vue 708 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/realTime/js/const_props.js 666 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/switchControl/images/ac.png 补丁 | 查看 | 原始文档 | blame | 历史
src/views/switchControl/images/ac1.png 补丁 | 查看 | 原始文档 | blame | 历史
src/views/switchControl/images/dc.png 补丁 | 查看 | 原始文档 | blame | 历史
src/views/switchControl/images/dc1.png 补丁 | 查看 | 原始文档 | blame | 历史
src/views/switchControl/index.vue 367 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
public/images/ac.png
public/images/ac1.png
public/images/batt.png
public/images/dc.png
public/images/dc1.png
public/images/header-bg.png

src/App.vue
@@ -15,5 +15,6 @@
#app {
  height: 100vh;
  background: #011F39;
  color: #fff;
}
</style>
src/assets/images/gantan.png
src/assets/js/getBinaryDigits.js
New file
@@ -0,0 +1,23 @@
/**
 *  将整数转为二进制数 并输出每一位的值到数组中 从高位到低位 二进制位数可指定 (多的裁切 不够的补0)
 */
export default function getBinaryDigits(num, bits) {
  // 将数值转换为二进制字符串
  let binaryStr = num.toString(2);
  let len = binaryStr.length;
  // 位数过多的裁切 不够的补0
  if (len > bits) {
    let start = len - bits;
    binaryStr = binaryStr.slice(start);
  } else if (len < bits) {
    let len0 = bits - len;
    let preStr = new Array(len0 + 1).join("0");
    binaryStr = preStr + binaryStr;
  }
  // 将二进制字符串转换为数组
  let binaryArray = binaryStr
    .split("")
    .map((v) => v * 1)
    .reverse();
  return binaryArray;
}
src/components/alarmCard.vue
@@ -4,7 +4,8 @@
    <div
      :class="[
        'state',
        { level1: 1 == level, level2: 2 == level, level3: 3 == level },
        { level1: 1 == level, level2: 2 == level, level3: 3 == level , 'alarm': flag },
      ]"
    ></div>
  </div>
@@ -12,7 +13,7 @@
<script>
export default {
  name: "",
  name: "AlarmCard",
  props: {
    name: {
      type: String,
@@ -25,20 +26,49 @@
        return [0, 1, 2, 3].some((v) => v == value);
      },
    },
    childrenCount: {
      type: Number,
      default: 0,
    },
    childrenVisible: {
      type: Boolean,
      default: false
    },
    flag: {
      type: Number,
      default: 0,
    }
  },
  computed: {
    cols() {
      return Math.ceil(Math.sqrt(this.childrenCount));
    },
    rows() {
      if (!this.cols) {
        return 0;
      }
      return Math.ceil(this.childrenCount / this.cols);
    },
  },
  data() {
    return {};
  },
  components: {},
  methods: {},
  methods: {
    close() {
      console.log('close?');
      this.$emit('close');
    }
  },
  mounted() {},
  mounted() {
  },
};
</script>
<style scoped lang="less">
.alarm-card {
  background: #0C4D77;
  background: #0c4d77;
  border: 1px solid #78eef8;
  border-radius: 4px;
  // width: 320px;
@@ -53,15 +83,58 @@
    background: #78eef8;
    border-radius: 4px;
    align-self: stretch;
    &.level1 {
      background: #4871E3;
    &.level1.alarm {
      background: #4871e3;
    }
    &.level2 {
      background: #F69F40;
    &.level2.alarm {
      background: #f69f40;
    }
    &.level3 {
      background: #FF3801;
    &.level3.alarm {
      background: #ff3801;
    }
  }
  .card-children-container {
    z-index: 100;
    position: fixed;
    top: 50%;
    left: 50%;
    width: 1600px;
    // height: 600px;
    transform: translate(-50%, -50%);
    background: gray;
    padding: 20px;
    display: flex;
    flex-direction: column;
    &.small {
      width: 800px;
    }
    .sub-title {
      text-align: center;
      font-size: 20px;
      padding-bottom: 10px;
    }
    .row {
      display: flex;
      &~.row {
        margin-top: 8px;
      }
      .col {
        flex: 1;
        & ~.col {
          margin-left: 8px;
        }
      }
    }
  }
  .mask {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    background: rgba(0,0,0,.4);
    z-index: 99;
  }
}
</style>
src/components/alarmCardPop.vue
New file
@@ -0,0 +1,159 @@
<template>
  <div class="">
    <div class="mask" v-if="visible" @click="close"></div>
    <div
      :class="['card-children-container', { small: cols < 5 }]"
      v-show="visible"
    >
      <div class="p-header">
        <el-button
          class="btn-close"
          icon="el-icon-close"
          size="mini"
          circle
          @click="close"
        ></el-button>
        <div class="sub-title">{{ title }}</div>
      </div>
      <div class="p-body">
        <div class="row" v-for="row in rows" :key="'row_' + row">
          <div
            class="col"
            v-for="col in cols"
            :key="'row' + row + '_col_' + col"
          >
            <alarm-card
              :name="(row - 1) * cols + col + ''"
              :level="bits[(row - 1) * cols + col - 1] ? 3 : 0"
              v-if="(row - 1) * cols + col <= count"
              >{{ (row - 1) * cols + col }}</alarm-card
            >
          </div>
        </div>
      </div>
    </div>
  </div>
</template>
<script>
import AlarmCard from "./alarmCard.vue";
import getBinaryDigits from "@/assets/js/getBinaryDigits";
export default {
  name: "",
  props: {
    visible: {
      type: Boolean,
      default: false,
    },
    count: {
      type: Number,
      required: true,
    },
    title: {
      type: String,
      default: "",
    },
    value: {
      type: Array,
      required: true,
    },
  },
  computed: {
    cols() {
      return Math.ceil(Math.sqrt(this.count));
    },
    rows() {
      if (!this.cols) {
        return 0;
      }
      return Math.ceil(this.count / this.cols);
    },
    bits() {
      let arr = [];
      this.value.forEach((v) => {
        arr.push(...getBinaryDigits(v, 25));
      });
      return arr;
    },
  },
  data() {
    return {};
  },
  components: {
    AlarmCard,
  },
  methods: {
    close() {
      console.log("close?");
      this.$emit("update:visible", false);
    },
  },
  mounted() {},
};
</script>
<style scoped lang="less">
.card-children-container {
  color: #fff;
  z-index: 100;
  position: fixed;
  top: 50%;
  left: 50%;
  width: 1600px;
  // height: 600px;
  transform: translate(-50%, -50%);
  // padding: 20px;
  display: flex;
  flex-direction: column;
  &.small {
    width: 800px;
  }
  .p-header {
    background: #78EEF8;
    color: #072943;
    font-weight: bold;
    height: 36px;
    line-height: 36px;
    border-radius: 6px 6px 0 0;
  }
  .p-body {
    background: #0C4D77;
    border: 1px solid #78EEF8;
    border-radius: 0 0 6px 6px;
    padding: 20px;
  }
  .btn-close {
    position: absolute;
    top: 4px;
    right: 10px;
  }
  .sub-title {
    text-align: center;
    font-size: 20px;
  }
  .row {
    display: flex;
    & ~ .row {
      margin-top: 8px;
    }
    .col {
      flex: 1;
      & ~ .col {
        margin-left: 8px;
      }
    }
  }
}
.mask {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background: rgba(0, 0, 0, 0.4);
  z-index: 99;
}
</style>
src/components/gauge3.vue
New file
@@ -0,0 +1,64 @@
<template>
  <div class="container">
    <instrument-board :name="labels[0]" :unit="unit" class="item" ref="one"></instrument-board>
    <instrument-board :name="labels[1]" :unit="unit" class="item" ref="two"></instrument-board>
    <instrument-board :name="labels[2]" :unit="unit" class="item" ref="three"></instrument-board>
  </div>
</template>
<script>
import instrumentBoard from './instrumentBoard.vue'
export default {
  name: '',
  props: {
    labels: {
      type: Array,
      default() {
        return ['A相', 'B相', 'C相']
      }
    },
    unit: {
      type: String,
      default: '',
    }
  },
  data () {
    return {
    }
  },
  components: {
    instrumentBoard,
  },
  methods: {
    resize() {
      this.$refs.one.resize();
      this.$refs.two.resize();
      this.$refs.three.resize();
    },
    setData(data) {
      this.$refs.one.setData(data[0]);
      this.$refs.two.setData(data[1]);
      this.$refs.three.setData(data[2]);
    }
  },
  mounted () {
    this.resize();
    this.setData([0, 0, 0]);
  }
}
</script>
<style scoped lang="less">
.container {
  height: 100%;
  display: flex;
  .item {
    flex: 1;
  }
}
</style>
src/components/gradientBtn.vue
New file
@@ -0,0 +1,99 @@
<template>
  <div :class="['gradient-btn', size, {active}]" @click="handlerClick" :style="styleVar">
    <slot>按钮</slot>
  </div>
</template>
<script>
export default {
  name: "",
  data() {
    return {};
  },
  props: {
    startColor: {
      type: String,
      default: "#50C9FE",
    },
    stopColor: {
      type: String,
      default: "#3473DA",
    },
    direction: {
      type: Number,
      default: 180,
    },
    color: {
      type: String,
      defualt: "#fff",
    },
    size: {
      type: String,
      validator(v) {
        return ['', "lg", "sm", "xs"].some((value) => v == value);
      },
      default: ''
    },
    active: {
      type: Boolean,
      default: false,
    }
  },
  components: {},
  computed: {
    styleVar() {
      return {
        "--color": this.color,
        "--startColor": this.startColor,
        "--stopColor": this.stopColor,
        "--direction": this.direction + "deg",
      };
    },
  },
  methods: {
    handlerClick() {
      this.$emit("click");
    },
  },
  mounted() {},
};
</script>
<style scoped lang="less">
.gradient-btn {
  display: inline-block;
  cursor: pointer;
  min-width: 3em;
  padding: 10px;
  border-radius: 6px;
  display: flex;
  justify-content: center;
  align-items: center;
  color: var(--color);
  background: linear-gradient(
    var(--direction),
    var(--startColor),
    var(--stopColor)
  );
  &.lg {
    padding: 16px;
    border-radius: 8px;
  }
  &.sm {
    padding: 8px;
    border-radius: 4px;
  }
  &.xs {
    padding: 4px;
    border-radius: 3px;
  }
  &~.gradient-btn {
    margin-left: 6px;
  }
  &.active {
    background: #F2891B;
  }
}
</style>
src/components/instrumentBoard.vue
@@ -4,46 +4,6 @@
var highlight = "#03b7c9";
var demoData = [
  {
    name: "电压",
    value: 220,
    unit: "V",
    pos: ["16.6%", "40%"],
    range: [0, 400],
  },
  { name: "电流", value: 32, unit: "A", pos: ["49.8%", "40%"], range: [0, 60] },
  {
    name: "功率因数",
    value: 0.9,
    pos: ["83%", "40%"],
    range: [0.1, 1.0],
    splitNum: 9,
  },
  // {
  //   name: "有功功率",
  //   value: 6.34,
  //   unit: "kW",
  //   pos: ["16.6%", "75%"],
  //   range: [0, 50],
  // },
  // {
  //   name: "有功电能",
  //   value: 6.28,
  //   unit: "kWh",
  //   pos: ["49.8%", "75%"],
  //   range: [0, 50],
  // },
  // {
  //   name: "电网频率",
  //   value: 50,
  //   unit: "Hz",
  //   pos: ["83%", "75%"],
  //   range: [0, 100],
  // },
];
export default {
  extends: BaseChart,
  props: {
@@ -55,26 +15,22 @@
      type: String,
      default: "",
    },
    r: {
      type: [String, Number],
      required: true,
    }
    range: {
      type: Array,
      default() {
        return [0, 400];
      },
    },
  },
  data() {
    return {
      // r: '33.3%',
      pos: ["50%", "48%"],
      r: "80%",
      r1: "62%",
    };
  },
  computed: {
  },
  watch: {
    r() {
      this.$nextTick(() => {
        this.resize();
      });
    }
  },
  computed: {},
  watch: {},
  methods: {
    fullScreen() {
      return false;
@@ -85,174 +41,136 @@
    },
    getOption(data) {
      let xLabel = data.xLabel;
      let sData = data.sData;
      let sName = this.name;
      let maxD = Math.max(...sData);
      if (maxD <= 0) {
        maxD = 1;
      } else {
        maxD = Math.round(maxD * 1.2 * 100) / 100;
      }
      let fillData = sData.map(() => maxD);
      let min = 0;
      let max =
        sData.length == 0
          ? 0
          : function (data) {
              let max = data.max;
              if (max == -Infinity) {
                max = 1;
              }
              // max = Math.max(Math.round((max + max * 0.2) * 100) / 100);
              return max;
            };
      let self = this;
      let { pos, range, r, r1, unit, name } = this;
      return {
        grid: {
          left: "1%",
          right: "1%",
          bottom: "2%",
          top: "2%",
          left: 0,
          right: 0,
          bottom: 0,
          top: 0,
          containLabel: true,
        },
        series: (function () {
          var result = [];
        series: [
          // 外围刻度
          {
            type: "gauge",
            center: pos,
            radius: r,
          demoData.forEach(function (item) {
            result.push(
              // 外围刻度
              {
                type: "gauge",
                center: item.pos,
                // radius: "33.33%", // 1行3个
                radius: self.r,
            splitNumber: 5,
            min: range[0],
            max: range[1],
            // startAngle: 225,
            startAngle: 200,
            endAngle: -20,
            axisLine: {
              show: true,
              lineStyle: {
                width: 2,
                shadowBlur: 0,
                color: [[1, highlight]],
              },
            },
            axisTick: {
              show: true,
              lineStyle: {
                color: highlight,
                width: 1,
              },
              length: -5,
              splitNumber: 10,
            },
            splitLine: {
              show: true,
              // show: false,
              // length: -14,
              length: 4,
              lineStyle: {
                color: highlight,
              },
            },
            axisLabel: {
              distance: 5,
              // textStyle: {
              //   color: highlight,
              //   fontSize: "14",
              //   fontWeight: "bold",
              // },
            },
            pointer: {
              show: 0,
            },
            detail: {
              show: 0,
            },
          },
                splitNumber: item.splitNum || 10,
                min: item.range[0],
                max: item.range[1],
                startAngle: 225,
                endAngle: -45,
                axisLine: {
                  show: true,
                  lineStyle: {
                    width: 2,
                    shadowBlur: 0,
                    color: [[1, highlight]],
                  },
                },
                axisTick: {
                  show: true,
                  lineStyle: {
                    color: highlight,
                    width: 1,
                  },
                  // length: -5,
                  splitNumber: 10,
                },
                splitLine: {
                  // show: true,
                  show: false,
                  // length: -14,
                  lineStyle: {
                    color: highlight,
                  },
                },
                axisLabel: {
                  distance: -20,
                  // textStyle: {
                  //   color: highlight,
                  //   fontSize: "14",
                  //   fontWeight: "bold",
                  // },
                },
                pointer: {
                  show: 0,
                },
                detail: {
                  show: 0,
          // 内侧指针、数值显示
          {
            name: name,
            type: "gauge",
            center: pos,
            radius: r1,
            startAngle: 200,
            endAngle: -25,
            min: range[0],
            max: range[1],
            axisLine: {
              show: true,
              lineStyle: {
                width: 16,
                color: [[1, "rgba(255,255,255,.1)"]],
              },
            },
            axisTick: {
              show: 0,
            },
            splitLine: {
              show: 0,
            },
            axisLabel: {
              show: 0,
            },
            pointer: {
              show: true,
              length: "85%",
              width: 3,
            },
            detail: {
              show: true,
              offsetCenter: [0, "90%"],
              textStyle: {
                fontSize: 16,
                color: "#fff",
              },
              formatter: [
                "{name|" + name + "}",
                "{value} " + (unit || ""),
              ].join("\n"),
              rich: {
                name: {
                  fontSize: 12,
                  lineHeight: 20,
                  color: "#ddd",
                },
              },
              // 内侧指针、数值显示
            },
            itemStyle: {
              normal: {
                color: highlight,
              },
            },
            data: [
              {
                name: item.name,
                type: "gauge",
                center: item.pos,
                radius: "30.33%",
                startAngle: 225,
                endAngle: -45,
                min: item.range[0],
                max: item.range[1],
                axisLine: {
                  show: true,
                  lineStyle: {
                    width: 16,
                    color: [[1, "rgba(255,255,255,.1)"]],
                  },
                },
                axisTick: {
                  show: 0,
                },
                splitLine: {
                  show: 0,
                },
                axisLabel: {
                  show: 0,
                },
                pointer: {
                  show: true,
                  length: "105%",
                },
                detail: {
                  show: true,
                  offsetCenter: [0, "200%"],
                  textStyle: {
                    fontSize: 20,
                    color: "#fff",
                  },
                  formatter: [
                    "{value} " + (item.unit || ""),
                    "{name|" + item.name + "}",
                  ].join("\n"),
                  rich: {
                    name: {
                      fontSize: 14,
                      lineHeight: 30,
                      color: "#ddd",
                    },
                  },
                },
                itemStyle: {
                  normal: {
                    color: highlight,
                  },
                },
                data: [
                  {
                    value: item.value,
                  },
                ],
              }
            );
          });
          return result;
        })(),
                value: data,
              },
            ],
          },
        ],
      };
    },
  },
  mounted() {
    this.setData({
      xLabel: [],
      sData: [],
    });
  },
};
</script>
src/components/ipInput.vue
New file
@@ -0,0 +1,233 @@
<template>
  <div class="ip-input-container">
    <div
      class="ip-segment"
      v-for="(segment, index) in segments"
      :key="'ip_' + index"
    >
      <div class="inner">
        <input
          type="text"
          maxlength="3"
          class="ip-segment-input"
          :value="segment"
          :placeholder="placeholder"
          v-on:keydown="onInputKeydown($event, index)"
          v-on:input="onInput($event, index)"
          v-on:blur="onInputBlur()"
          v-on:paste="onPaste($event, index)"
        />
      </div>
      <i v-show="index != segments.length - 1">.</i>
    </div>
  </div>
</template>
<script>
/* global document*/
/**
 * get the cursor position of the element
 * @param  {Element} el the element
 * @return {Integer}    the position fo the cursor
 */
function getRange(el) {
  var cuRange;
  var tbRange;
  var headRange;
  var range;
  var dupRange;
  var ret = {};
  if (el.setSelectionRange) {
    // standard
    ret.begin = el.selectionStart;
    ret.end = el.selectionEnd;
    ret.result = el.value.substring(ret.begin, ret.end);
  } else if (document.selection) {
    // ie
    if (el.tagName.toLowerCase() === "input") {
      cuRange = document.selection.createRange();
      tbRange = el.createTextRange();
      tbRange.collapse(true);
      tbRange.select();
      headRange = document.selection.createRange();
      headRange.setEndPoint("EndToEnd", cuRange);
      ret.begin = headRange.text.length - cuRange.text.length;
      ret.end = headRange.text.length;
      ret.result = cuRange.text;
      cuRange.select();
    } else if (el.tagName.toLowerCase() === "textarea") {
      range = document.selection.createRange();
      dupRange = range.duplicate();
      dupRange.moveToElementText(el);
      dupRange.setEndPoint("EndToEnd", range);
      ret.begin = dupRange.text.length - range.text.length;
      ret.end = dupRange.text.length;
      ret.result = range.text;
    }
  }
  el.focus();
  return ret;
}
export default {
  props: {
    ip: {
      type: String,
      required: true,
    },
    placeholder: String,
    onChange: Function,
    onBlur: Function,
  },
  data() {
    return {
      segments: ["", "", "", ""],
    };
  },
  watch: {
    ip(ip) {
      this.syncIp(ip);
    },
  },
  methods: {
    onInputKeydown(event, index) {
      var keyCode = event.keyCode || event.which;
      var value = event.target.value;
      if (keyCode === 8 || keyCode === 37) {
        // move the cursor to previous input if backspace and left arrow is pressed at the begin of one input
        if (
          (value.length === 0 || getRange(event.target).end === 0) &&
          index > 0
        ) {
          this.$el.getElementsByTagName("input")[(index - 1) % 4].focus();
          // When jump to pre input(enter "backspace"), thr cursor should in the end.
          // before fix: 127.|0.0.0  =>   12|7.0.0.1
          // after fix: 127.|0.0.0 = >   127|.0.0.0
          // notes: "|" mean the cursor position.
          event.preventDefault();
        }
      } else if (keyCode === 39) {
        if (getRange(event.target).end === value.length && index < 3) {
          // move to cursor to the next input if right arrow is pressed at the end of one input
          this.$el.getElementsByTagName("input")[(index + 1) % 4].focus();
        }
      } else if (keyCode == 110) {
        // console.log('...', index);
        this.$el.getElementsByTagName("input")[(index + 1) % 4].focus();
      }
    },
    onInput(event, index) {
      var value = event.target.value;
      event.target.value = this.segments[index];
      var segment = Number(value);
      if (isNaN(segment)) {
        return;
      } else if (value === "") {
        this.segments.splice(index, 1, "");
      } else if (value.indexOf(".") > -1) {
        // console.log('...?', index);
        value = value.replace('.', '');
        // this.$el.getElementsByTagName("input")[(index + 1) % 4].focus();
      } else if (segment > 255 || segment < 0) {
        // set the segment to 255 if out of ip range
        this.segments.splice(index, 1, 255);
      } else {
        this.segments.splice(index, 1, segment);
      }
      // jump to next input
      if (value.length >= 3) {
        // console.log('...xxx', index, value);
        this.$el.getElementsByTagName("input")[(index + 1) % 4].focus();
      }
    },
    onInputBlur() {
      setTimeout(() => {
        var className = document.activeElement.className;
        if (className.indexOf("ip-segment-input") === -1) {
          if (this.onBlur) {
            this.onBlur(this.segments.join("."));
          }
        }
      }, 50);
    },
    onPaste(e, index) {
      var pasteText = e.clipboardData.getData("text/plain");
      var segments = pasteText.split(".");
      segments.forEach((segment, i) => {
        if (
          index + i < 4 &&
          !isNaN(segment) &&
          segment >= 0 &&
          segment <= 255
        ) {
          this.segments.splice(index + i, 1, segment);
        }
      });
      e.preventDefault();
    },
    syncIp(ip) {
      if (ip && ip.indexOf(".") !== -1) {
        ip.split(".").map((segment, index) => {
          if (isNaN(segment) || segment < 0 || segment > 255) {
            segment = 255;
          }
          this.segments.splice(index, 1, segment);
          return segment;
        });
      }
    },
  },
  mounted() {
    this.syncIp(this.ip);
    this.$watch(
      () => {
        return this.segments.join(".");
      },
      (val, oldValue) => {
        if (val !== oldValue) {
          if (val === "...") {
            val = "";
          }
          if (this.onChange) {
            this.onChange(val);
          }
        }
      }
    );
  },
};
</script>
<style lang="less" scoped>
.ip-input-container {
  // width: 100%;
  height: 28px;
  display: flex;
  background-color: #fff;
}
.ip-segment {
  height: 26px;
  flex: 1;
  display: flex;
  .inner {
    display: flex;
    flex: 1;
  }
  input {
    width: 100%;
    height: 26px;
    line-height: normal;
    border: none;
    outline: none;
    text-align: center;
    text-indent: 0px;
    margin: 0px;
    padding: 0px;
    background-color: transparent;
  }
  i {
    font-size: 18px;
    font-weight: 700;
    color: #000;
  }
}
</style>
src/components/listCard.vue
@@ -6,9 +6,10 @@
        v-for="(iitem, iidx) in item"
        :key="'item_' + iidx"
      >
        <template v-if="iitem">
          {{ iitem.label }}: {{ valueObj[iitem.key] || "" }}
        </template>
        <div class="content" v-if="iitem">
          <div class="label">{{ iitem.label }}:</div>
          <div class="value">{{ valueObj[iitem.key] || "" }}</div>
        </div>
      </div>
    </div>
  </div>
@@ -46,7 +47,8 @@
  computed: {
    // 添加空行 并转为二维数组
    list() {
      let { datas: list, emptyIdxs } = this;
      let { datas, emptyIdxs } = this;
      let list = JSON.parse(JSON.stringify(datas));
      emptyIdxs.sort((a, b) => a - b);
      for (let i = 0, j = emptyIdxs.length; i < j; i++) {
        list.splice(emptyIdxs[i], 0, null);
@@ -111,5 +113,16 @@
      }
    }
  }
  .content {
    flex: 1;
    display: flex;
    justify-content: space-between;
    .value {
      width: 88px;
      margin-left: 6px;
      color: #75e8f2;
      flex-shrink: 0;
    }
  }
}
</style>
src/components/panel.vue
@@ -1,6 +1,10 @@
<template>
  <div class="panel">
    <div class="inner">
      <!-- 工具栏 -->
      <div class="tools">
        <slot name="tools"></slot>
      </div>
      <!-- 标题 -->
      <div class="title">{{ title }}</div>
      <!-- 内容 -->
@@ -160,6 +164,7 @@
    background: radial-gradient(rgba(01, 31, 57, 0.25) 63%, #77eef7 280%);
    display: flex;
    flex-direction: column;
    position: relative;
    .title {
      height: 42px;
      text-align: center;
@@ -171,6 +176,11 @@
    .content {
      flex: 1;
    }
    .tools {
      position: absolute;
      top: 0;
      right: 0;
    }
  }
}
</style>
src/components/ycGrid.vue
New file
@@ -0,0 +1,70 @@
<template>
  <div class="card-children-container">
    <div class="row" v-for="row in rows" :key="'row_' + row">
      <div class="col" v-for="col in cols" :key="'row' + row + '_col_' + col">
        <template v-if="(row - 1) * cols + col <= count">
          <slot :data="config" :index="(row - 1) * cols + col - 1"></slot>
        </template>
      </div>
    </div>
  </div>
</template>
<script>
export default {
  name: "",
  props: {
    count: {
      type: Number,
      required: true,
    },
    config: {
      type: [Object, Array],
      required: true,
    },
    cols: {
      type: Number,
      default: 3
    }
  },
  computed: {
    // cols() {
    //   return Math.ceil(Math.sqrt(this.count));
    // },
    rows() {
      if (!this.cols) {
        return 0;
      }
      return Math.ceil(this.count / this.cols);
    },
  },
  data() {
    return {};
  },
  methods: {},
  mounted() {},
};
</script>
<style scoped lang="less">
.card-children-container {
  color: #fff;
  height: 100%;
  display: flex;
  flex-direction: column;
  .row {
    display: flex;
    flex: 1;
    & ~ .row {
      margin-top: 8px;
    }
    .col {
      flex: 1;
      & ~ .col {
        margin-left: 8px;
      }
    }
  }
}
</style>
src/router/routes.js
@@ -44,6 +44,34 @@
    ]
  },
  {
    path: "/switchcontrol",
    component: Layout,
    meta: { title: "交流/直流微断测控", icon: 'dashboard'},
    name: "switchControl",
    children: [
      {
        path: '',
        component: () => import('@/views/switchControl'),
        name: 'switchControl',
        meta: {title: '交流/直流微断测控', icon: 'dashboard'}
      },
    ]
  },
  {
    path: "/power-cabinet-control",
    component: Layout,
    meta: { title: "通信电源柜测控", icon: 'dashboard'},
    name: "powerCabinetControl",
    children: [
      {
        path: '',
        component: () => import('@/views/powerCabinetControl'),
        name: 'powerCabinetControl',
        meta: {title: '通信电源柜测控', icon: 'dashboard'}
      },
    ]
  },
  {
    path: "/user",
    component: Layout,
    redirect: '/user/list',
src/views/home/index.vue
@@ -13,6 +13,7 @@
import pdgImg from "./images/pdg.png";
import kggImg from "./images/kgg.png";
import hrImg from "./images/hr.png";
import ListCard from "@/components/listCard.vue";
import createWs from "@/assets/js/websocket/plus";
const WSMixin = createWs("dev", "dfu");
@@ -28,6 +29,7 @@
    ProtectorBox,
    TextBox,
    SvgLine,
    ListCard,
  },
  data() {
    const baseURL = getWebUrl();
@@ -76,18 +78,7 @@
            </div>
          </div>
          <div class="main">
            <div class="list">
              <div class="row-item" v-for="idx in 9" :key="'pdg_' + idx">
                {{ idx - 1 }}{{ PDG[idx - 1].label }}:
              </div>
            </div>
            <div class="list">
              <div class="row-item" v-for="idx of 9" :key="'pdg2_' + idx">
                <template v-if="PDG[idx + 8]"
                  >{{ idx + 8 }}{{ PDG[idx + 8].label }}:</template
                >
              </div>
            </div>
            <list-card :datas="PDG" :rows="9" :cols="2"></list-card>
          </div>
        </div>
        <div class="info info2">
@@ -108,18 +99,7 @@
            </div>
          </div>
          <div class="main">
            <div class="list">
              <div class="row-item" v-for="idx in 6" :key="'kgg_' + idx">
                {{ idx - 1 }}{{ KGG[idx - 1].label }}:
              </div>
            </div>
            <div class="list">
              <div class="row-item" v-for="idx of 6" :key="'kgg2_' + idx">
                <template v-if="KGG[idx + 5]"
                  >{{ idx + 5 }}{{ KGG[idx + 5].label }}:</template
                >
              </div>
            </div>
            <list-card :datas="KGG" :rows="6" :cols="2"></list-card>
          </div>
        </div>
@@ -141,20 +121,7 @@
            </div>
          </div>
          <div class="main">
            <div class="list">
              <div class="row-item" v-for="idx in 4" :key="'hr_' + idx">
                <template v-if="idx < 4"
                  >{{ idx - 1 }}{{ HR[idx - 1].label }}:</template
                >
              </div>
            </div>
            <div class="list">
              <div class="row-item" v-for="idx of 4" :key="'hr2_' + idx">
                <template v-if="idx < 4 && HR[idx + 2]"
                  >{{ idx + 2 }}{{ HR[idx + 2].label }}:</template
                >
              </div>
            </div>
            <list-card :datas="HR" :emptyIdxs="[3]" :rows="4" :cols="2"></list-card>
          </div>
        </div>
      </div>
@@ -599,29 +566,7 @@
      }
      .main {
        flex: 1;
        display: flex;
        padding: 0 6px;
        .list {
          flex: 1;
          display: flex;
          flex-direction: column;
          padding: 10px 0;
          & + .list {
            margin-left: 6px;
          }
          .row-item {
            flex: 1;
            display: flex;
            align-items: center;
            padding-left: 10px;
            // height: 20px;
            // line-height: 20px;
            background: #153952;
            &:nth-child(2n) {
              background: rgba(21, 57, 82, 0.6);
            }
          }
        }
        padding: 10px 6px;
      }
      &.info1 {
        flex: 10;
src/views/powerCabinetControl/components/card.vue
New file
@@ -0,0 +1,133 @@
<template>
  <div class="card flex-c">
    <div class="card-title">
      <div class="flex-r">
        <div class="i"></div>
        {{ title }}
      </div>
      <el-checkbox v-model="checked"></el-checkbox>
    </div>
    <div class="card-content">
      <div class="row">
        实时:
        <div class="value">18</div>
        <div class="btn"></div>
      </div>
      <div class="row">
        模拟:
        <el-input-number
          class="input"
          size="mini"
          v-model="num"
          :step="1"
        ></el-input-number>
        <div class="btn">
          <gradient-btn :active="setFlag" size="xs">{{setFlag ? btnText + '中' : btnText}}</gradient-btn>
        </div>
      </div>
    </div>
  </div>
</template>
<script>
import gradientBtn from "@/components/gradientBtn.vue";
export default {
  name: "",
  props: {
    title: {
      type: String,
      default: "我是标题",
    },
    setFlag: {
      type: Boolean,
      default: false,
    },
    btnText: {
      type: String,
      default: '给定'
    }
  },
  data() {
    return {
      checked: true,
      num: 0,
    };
  },
  components: {
    gradientBtn,
  },
  methods: {},
  mounted() {},
};
</script>
<style scoped lang="less">
.flex-r {
  display: flex;
  flex-direction: row;
}
.flex-c {
  display: flex;
  flex-direction: column;
}
.card {
  height: 100%;
  border: 1px solid #3e8d9d;
  border-radius: 4px;
  color: #fff;
  overflow: hidden;
  .card-title {
    background: #0c4d77;
    height: 30px;
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding-right: 6px;
  }
  .i {
    margin-left: 4px;
    margin-right: 6px;
    width: 20px;
    height: 20px;
    border-radius: 50%;
    background: #77edf6 url("../../../assets/images/gantan.png") 50% 50% / auto
      60% no-repeat;
  }
  .card-content {
    flex: 1;
    background: #011f39;
    display: flex;
    flex-direction: column;
    padding: 6px;
  }
  .value {
    flex: 1;
    background: #fff;
    color: #000;
    margin-left: 6px;
    margin-right: 6px;
    padding-left: 6px;
    height: 26px;
    line-height: 26px;
    border-radius: 6px;
  }
  .input {
    color: #000;
    flex: 1;
    margin-left: 6px;
    margin-right: 6px;
    /deep/ .el-input__inner {
      color: inherit;
    }
  }
  .btn {
    width: 76px;
  }
  .row {
    flex: 1;
    display: flex;
    align-items: center;
  }
}
</style>
src/views/powerCabinetControl/components/card2.vue
New file
@@ -0,0 +1,124 @@
<template>
  <div class="card flex-c">
    <div class="card-title">
      <div class="flex-r">
        <div class="i"></div>
        {{ title }}
      </div>
      <el-checkbox v-model="checked"></el-checkbox>
    </div>
    <div class="card-content">
      <div class="col">
        实时:
        <div class="value">正常</div>
      </div>
      <div class="col">
        模拟:
        <div class="btn">
          <gradient-btn :active="setFlag" size="xs">{{setFlag ? '执行中' : '执行'}}</gradient-btn>
        </div>
      </div>
    </div>
  </div>
</template>
<script>
import gradientBtn from "@/components/gradientBtn.vue";
export default {
  name: "",
  props: {
    title: {
      type: String,
      default: "我是标题",
    },
    setFlag: {
      type: Boolean,
      default: false,
    }
  },
  data() {
    return {
      checked: true,
      num: 0,
    };
  },
  components: {
    gradientBtn,
  },
  methods: {},
  mounted() {},
};
</script>
<style scoped lang="less">
.flex-r {
  display: flex;
  flex-direction: row;
}
.flex-c {
  display: flex;
  flex-direction: column;
}
.card {
  height: 100%;
  border: 1px solid #77edf6;
  border-radius: 4px;
  color: #fff;
  overflow: hidden;
  .card-title {
    background: #011F39;
    height: 30px;
    color: #77edf6;
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding-right: 6px;
    border-bottom: 1px solid #77edf6;
  }
  .i {
    margin-left: 4px;
    margin-right: 6px;
    width: 20px;
    height: 20px;
    border-radius: 50%;
    background: #77edf6 url("../../../assets/images/gantan.png") 50% 50% / auto
      60% no-repeat;
  }
  .card-content {
    flex: 1;
    background: #0C4D77;
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 6px;
  }
  .col {
    display: flex;
    align-items: center;
  }
  .value {
    flex: 1;
    color: #77edf6;
    margin-left: 6px;
    margin-right: 6px;
    padding-left: 6px;
    height: 26px;
    line-height: 26px;
    border-radius: 6px;
  }
  .input {
    color: #000;
    flex: 1;
    margin-left: 6px;
    margin-right: 6px;
    /deep/ .el-input__inner {
      color: inherit;
    }
  }
  .btn {
    width: 76px;
    padding-left: 8px;
  }
}
</style>
src/views/powerCabinetControl/components/ipCard.vue
New file
@@ -0,0 +1,148 @@
<template>
  <div class="card flex-c">
    <div class="card-title">
      <div class="flex-r">
        <div class="i"></div>
        {{ title }}
      </div>
      <el-checkbox v-model="checked"></el-checkbox>
    </div>
    <div class="card-content">
      <div class="row">
        实时:
        <div class="value">18</div>
        <div class="btn"></div>
      </div>
      <div class="row">
        模拟:
        <ip-input class="input" :onChange="change" :onBlur="blur" :ip="ip"></ip-input>
        <div class="btn">
          <gradient-btn :active="setFlag" size="xs">{{
            setFlag ? "设定中" : "设定"
          }}</gradient-btn>
        </div>
      </div>
    </div>
  </div>
</template>
<script>
import gradientBtn from "@/components/gradientBtn.vue";
import IpInput from "@/components/ipInput.vue";
export default {
  name: "",
  props: {
    title: {
      type: String,
      default: "我是标题",
    },
    setFlag: {
      type: Boolean,
      default: false,
    },
    ip: {
      type: String,
      required: true
    }
  },
  data() {
    return {
      checked: true,
      num: 0,
    };
  },
  components: {
    gradientBtn,
    IpInput,
  },
  methods: {
    change(value) {
      // console.log(value, 'ip change', value.split('.'));
      let segments = value.split('.');
      if(!segments.some(v=>v=='')){
        // console.log(value, 'ip', this.ip);
        this.$emit('update:ip', value);
        this.$emit('change', value);
      }
    },
    blur(value) {
      // console.log(value, 'blur', this.ip);
      this.$emit('update:ip', value);
      this.$emit('blur', value)
    }
  },
  mounted() {},
};
</script>
<style scoped lang="less">
.flex-r {
  display: flex;
  flex-direction: row;
}
.flex-c {
  display: flex;
  flex-direction: column;
}
.card {
  height: 100%;
  border: 1px solid #3e8d9d;
  border-radius: 4px;
  color: #fff;
  overflow: hidden;
  .card-title {
    background: #0c4d77;
    height: 30px;
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding-right: 6px;
  }
  .i {
    margin-left: 4px;
    margin-right: 6px;
    width: 20px;
    height: 20px;
    border-radius: 50%;
    background: #77edf6 url("../../../assets/images/gantan.png") 50% 50% / auto
      60% no-repeat;
  }
  .card-content {
    flex: 1;
    background: #011f39;
    display: flex;
    flex-direction: column;
    padding: 6px;
  }
  .value {
    flex: 1;
    background: #fff;
    color: #000;
    margin-left: 6px;
    margin-right: 6px;
    padding-left: 6px;
    height: 26px;
    line-height: 26px;
    border-radius: 6px;
  }
  .input {
    color: #000;
    flex: 1;
    border-radius: 6px;
    margin-left: 6px;
    margin-right: 6px;
    /deep/ .el-input__inner {
      color: inherit;
    }
  }
  .btn {
    width: 76px;
  }
  .row {
    flex: 1;
    display: flex;
    align-items: center;
  }
}
</style>
src/views/powerCabinetControl/index.vue
New file
@@ -0,0 +1,375 @@
<template>
  <div class="p-main">
    <el-tabs class="tab" type="border-card" @tab-click="tabClick">
      <el-tab-pane label="交流/直流配电柜">
        <div class="tab-content content1 flex-r">
          <panel class="panel left" title="遥测量模拟">
            <div slot="tools" class="btn-grp">
              <gradient-btn size="xs">全选</gradient-btn>
              <gradient-btn size="xs">批量给定</gradient-btn>
            </div>
            <div class="content">
              <yc-grid :count="18" :config="[1, 2, 3]">
                <template v-slot="scope">
                  <card :setFlag="Math.random() > 0.5"></card>
                </template>
              </yc-grid>
            </div>
          </panel>
          <panel class="panel right" title="遥信量模拟">
            <div slot="tools" class="btn-grp">
              <gradient-btn size="xs">全选</gradient-btn>
              <gradient-btn size="xs">批量执行</gradient-btn>
            </div>
            <div class="content">
              <yc-grid :count="28" :cols="4" :config="[1, 2, 3]">
                <template v-slot="scope">
                  <card2></card2>
                </template>
              </yc-grid>
            </div>
          </panel>
        </div>
      </el-tab-pane>
      <el-tab-pane label="高频开关整流柜">
        <div class="tab-content content2 flex-r">
          <panel class="panel left" title="遥测量模拟">
            <div slot="tools" class="btn-grp">
              <gradient-btn size="xs">全选</gradient-btn>
              <gradient-btn size="xs">批量给定</gradient-btn>
            </div>
            <div class="content">
              <yc-grid :count="18" :config="[1, 2, 3]">
                <template v-slot="scope">
                  <card></card>
                </template>
              </yc-grid>
            </div>
          </panel>
          <panel class="panel right" title="遥信量模拟">
            <div slot="tools" class="btn-grp">
              <gradient-btn size="xs">全选</gradient-btn>
              <gradient-btn size="xs">批量执行</gradient-btn>
            </div>
            <div class="content">
              <yc-grid :count="28" :cols="4" :config="[1, 2, 3]">
                <template v-slot="scope">
                  <card2></card2>
                </template>
              </yc-grid>
            </div>
          </panel>
        </div>
      </el-tab-pane>
      <el-tab-pane label="核容装置">
        <div class="tab-content content3 flex-r">
          <panel class="panel left" title="遥调量模拟">
            <div slot="tools" class="btn-grp">
              <gradient-btn size="xs">全选</gradient-btn>
              <gradient-btn size="xs">批量设定</gradient-btn>
            </div>
            <div class="content">
              <div class="grid1">
                <yc-grid :count="6" :config="[1, 2, 3]">
                  <template v-slot="scope">
                    <card btnText="设定"></card>
                  </template>
                </yc-grid>
              </div>
              <div class="grid1">
                <yc-grid :count="3" :cols="2" :config="ips">
                  <template v-slot="scope">
                    <ip-card :ip.sync="scope.data[scope.index].ip" @change="changeIp"></ip-card>
                  </template>
                </yc-grid>
              </div>
            </div>
          </panel>
          <panel class="panel right" title="遥控量模拟">
            <div class="content">
              <el-row class="el_row" :gutter="20">
                <el-col class="el_col" :span="12">
                  <div class="card">
                    <div class="card-title">蓄电池放电模拟</div>
                    <div class="card-content">
                      <div class="item-row">
                        <div class="label">蓄电池实时状态:</div>
                        <div class="value">浮充</div>
                      </div>
                      <div class="item-row">
                        <div class="label">蓄电池放电模拟:</div>
                        <div class="btn-grp">
                          <gradient-btn size="sm">开始放电</gradient-btn>
                          <gradient-btn active size="sm">停止放电</gradient-btn>
                        </div>
                      </div>
                    </div>
                  </div>
                </el-col>
                <el-col class="el_col" :span="12">
                  <div class="card">
                    <div class="card-title">蓄电池内阻模拟</div>
                    <div class="card-content">
                      <div class="item-row">
                        <div class="label">蓄电池实时状态:</div>
                        <div class="value">浮充</div>
                      </div>
                      <div class="item-row">
                        <div class="label">内阻测试模拟:</div>
                        <div class="btn-grp">
                          <gradient-btn size="sm">启动内阻测试</gradient-btn>
                          <gradient-btn active size="sm"
                            >停止内阻测试</gradient-btn
                          >
                        </div>
                      </div>
                    </div>
                  </div>
                </el-col>
                <el-col class="el_col" :span="12">
                  <div class="card">
                    <div class="card-title">核容装置K1/D1测试模拟</div>
                    <div class="card-content">
                      <div class="item-row">
                        <div class="label">核容装置状态:</div>
                        <div class="value">浮充</div>
                      </div>
                      <div class="item-row">
                        <div class="label">K1/D1测试模拟:</div>
                        <div class="btn-grp">
                          <gradient-btn size="sm">启动K1/D1测试</gradient-btn>
                          <gradient-btn active size="sm"
                            >停止K1/D1测试</gradient-btn
                          >
                        </div>
                      </div>
                    </div>
                  </div>
                </el-col>
                <el-col class="el_col" :span="12">
                  <div class="card">
                    <div class="card-title">蓄电池内阻模拟</div>
                    <div class="card-content">
                      <div class="item-row">
                        <div class="label">核容装置状态:</div>
                        <div class="value">浮充</div>
                      </div>
                      <div class="item-row">
                        <div class="label">装置重启模拟:</div>
                        <div class="btn-grp">
                          <gradient-btn size="sm">重启核容装置</gradient-btn>
                        </div>
                      </div>
                    </div>
                  </div>
                </el-col>
                <el-col class="el_col" :span="12">
                  <div class="card">
                    <div class="card-title">核容装置IP配置</div>
                    <div class="card-content">
                      <div class="item-row">
                        <div class="label">核容装置IP地址:</div>
                        <div class="value">192.168.10.112</div>
                      </div>
                      <div class="item-row">
                        <div class="label">核容装置IP网关:</div>
                        <div class="value">192.168.10.1</div>
                      </div>
                      <div class="item-row">
                        <div class="label">核容装置子网掩码:</div>
                        <div class="value">255.255.255.0</div>
                      </div>
                      <div class="item-row">
                        <div class="label">核容装置配置IP地址:</div>
                        <div class="value">192.168.10.112</div>
                      </div>
                      <div class="item-row">
                        <div class="label">核容装置配置IP网关:</div>
                        <div class="value">192.168.10.1</div>
                      </div>
                      <div class="item-row">
                        <div class="label">核容装置配置子网掩码:</div>
                        <div class="value">255.255.255.0</div>
                      </div>
                      <div class="item-row">
                        <div class="label">装置重启模拟:</div>
                        <div class="btn-grp">
                          <gradient-btn size="sm">暂时配置生效</gradient-btn>
                          <gradient-btn active size="sm"
                            >永久配置生效</gradient-btn
                          >
                        </div>
                      </div>
                    </div>
                  </div>
                </el-col>
              </el-row>
            </div>
          </panel>
        </div>
      </el-tab-pane>
    </el-tabs>
  </div>
</template>
<script>
import Panel from "@/components/panel.vue";
import ycGrid from "@/components/ycGrid.vue";
import AlarmCard from "@/components/alarmCard.vue";
import gradientBtn from "@/components/gradientBtn.vue";
import card from "./components/card";
import card2 from "./components/card2";
import IpCard from "./components/ipCard";
export default {
  name: "",
  components: {
    Panel,
    ycGrid,
    AlarmCard,
    gradientBtn,
    card,
    card2,
    IpCard,
  },
  data() {
    return {
      ips: [{ ip: "192.168.10.222" }, { ip: "255.0.0.0" }, { ip: "0.0.0.0" }],
    };
  },
  methods: {
    tabClick() {},
    changeIp(ip) {
      console.log(ip, "hhhhhh");
    },
  },
  mounted() {},
};
</script>
<style scoped lang="less">
.p-main {
  height: 100%;
  .tab {
    height: 100%;
    background: transparent;
    border: 0 none;
    box-shadow: none;
    display: flex;
    flex-direction: column;
    /deep/ .el-tabs__header {
      border: 0 none;
      background-color: transparent;
    }
    /deep/ .el-tabs__content {
      flex: 1;
      padding: 4px;
      .el-tab-pane {
        height: 100%;
      }
    }
    .flex-c {
      display: flex;
      flex-direction: column;
    }
    .flex-r {
      display: flex;
      flex-direction: row;
    }
    .tab-content {
      height: 100%;
    }
    /deep/ .el-tabs__header .el-tabs__item {
      background: #78eef8;
      color: #000;
      border-radius: 4px;
      font-weight: bold;
      font-size: 18px;
      border: 0 none;
      & + .el-tabs__item {
        margin-left: 6px;
      }
      &.is-active {
        color: #fff;
        background-color: #0081ff;
      }
    }
  }
}
.panel {
  color: #fff;
  // height: 100%;
  flex: 1;
  &.right {
    margin-left: 10px;
    flex: 1.44;
    .content {
      height: 100%;
      padding: 10px 30px;
      position: relative;
      display: flex;
      flex-direction: column;
      justify-content: space-between;
    }
  }
}
.btn-grp {
  padding: 10px;
  display: flex;
}
.tab-content .content {
  height: 100%;
  padding: 10px;
}
.grid1 {
  height: 240px;
  margin-bottom: 20px;
}
.card {
  height: 100%;
  border: 1px solid #3e8d9d;
  border-radius: 4px;
  color: #fff;
  overflow: hidden;
  .card-title {
    background: #0c4d77;
    height: 30px;
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding-left: 6px;
  }
  .card-content {
    flex: 1;
    background: #011f39;
    display: flex;
    flex-direction: column;
    padding: 6px;
    .item-row {
      display: flex;
      align-items: center;
      .label {
        width: 12em;
        line-height: 30px;
      }
      .value {
        color: #78eef8;
      }
      .btn-grp {
        padding-left: 0;
        flex: 1;
        display: flex;
        justify-content: space-between;
        /deep/ .gradient-btn {
          min-width: 110px;
        }
      }
    }
  }
}
.el_col:nth-child(n + 3) {
  margin-top: 20px;
}
</style>
src/views/realTime/index.vue
@@ -1,6 +1,6 @@
<template>
  <div class="p-main">
    <el-tabs class="tab" type="border-card"  @tab-click="tabClick">
    <el-tabs class="tab" type="border-card" @tab-click="tabClick">
      <el-tab-pane label="交流/直流配电柜">
        <div class="tab-content content1 flex-r">
          <panel class="panel left" title="交流/直流配电柜遥测量">
@@ -26,14 +26,14 @@
                <div class="card has-title">
                  <div class="card-title">第1路交流三相输入电流(A)</div>
                  <div class="card-content">
                    <instrument-board
                      ref="board1"
                      :r="boardR"
                    ></instrument-board>
                    <gauge3 unit="A" ref="board1"></gauge3>
                  </div>
                </div>
                <div class="card has-title">
                  <div class="card-title">第2路交流三相输入电流(A)</div>
                  <div class="card-content">
                    <gauge3 unit="A" ref="board2"></gauge3>
                  </div>
                </div>
              </div>
              <div class="card card2 row4">
@@ -55,6 +55,8 @@
                      class="state-item"
                      :level="item.level"
                      :name="item.name"
                      :flag="item.flag"
                      @click.native="cardChildShow(item)"
                    ></alarm-card>
                  </el-col>
                </el-row>
@@ -69,6 +71,7 @@
                    <alarm-card
                      :level="item.level"
                      :name="item.name"
                      @click.native="cardChildShow(item)"
                    ></alarm-card>
                  </el-col>
                </el-row>
@@ -78,7 +81,7 @@
        </div>
      </el-tab-pane>
      <el-tab-pane label="高频开关整流柜">
        <div class="tab-content content1 flex-r">
        <div class="tab-content content2 flex-r">
          <panel class="panel left" title="高频开关整流柜遥测量">
            <div class="content">
              <div class="row row1">
@@ -102,14 +105,14 @@
                <div class="card has-title">
                  <div class="card-title">第2路交流三相输入电压(V)</div>
                  <div class="card-content">
                    <instrument-board
                      ref="board2"
                      :r="boardR"
                    ></instrument-board>
                    <gauge3 unit="V" ref="board3"></gauge3>
                  </div>
                </div>
                <div class="card has-title">
                  <div class="card-title">三相交流输出电流(A)</div>
                  <div class="card-content">
                    <gauge3 unit="A" ref="board4"></gauge3>
                  </div>
                </div>
              </div>
              <div class="card card2 row4">
@@ -131,6 +134,7 @@
                      class="state-item"
                      :level="item.level"
                      :name="item.name"
                      @click.native="cardChildShow(item)"
                    ></alarm-card>
                  </el-col>
                </el-row>
@@ -139,8 +143,115 @@
          </panel>
        </div>
      </el-tab-pane>
      <el-tab-pane label="核容装置"> </el-tab-pane>
      <el-tab-pane label="核容装置">
        <div class="tab-content content3 flex-r">
          <panel class="panel left" title="核容装置遥测量">
            <div class="content">
              <div class="row row5">
                <div class="card has-title">
                  <div class="card-title">核容装置与电池组</div>
                  <div class="card-content">
                    <list-card :datas="props5" :rows="7" :cols="3"></list-card>
                  </div>
                </div>
              </div>
              <div class="row">
                <div class="card has-title">
                  <div class="card-title">单体信息</div>
                  <div class="card-content">
                    <div class="h3">
                      <!-- 1-24节单体电压 -->
                      <div class="info-title">
                        1-24节单体{{ battInfoTypeStr }}
                      </div>
                      <!-- 电压 内阻 温度 剩余容量 均衡电流 -->
                      <el-radio-group
                        v-model="battInfoType"
                        class="radio-grp"
                        size="mini"
                      >
                        <el-radio-button :label="0">电压</el-radio-button>
                        <el-radio-button :label="1">内阻</el-radio-button>
                        <el-radio-button :label="2">温度</el-radio-button>
                        <el-radio-button :label="3">剩余容量</el-radio-button>
                        <el-radio-button :label="4">均衡电流</el-radio-button>
                      </el-radio-group>
                    </div>
                    <div class="batt-contain">
                      <el-row
                        class="el_row"
                        :gutter="10"
                        v-for="i in 3"
                        :key="'row_' + i"
                      >
                        <el-col
                          class="el_col"
                          :span="3"
                          v-for="idx in 8"
                          :key="'batt_' + i + '_' + idx"
                        >
                          <div class="batt">
                            <div class="name"># {{ (i - 1) * 8 + idx }}</div>
                            <div class="value">50V</div>
                          </div>
                        </el-col>
                      </el-row>
                    </div>
                  </div>
                </div>
              </div>
            </div>
          </panel>
          <panel class="panel right" title="核容装置遥信量">
            <div class="content">
              <div class="state-row">
                <div class="title1">核容装置与电池组</div>
                <div class="state-content">
                  <alarm-legend class="legend"></alarm-legend>
                  <el-row :gutter="30">
                    <el-col
                      :span="12"
                      v-for="(item, idx) in alarmList4"
                      :key="'alarm1_' + idx"
                    >
                      <alarm-card
                        class="state-item"
                        :level="item.level"
                        :name="item.name"
                        @click.native="cardChildShow(item)"
                      ></alarm-card>
                    </el-col>
                  </el-row>
                </div>
              </div>
              <div class="state-row">
                <div class="title1">单体信息</div>
                <el-row :gutter="30">
                  <el-col
                    :span="12"
                    v-for="(item, idx) in alarmList5"
                    :key="'alarm2_' + idx"
                  >
                    <alarm-card
                      :level="item.level"
                      :name="item.name"
                      @click.native="cardChildShow(item)"
                    ></alarm-card>
                  </el-col>
                </el-row>
              </div>
            </div>
          </panel>
        </div>
      </el-tab-pane>
    </el-tabs>
    <!-- childrenState -->
    <alarm-card-pop
      :visible.sync="childrenVisible"
      :title="childrenTitle"
      :value="[0x1fffffa, 0x0, 0xff, 0xff00]"
      :count="childrenCount"
    ></alarm-card-pop>
  </div>
</template>
@@ -149,9 +260,12 @@
import Panel from "@/components/panel.vue";
import ListCard from "@/components/listCard.vue";
import AlarmCard from "@/components/alarmCard.vue";
import AlarmCardPop from "@/components/alarmCardPop.vue";
import AlarmLegend from "@/components/alarmLegend.vue";
import InstrumentBoard from "@/components/instrumentBoard";
import gauge3 from "@/components/gauge3";
import bar1 from "@/components/bar1";
import const_props from "./js/const_props";
export default {
  name: "Details",
@@ -159,444 +273,44 @@
    Panel,
    ListCard,
    AlarmCard,
    AlarmCardPop,
    AlarmLegend,
    InstrumentBoard,
    gauge3,
    bar1,
  },
  data() {
    const props1 = [
      {
        label: "交流配电柜温度(℃)",
        key: "",
      },
      {
        label: "交流电压告警阀值下限(V)",
        key: "",
      },
      {
        label: "第1路直流输入电压(V)",
        key: "",
      },
      {
        label: "1段直流母线输出电压(V)",
        key: "",
      },
      {
        label: "2段直流母线输出电流(A)",
        key: "",
      },
      {
        label: "直流配电柜温度(℃)",
        key: "",
      },
      {
        label: "直流电压告警阀值下限(V)",
        key: "",
      },
    ];
    const props2 = [
      {
        label: "交流电压告警阀值上限(V)",
        key: "",
      },
      {
        label: "第二路直流输入电压(V)",
        key: "",
      },
      {
        label: "2段直流母线输出电压(V)",
        key: "",
      },
      {
        label: "2段直流母线输出电流(A)",
        key: "",
      },
      {
        label: "直流电压告警阀值上限(V)",
        key: "",
      },
    ];
    const props3 = [
      {
        label: "直流输出电压(V)",
        key: "",
      },
      {
        label: "蓄电池组充电电流(A)",
        key: "",
      },
      {
        label: "均充电压(V)",
        key: "",
      },
      {
        label: "电池N端电压(V)",
        key: "",
      },
      {
        label: "模块N输出电流(A)",
        key: "",
      },
      {
        label: "交流电压告警阀值下限(V)",
        key: "",
      },
      {
        label: "直流电压告警阀值下限(V)",
        key: "",
      },
    ];
    const props4 = [
      {
        label: "负载电流(A)",
        key: "",
      },
      {
        label: "电池充电限流值(A)",
        key: "",
      },
      {
        label: "浮充电压(V)",
        key: "",
      },
      {
        label: "高频开关电源柜温度(℃)",
        key: "",
      },
      {
        label: "交流电压告警阀值上限(V)",
        key: "",
      },
      {
        label: "直流电压告警阀值上限(V)",
        key: "",
      },
    ];
    const alarmList1 = [
      {
        name: "交流输入1停电",
        level: 0,
      },
      {
        name: "交流输入2停电",
        level: 1,
      },
      {
        name: "交流输入1防雷器故障",
        level: 2,
      },
      {
        name: "交流输入2防雷器故障",
        level: 0,
      },
      {
        name: "第1路交流输入开关跳闸",
        level: 3,
      },
      {
        name: "第2路交流输入开关跳闸",
        level: 0,
      },
      {
        name: "第1路交流A相过压",
        level: 0,
      },
      {
        name: "第1路交流A相欠压",
        level: 0,
      },
      {
        name: "第1路交流B相过压",
        level: 0,
      },
      {
        name: "第1路交流B相欠压",
        level: 0,
      },
      {
        name: "第1路交流C相过压",
        level: 0,
      },
      {
        name: "第1路交流C相欠压",
        level: 0,
      },
      {
        name: "第2路交流A相过压",
        level: 0,
      },
      {
        name: "第2路交流A相欠压",
        level: 0,
      },
      {
        name: "第2路交流B相过压",
        level: 0,
      },
      {
        name: "第2路交流B相欠压",
        level: 0,
      },
      {
        name: "第2路交流C相过压",
        level: 0,
      },
      {
        name: "第2路交流C相欠压",
        level: 0,
      },
      {
        name: "第1路交流A相缺相",
        level: 0,
      },
      {
        name: "第1路交流B相缺相",
        level: 0,
      },
      {
        name: "第1路交流C相缺相",
        level: 0,
      },
      {
        name: "第2路交流A相缺相",
        level: 0,
      },
      {
        name: "第2路交流B相缺相",
        level: 0,
      },
      {
        name: "第2路交流C相缺相",
        level: 0,
      },
      {
        name: "交流监控单元故障",
        level: 0,
      },
      {
        name: "1段交流母线输出开关1~N跳闸",
        level: 0,
      },
      {
        name: "2段交流母线输出开关1~N跳闸",
        level: 0,
      },
      {
        name: "交流配电柜总告警",
        level: 0,
      },
      {
        name: "交流配电柜温度告警",
        level: 0,
      },
    ];
    const alarmList2 = [
      {
        name: "第1路直流过压",
        level: 0,
      },
      {
        name: "第1路直流欠压",
        level: 0,
      },
      {
        name: "第2路直流过压",
        level: 0,
      },
      {
        name: "第2路直流欠压",
        level: 0,
      },
      {
        name: "第1路输入开关跳闸",
        level: 0,
      },
      {
        name: "第2路输入开关跳闸",
        level: 0,
      },
      {
        name: "1段直流第N路开关跳闸",
        level: 0,
      },
      {
        name: "2段直流第N路开关跳闸",
        level: 0,
      },
      {
        name: "温度告警",
        level: 0,
      },
      {
        name: "监控单元故障",
        level: 0,
      },
      {
        name: "直流配电柜总告警",
        level: 0,
      },
    ];
    const alarmList3 = [
      {
        name: "交流输入1停电",
        level: 0,
      },
      {
        name: "交流输入2停电",
        level: 0,
      },
      {
        name: "交流输入1防雷器故障",
        level: 0,
      },
      {
        name: "交流输入2防雷器故障",
        level: 0,
      },
      {
        name: "第1路交流输入开关跳闸",
        level: 0,
      },
      {
        name: "第2路交流输入开关跳闸",
        level: 0,
      },
      {
        name: "第1路交流A相过压",
        level: 0,
      },
      {
        name: "第1路交流A相欠压",
        level: 0,
      },
      {
        name: "第1路交流B相过压",
        level: 0,
      },
      {
        name: "第1路交流B相欠压",
        level: 0,
      },
      {
        name: "第1路交流C相过压",
        level: 0,
      },
      {
        name: "第1路交流C相欠压",
        level: 0,
      },
      {
        name: "第2路交流A相过压",
        level: 0,
      },
      {
        name: "第2路交流A相欠压",
        level: 0,
      },
      {
        name: "第2路交流B相过压",
        level: 0,
      },
      {
        name: "第2路交流B相欠压",
        level: 0,
      },
      {
        name: "第2路交流C相过压",
        level: 0,
      },
      {
        name: "第2路交流C相欠压",
        level: 0,
      },
      {
        name: "第1路交流A相缺相",
        level: 0,
      },
      {
        name: "第1路交流B相缺相",
        level: 0,
      },
      {
        name: "第1路交流C相缺相",
        level: 0,
      },
      {
        name: "第2路交流A相缺相",
        level: 0,
      },
      {
        name: "第2路交流B相缺相",
        level: 0,
      },
      {
        name: "第2路交流C相缺相",
        level: 0,
      },
      {
        name: "交流监控单元故障",
        level: 0,
      },
      {
        name: "模块N故障",
        level: 0,
      },
      {
        name: "高频开关电源柜总告警",
        level: 0,
      },
      {
        name: "直流输出过压",
        level: 0,
      },
      {
        name: "直流输出欠压",
        level: 0,
      },
      {
        name: "电池组下电保护告警",
        level: 0,
      },
      {
        name: "电池组N熔丝告警",
        level: 0,
      },
      {
        name: "负载熔丝状态",
        level: 0,
      },
      {
        name: "均浮充状态",
        level: 0,
      },
      {
        name: "在用交流输入路数",
        level: 0,
      },
    ];
    return {
      boardR: "33.3%",
    const {
      props1,
      props2,
      props3,
      props4,
      props5,
      alarmList1,
      alarmList2,
      alarmList3,
      alarmList4,
      alarmList5,
    } = const_props;
    return {
      childrenVisible: false,
      childrenTitle: "",
      childrenCount: 0,
      childrenState: 0,
      battInfoType: 0,
      props1,
      props2,
      props3,
      props4,
      props5,
      alarmList1,
      alarmList2,
      alarmList3,
      alarmList4,
      alarmList5,
    };
  },
  mounted() {
    // this.$nextTick(() => {
    //   this.getRadius();
    // });
    // window.addEventListener("resize", this.getRadius);
  },
  mounted() {},
  methods: {
    getRadius() {
      this.boardR = this.$refs.board.$el.clientWidth / 6;
      console.log(this.boardR, "?????");
      this.$refs.board1.setData({ xLabel: [], sData: [] });
    },
    tabClick() {
      this.$nextTick(() => {
        this.$refs.bar1.resize();
@@ -605,18 +319,32 @@
        this.$refs.bar4.resize();
        this.$refs.board1.resize();
        this.$refs.board2.resize();
        this.$refs.board3.resize();
        this.$refs.board4.resize();
      });
    },
    cardChildShow(obj) {
      console.log("enter", obj);
      if (obj.childrenCount) {
        this.childrenTitle = obj.name;
        this.childrenVisible = true;
        this.childrenCount = obj.childrenCount;
        this.childrenState = obj.childrenState;
      }
    },
  },
  beforeDestroy() {
    // 销毁resize事件
    // window.removeEventListener("resize", this.getRadius);
  },
  computed: {
    ...mapState({
      cachedViews: (state) => state.tagsView.cachedViews,
    }),
    battInfoTypeStr() {
      return ["电压", "内阻", "温度", "剩余容量", "均衡电流"][
        this.battInfoType
      ];
    },
  },
};
</script>
@@ -721,6 +449,94 @@
      }
    }
  }
  .tab-content.content3 {
    .panel.left {
      flex: 1.43;
      .row .card-content {
        padding: 4px;
        display: flex;
        flex-direction: column;
      }
      .row5 .card-content {
        padding: 10px;
      }
      .card .h3 {
        padding-left: 8px;
        color: #f69f40;
        display: flex;
        justify-content: space-between;
        align-items: center;
        background: #153953;
      }
      .batt-contain {
        margin-top: 4px;
        padding: 6px;
        flex: 1;
        display: flex;
        flex-direction: column;
        .el_row {
          flex: 1;
          & ~ .el_row {
            margin-top: 8px;
          }
        }
        .el_col {
          height: 100%;
        }
        .batt {
          height: 100%;
          background: url("images/batt.png") 50% 50% / 100% 100% no-repeat;
          text-align: center;
          position: relative;
          .name {
            color: #011f39;
            font-weight: bold;
            font-size: 12px;
            position: absolute;
            top: 42%;
            left: 50%;
            transform: translate(-50%, -50%);
          }
          .value {
            position: absolute;
            top: 54%;
            left: 18%;
            right: 18%;
            bottom: 16%;
            background: #f69f40;
            border-radius: 4px;
            text-align: center;
            display: flex;
            justify-content: center;
            align-items: center;
            color: #000;
            font-weight: 700;
          }
        }
      }
    }
    .panel.right {
      flex: 1;
      .state-row {
        /deep/ .el-col {
          margin-top: 10px;
        }
        &:first-child {
          display: flex;
          flex-direction: column;
        }
        .title1 {
          font-size: 18px;
          padding-top: 8px;
        }
        .state-content {
          position: relative;
          flex: 1;
        }
      }
    }
  }
  .card {
    border-radius: 6px;
    border: 1px #4392a2 solid;
@@ -748,4 +564,20 @@
.card-content {
  flex: 1;
}
.radio-grp {
  // #007BA4;
  /deep/ .el-radio-button__inner {
    color: #fff;
    background: #007ba4;
    border: 1px solid #007ba4;
  }
  /deep/ .el-radio-button:not(:last-child) .el-radio-button__inner {
    border-right-color: #32a4b7;
  }
  /deep/ .el-radio-button__orig-radio:checked + .el-radio-button__inner {
    background-color: #46b5be;
    border-color: #46b5be;
    box-shadow: -1px 0 0 0 #46b5be;
  }
}
</style>
src/views/realTime/js/const_props.js
New file
@@ -0,0 +1,666 @@
const props1 = [
  {
    label: "交流配电柜温度(℃)",
    key: "",
  },
  {
    label: "交流电压告警阀值下限(V)",
    key: "",
  },
  {
    label: "第1路直流输入电压(V)",
    key: "",
  },
  {
    label: "1段直流母线输出电压(V)",
    key: "",
  },
  {
    label: "2段直流母线输出电流(A)",
    key: "",
  },
  {
    label: "直流配电柜温度(℃)",
    key: "",
  },
  {
    label: "直流电压告警阀值下限(V)",
    key: "",
  },
];
const props2 = [
  {
    label: "交流电压告警阀值上限(V)",
    key: "",
  },
  {
    label: "第二路直流输入电压(V)",
    key: "",
  },
  {
    label: "2段直流母线输出电压(V)",
    key: "",
  },
  {
    label: "2段直流母线输出电流(A)",
    key: "",
  },
  {
    label: "直流电压告警阀值上限(V)",
    key: "",
  },
];
const props3 = [
  {
    label: "直流输出电压(V)",
    key: "",
  },
  {
    label: "蓄电池组充电电流(A)",
    key: "",
  },
  {
    label: "均充电压(V)",
    key: "",
  },
  {
    label: "电池N端电压(V)",
    key: "",
    childrenCount: 2,
  },
  {
    label: "模块N输出电流(A)",
    key: "",
    childrenCount: 32
  },
  {
    label: "交流电压告警阀值下限(V)",
    key: "",
  },
  {
    label: "直流电压告警阀值下限(V)",
    key: "",
  },
];
const props4 = [
  {
    label: "负载电流(A)",
    key: "",
  },
  {
    label: "电池充电限流值(A)",
    key: "",
  },
  {
    label: "浮充电压(V)",
    key: "",
  },
  {
    label: "高频开关电源柜温度(℃)",
    key: "",
  },
  {
    label: "交流电压告警阀值上限(V)",
    key: "",
  },
  {
    label: "直流电压告警阀值上限(V)",
    key: "",
  },
];
const props5 = [
  {
    label: "核容系统工作状态",
    key: "",
  },
  {
    label: "第1组电池在线端电压(V)",
    key: "",
  },
  {
    label: "第1组电池测试终止时间(h)",
    key: "",
  },
  {
    label: "第1组核容测试终止单体电压下限阀值(V)",
    key: "",
  },
  {
    label: "第1组核容测试时的已放电时间(h)",
    key: "",
  },
  {
    label: "第1组核容测试时终止时的核容电流(A)",
    key: "",
  },
  {
    label: "二极管D1导通压降(V)",
    key: "",
  },
  {
    label: "第1组电池组电压(V)",
    key: "",
  },
  {
    label: "第1组电池测试终止电压(V)",
    key: "",
  },
  {
    label: "第1组电池核容测试终止容量上限阀值",
    key: "",
  },
  {
    label: "第1组核容测试终止单体温度上限阀值(℃)",
    key: "",
  },
  {
    label: "第1组核容测试终止时的蓄电池组端电压(V)",
    key: "",
  },
  {
    label: "常闭接触器K1触点电阻值",
    key: "",
  },
  {
    label: "二极管D1导通测试电流(A)",
    key: "",
  },
  {
    label: "第1组电池组电流(A)",
    key: "",
  },
  {
    label: "第1组电池测试终止容量(AH)",
    key: "",
  },
  {
    label: "第1组核容测试放电电流设定值",
    key: "",
  },
  {
    label: "第1组电池测试时终止放电容量(AH)",
    key: "",
  },
  {
    label: "第1组核容测试终止时的在线电源端电压(V)",
    key: "",
  },
  {
    label: "常闭接触器K1触点测试电流",
    key: "",
  },
  {
    label: "核容系统内部温度(℃)",
    key: "",
  },
];
const alarmList1 = [
  {
    name: "交流输入1停电",
    level: 3,
    flag: 0
  },
  {
    name: "交流输入2停电",
    level: 3,
    flag: 0
  },
  {
    name: "交流输入1防雷器故障",
    level: 2,
    flag: 0
  },
  {
    name: "交流输入2防雷器故障",
    level: 2,
    flag: 0
  },
  {
    name: "第1路交流输入开关跳闸",
    level: 2,
    flag: 0
  },
  {
    name: "第2路交流输入开关跳闸",
    level: 2,
    flag: 0
  },
  {
    name: "第1路交流A相过压",
    level: 2,
    flag: 0
  },
  {
    name: "第1路交流A相欠压",
    level: 2,
    flag: 0
  },
  {
    name: "第1路交流B相过压",
    level: 2,
    flag: 0
  },
  {
    name: "第1路交流B相欠压",
    level: 2,
    flag: 0
  },
  {
    name: "第1路交流C相过压",
    level: 2,
    flag: 0
  },
  {
    name: "第1路交流C相欠压",
    level: 2,
    flag: 0
  },
  {
    name: "第2路交流A相过压",
    level: 2,
    flag: 0
  },
  {
    name: "第2路交流A相欠压",
    level: 2,
    flag: 0
  },
  {
    name: "第2路交流B相过压",
    level: 2,
    flag: 0
  },
  {
    name: "第2路交流B相欠压",
    level: 2,
    flag: 0
  },
  {
    name: "第2路交流C相过压",
    level: 2,
    flag: 0
  },
  {
    name: "第2路交流C相欠压",
    level: 2,
    flag: 0
  },
  {
    name: "第1路交流A相缺相",
    level: 2,
    flag: 0
  },
  {
    name: "第1路交流B相缺相",
    level: 2,
    flag: 0
  },
  {
    name: "第1路交流C相缺相",
    level: 2,
    flag: 0
  },
  {
    name: "第2路交流A相缺相",
    level: 2,
    flag: 0
  },
  {
    name: "第2路交流B相缺相",
    level: 2,
    flag: 0
  },
  {
    name: "第2路交流C相缺相",
    level: 2,
    flag: 0
  },
  {
    name: "交流监控单元故障",
    level: 2,
    flag: 0
  },
  {
    name: "1段交流母线输出开关1~N跳闸",
    level: 1,
    flag: 0,
    childrenVisible: false,
    childrenCount: 100,
    childrenState: 39465
  },
  {
    name: "2段交流母线输出开关1~N跳闸",
    level: 1,
    flag: 0,
    childrenCount: 100
  },
  {
    name: "交流配电柜总告警",
    level: 1,
    flag: 0
  },
  {
    name: "交流配电柜温度告警",
    level: 1,
    flag: 0
  },
];
const alarmList2 = [
  {
    name: "第1路直流过压",
    level: 2,
    flag: 0
  },
  {
    name: "第1路直流欠压",
    level: 2,
    flag: 0
  },
  {
    name: "第2路直流过压",
    level: 2,
    flag: 0
  },
  {
    name: "第2路直流欠压",
    level: 2,
    flag: 0
  },
  {
    name: "第1路直流输入开关跳闸",
    level: 1,
    flag: 0
  },
  {
    name: "第2路直流输入开关跳闸",
    level: 1,
    flag: 0
  },
  {
    name: "1段直流第N路开关跳闸",
    level: 1,
    flag: 0,
    childrenCount: 100
  },
  {
    name: "2段直流第N路开关跳闸",
    level: 1,
    flag: 0,
    childrenCount: 100
  },
  {
    name: "温度告警",
    level: 1,
    flag: 0
  },
  {
    name: "监控单元故障",
    level: 1,
    flag: 0
  },
  {
    name: "直流配电柜总告警",
    level: 1,
    flag: 0
  },
];
const alarmList3 = [
  {
    name: "交流输入1停电",
    level: 3,
    flag: 0
  },
  {
    name: "交流输入2停电",
    level: 3,
    flag: 0
  },
  {
    name: "交流输入1防雷器故障",
    level: 2,
    flag: 0
  },
  {
    name: "交流输入2防雷器故障",
    level: 2,
    flag: 0
  },
  {
    name: "第1路交流输入开关跳闸",
    level: 2,
    flag: 0
  },
  {
    name: "第2路交流输入开关跳闸",
    level: 2,
    flag: 0
  },
  {
    name: "第1路交流A相过压",
    level: 2,
    flag: 0
  },
  {
    name: "第1路交流A相欠压",
    level: 2,
    flag: 0
  },
  {
    name: "第1路交流B相过压",
    level: 2,
    flag: 0
  },
  {
    name: "第1路交流B相欠压",
    level: 2,
    flag: 0
  },
  {
    name: "第1路交流C相过压",
    level: 2,
    flag: 0
  },
  {
    name: "第1路交流C相欠压",
    level: 2,
    flag: 0
  },
  {
    name: "第2路交流A相过压",
    level: 2,
    flag: 0
  },
  {
    name: "第2路交流A相欠压",
    level: 2,
    flag: 0
  },
  {
    name: "第2路交流B相过压",
    level: 2,
    flag: 0
  },
  {
    name: "第2路交流B相欠压",
    level: 2,
    flag: 0
  },
  {
    name: "第2路交流C相过压",
    level: 2,
    flag: 0
  },
  {
    name: "第2路交流C相欠压",
    level: 2,
    flag: 0
  },
  {
    name: "第1路交流A相缺相",
    level: 2,
    flag: 0
  },
  {
    name: "第1路交流B相缺相",
    level: 2,
    flag: 0
  },
  {
    name: "第1路交流C相缺相",
    level: 2,
    flag: 0
  },
  {
    name: "第2路交流A相缺相",
    level: 2,
    flag: 0
  },
  {
    name: "第2路交流B相缺相",
    level: 2,
    flag: 0
  },
  {
    name: "第2路交流C相缺相",
    level: 2,
    flag: 0
  },
  {
    name: "交流监控单元故障",
    level: 2,
    flag: 0
  },
  {
    name: "模块N开关机状态",
    level: 1,
    flag: 0,
    childrenCount: 32,
    childrenState: 4561
  },
  {
    name: "模块N故障",
    level: 1,
    flag: 0,
    childrenCount: 32,
    childrenState: 4561
  },
  {
    name: "高频开关电源柜总告警",
    level: 1,
    flag: 0
  },
  {
    name: "直流输出过压",
    level: 2,
    flag: 0
  },
  {
    name: "直流输出欠压",
    level: 2,
    flag: 0
  },
  {
    name: "电池组下电保护告警",
    level: 2,
    flag: 0
  },
  {
    name: "电池组N熔丝告警",
    level: 2,
    flag: 0,
    childrenCount: 2
  },
  {
    name: "负载熔丝状态",
    level: 2,
    flag: 0
  },
  {
    name: "均浮充状态",
    level: 1,
    flag: 0
  },
  {
    name: "在用交流输入路数",
    level: 0,
    flag: 0
  },
];
const alarmList4 = [
  {
    name: "第1组电池组电压告警",
    level: 2,
    flag: 0
  },
  {
    name: "常闭接触器K1告警",
    level: 2,
    flag: 0
  },
  {
    name: "核容装置通讯告警",
    level: 2,
    flag: 0
  },
  {
    name: "核容装置过温告警",
    level: 2,
    flag: 0
  },
  {
    name: "二极管D1告警",
    level: 2,
    flag: 0
  },
  {
    name: "第N个外部输入干接点告警",
    level: 2,
    flag: 0,
    childrenCount: 20
  },
  {
    name: "核容装置总告警",
    level: 2,
    flag: 0
  },
];
const alarmList5 = [
  {
    name: "单体电压告警",
    level: 1,
    flag: 0,
    childrenCount: 24
  },
  {
    name: "单体内阻告警",
    level: 1,
    flag: 0,
    childrenCount: 24
  },
  {
    name: "单体极柱温度告警",
    level: 1,
    flag: 0,
    childrenCount: 24
  },
  {
    name: "单体剩余容量告警",
    level: 1,
    flag: 0,
    childrenCount: 24
  },
];
export default {
  props1,
  props2,
  props3,
  props4,
  props5,
  alarmList1,
  alarmList2,
  alarmList3,
  alarmList4,
  alarmList5,
};
src/views/switchControl/images/ac.png
src/views/switchControl/images/ac1.png
src/views/switchControl/images/dc.png
src/views/switchControl/images/dc1.png
src/views/switchControl/index.vue
New file
@@ -0,0 +1,367 @@
<template>
  <div class="p-contain">
    <panel class="panel side" title="通信电源柜线路选择">
      <div class="content">
        <div class="list-item AC active">
          <div class="i"></div>
          <div class="name">交流进线1</div>
        </div>
        <div class="list-item AC">
          <div class="i"></div>
          <div class="name">交流进线2</div>
        </div>
        <div class="list-item DC">
          <div class="i"></div>
          <div class="name">直流进线1</div>
        </div>
        <div class="list-item DC">
          <div class="i"></div>
          <div class="name">直流进线2</div>
        </div>
      </div>
    </panel>
    <div class="main">
      <panel class="panel row" title="交直流断路器控制">
        <div class="content">
          <el-table
            id="batteryrTimequeryTable"
            stripe
            size="small"
            :data="table.datas"
            height="100%"
            class="tableCent"
            tooltip-effect="light"
          >
            <el-table-column
              v-for="header in table.headers"
              :key="header.prop"
              :prop="header.prop"
              :label="header.label"
              :width="header.width"
              :min-width="header.minWidth"
              show-overflow-tooltip
              align="center"
            ></el-table-column>
            <el-table-column
              prop="cztime"
              fixed="right"
              width="180px"
              align="center"
              label="操作"
            >
              <template slot-scope="scope">
                <el-button type="primary" size="mini">合闸</el-button>
                <el-button disabled="" type="primary" size="mini"
                  >分闸</el-button
                >
              </template>
            </el-table-column>
          </el-table>
        </div>
      </panel>
      <panel class="panel row row1" title="断路器电参量实时参数">
        <div class="content">
          <div class="yc-panel">
            <div class="yc-title">三相相电压(V)</div>
            <div class="yc-content">
              <bar1 ref="bar1"></bar1>
            </div>
          </div>
          <div class="border">
            <list-card :datas="props1" :cols="1" :rows="4"></list-card>
          </div>
          <div class="yc-panel">
            <div class="yc-title">三相相电压(V)</div>
            <div class="yc-content">
              <bar1 ref="bar1"></bar1>
            </div>
          </div>
          <div class="border">
            <list-card :datas="props2" :cols="1" :rows="4"></list-card>
          </div>
        </div>
      </panel>
    </div>
  </div>
</template>
<script>
import Panel from "@/components/panel.vue";
import ListCard from "@/components/listCard.vue";
import gauge3 from "@/components/gauge3";
import bar1 from "@/components/bar1";
export default {
  name: "",
  data() {
    const props1 = [
      {
        label: "AB相线电压(V)",
        key: "",
      },
      {
        label: "BC相线电压(V)",
        key: "",
      },
      {
        label: "CA相线电压(V)",
        key: "",
      },
      {
        label: "线电压平均值(V)",
        key: "",
      },
    ];
    const props2 = [
      {
        label: "电流不平衡度(%)",
        key: "",
      },
      {
        label: "零序电流(A)",
        key: "",
      },
      {
        label: "总有功功率",
        key: "",
      },
      {
        label: "总功率因数",
        key: "",
      },
    ];
    return {
      props1,
      props2,
      table: {
        headers: [
          {
            prop: "a",
            label: "断路器类型",
            minWidth: 320,
          },
          {
            prop: "b",
            label: "断路器名称",
            width: 120,
          },
          {
            prop: "c",
            label: "所在位置",
            width: 162,
          },
          {
            prop: "d",
            label: "级数",
            width: 80,
          },
          {
            prop: "e",
            label: "开关状态",
            width: 160,
          },
          {
            prop: "f",
            label: "告警状态",
            width: 120,
          },
        ],
        datas: [
          {
            a: 1,
            b: 2,
            c: 3,
            d: 4,
          },
          {
            a: 1,
            b: 2,
            c: 3,
            d: 4,
          },
          {
            a: 1,
            b: 2,
            c: 3,
            d: 4,
          },
          {
            a: 1,
            b: 2,
            c: 3,
            d: 4,
          },
          {
            a: 1,
            b: 2,
            c: 3,
            d: 4,
          },
          {
            a: 1,
            b: 2,
            c: 3,
            d: 4,
          },
          {
            a: 1,
            b: 2,
            c: 3,
            d: 4,
          },
        ],
      },
    };
  },
  components: {
    Panel,
    ListCard,
    gauge3,
    bar1,
  },
  methods: {},
  mounted() {},
};
</script>
<style scoped lang="less">
.p-contain {
  height: 100%;
  display: flex;
  .side {
    flex: 1;
    .content {
      display: flex;
      flex-direction: column;
      padding: 0 40px;
      .list-item {
        margin-top: 30px;
        height: 50px;
        display: flex;
        background: #0c4d77;
        border: 1px #78eef8 solid;
        align-items: center;
        border-radius: 6px;
        color: #fff;
        font-size: 20px;
        .i {
          width: 40px;
          height: 40px;
          border-radius: 50%;
          margin-left: 20px;
          margin-right: 30px;
        }
        &.AC .i {
          background: #78eef8 url("../images/ac1.png") 50% 50% / 60% auto
            no-repeat;
        }
        &.DC .i {
          background: #78eef8 url("../images/dc1.png") 50% 50% / 60% auto
            no-repeat;
        }
        &.active {
          background: #f69f40;
          border-color: #f69f40;
          color: #011f39;
          font-weight: 700;
        }
        &.active.AC .i {
          background: #011f39 url("../images/ac.png") 50% 50% / 60% auto
            no-repeat;
        }
        &.active.DC .i {
          background: #011f39 url("../images/dc.png") 50% 50% / 60% auto
            no-repeat;
        }
      }
    }
  }
  .main {
    flex: 2.476;
    margin-left: 10px;
    display: flex;
    flex-direction: column;
    .panel .content {
      height: 100%;
      padding: 10px;
      .tableCent {
        background: #00253f;
        &::before {
          height: 0;
        }
        /deep/ th.el-table__cell {
          background: #0c4d77;
          font-size: 18px;
          color: #fff;
        }
        /deep/ th.el-table__cell.is-leaf,
        /deep/ td.el-table__cell {
          border: 0 none;
        }
        /deep/ tr {
          background: #153953;
        }
        /deep/
          .el-table__body
          tr.hover-row.hover-row.hover-row
          > td.el-table__cell {
          background: #4871e3;
        }
        /deep/ .el-table__body tr.el-table__row--striped td.el-table__cell {
          background: #0d314b;
        }
      }
    }
    .row {
      flex: 1.378;
    }
    .row1 {
      color: #fff;
      flex: 1;
      margin-top: 10px;
      .content {
        display: flex;
      }
    }
  }
  .yc-panel {
    color: #fff;
    flex: 1.48;
    border: 1px solid #4da2b1;
    border-radius: 6px;
    overflow: hidden;
    display: flex;
    flex-direction: column;
    margin-left: 10px;
    &:first-child {
      margin-left: 0;
    }
    .yc-title {
      text-align: center;
      font-size: 18px;
      height: 36px;
      line-height: 36px;
      background: #0c4d77;
    }
    .yc-content {
      flex: 1;
      display: flex;
      flex-direction: column;
      background: #011f39;
    }
  }
  .border {
    flex: 1;
    border-radius: 6px;
    border: 1px #4da2b1 solid;
    background: #011f39;
    padding: 46px 8px;
    margin-left: 10px;
  }
}
</style>