ZZJ
2022-01-12 9d43e7051075f1fc1b2fee680a79f90becddd63f
src/pages/settings/views/clusterManagement.vue
@@ -1,9 +1,13 @@
<template>
  <div class="all">
    <div class="cluster-guanli" v-if="showCurCluster">
      <cloud-node :nodes="innerNodes"></cloud-node>
    <!--  -->
    <div class="cluster-guanli" v-if="showCurCluster && isHasColony">
      <!-- <cloud-node :nodes="innerNodes"></cloud-node> -->
      <net-node :innerNodes="innerNodes"></net-node>
      <div class="bar">
      <div class="cls-bar">视频分析集群管理</div>
      <div class="cls-bar">
        <div class="title">集群名称</div>
        <div class="input-area">
          <div class="text" v-show="!isFillingName">
@@ -23,31 +27,33 @@
          >
          <span
            class="icon iconfont"
            style="font-size: 18px"
            @click="clearInput(1)"
            v-show="isFillingName"
            >&#xe649;</span
            >&#xe785;</span
          >
          <span
            class="icon iconfont"
            style="font-size: 20px; color: var(--colorCard)"
            @click="updateCluster(1)"
            v-show="isFillingName"
            >&#xe62a;</span
          >
        </div>
      </div>
      <div class="bar">
      <div class="cls-bar">
        <div class="title">集群ID</div>
        <div class="input-area">
          <div class="text">{{ clusterid }}</div>
        </div>
      </div>
      <div class="bar">
      <div class="cls-bar">
        <div class="title">集群密码</div>
        <div class="input-area">
          <div class="text">{{ ruleForm.clusterpwd }}</div>
        </div>
      </div>
      <div class="bar">
      <div class="cls-bar">
        <div class="title">集群IP</div>
        <div class="input-area">
          <div class="text" v-show="!isFillingIp">{{ ruleForm.virtualIp }}</div>
@@ -66,43 +72,53 @@
          >
          <span
            class="icon iconfont"
            style="font-size: 18px"
            @click="clearInput(2)"
            v-show="isFillingIp"
            >&#xe649;</span
            >&#xe785;</span
          >
          <span
            class="icon iconfont"
            @click="updateCluster(2)"
            style="font-size: 20px; color: var(--colorCard)"
            v-show="isFillingIp"
            >&#xe62a;</span
          >
        </div>
      </div>
      <div class="exit" @click="exitCluster">退出集群</div>
    </div>
    <div class="cluster-content">
      <div class="cluster-center" ref="left" v-if="!showCurCluster">
        <div class="menu-item" @click="isCreate = true">创建集群</div>
        <div class="menu-item" @click="isCreate = false">加入已有集群</div>
      <div class="btns">
        <div class="ok" @click="updateCluster">保存</div>
        <div class="exit" @click="exitCluster">退出集群</div>
      </div>
      <div class="cluster-right" v-if="!showCurCluster">
        <div class="create-new" v-if="isCreate">
          <el-form
            :model="ruleForm"
            :rules="rules"
            ref="ruleForm"
            label-width="150px"
          >
            <el-form-item label="集群名称" prop="clustername">
    </div>
    <!-- !showCurCluster || !isHasColony -->
    <div class="cluster-content" v-if="!showCurCluster || !isHasColony">
      <div class="cluster-center" ref="left" v-if="!showCurCluster || !isHasColony">
        <div
          class="menu-item"
          :class="activePage == i ? 'menu-item-active' : ''"
          v-for="(item, i) in tabList"
          :key="i"
          @click="openRight(i)"
        >
          <span class="icon iconfont" v-if="activePage == 0">&#xe73c;</span>
          <span class="icon iconfont" v-if="activePage == 1">&#xe721;</span>
          {{ item }}
        </div>
      </div>
      <div class="cluster-right" v-if="!showCurCluster || !isHasColony">
        <div class="create-new" v-if="activePage == 0">
          <el-form :model="ruleForm" :rules="rules" ref="ruleForm">
            <el-form-item prop="clustername">
              <div class="p-title">集群名称</div>
              <el-input
                v-model="ruleForm.clustername"
                placeholder="手动输入, 如“集群A”"
                size="small"
              ></el-input>
            </el-form-item>
            <el-form-item label="集群ID">
            <el-form-item>
              <div class="p-title">集群ID</div>
              <el-input
                v-model="clusterid"
                placeholder="不允许输入,保存后回显"
@@ -110,7 +126,8 @@
                size="small"
              ></el-input>
            </el-form-item>
            <el-form-item label="集群密码" prop="clusterpwd">
            <el-form-item prop="clusterpwd">
              <div class="p-title">集群密码</div>
              <el-input
                v-model="ruleForm.clusterpwd"
                placeholder="请输入6位密码,或点击生成"
