ZZJ
2021-10-13 878ce80ef3ca88a2c108fbc713cd6ea461c44de1
拓扑图
2个文件已添加
6个文件已修改
7527 ■■■■■ 已修改文件
src/pages/settings/components/NetNode.vue 281 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pages/settings/components/netNodeData.js 6808 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pages/settings/index/index.vue 41 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pages/settings/views/NetSettings.vue 60 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pages/settings/views/clusterManagement.vue 13 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pages/settings/views/deviceInfo.vue 287 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pages/vindicate/index/App.vue 37 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pages/vindicate/views/sysInfo.vue 补丁 | 查看 | 原始文档 | blame | 历史
src/pages/settings/components/NetNode.vue
New file
@@ -0,0 +1,281 @@
<template>
  <div class="net-node">
      <div class="vue-d3-network">
        <D3Network
        ref='net'
        :net-nodes="nodes"
        :net-links="links"
        :options="options"
        />
      </div>
      <span class="icon iconfont zoom-in"
      @click="changeForce(1)"
      :class="{'zoom-disabled'
      :disabled.zoomIn}">&#xeb89;</span>
      <span class="icon iconfont zoom-out"
      @click="changeForce(0)"
      :class="{'zoom-disabled'
      :disabled.zoomOut}">&#xe758;</span>
      <div class="illustrate">
        <div>
        <span class="illu-server"></span> 服务器
        </div>
        <div>
        <span class="analysis"></span> 分析盒子
        </div>
      </div>
  </div>
</template>
<script>
import D3Network from 'vue-d3-network'
import {nodes,links} from './netNodeData'
export default {
created () {
    this.reset()
},
props:{
    innerNodes:Array
},
data () {
  return {
    //   settings: {
    //       maxLinks: 2,
    //       maxNodes: 130
    //   },
      nodes,
      links,
      options: {
          size: {
              w: 600,
              h: 240
        },
        offset: {
              x: 0,
              y: 0
        },
        nodeSize: 18,
        force: 300,
        nodeLabels: true
      },
      disabled:{
          zoomIn:false,
          zoomOut:false
      }
  }
},
components: {
    D3Network
},
methods: {
    // 初始化
    // reset () {
    //    this.nodes = this.makeRandomNodes(this.settings.maxNodes)
    //    this.links = this.makeRandomLinks(this.nodes, this.settings.maxLinks)
    //    console.log(this.nodes);
    //    console.log(this.links);
    // },
    // 随机生成节点
    // makeRandomNodes (maxNodes) {
    //    let nodes = Array.apply(null, { length: maxNodes })
    //    .map((value, index) => { return this.newNode(index) })
    //    return nodes
    // },
    // newNode (nodeId) {
    //   return { id: nodeId, name: this.newNodeName(),_cssClass:"node-default" }
    // },
    // newNodeName () {
    // return Math.random().toString(36).substring(7)
    // },
    // 随机生成连线
    // newLink (id, sid, tid) {
    // return { id, sid, tid,_color:"rgb(90,90,90)" }
    // },
    // makeRandomLinks (nodes, maxLinks) {
    // let links = []
    // let id = 0
    // for (let node of nodes) {
    // let total = Math.floor(Math.random() * maxLinks)
    // for (let i = 0; i <= total; i++) {
    //   let target = Math.floor(Math.random() * nodes.length)
    //   let source = node.id
    //   id++
    //   links.push(this.newLink(id, source, target))
    //  }
    // }
    // return links
    // },
    // 初始化
    reset() {
        let linkId = 200
        this.innerNodes.forEach((item,index) => {
        if (index === 0) {
            this.nodes = this.addNode(item,"server")
            this.links = this.addLink(linkId,6,`${item.node_id}`,"rgba(90,90,90,.6)")
            this.links = this.addLink(linkId+1,8,`${item.node_id}`,"rgba(90,90,90,.6)")
            linkId+=2
        }
        else {
            this.nodes = this.addNode(item,"server")
            this.links = this.addLink(linkId,item.node_id,this.innerNodes[index-1].node_id,"#4E94FF")
            linkId+=1
            }
        })
    },
    // 添加新节点
    addNode(newNode,type) {
        return [...this.nodes,{
                   "id": `${newNode.node_id}`,
                   "name": `${newNode.nodeName}`,
                   "_cssClass": `node-${type}`,
                   "_labelClass": `label-${type}`,
                   "x": 400,
                   "y": 100
                }]
    },
    // 添加新连线
    addLink(id,sid,tid,color) {
        return [...this.links,{
            "id": id,
            "sid": sid,
            "tid": tid,
            "_color": color,
            "_svgAttrs": {"stroke-width": 2}
            }]
    },
    // 调整作用力
    changeForce(judge) {
    if(judge && this.options.nodeSize >25) {
        this.disabled.zoomIn = true
        return
    }
    if(!judge && this.options.nodeSize <11) {
        this.disabled.zoomOut = true
        return
    }
    const force =judge? this.options.force + 70 : this.options.force - 70
    let nodeSize = judge? this.options.nodeSize + 2 : this.options.nodeSize - 2
    this.disabled.zoomOut = this.disabled.zoomIn = false
    this.options = {
          size: {
              w: 600,
              h: 240
        },
        offset: {
              x: 0,
              y: 0
        },
        nodeSize: nodeSize,
        force
      }
    console.log( this.options);
    },
  }
}
</script>
<style lang="scss" scoped>
.net-node {
    position: relative;
    overflow: hidden;
    margin-top:10px ;
    margin-bottom:4px ;
    padding-top:10px ;
    height: 240px;
    background-color: rgba(255, 255, 255, 0.719);
    ::v-deep .node-default {
        fill: #fff;
        stroke: rgb(90,90,90);
        stroke-width: 1px;
    }
    ::v-deep .node-server {
        fill: #fff;
        stroke: #4E94FF;
        stroke-width: 2px;
    }
    ::v-deep .label-default {
        display: none;
    }
     ::v-deep .label-server {
        font-weight: 700;
    }
    .zoom-in,.zoom-out {
        position: absolute;
        font-size: 21px;
        cursor: pointer;
        color: #333;
        &:hover {
        color: var(--colorCard);
        }
        &.zoom-disabled:hover {
        color: #333;
        cursor: not-allowed;
        }
    }
    .zoom-in {
        top: 20px;
        right: 20px;
    }
    .zoom-out {
        top: 50px;
        right: 20px;
    }
    .illustrate {
        position: absolute;
        display: flex;
        flex-direction: column;
        justify-content: center;
        padding-left:8px ;
        top: 180px;
        right: 20px;
        height: 40px;
        width: 68px;
        background-color: #fff;
        text-align: left;
        font-weight: bold;
        font-size: 12px;
        .illu-server {
            display: inline-block;
            width: 4px;
            height: 4px;
            border: 2px solid #4E94FF;
            border-radius:4px ;
        }
        .analysis {
            display: inline-block;
            width: 4px;
            height: 4px;
            border: 2px solid #4EF4FF;
            border-radius:4px ;
        }
    }
}
</style>
src/pages/settings/components/netNodeData.js
New file
Diff too large
src/pages/settings/index/index.vue
@@ -1544,7 +1544,7 @@
  background-color: rgba(255, 255, 255, 0.9);
  backdrop-filter: blur(4px);
  .border-change {
    border-radius: 20px !important;
    border-radius: 15px !important;
  }
  .search-box {
    width: 332px;
@@ -1552,12 +1552,15 @@
    position: fixed;
    left: calc(50% - 166px);
    top: 50px;
    background: rgba(255, 255, 255, 0.8);
    border: 2px solid var(--colorCard);
    box-sizing: border-box;
    backdrop-filter: blur(4px);
    border-radius: 40px;
    .search-res {
      background-color: rgba(255,255,255,.5);
    }
    .search-input {
      font-size: 14px;
      .el-input--mini .el-input__inner {
@@ -1585,6 +1588,30 @@
        transition: border-color 0.2s cubic-bezier(0.645, 0.045, 0.355, 1);
        width: 100%;
        font-weight: bold;
        &::-webkit-input-placeholder { /* WebKit browsers */
        color: #828282;
        font-weight: normal;
        font-size: 14px;
        }
        &:-moz-placeholder { /* Mozilla Firefox 4 to 18 */
        color: #828282;
        font-weight: normal;
        font-size: 14px;
        }
        &::-moz-placeholder { /* Mozilla Firefox 19+ */
        color: #828282;
        font-weight: normal;
        font-size: 14px;
        }
        &:-ms-input-placeholder { /* Internet Explorer 10+ */
        color: #828282;
        font-weight: normal;
        font-size: 14px;
      }
      }
      .el-input__suffix {
        display: flex;
@@ -1648,6 +1675,12 @@
      justify-content: center;
      align-items: center;
      cursor: pointer;
      border: 2px solid #F2F2F7;
      &:hover {
        border: 2px solid #4E94FF;
        background: #F2F2F7;
      }
      .child-info {
        display: flex;
@@ -1659,7 +1692,7 @@
        img {
          width: 64px;
          margin: 0 auto;
          margin-top: 65px;
          margin-top: 61px;
          height: 50px;
        }
        .welcome-title {
@@ -2589,8 +2622,6 @@
    background: #fbfaff;
    padding: 0;
  }
}
.del-account-message-box {
}
</style>
src/pages/settings/views/NetSettings.vue
@@ -79,7 +79,7 @@
            </div>
          </div>
        </div>
        <div class="wifi-detail" v-if="activePage == 1 && inWifiDetail">
        <div class="wifi-detail" v-if="activePage == 1 && inWifiDetail" ref="ipvHolder">
          <div class="title">无线网络</div>
          <div class="btns">
            <div class="cancel">删除</div>
@@ -91,7 +91,6 @@
            <el-form
              :model="wifiForm"
              :rules="wifiFormRules"
              ref="wifiForm"
              class="join-form"
            >
@@ -119,12 +118,14 @@
          <switchBar
            :barName="`高级设置`"
            @switchChange="highClassSetting"
            :value="isHighClass"
          ></switchBar>
          <div class="general-box">
            <div class="in-title">IPV4</div>
          <div class="general-box fold" :class="{'hidden':IPV4_hid}" >
            <div class="in-title">IPV4
              <span class="icon iconfont icon-fold"
               @click="toggleFold('IPV4_hid')">&#xe757;</span>
            </div>
            <el-form :model="ipv4Form" :rules="ipv4FormRules" ref="ipv4Form">
              <el-form-item>
@@ -177,10 +178,13 @@
            </el-form>
          </div>
          <div class="general-box">
            <div class="in-title">IPV6</div>
          <div class="general-box fold" :class="{'hidden':IPV6_hid}" ref="ipv6Holder">
            <div class="in-title">IPV6
              <span class="icon iconfont icon-fold"
              @click="toggleFold('IPV6_hid')">&#xe757;</span>
            </div>
            <el-form :model="ipv6Form" :rules="ipv6FormRules" ref="ipv4Form">
            <el-form :model="ipv6Form" :rules="ipv6FormRules" ref="ipv6Form">
              <el-form-item>
                <div class="p-title">方法</div>
                <el-select v-model="value" placeholder="请选择" size="small">
@@ -414,6 +418,8 @@
        },
      ],
      value: "",
      IPV4_hid: false,
      IPV6_hid: false
    };
  },
  components: {
@@ -489,10 +495,15 @@
      });
    },
    openRight(i) {
      this.activePage = i;
      if (i == 0) {
        this.ruleForm.deviceName = "";
        this.ruleForm.port = "";
        this.getCurServer()
      }
      if (i == 1) {
        this.inWifiDetail = false;
      }
      this.activePage = i;
    },
    saveWire(ifname) {
      let data = {
@@ -549,6 +560,17 @@
        this.openWireDetail(item);
      });
    },
    toggleFold(tog) {
    const demo = this.$refs.ipvHolder
    if(!(this.IPV4_hid&&!this.IPV6_hid)){
       setTimeout(() => {
       demo.scrollIntoView({block: "end", inline: "nearest",behavior: 'smooth'})
       }, 300);
    }
    this[tog] = !this[tog]
     }
  },
  computed: {
    showStatus() {
@@ -814,11 +836,30 @@
    .wifi-detail {
      max-width: 600px;
      margin: 0 auto;
      transition: all 0.3s linear 0s;
      .general-box {
        overflow: hidden;
        transition: all 0.3s linear 0s;
        background: #f2f2f7;
        border-radius: 8px;
        padding-bottom: 10px;
        margin-bottom: 20px;
        &.fold {
        height: 342px;
          .icon-fold {
            display: inline-block;
            font-size: 14px;
            margin-left: 360px;
            transition: all 0.3s linear 0s;
            cursor: pointer;
          }
        }
        &.hidden {
        height: 34px;
         .icon-fold {
           transform: rotate(180deg);
         }
        }
        .el-form-item {
          margin-bottom: 0px;
        }
@@ -879,6 +920,7 @@
        line-height: 48px;
      }
      .ad {
        margin-top: 10px;
        height: 32px;
        /* margin: 4px 0px 4px 5px; */
        /* border-radius: 5px; */
src/pages/settings/views/clusterManagement.vue
@@ -2,7 +2,8 @@
  <div class="all">
    <!--  -->
    <div class="cluster-guanli" v-if="showCurCluster && isHasColony">
      <cloud-node :nodes="innerNodes"></cloud-node>
      <!-- <cloud-node :nodes="innerNodes"></cloud-node> -->
      <net-node :innerNodes="innerNodes"></net-node>
      <div class="cls-bar">视频分析集群管理</div>
@@ -222,7 +223,8 @@
  updateClusterName,
  joinCluster,
} from "@/api/clusterManage";
import cloudNode from "../components/CloudNode";
// import cloudNode from "../components/CloudNode";
import NetNode from '../components/NetNode'
import ipInput from "../components/IPInput";
import { isIPv4 } from "@/scripts/validate";
@@ -296,8 +298,9 @@
    };
  },
  components: {
    cloudNode,
    ipInput,
    // cloudNode,
    NetNode,
    ipInput
  },
  mounted() {
    this.findCluster();
@@ -773,8 +776,6 @@
      .el-form-item__label-wrap
      > .el-form-item__label:before {
      display: none;
    }
    .create-new {
    }
    .el-form-item__content {
src/pages/settings/views/deviceInfo.vue
@@ -8,43 +8,43 @@
            <span class="general-info">设备信息</span>
          </div>
          <div class=" info-bar">
            <span class="name">设备ID</span>
            <span class="name">设备ID:</span>
            <span class="desc">{{ deviceInfo.server_id }}</span>
          </div>
          <div class=" info-bar">
            <span class="name">设备型号</span>
            <span class="name">设备型号:</span>
            <span class="desc">{{ deviceInfo.deviceModel }}</span>
          </div>
          <div class=" info-bar">
            <span class="name">设备类型</span>
            <span class="name">设备类型:</span>
            <span class="desc">{{ deviceInfo.deviceDesc }}</span>
          </div>
          <div class=" info-bar">
            <span class="name">通道个数</span>
            <span class="name">通道个数:</span>
            <span class="desc">{{ deviceInfo.channelCount }}</span>
          </div>
          <div class=" info-bar">
            <span class="name">主控版本</span>
            <span class="name">主控版本:</span>
            <span class="desc">{{ deviceInfo.masterVersion }}</span>
          </div>
          <div class=" info-bar">
            <span class="name">web版本</span>
            <span class="name">web版本:</span>
            <span class="desc">{{ deviceInfo.webVersion }}</span>
          </div>
          <div class=" info-bar">
            <span class="name">硬盘信息</span>
            <span class="name">硬盘信息:</span>
            <span class="desc">{{ deviceInfo.disks }}</span>
          </div>
          <div class=" info-bar">
            <span class="name">CPU</span>
            <span class="name">CPU:</span>
            <span class="desc">{{ deviceInfo.cpu }}</span>
          </div>
          <div class=" info-bar">
            <span class="name">内存</span>
            <span class="name">内存:</span>
            <span class="desc">{{ deviceInfo.memory }}</span>
          </div>
          <div class=" info-bar">
            <span class="name">运行时间</span>
            <span class="name">运行时间:</span>
            <span class="desc">{{ deviceInfo.runningTime }}</span>
          </div>
        </div>
@@ -215,273 +215,14 @@
    overflow: auto;
    box-sizing: border-box;
    padding: 10px 15px !important;
   /*  .el-form-item.is-required:not(.is-no-asterisk)
      > .el-form-item__label:before,
    .el-form-item.is-required:not(.is-no-asterisk)
      .el-form-item__label-wrap
      > .el-form-item__label:before {
      display: none;
    }
    .el-select {
      width: 100%;
    }
    .el-form-item {
      margin-bottom: 10px;
      height: 50px;
      background: #f8f8f8;
      padding: 4px 20px;
      -webkit-box-sizing: border-box;
      box-sizing: border-box;
      border-radius: 10px;
      .el-form-item__label {
        text-align: left;
        line-height: 42px;
      }
    }
    .el-form-item__content {
      line-height: 40px;
      position: relative;
      font-size: 14px;
    }
    .ip-input-container {
      max-width: none !important;
    }
    .lang {
      position: relative;
      height: calc(83% - 0px);
      .title {
        height: 35px;
        line-height: 35px;
        font-size: 16px;
        text-align: left;
        margin-bottom: 5px;
      }
      .bar-group {
        overflow: auto;
        height: 100%;
      }
      .bar {
        height: 44px;
        background-color: #f8f8f8;
        border-radius: 10px;
        line-height: 44px;
        box-sizing: border-box;
        padding: 0 30px 0 20px;
        display: flex;
        justify-content: space-between;
        margin-bottom: 10px;
        .left-part {
          .icon {
            color: rgba(191, 191, 191, 1);
            font-size: 16px;
            margin-right: 5px;
          }
        }
        .name {
          font-size: 15px;
        }
        .btns {
          width: 50px;
          display: flex;
          justify-content: space-between;
          color: rgba(191, 191, 191, 1);
          .el-icon-video-pause {
            cursor: pointer;
            font-size: 23px;
            vertical-align: middle;
            color: #409eff;
          }
          .el-icon-video-play {
            cursor: pointer;
            font-size: 23px;
            vertical-align: middle;
            color: #409eff;
          }
        }
        .desc {
          font-size: 14px;
          color: rgba(134, 134, 134, 1);
        }
      }
      .bar:hover {
        background-color: rgba(233, 233, 233, 1);
      }
      .add-group {
        margin: 10px auto;
        width: fit-content;
      }
      .upload-demo {
        -webkit-transition: all 0.3s;
        transition: all 0.5s;
        position: absolute;
        bottom: -40px;
        left: calc(50% - 145px);
        .el-upload-dragger {
          width: 290px;
        }
      }
      .add-btn {
        height: 40px;
        line-height: 40px;
        margin: 0 auto;
        cursor: pointer;
        width: fit-content;
        .icon {
          font-size: 32px;
          color: rgba(61, 104, 225, 1);
        }
      }
      .min-dur {
        box-sizing: border-box;
        padding: 0 20px;
        background-color: rgba(248, 248, 248, 1);
        height: 105px;
        margin-bottom: 20px;
        border-radius: 15px;
        .title {
          height: 45px;
          line-height: 45px;
          text-align: left;
          box-sizing: border-box;
          padding: 0 6px;
          font-size: 14px;
        }
      }
      .min-dur:hover {
        background-color: rgba(233, 233, 233, 1);
    .info-bar {
     border-radius: 8px;
      }
      .entity {
        display: flex;
        align-items: center;
        height: 30px;
        .sec {
          min-width: 30px;
          line-height: 80px;
          margin-right: 10px;
          color: rgba(120, 120, 120, 1);
          font-size: 14px;
        }
        .block {
          flex: 1;
          margin: 0 20px 0 6px;
        }
        .el-input-number--small {
          width: 100px;
        }
        .el-input-number.is-controls-right .el-input__inner {
          padding-left: 16px;
        }
        #cut_min_duration {
          .el-slider__bar {
            background-color: #3d68e1;
          }
          .el-slider__button-wrapper .el-tooltip {
            width: 18px;
            height: 18px;
            border: 4px solid #3d68e1;
            box-sizing: border-box;
          }
        }
        #cut_max_duration {
          .el-slider__bar {
            background-color: #ff9e6e;
          }
          .el-slider__button-wrapper .el-tooltip {
            width: 18px;
            height: 18px;
            border: 4px solid #ff9e6e;
            box-sizing: border-box;
          }
        }
      }
    }
    .save-btn {
      background-color: #3d68e1;
      width: 240px;
      height: 40px;
      margin: 0 auto;
      border-radius: 10px;
      color: #fff;
      line-height: 40px;
      cursor: pointer;
      font-size: 14px;
      margin-top: 20px;
    }
    .self-setting {
      .top-title {
        font-size: 16px;
        height: 30px;
        line-height: 30px;
        margin-bottom: 10px;
      }
      .icon-bar:hover {
        background-color: rgba(233, 233, 233, 1);
      }
      .icon-bar {
        cursor: pointer;
        background-color: rgba(248, 248, 248, 1);
        box-sizing: border-box;
        padding: 15px 25px;
        border-radius: 12px;
        margin-bottom: 12px;
        .bar-title {
          line-height: 20px;
          height: 20px;
          margin-bottom: 10px;
          display: flex;
          justify-content: space-between;
          .title {
            font-size: 14px;
          }
        }
        .entity {
          display: flex;
          .entity-img {
            background-color: rgba(248, 248, 248, 1);
            width: 50px;
            height: 50px;
            margin-right: 10px;
            img {
              width: 50px;
              height: 50px;
            }
          }
        }
      }
      .bg-bar {
        background-color: rgba(248, 248, 248, 1);
        box-sizing: border-box;
        padding: 15px 25px;
        border-radius: 12px;
        margin-bottom: 12px;
        .bg-list {
          display: flex;
          .bg-img {
            margin-right: 12px;
            cursor: pointer;
            // width: 120px;
                height: 80px;
            border: 2px solid transparent;
            img {
             border-radius: 5px;
    height: 100%;
            }
          }
          .bg-img:hover {
            border: 2px solid yellow;
          }
          .bg-list-active {
            border: 2px solid yellow;
          }
        }
      }
    } */
   .info-bar .name {
    color: #4F4F4F;
  }
}
</style>
src/pages/vindicate/index/App.vue
@@ -20,7 +20,7 @@
    <sysInfo v-if="activePage == 3" style="width: 100%" ref="view_3"></sysInfo>
  </div>
    <div class="welcome-page" v-else ref="curPage">
    <div class="welcome-page" v-else ref="curPage" @click="showRecomand = false">
    <div
      class="search-box"
      :class="showRecomand ? 'border-change' : ''"
@@ -110,6 +110,7 @@
      full: 0,
      showWelcome:true,
      searchText:'',
      showRecomand:false
    };
  },
  created() {
@@ -198,7 +199,7 @@
    position: fixed;
    left: calc(50% - 166px);
    top: 50px;
    background: rgba(255, 255, 255, 0.8);
    opacity: 0.8;
    border: 2px solid #4e94ff;
    box-sizing: border-box;
@@ -231,6 +232,29 @@
        transition: border-color 0.2s cubic-bezier(0.645, 0.045, 0.355, 1);
        width: 100%;
        font-weight: bold;
        &::-webkit-input-placeholder { /* WebKit browsers */
        color: #828282;
        font-weight: normal;
        font-size: 14px;
        }
        &:-moz-placeholder { /* Mozilla Firefox 4 to 18 */
        color: #828282;
        font-weight: normal;
        font-size: 14px;
        }
        &::-moz-placeholder { /* Mozilla Firefox 19+ */
        color: #828282;
        font-weight: normal;
        font-size: 14px;
        }
        &:-ms-input-placeholder { /* Internet Explorer 10+ */
        color: #828282;
        font-weight: normal;
        font-size: 14px;
      }
      }
      .el-input__suffix {
        display: flex;
@@ -253,6 +277,7 @@
    .search-res {
      max-height: 240px;
      overflow: auto;
      background-color: rgba(255, 255, 255, 0.5);
      .res-bar {
        height: 40px;
        line-height: 40px;
@@ -297,6 +322,12 @@
      justify-content: center;
      align-items: center;
      cursor: pointer;
      border: 2px solid #F2F2F7;
      &:hover {
        border: 2px solid #4E94FF;
        background: #F2F2F7;
      }
      // box-shadow: 2px 2px 4px rgb(226, 226, 226);
      .child-info {
@@ -310,7 +341,7 @@
        img {
          width: 64px;
          margin: 0 auto;
          margin-top: 65px;
          margin-top: 61px;
          height: 50px;
        }
        .welcome-title {
src/pages/vindicate/views/sysInfo.vue