@@ -121,7 +138,8 @@
                >
              </el-input>
            </el-form-item>
            <el-form-item label="集群IP" prop="virtualIp">
            <el-form-item prop="virtualIp">
              <div class="p-title">集群IP</div>
              <ip-input
                :ip="ruleForm.virtualIp"
                :on-blur="onIpBlur"
@@ -129,22 +147,27 @@
              ></ip-input>
            </el-form-item>
          </el-form>
          <div class="save-btn" @click="saveCluster('ruleForm')">保存</div>
          <div class="btns">
            <div class="ok" @click="saveCluster('ruleForm')">保存</div>
          </div>
        </div>
        <div class="join-exist" v-if="!isCreate">
        <div class="join-exist" v-if="activePage == 1">
          <el-form
            :model="joinForm"
            :rules="joinRules"
            :rules="joinExistRules"
            ref="joinForm"
            class="join-form"
            label-width="150px"
            v-loading="joinLoading"
          >
            <el-form-item label="集群ID" prop="clusterid">
            <el-form-item  prop="clusterid">
              <div class="p-title">集群ID</div>
              <el-input v-model="joinForm.clusterid" size="small"></el-input>
            </el-form-item>
            <el-form-item label="IP地址" prop="clusterip">
            <el-form-item  prop="clusterip">
              <div class="p-title">IP地址</div>
              <el-input
                v-model="joinForm.clusterip"
                placeholder="请输入集群内任意IP地址"
@@ -152,7 +175,8 @@
                autocomplete="new-password"
              ></el-input>
            </el-form-item>
            <el-form-item label="集群密码" prop="clusterpwd">
            <el-form-item  prop="clusterpwd">
              <div class="p-title">集群密码</div>
              <el-input
                v-model="joinForm.clusterpwd"
                placeholder="请输入集群密码"
@@ -178,8 +202,9 @@
              </el-input>
            </el-form-item>
          </el-form>
          <div class="save-btn" @click="join('joinForm')">加入集群</div>
           <div class="btns">
        <div class="ok" @click="join('joinForm')">加入集群</div>
      </div>
        </div>
      </div>
    </div>
@@ -190,21 +215,17 @@
import {
  createSerfCluster,
  randomPwd,
  leave,
  search,
  getSearchNodes,
  stopSearching,
  findCluster,
  updateClusterName,
  joinCluster,
  leave,
  getVrrp,
  setVrrp,
  createESNode,
  addESNode,
  getEsClusterInfo,
} from "@/api/clusterManage";
import cloudNode from "../components/CloudNode";
import ipInput from "@/components/subComponents/IPInput";
// import cloudNode from "../components/CloudNode";
import NetNode from '../components/NetNode'
import ipInput from "../components/IPInput";
import { isIPv4 } from "@/scripts/validate";
export default {
@@ -221,12 +242,18 @@
        }
      }, 1000);
    };
    const checkID = (rule, value, callback) => {
      if (!value) {
        return callback(new Error("密码不能为空"));
      }
    };
    return {
      innerNodes: [],
      intervalTimer: null,
      isFillingName: false,
      isFillingIp: false,
      inputName: "",
      activePage: 0,
      inputIp: "",
      serverIp: "",
      members: [],
@@ -255,37 +282,35 @@
      searchNum: "",
      scheduleId: "",
      isCreate: true,
      tabList: ["创建集群", "加入已有集群"],
      rules: {
        clustername: [
          { required: true, message: "请输入集群名称", trigger: "change" },
          { required: true, message: "请输入集群名称", trigger: "blur" },
        ],
        clusterpwd: [{ validator: checkPwd, trigger: "change" }],
        clusterpwd: [{ validator: checkPwd, trigger: "blur" }],
        virtualIp: [{ required: true, validator: isIPv4, trigger: "change" }],
      },
      joinRules: {
        clusterid: [
          { required: true, message: "请输入集群ID", trigger: "change" },
        ],
        clusterip: [{ required: true, validator: isIPv4, trigger: "change" }],
        clusterpwd: [{ validator: checkPwd, trigger: "change" }],
      joinExistRules: {
        clusterid: [{ validator: checkID, trigger: "blur" }],
        clusterip: [{ validator: isIPv4, trigger: "blur" }],
        clusterpwd: [{ validator: checkPwd, trigger: "blur" }],
      },
    };
  },
  components: {
    cloudNode,
    ipInput,
    // cloudNode,
    NetNode,
    ipInput
  },
  mounted() {
    this.findCluster();
    let _this = this;
    this.intervalTimer = setInterval(() => {
      _this.findCluster();
      this.findCluster();
    }, 30000);
  },
  beforeDestroy() {
    clearInterval(this.intervalTimer);
  },
  props: ["barName"],
  methods: {
    async createCluster(json) {
      let res = await createSerfCluster(json);
@@ -323,18 +348,21 @@
    async joinCluster(json) {
      let res = await joinCluster(json);
      if (res.success) {
        this.members = []
        this.members = [];
      }
      this.$notify({
        title: res.success ? "成功" : "失败",
        message: res.msg,
        type: res.success ? "success" : "error"
        type: res.success ? "success" : "error",
      });
    },
    join(formName) {
      debugger
      let _this = this;
      this.$refs[formName].validate((valid) => {
      debugger
        if (valid) {
      debugger
          _this.joinLoading = true;
          let nodeIps = _this.members.map((i) => {
            return i.Address;
@@ -399,6 +427,9 @@
        this.stopSearch();
      }, 10 * 1000);
    },
    openRight(i) {
      this.activePage = i;
    },
    async stopSearch() {
      if (!this.loading) {
        return true;
@@ -407,7 +438,7 @@
        searchNum: this.searchNum,
      })
        .then((res) => {
        this.loading = false;
          this.loading = false;
          this.searchDis = false;
          window.clearInterval(this.scheduleId);
        })
@@ -448,12 +479,52 @@
      this.ruleForm.clusterpwd = uuid.join("");
    },
    exitCluster() {
      clearInterval(this.intervalTimer);
      this.showCurCluster = false;
      this.ruleForm.virtualIp = "";
      this.ruleForm.clustername = "";
      this.ruleForm.clusterpwd = "";
      this.clusterid = "";
      const h = this.$createElement;
      this.$msgbox({
        title: "",
        message: h(
          "div",
          {
            style:
              "display: flex;  flex-direction: column; justify-content: center; align-items: center;",
          },
          [
            h("span", { class: "icon iconfont warn-icon" }, "\ue71c"),
            h("span", { class: "warn-title" }, "退出集群"),
            h("span", { class: "warn-dec" }, "确定退出集群吗?"),
          ]
        ),
        showCancelButton: true,
        showClose: true,
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        customClass: "del-account-message-box",
      }).then(
        async () => {
          let res = await leave();
          this.$notify({
            title: res.success ? "成功" : "失败",
            message: res.msg,
            type: res.success ? "success" : "error",
          });
          if (res && res.success) {
            clearInterval(this.intervalTimer);
            this.showCurCluster = false;
            this.ruleForm.virtualIp = "";
            this.ruleForm.clustername = "";
            this.ruleForm.clusterpwd = "";
            this.clusterid = "";
          }
        },
        (err) => {
          clearInterval(this.intervalTimer);
          this.showCurCluster = false;
          this.ruleForm.virtualIp = "";
          this.ruleForm.clustername = "";
          this.ruleForm.clusterpwd = "";
          this.clusterid = "";
        }
      );
    },
    clearInput(typ) {
      if (typ == 1) {
@@ -480,11 +551,10 @@
      }
    },
    onIpBlur(ip) {
      console.log(ip);
      this.ruleForm.virtualIp = ip;
    },
    async updateCluster(v) {
      if (v == 1) {
      if (v == 1 || v == undefined) {
        this.ruleForm.clustername = this.selfForm.clustername;
      }
      if (this.ruleForm.clustername === "") {
@@ -502,6 +572,7 @@
      if (res.success) {
        this.findCluster();
      }
      this.$notify({
        title: res.success ? "成功" : "失败",
        message: res.msg,
@@ -550,27 +621,93 @@
<style lang="scss">
.all {
  width: 100%;
  background: #f2f2f7;
}
.cluster-guanli {
  margin: 0 auto;
  width: 520px;
  .bar {
    height: 40px;
    background-color: rgba(248, 248, 248, 1);
    margin-bottom: 10px;
width: 760px;
  padding: 0 10px;
  .btns {
    margin-top: 30px !important;
    .exit {
      width: 188px;
      height: 40px;
      cursor: pointer;
      border-radius: 25px;
      background-color: #fe6d68;
      color: #fff;
      line-height: 40px;
      font-weight: bold;
      font-size: 16px;
      margin-left: 60px;
      margin-top: 0;
    }
  }
  .cloud {
    width: 100%;
    display: flex;
    height: 255px;
    border-radius: 8px;
    background: linear-gradient(
      180deg,
      #ffffff 0%,
      rgba(255, 255, 255, 0) 100%
    );
    .inner {
      background: url(/images/settings/easy-cloud.png) no-repeat;
      background-size: contain;
      margin: 0 auto;
      width: 240px;
      .rect {
        position: relative;
        margin: 0;
        height: 100%;
      }
    }
  }
  .cls-bar {
    height: 48px;
    background-color: #ffffff;
    margin-bottom: 6px;
    display: flex;
    box-sizing: border-box;
    padding: 0 20px;
    padding: 0 30px;
    justify-content: space-between;
    align-items: center;
    border-radius: 8px;
    font-weight: bold;
    font-size: 14px;
    color: #333333;
    .title {
      font-size: 14px;
    }
    .input-area {
      display: flex;
      width: 340px;
      width: 540px;
      height: 30px;
      line-height: 30px;
      justify-content: inherit;
      //   padding: 0 20px;
      box-sizing: border-box;
      background: #f2f2f7;
      border-radius: 20px;
      padding: 0 30px;
      .el-input--mini .el-input__inner {
        height: 24px;
        line-height: 24px;
        /* border: 1px solid transparent; */
        background: inherit;
        padding-left: 0;
        border: none;
        border-radius: 0px;
        font-size: 14px;
      }
      .icon {
        cursor: pointer;
        font-size: 14px;
        margin-left: 10px;
      }
    }
  }
  .exit {
@@ -583,6 +720,7 @@
    line-height: 40px;
    font-size: 14px;
    margin-top: 20px;
    cursor: pointer;
  }
}
.cluster-content {
@@ -592,6 +730,8 @@
  flex: 1;
  flex-basis: auto;
  box-sizing: border-box;
  background: #fbfaff;
  .cluster-center {
    height: 100%;
    width: 280px;
@@ -599,25 +739,41 @@
    box-sizing: border-box;
    flex-shrink: 0;
    padding: 10px;
    // background-color: lightpink;
    padding-top: 6px;
    border-right: 4px solid #f2f2f7;
    border-left: 4px solid #f2f2f7;
    border-top: 4px solid #f2f2f7;
    .menu-item {
      background-color: #f8f8f8;
      height: 40px;
      cursor: pointer;
      height: 56px;
      margin-bottom: 10px;
      border-radius: 8px;
      line-height: 40px;
      font-size: 14px;
      line-height: 56px;
      text-align: left;
      box-sizing: border-box;
      padding: 0 20px;
      font-weight: bold;
      font-size: 16px;
    }
    .menu-item-active {
      background-color: var(--colorCard);
      color: white;
    }
    // .menu-item:hover {
    //   background-color: var(--colorCard);
    //   color: white;
    // }
  }
  .cluster-right {
    flex: 1;
    flex-basis: auto;
    overflow: auto;
    // background-color: rgba(240, 242, 245, 1);
    box-sizing: border-box;
    position: relative;
    border-top: 4px solid #f2f2f7;
    padding: 20px 40px;
    // .create-new .join-exist {
    padding-top: 16px;
    .el-form-item.is-required:not(.is-no-asterisk)
      > .el-form-item__label:before,
    .el-form-item.is-required:not(.is-no-asterisk)
@@ -625,28 +781,83 @@
      > .el-form-item__label:before {
      display: none;
    }
    .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: 48px;
      display: flex;
      align-items: center;
      background: #f2f2f7;
      border-radius: 8px;
      padding: 0 15px 0 20px;
      .el-select-dropdown__item {
        color: #333333;
        height: 32px;
        font-size: 12px;
        line-height: 32px;
        text-align: center;
      }
      .el-popper {
        margin-top: 0;
        background: #fbfaff;
        box-shadow: 0px 2px 6px rgb(0 0 0 / 18%);
        border-radius: 2px;
        .el-select-dropdown__item.hover,
        .el-select-dropdown__item:hover {
          background-color: #f2f2f7;
          color: var(--colorCard);
        }
      }
    }
    .el-form-item__content {
      line-height: 40px;
      position: relative;
      font-size: 14px;
    .el-form-item__error {
      line-height: 0.7;
      left: 20px;
    }
    .el-form-item {
    margin-bottom: 10px;
      .el-input__inner {
        background-color: #ffffff;
        border: 2px solid transparent;
        border-radius: 20px;
        height: 32px;
        line-height: 32px;
        padding: 0 15px;
        font-size: 14px;
        font-weight: bold;
      }
      .el-input__inner:focus {
        border: 2px solid var(--colorCard);
      }
      .el-input__inner::placeholder {
        color: #c0c4cc;
        font-size: 12px;
        font-weight: normal;
      }
      .el-select {
        width: 100%;
      }
      .el-select .el-input .el-select__caret {
        color: #333333;
        font-size: 14px;
        font-weight: 600;
      }
    }
    .p-title {
      height: 48px;
      text-align: left;
      line-height: 48px;
      width: 90px;
      font-weight: 600;
    }
    .ip-input-container {
      max-width: none !important;
      height: 32px;
      line-height: normal;
      box-sizing: border-box;
      // background-color: #f2f2f7;
      text-align: left;
      border-radius: 20px;
      border: 2px solid transparent;
    }
    // }
    .ntp-bar {
      height: 40px;
      background-color: rgba(248, 248, 248, 1);