ZZJ
2022-01-26 da4f50e1008b815067cf47352747bf6d23b8b043
bug修复
6个文件已修改
2796 ■■■■ 已修改文件
src/components/giantTree/index.vue 98 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/searching/UploadImg.vue 216 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pages/cameraAccess/components/TimeSlider.vue 481 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pages/datapush/index/RightEvent.vue 1916 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pages/desktop/index/components/Tools.vue 46 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pages/settings/views/clusterManagement.vue 39 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/giantTree/index.vue
@@ -26,12 +26,23 @@
      :style="{ left: clientX + 'px', top: clientY + 'px' }"
    >
      <el-card :body-style="{ padding: '10px' }">
        <el-form :model="dialogForm" size="mini" :rules="rules" ref="dialogForm" label-width="70px">
        <el-form
          :model="dialogForm"
          size="mini"
          :rules="rules"
          ref="dialogForm"
          label-width="70px"
        >
          <el-form-item label="名称:" prop="name">
            <el-input v-model="dialogForm.text" oninput="if(value.length>10)value=value.slice(0,10)"></el-input>
            <el-input
              v-model="dialogForm.text"
              oninput="if(value.length>10)value=value.slice(0,10)"
            ></el-input>
          </el-form-item>
          <div class="text-center pb-2">
            <el-button size="mini" type="primary" @click="submitForm">保存</el-button>
            <el-button size="mini" type="primary" @click="submitForm"
              >保存</el-button
            >
            <el-button size="mini" @click="hideDialogBox">取消</el-button>
          </div>
        </el-form>
@@ -41,32 +52,32 @@
</template>
<script>
import ZTree from "./zTree/ztree"
import ZTree from "./zTree/ztree";
export default {
  name: "GiantTreeMenu",
  components: {
    ZTree
    ZTree,
  },
  props: {
    app: {
      type: String,
      default: "Video"
      default: "Video",
    },
    node: {
      type: Array
      type: Array,
    },
    treeName: {
      type: String,
      default: ""
      default: "",
    },
    gb28181: {
      type: Boolean,
      default: false
      default: false,
    },
    height: {
      type: Number,
      default: 0
      default: 0,
    },
    setting: {
      type: Object,
@@ -82,15 +93,15 @@
      clientX: 0,
      clientY: 0,
      dialogForm: {
        text: ""
        text: "",
      },
      rules: {
        text: [
          { required: true, message: "请输入节点名称", trigger: "change" },
          { min: 2, max: 10, message: "长度在2到10个字", trigger: "change" }
        ]
          { min: 2, max: 10, message: "长度在2到10个字", trigger: "change" },
        ],
      },
      curNodeTid: '',
      curNodeTid: "",
    };
  },
  created() {
@@ -104,27 +115,29 @@
      if (newValue !== this.treeName) {
        this.TreeDataPool.cleanTree(this.treeName);
      }
    }
    },
  },
  methods: {
    handleCreated: function (ztreeObj) {
      let _this = this;
      this.ztreeObj = ztreeObj;
      ztreeObj.expandAll(true)
      ztreeObj.expandAll(true);
      // onCreated 中操作ztreeObj对象展开第一个节点
      // ztreeObj.expandNode(ztreeObj.getNodes()[0], true);
      // 摄像机配置切换时, 设置选中状态
      if (this.TreeDataPool.selectedNode.id) {
        // 取消所有多选的节点,仅保留当前单选的节点
        this.TreeDataPool.selectedNodes = [this.TreeDataPool.selectedNode.id]
        this.TreeDataPool.selectedNodes = [this.TreeDataPool.selectedNode.id];
        this.curNodeTid = this.TreeDataPool.selectedNode.tId;
        //摄像机信息更新信息后,如果节点位置有变tId就不准了,this.TreeDataPool.selectedNode此时还是旧的信息
        let ztreeNodes = ztreeObj.getNodes();
        //var curNodeTid = '';
        _this.findTidByIdFromArr(ztreeNodes);
        this.TreeDataPool.selectedNode.tId = _this.curNodeTid;
        let node = this.ztreeObj.getNodeByTId(this.TreeDataPool.selectedNode.tId)
        let node = this.ztreeObj.getNodeByTId(
          this.TreeDataPool.selectedNode.tId
        );
        // 多选时, 选中单选单击的节点
        if (this.TreeDataPool.multiple) {
@@ -132,7 +145,7 @@
          this.ztreeObj.checkNode(node, true, false, false);
        }
        this.ztreeObj.selectNode(node, false, true)
        this.ztreeObj.selectNode(node, false, true);
      }
    },
@@ -148,7 +161,6 @@
          this.findTidByIdFromArr(arr[i].children);
        }
      }
    },
    onDblClick(evt, treeId, item) {
      if (item.type !== "4" || this.app !== "Camera") {
@@ -163,14 +175,18 @@
        this.TreeDataPool.activeVideoIndex !== "" &&
        this.TreeDataPool.activeVideoIndex <= videoArr.length - 1
      ) {
        this.TreeDataPool.setVideoArr(this.TreeDataPool.activeVideoIndex, undefined, this);
        this.TreeDataPool.setVideoArr(
          this.TreeDataPool.activeVideoIndex,
          undefined,
          this
        );
        this.$nextTick(() => {
          this.TreeDataPool.setVideoArr(
            this.TreeDataPool.activeVideoIndex,
            item,
            this
          );
        })
        });
        return;
      }
@@ -188,14 +204,18 @@
        }
      }
      if (nullVideoIndex === "") {
        this.TreeDataPool.setVideoArr(this.TreeDataPool.activeVideoIndex, undefined, this);
        this.TreeDataPool.setVideoArr(
          this.TreeDataPool.activeVideoIndex,
          undefined,
          this
        );
        this.$nextTick(() => {
          this.TreeDataPool.setVideoArr(
            this.TreeDataPool.activeVideoIndex,
            item,
            this
          );
        })
        });
      } else {
        // this.TreeDataPool.setVideoArr(this.TreeDataPool.activeVideoIndex, undefined, this);
        this.$nextTick(() => {
@@ -204,7 +224,7 @@
            item,
            this
          );
        })
        });
        this.TreeDataPool.activeVideoIndex = nullVideoIndex;
      }
    },
@@ -218,7 +238,7 @@
      this.dialogForm = {
        text: "",
        method: "add",
        node: node.id
        node: node.id,
      };
      this.showDialogBox(event);
    },
@@ -228,7 +248,7 @@
        method: "edit",
        node: node.id,
        alias: node.alias,
        gb28181: this.gb28181
        gb28181: this.gb28181,
      };
      this.showDialogBox(event);
    },
@@ -237,7 +257,7 @@
    },
    submitForm() {
      // 提交新增或者编辑区域节点表单
      this.$refs.dialogForm.validate(valid => {
      this.$refs.dialogForm.validate((valid) => {
        if (valid) {
          if (this.dialogForm.method == "add") {
            this.TreeDataPool.add(this.dialogForm.text, this.dialogForm.node);
@@ -267,7 +287,6 @@
      this.showDialog = true;
    },
    itemClick(evt, treeId, treeNode) {
      this.TreeDataPool.selectedNode = treeNode;
      this.TreeDataPool.treeType = this.treeName;
@@ -296,7 +315,7 @@
    itemCheck(evt, treeId, treeNode) {
      this.TreeDataPool.selectedNode = treeNode;
      this.TreeDataPool.treeType = this.treeName;
      debugger
      debugger;
      // 多选
      // this.ztreeObj.checkNode(treeNode, true, false, false);
      let checkedNodes = this.ztreeObj.getCheckedNodes(true);
@@ -306,25 +325,24 @@
      this.TreeDataPool.countCheckedNodes(checkedNodes);
      // 保存一份数据
      this.TreeDataPool.activeTreeData = this.ztreeObj.getNodes()
      this.TreeDataPool.activeTreeData = this.ztreeObj.getNodes();
    },
    //展开
    itemExpand(e, id, node) {
      delete this.TreeDataPool.foldNodeList[node.id]
      delete this.TreeDataPool.foldNodeList[node.id];
    },
    // 折叠
    itemCollapse(e, id, node) {
      this.TreeDataPool.foldNodeList[node.id] = true
      this.TreeDataPool.foldNodeList[node.id] = true;
    },
    dropNode(node, item, draggedItem, e) {
      // console.log('dropNode', node, item, draggedItem);
      this.TreeDataPool.dropNode(draggedItem.id, item.id)
      this.TreeDataPool.dropNode(draggedItem.id, item.id);
    },
    showCameraPic(nodeId) {
      this.TreeDataPool.showBaseImage(nodeId)
    }
  }
      this.TreeDataPool.showBaseImage(nodeId);
    },
  },
};
</script>
<style lang="scss" scoped>
@@ -385,7 +403,7 @@
}
.tree-menu {
  // max-width: 350px;
  overflow-x: hidden;
  overflow-x: auto;
  overflow-y: hidden;
  margin-bottom: 4px;
}
@@ -410,8 +428,6 @@
  background: rgba(0, 0, 0, 0.4);
}
.tree-menu:hover {
  overflow-x: visible;
  overflow-y: auto;
  margin-bottom: 0px;
}
</style>
src/components/searching/UploadImg.vue
@@ -5,14 +5,21 @@
        数据源
        <i
          class="iconfont iconchushaixuanxiang close"
          style="margin-left:200px;cursor:pointer;color:#ccc"
          style="margin-left: 200px; cursor: pointer; color: #ccc"
          @click="closeUploadImg"
        ></i>
      </h2>
      <p class="compearValue">
        <span
          style="font-family: PingFangSC-Regular;font-size: 13px;color: #333333;letter-spacing: 0.28px;margin-right:10px"
        >对比阈值</span>
          style="
            font-family: PingFangSC-Regular;
            font-size: 13px;
            color: #333333;
            letter-spacing: 0.28px;
            margin-right: 10px;
          "
          >对比阈值</span
        >
        <el-input-number
          size="mini"
          v-model="VideoPhotoData.threshold"
@@ -22,7 +29,12 @@
        ></el-input-number>
      </p>
      <div class="upload-img-box">
        <img :src="'/httpImage/'+tempUploadImg" alt="临时测试" v-show="!displayUpload" class="bigPhoto" />
        <img
          :src="'/httpImage/' + tempUploadImg"
          alt="临时测试"
          v-show="!displayUpload"
          class="bigPhoto"
        />
        <el-upload
          ref="upload"
          :list-type="'picture-card'"
@@ -39,11 +51,22 @@
          <i
            ref="uploadIcon"
            class="el-icon-upload"
            style="color:#3D68E1;font-size:60px;position:relative;left:50px"
            style="
              color: #3d68e1;
              font-size: 60px;
              position: relative;
              left: 50px;
            "
          ></i>
          <span
            class="el-upload__text"
            style="font-size:12px;color:#3D68E1;position:relative;top:25px;left:-30px"
            style="
              font-size: 12px;
              color: #3d68e1;
              position: relative;
              top: 25px;
              left: -30px;
            "
          >
            <em>点击选择上传图片</em>
          </span>
@@ -54,24 +77,35 @@
          <img width="100%" :src="dialogImageUrl" alt />
        </el-dialog>-->
      </div>
      <div class="res-img-box" v-if="resReady" :style="oneLine? 'height:95px':'height:185px'">
        <div class="single-box fl" v-for="(item, index) in realSmallPath" :key="index">
      <div
        class="res-img-box"
        v-if="resReady"
        :style="oneLine ? 'height:95px' : 'height:185px'"
      >
        <div
          class="single-box fl"
          v-for="(item, index) in realSmallPath"
          :key="index"
        >
          <img
            :src="item
              ? '/httpImage/'+item
              : tempImg
          "
            @click="selected($event,index)"
            style="max-height:100%"
            :style="index == clickNum ? 'border:1px solid #FF7733':''"
            :src="item ? '/httpImage/' + item : tempImg"
            @click="selected($event, index)"
            style="max-height: 100%"
            :style="index == clickNum ? 'border:1px solid #FF7733' : ''"
          />
          <img class="select" v-show="index == clickNum" :src="selectedIcon" alt />
          <img
            class="select"
            v-show="index == clickNum"
            :src="selectedIcon"
            alt
          />
        </div>
        <div class="single-box fl" v-for="(item, index) in unrealSmallPath" :key="index+'t'">
          <img :src="item
                ? item
                : tempImg
            " />
        <div
          class="single-box fl"
          v-for="(item, index) in unrealSmallPath"
          :key="index + 't'"
        >
          <img :src="item ? item : tempImg" />
        </div>
      </div>
      <el-select
@@ -80,20 +114,28 @@
        multiple
        collapse-tags
        @change="selectChange"
        style="margin: 15px 0;width: 100%"
        style="margin: 15px 0; width: 100%"
        placeholder="请选择"
      >
        <el-option
          v-for="item in VideoPhotoData.tabsForUploadImg"
          :key="item.key+'p'"
          :key="item.key + 'p'"
          :label="item.title"
          :disabled="item.disabled"
          :value="item.key"
        ></el-option>
      </el-select>
      <el-button-group v-if="resReady" style="margin-top:10px;">
        <el-button type="info" size="small" @click="reUpload">重新上传</el-button>
        <el-button type="primary" size="small" style="margin-left:10px" @click="searchStart">开始检索</el-button>
      <el-button-group v-if="resReady" style="margin-top: 10px">
        <el-button type="info" size="small" @click="reUpload"
          >重新上传</el-button
        >
        <el-button
          type="primary"
          size="small"
          style="margin-left: 10px"
          @click="searchStart"
          >开始检索</el-button
        >
      </el-button-group>
    </div>
  </div>
@@ -101,26 +143,26 @@
<script>
import Card from "../subComponents/Card";
import request from "@/scripts/httpRequest"
import request from "@/scripts/httpRequest";
export default {
  watch: {
    "VideoPhotoData.tabsForUploadImg": function (value) {
      this.selectChange()
      this.selectChange();
    },
    "VideoPhotoData.uploadImg": {
      handler(val) {
        // console.log('val:::', val)
        if (val !== "") {
          this.tempUploadImg = val
          this.realSmallPath = [val]
          this.unrealSmallPath = [this.tempImg, this.tempImg]
          this.resReady = true
          this.displayUpload = false
          this.tempUploadImg = val;
          this.realSmallPath = [val];
          this.unrealSmallPath = [this.tempImg, this.tempImg];
          this.resReady = true;
          this.displayUpload = false;
        }
      },
      immediate: true,
      deep: true
    }
      deep: true,
    },
  },
  computed: {
    getResImg() {
@@ -139,7 +181,7 @@
        arr.length = 9;
      }
      return arr;
    }
    },
  },
  data() {
    return {
@@ -159,21 +201,21 @@
      realSmallPath: [],
      unrealSmallPath: [],
      oneLine: true,
      multiSelect: false
      multiSelect: false,
    };
  },
  mounted() {
    this.selectChange()
    this.selectChange();
    this.$nextTick(() => {
      let scrollContain = this.$refs.rightSection
      console.log("赋值容器:", scrollContain)
      this.VideoPhotoData.scrollContainDom = scrollContain
    })
      let scrollContain = this.$refs.rightSection;
      console.log("赋值容器:", scrollContain);
      this.VideoPhotoData.scrollContainDom = scrollContain;
    });
  },
  methods: {
    closeUploadImg() {
      this.VideoPhotoData.uploadDiaplay = false
      this.VideoPhotoData.clearStatus()
      this.VideoPhotoData.uploadDiaplay = false;
      this.VideoPhotoData.clearStatus();
    },
    selectChange() {
      if (!this.compareTabs.includes("esData") && this.compareTabs.length > 0) {
@@ -182,7 +224,7 @@
            this.VideoPhotoData.tabsForUploadImg[i].disabled = true;
          }
        }
        this.$emit('labelDisabled', true)
        this.$emit("labelDisabled", true);
        return;
      }
      if (this.compareTabs.includes("esData")) {
@@ -191,7 +233,7 @@
            this.VideoPhotoData.tabsForUploadImg[i].disabled = true;
          }
        }
        this.$emit('labelDisabled', false)
        this.$emit("labelDisabled", false);
      } else {
        for (let i = 0; i < this.VideoPhotoData.tabsForUploadImg.length; i++) {
          this.VideoPhotoData.tabsForUploadImg[i].disabled = false;
@@ -199,36 +241,38 @@
      }
    },
    selected(e, index) {
      this.clickNum = index
      this.clickNum = index;
    },
    async uploadImg(param) {
      const fd = new FormData()
      fd.append('file', param.file)
      fd.append('picQuality', this.VideoPhotoData.threshold)
      const fd = new FormData();
      fd.append("file", param.file);
      fd.append("picQuality", this.VideoPhotoData.threshold);
      let res = await request({
        method: 'post',
        method: "post",
        url: `/data/api-v/dbperson/faceExtract`,
        data: fd
      })
      this.unrealSmallPath.length = 0
      console.log("切图返回:", res)
        data: fd,
      });
      this.unrealSmallPath.length = 0;
      console.log("切图返回:", res);
      if (res.success) {
        document.querySelector(".el-upload-list").querySelector("img").src = "/httpImage/" + res.data.uploadImage
        document.querySelector(".el-upload-list").querySelector("img").src =
          "/httpImage/" + res.data.uploadImage;
        this.resReady = true;
        this.realSmallPath = res.data.smImage
        this.VideoPhotoData.isHaveRealSmallImg = res.data.smImage.length > 0 ? true : false
        this.realSmallPath = res.data.smImage;
        this.VideoPhotoData.isHaveRealSmallImg =
          res.data.smImage.length > 0 ? true : false;
        if (res.data.smImage.length > 3) {
          this.oneLine = false
          this.oneLine = false;
        } else {
          this.oneLine = true
          this.oneLine = true;
        }
        if (res.data.smImage.length % 3 !== 0) {
          // 用虚拟人像补全整行
          const length = res.data.smImage.length % 3
          console.log("看看length的值", length)
          this.unrealSmallPath.length = 0
          const length = res.data.smImage.length % 3;
          console.log("看看length的值", length);
          this.unrealSmallPath.length = 0;
          for (var i = 0; i < 3 - length; i++) {
            this.unrealSmallPath.push(this.tempImg)
            this.unrealSmallPath.push(this.tempImg);
          }
        }
      }
@@ -237,36 +281,36 @@
      this.$notify({
        title: "成功",
        message: "图片上传成功!",
        type: "success"
        type: "success",
      });
      this.resReady = true;
      console.log("文件列表:", file, fileList)
      console.log("上传的文件:", this.bigPhoto)
      console.log("文件列表:", file, fileList);
      console.log("上传的文件:", this.bigPhoto);
    },
    beforeUpload() {
      this.$refs.uploadIcon.parentNode.classList.add("s-display");
      console.log("上传之前文件:", this.bigPhoto)
      console.log("上传之前文件:", this.bigPhoto);
    },
    uploadError(err) {
      this.$notify({
        title: "失败",
        message: "图片上传失败!" + err.data,
        type: "error"
        message: err.msg,
        type: "error",
      });
      console.log("上传失败", err)
      console.log("上传失败", err);
      this.dialogImageUrl = "";
      this.dialogVisible = false;
      this.$refs.uploadIcon.parentNode.classList.remove("s-display");
    },
    toAdd(item) {
      this.CardList.addBaseList.push(item)
      this.CardList.addBaseList.push(item);
    },
    removeImg() {
      this.resReady = false;
      this.$refs.uploadIcon.parentNode.classList.remove("s-display");
    },
    reUpload() {
      this.displayUpload = true
      this.displayUpload = true;
      this.$refs.upload.clearFiles();
      // this.dialogImageUrl = "";
      // this.dialogVisible = false;
@@ -279,30 +323,30 @@
          title: "警告",
          type: "warning",
          message: "您还没有选择要比对的目标库",
        })
        return
        });
        return;
      }
      this.rightSectionDisplay = true;
      this.VideoPhotoData.uploadType = true;
      this.VideoPhotoData.picUrl = this.realSmallPath[this.clickNum]
      this.VideoPhotoData.compareTabs = this.compareTabs
      console.log("选的库:", this.compareTabs)
      this.VideoPhotoData.showType = "findByPic"
      this.VideoPhotoData.picUrl = this.realSmallPath[this.clickNum];
      this.VideoPhotoData.compareTabs = this.compareTabs;
      console.log("选的库:", this.compareTabs);
      this.VideoPhotoData.showType = "findByPic";
      if (this.displayUpload) {
        this.VideoPhotoData.findPerson()
        this.VideoPhotoData.findPerson();
      } else {
        this.VideoPhotoData.findPerson2()
        this.VideoPhotoData.findPerson2();
      }
    },
    getDetails(ev, index) {
      this.CardList.datalist = this.VideoPhotoData.persons
      this.CardList.datalist = this.VideoPhotoData.persons;
      let obj = this.CardList.datalist[index];
      this.CardList.details = Array.from(
        new Set([...this.CardList.details, ...[obj]])
      );
      this.VideoPhotoData.activeCard = obj.activeObject.id
    }
  }
      this.VideoPhotoData.activeCard = obj.activeObject.id;
    },
  },
};
</script>
<style lang="scss">
@@ -311,7 +355,7 @@
  height: 100%;
  box-sizing: border-box;
  padding: 5px;
  .el-button--info{
  .el-button--info {
    color: #222;
  }
  .upload-area {
src/pages/cameraAccess/components/TimeSlider.vue
@@ -1,226 +1,257 @@
<template>
  <div class="sub-time-box">
    <div class="btn-control">
      <div class="el-tabs-edit">
        <span v-if="!editSlider" class="add-btn" @click="handleTabsEdit('','edit')">
          <i class="el-icon-edit"></i>
          编辑
        </span>
        <span v-else class="add-btn" @click="handleTabsEdit('','lock')">
          <i class="el-icon-lock"></i>
          锁定
        </span>
      </div>
      <div class="el-tabs-add">
        <span class="add-btn" @click="handleTabsEdit('','add')">
          <i class="iconfont iconhebingxingzhuang"></i>
          新增
        </span>
      </div>
    </div>
    <el-tabs v-model="activeTab" type="border-card" editable @edit="handleTabsEdit">
      <el-tab-pane v-for="item in VideoManageData.TimeRules" :key="item.id" :name="item.id">
        <span slot="label" @click="tabClick(item)" style="width:100px">{{item.name}}</span>
        <multi-range-slider
          :timeData="JSON.parse(item.time_rule)"
          :mainId="`${item.id}_${type}`"
          :itemId="item.id"
          :itemName="item.name"
          :edit="editSlider"
          @range-update="updateTimeRule"
        ></multi-range-slider>
      </el-tab-pane>
    </el-tabs>
  </div>
</template>
<script>
import MultiRangeSlider from "@/components/subComponents/MultiRangeSlider";
import { saveTimeRule, deleteTimeRule } from "@/api/timeRule";
export default {
  name: "TimeSlider",
  components: {
    MultiRangeSlider
  },
  props: {
    type: {
      default: "",
      type: String
    }
  },
  data() {
    return {
      editSlider: false,
      activeTab: "",
      activeIndex: 0,
      cavasLength: 800,
      allDay: [
        { day: 1, time_range: [{ start: "00:00", end: "24:00" }] },
        { day: 2, time_range: [{ start: "00:00", end: "24:00" }] },
        { day: 3, time_range: [{ start: "00:00", end: "24:00" }] },
        { day: 4, time_range: [{ start: "00:00", end: "24:00" }] },
        { day: 5, time_range: [{ start: "00:00", end: "24:00" }] },
        { day: 6, time_range: [{ start: "00:00", end: "24:00" }] },
        { day: 7, time_range: [{ start: "00:00", end: "24:00" }] }
      ]
    };
  },
  mounted() {
    // window.addEventListener('resize', this.windowSizeChange)
  },
  methods: {
    handleTabsEdit(tabId, action) {
      let tabs = this.VideoManageData.TimeRules;
      if (action === "add") {
        let newRule = {
          id: "",
          name: "时间段" + this.VideoManageData.TimeRules.length,
          time_rule: this.allDay
        };
        this.updateTimeRule(newRule);
      }
      if (action === "remove") {
        this.$confirm(
          "此操作将永久删除该规则, 所关联的任务将会失效,是否继续?",
          {
            center: true,
            confirmButtonText: "确定",
            cancelButtonText: "取消",
          }
        ).then(() => {
          deleteTimeRule({ id: tabId }).then(rsp => {
            if (rsp && rsp.success) {
              this.VideoManageData.getTimeRule();
              // this.VideoManageData.TimeRules.splice(2, 1)
              this.activeTab = this.VideoManageData.TimeRules[0].id;
              this.$notify({
                type: "success",
                message: "删除成功!"
              });
            }
          });
        }).catch(() => { });
      }
      if (action == "edit") {
        this.editSlider = true;
      }
      if (action == "lock") {
        this.editSlider = false;
      }
    },
    windowSizeChange() {
      let timeSlideWidth = document.querySelector(".sub-time-box").clientWidth
      this.cavasLength = timeSlideWidth
      console.log("时间组件宽度:", timeSlideWidth)
    },
    updateTimeRule(rule) {
      saveTimeRule(rule).then(rsp => {
        if (rsp && rsp.success) {
          this.VideoManageData.getTimeRule();
          this.activeTab = rsp.data.id;
        }
      });
    },
    tabClick(item) {
      if (this.activeTab === item.id) {
        this.$prompt("", "修改名称", {
          confirmButtonText: "确定",
          cancelButtonText: "取消",
          inputValue: item.name,
          inputPattern: /^[\S]{1,16}$/,
          inputErrorMessage: "名称不能包含空格"
        }).then(({ value }) => {
          this.updateTimeRule({
            id: item.id,
            name: value,
            time_rule: JSON.parse(item.time_rule)
          });
          this.$notify({
            type: "success",
            message: "时间规则名称修改成功"
          });
        }).catch(() => { });
      }
    }
  }
};
</script>
<style lang='scss'>
.sub-time-box {
  padding-right: 30px;
  position: relative;
  /* height: calc(100% - 32px);
  width: 100%;
  padding: 5px; */
  /* box-sizing: border-box; */
  /* border-right: 1px solid #ccc;
  border-top: 1px solid #ccc;
  border-bottom: 1px solid #ccc; */
  .btn-control {
    position: absolute;
    margin-top: -27px;
    top: 0;
    right: 30px;
    display: flex;
    i {
      font-size: 16px;
    }
  }
  .el-tabs__item {
    border-right-color: #e2e2e2 !important;
    border-left-color: #e2e2e2 !important;
    border-top-color: #e2e2e2 !important;
  }
  .el-tab-pane {
    height: calc(100% - 50px);
  }
  // .el-tabs__new-tab {
  //   margin: 15px 19px 9px 10px;
  // }
  .el-tabs {
    height: 100%;
  }
  .el-tabs__header {
    margin: 0px !important;
    height: 45px !important;
    border-top: 1px solid #e2e2e2 !important;
    border-bottom: 1px solid #e2e2e2 !important;
    background-color: #fff !important;
    .is-active {
      border-bottom-color: #fff !important;
    }
    .el-tabs__item {
      line-height: 45px !important;
    }
  }
  .el-tabs__content {
    overflow: auto !important;
    height: calc(100% - 51px) !important;
    padding: 13px 0px !important;
  }
  .el-tabs__new-tab {
    visibility: hidden;
    // width: 130px;
  }
  // .el-tabs-add {
  //   position: relative;
  //   display: flex;
  //   width: 70px;
  //   top: 32px;
  //   left: 88%;
  //   z-index: 1;
  // }
  // .el-tabs-edit {
  //   position: relative;
  //   display: -webkit-box;
  //   display: -ms-flexbox;
  //   display: flex;
  //   width: 70px;
  //   top: 47px;
  //   left: 79%;
  //   z-index: 1;
  // }
}
<template>
  <div class="sub-time-box">
    <div class="btn-control">
      <div class="el-tabs-edit">
        <span
          v-if="!editSlider"
          class="add-btn"
          @click="handleTabsEdit('', 'edit')"
        >
          <i class="el-icon-edit"></i>
          编辑
        </span>
        <span v-else class="add-btn" @click="handleTabsEdit('', 'lock')">
          <i class="el-icon-lock"></i>
          锁定
        </span>
      </div>
      <div class="el-tabs-add">
        <span class="add-btn" @click="handleTabsEdit('', 'add')">
          <i class="iconfont iconhebingxingzhuang"></i>
          新增
        </span>
      </div>
    </div>
    <el-tabs
      v-model="activeTab"
      type="border-card"
      editable
      @edit="handleTabsEdit"
    >
      <el-tab-pane
        v-for="item in VideoManageData.TimeRules"
        :key="item.id"
        :name="item.id"
      >
        <span slot="label" @click="tabClick(item)" style="width: 100px">{{
          item.name
        }}</span>
        <multi-range-slider
          :timeData="JSON.parse(item.time_rule)"
          :mainId="`${item.id}_${type}`"
          :itemId="item.id"
          :itemName="item.name"
          :edit="editSlider"
          @range-update="updateTimeRule"
        ></multi-range-slider>
      </el-tab-pane>
    </el-tabs>
  </div>
</template>
<script>
import MultiRangeSlider from "@/components/subComponents/MultiRangeSlider";
import { saveTimeRule, deleteTimeRule } from "@/api/timeRule";
export default {
  name: "TimeSlider",
  components: {
    MultiRangeSlider,
  },
  props: {
    type: {
      default: "",
      type: String,
    },
  },
  data() {
    return {
      editSlider: false,
      activeTab: "",
      activeIndex: 0,
      cavasLength: 800,
      allDay: [
        { day: 1, time_range: [{ start: "00:00", end: "24:00" }] },
        { day: 2, time_range: [{ start: "00:00", end: "24:00" }] },
        { day: 3, time_range: [{ start: "00:00", end: "24:00" }] },
        { day: 4, time_range: [{ start: "00:00", end: "24:00" }] },
        { day: 5, time_range: [{ start: "00:00", end: "24:00" }] },
        { day: 6, time_range: [{ start: "00:00", end: "24:00" }] },
        { day: 7, time_range: [{ start: "00:00", end: "24:00" }] },
      ],
    };
  },
  mounted() {
    // window.addEventListener('resize', this.windowSizeChange)
  },
  methods: {
    handleTabsEdit(tabId, action) {
      let tabs = this.VideoManageData.TimeRules;
      if (action === "add") {
        let newRule = {
          id: "",
          name: "时间段" + this.VideoManageData.TimeRules.length,
          time_rule: this.allDay,
        };
        this.updateTimeRule(newRule);
      }
      if (action === "remove") {
        console.log();
        if (this.VideoManageData.TimeRules.length == 1) {
          this.$notify({
            title: "警告",
            message: "此时间段正在使用中,无法删除!",
            type: "warning",
          });
          return;
        }
        this.$confirm(
          "此操作将永久删除该规则, 所关联的任务将会失效,是否继续?",
          {
            center: true,
            confirmButtonText: "确定",
            cancelButtonText: "取消",
          }
        )
          .then(() => {
            deleteTimeRule({ id: tabId }).then((rsp) => {
              if (rsp && rsp.success) {
                this.VideoManageData.getTimeRule();
                // this.VideoManageData.TimeRules.splice(2, 1)
                this.activeTab = this.VideoManageData.TimeRules[0].id;
                this.$notify({
                  type: "success",
                  message: "删除成功!",
                });
              }
            });
          })
          .catch(() => {});
      }
      if (action == "edit") {
        this.editSlider = true;
      }
      if (action == "lock") {
        this.editSlider = false;
      }
    },
    windowSizeChange() {
      let timeSlideWidth = document.querySelector(".sub-time-box").clientWidth;
      this.cavasLength = timeSlideWidth;
      console.log("时间组件宽度:", timeSlideWidth);
    },
    updateTimeRule(rule) {
      saveTimeRule(rule).then((rsp) => {
        if (rsp && rsp.success) {
          this.VideoManageData.getTimeRule();
          this.activeTab = rsp.data.id;
        }
      });
    },
    tabClick(item) {
      if (this.activeTab === item.id) {
        this.$prompt("", "修改名称", {
          confirmButtonText: "确定",
          cancelButtonText: "取消",
          inputValue: item.name,
          inputPattern: /^[\S]{1,16}$/,
          inputErrorMessage: "名称不能包含空格",
        })
          .then(({ value }) => {
            this.updateTimeRule({
              id: item.id,
              name: value,
              time_rule: JSON.parse(item.time_rule),
            });
            this.$notify({
              type: "success",
              message: "时间规则名称修改成功",
            });
          })
          .catch(() => {});
      }
    },
  },
};
</script>
<style lang='scss'>
.sub-time-box {
  padding-right: 30px;
  position: relative;
  /* height: calc(100% - 32px);
  width: 100%;
  padding: 5px; */
  /* box-sizing: border-box; */
  /* border-right: 1px solid #ccc;
  border-top: 1px solid #ccc;
  border-bottom: 1px solid #ccc; */
  .btn-control {
    position: absolute;
    margin-top: -27px;
    top: 0;
    right: 30px;
    display: flex;
    i {
      font-size: 16px;
    }
  }
  .el-tabs__item {
    border-right-color: #e2e2e2 !important;
    border-left-color: #e2e2e2 !important;
    border-top-color: #e2e2e2 !important;
  }
  .el-tab-pane {
    height: calc(100% - 50px);
  }
  // .el-tabs__new-tab {
  //   margin: 15px 19px 9px 10px;
  // }
  .el-tabs {
    height: 100%;
  }
  .el-tabs__header {
    margin: 0px !important;
    height: 45px !important;
    border-top: 1px solid #e2e2e2 !important;
    border-bottom: 1px solid #e2e2e2 !important;
    background-color: #fff !important;
    .is-active {
      border-bottom-color: #fff !important;
    }
    .el-tabs__item {
      line-height: 45px !important;
    }
  }
  .el-tabs__content {
    overflow: auto !important;
    height: calc(100% - 51px) !important;
    padding: 13px 0px !important;
  }
  .el-tabs__new-tab {
    visibility: hidden;
    // width: 130px;
  }
  // .el-tabs-add {
  //   position: relative;
  //   display: flex;
  //   width: 70px;
  //   top: 32px;
  //   left: 88%;
  //   z-index: 1;
  // }
  // .el-tabs-edit {
  //   position: relative;
  //   display: -webkit-box;
  //   display: -ms-flexbox;
  //   display: flex;
  //   width: 70px;
  //   top: 47px;
  //   left: 79%;
  //   z-index: 1;
  // }
}
</style>
src/pages/datapush/index/RightEvent.vue
@@ -1,926 +1,990 @@
<template>
  <div class="s-event-push-right">
    <div class="s-right-config">
      <el-form>
        <el-form-item label="名称">
          <el-input
            v-model="taskEditData.name"
            placeholder="请输入名称"
            size="small"
            style="width:400px"
          ></el-input>
        </el-form-item>
        <el-form-item label="时间">
          <el-date-picker
            v-model="taskEditData.time"
            format="yyyy-MM-dd HH:mm:ss"
            value-format="yyyy-MM-dd HH:mm:ss"
            type="datetimerange"
            range-separator="至"
            start-placeholder="开始日期"
            end-placeholder="结束日期"
            size="small"
          ></el-date-picker>
        </el-form-item>
        <span style="line-height: 38px;">推送服务器</span>
        <div class="icon-btn" v-if="urls.length < 1" @click="addUrl()">
          <i class="el-icon-circle-plus-outline"></i>
          <span>&nbsp;添加接口地址</span>
        </div>
        <div v-for="(item,index) in urls" :key="item.hash" class="flex-box server-url">
          <div>
            <el-checkbox v-model="item.enable"></el-checkbox>
            <span class="ml20">{{'URL&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'}}</span>
            <el-input v-model="item.url" style="width:360px;margin-left:0px;" size="small"></el-input>
          </div>
          <div class="server-add">
            <i
              class="el-icon-remove-outline"
              @click="delUrl(index)"
              style="color:red;margin-right:10px"
            />
            <i class="el-icon-circle-plus-outline" @click="addUrl()"></i>
          </div>
        </div>
        <el-form-item label="联动方式" style="margin-top: 20px;width:100">
          <el-select v-model="taskEditData.lineWay" placeholder="请选择" size="small">
            <el-option
              v-for="item in taskEditData.lineOptions"
              :key="item.value"
              :label="item.label"
              :value="item.value"
            ></el-option>
          </el-select>
        </el-form-item>
        <el-form-item label="标签">
          <el-radio v-model="taskEditData.radioValue" label="1">满足全部</el-radio>
          <el-radio v-model="taskEditData.radioValue" label="2">满足任意一个</el-radio>
        </el-form-item>
      </el-form>
    </div>
    <div class="s-right-mid"></div>
    <div class="s-right-rule">
      <div class="rule-title">
        <b style="margin-right:20px">任务配置</b>
        <div class="icon-btn" v-if="dataList.length === 0" @click="createSet">
          <i class="el-icon-circle-plus-outline"></i>
          <span>&nbsp;新增</span>
        </div>
        <div class="icon-btn" v-if="dataList.length > 0" @click="cleanSet">
          <i class="el-icon-remove-outline"></i>
          <span>&nbsp;清空</span>
        </div>
      </div>
      <div v-for="(rule,index) in dataList" :key="index" style="margin-top:10px">
        <el-row :gutter="20">
          <!-- 主题 -->
          <el-col :span="4">
            <el-select
              v-model="rule.topic_type"
              placeholder="请选择"
              @change="selectTopic(rule, true)"
              size="small"
            >
              <el-option
                v-for="item in rule.topicTypeOptions"
                :key="item.id"
                :label="item.name"
                :value="item.value"
              ></el-option>
            </el-select>
          </el-col>
          <!-- 过滤值 -->
          <el-col :span="4">
            <el-select
              v-model="rule.topic_arg"
              placeholder="请选择"
              @change="selectArg(rule, true)"
              size="small"
            >
              <el-option
                v-for="item in rule.topicArgOptions"
                :key="item.id"
                :label="item.name"
                :value="item.value"
              ></el-option>
            </el-select>
          </el-col>
          <!-- 操作符 -->
          <el-col :span="4">
            <el-select v-model="rule.operator" placeholder="请选择" size="small">
              <el-option label="==" value="="></el-option>
            </el-select>
          </el-col>
          <!-- 值类型 -->
          <el-col :span="4">
            <el-select
              v-model="rule.operator_type"
              placeholder="请选择"
              @change="selectOperator(rule, true)"
              size="small"
            >
              <el-option
                v-for="item in rule.operatorTypeOpionts"
                :key="item.id"
                :label="item.name"
                :value="item.value"
              ></el-option>
            </el-select>
          </el-col>
          <!-- 过滤值 -->
          <el-col :span="4">
            <div v-if="rule.operator_type === 'custom'">
              <el-input v-model="rule.rule_value" placeholder="请输入内容" size="small"></el-input>
            </div>
            <div v-else>
              <el-select
                v-model="rule.rule_values"
                multiple
                collapse-tags
                placeholder="请选择"
                size="small"
                @change="selectValue( rule, $event)"
              >
                <el-option
                  v-for="item in rule.ruleValueOptions"
                  :key="item.id"
                  :label="item.name"
                  :disabled="item.disabled"
                  :value="item.value"
                ></el-option>
              </el-select>
            </div>
          </el-col>
          <el-col :span="4">
            <div class="rule-edit-btn">
              <i
                v-show="dataList.length > 1"
                class="el-icon-remove-outline"
                @click="delRule(index)"
                style="color:red;margin-right:10px"
              />
              <i
                v-show="index === dataList.length -1"
                class="el-icon-circle-plus-outline"
                @click="addRule()"
                style="color:#3D68E1"
              ></i>
            </div>
          </el-col>
        </el-row>
        <el-row></el-row>
      </div>
      <div class="rule-title2">
        <b>规则</b>
        <div class="div-border" v-html="taskEditData.eventTxt"></div>
      </div>
      <div class="config-item">
        <b>推送字段</b>
        <el-button type="primary" size="mini" @click="openPushSetDialog">设置</el-button>
      </div>
      <div class="save-btn">
        <el-button type="info" size="small" @click="onCancle" style="color:#222">取消</el-button>
        <el-button type="primary" @click="eventPushsSave" size="small">保存</el-button>
      </div>
    </div>
    <el-dialog
      :visible="pushFieldDialog"
      :append-to-body="false"
      :close-on-click-modal="false"
      class="dialog-push-field"
      @close="pushFieldDialog=false"
    >
      <div slot="title" class="slot-title">
        <p>请选择想要推送的字段</p>
        <div class="right">
          <el-checkbox v-model="allFieldChecked" @change="allCheckChange"></el-checkbox>
        </div>
      </div>
      <div class="check-area" v-for="configObj in tempPushSet" :key="configObj.id">
        <div class="header">
          <div class="title">{{configObj.name}}</div>
          <div class="right">
            <el-checkbox v-model="configObj.checked" @change="toggleConfigCheck(configObj)">全选</el-checkbox>
          </div>
        </div>
        <div class="flex-box flex-wrap">
          <div class="param flex-box" v-for="param in configObj.children" :key="param.id">
            <el-checkbox v-model="param.checked" @change="checkChildren"></el-checkbox>
            <span class="param-name">{{param.name}}</span>
            <el-input
              v-model="param.alias"
              size="mini"
              :ref="`input_${param.id}`"
              @input="varifyField(param)"
              :style="{color:param.error?'red':'',borderColor:param.error?'red':''}"
            ></el-input>
          </div>
        </div>
      </div>
      <div slot="footer" class="text-center">
        <el-button size="small" @click="canclePushFieldSet">取消</el-button>
        <el-button
          size="small"
          type="primary"
          :disabled="disabledPushFieldSet"
          @click="submitPushFieldSet"
        >保存</el-button>
      </div>
    </el-dialog>
  </div>
</template>
<script>
import { eventPushsSave, findByEventTopic, getPushSet } from "@/api/event";
import { findDictionaryByType, findDictionaryByID } from "@/api/dictionary";
import { getTaskList } from "@/api/search";
export default {
  name: "rightEvent",
  props: {
    eventObject: {
      type: Object,
      default: () => {
        return {};
      }
    }
  },
  computed: {
    urls() {
      return this.taskEditData.urls
    }
  },
  data() {
    return {
      taskEditData: {},
      dataList: [],
      dictionary: [],
      cameras: [],
      tasks: [],
      tables: [],
      baseRule: {
        event_push_id: "",
        id: "",
        operator: "==",
        operator_type: "",
        rule_value: "",
        rule_values: [],
        topic_arg: "",
        topic_type: "",
        topicTypeOptions: {},
        topicArgOptions: {},
        operatorOptions: {},
        operatorTypeOpionts: {},
        ruleValueOptions: []
      },
      pushFieldDialog: false,
      tempPushSet: [],
      pushFields: [],
      allFieldChecked: false,
      disabledPushFieldSet: true,
    };
  },
  watch: {
    eventObject: {
      handler(newVal, oldVal) {
        this.taskEditData.enable = this.eventObject.enable;
        if (newVal !== oldVal) {
          if (this.taskEditData.id !== newVal.id) {
            this.dataList = [];
            this.taskEditData.id = newVal.id;
            this.taskEditData.name = newVal.name;
            this.taskEditData.time = [
              this.eventObject.time_start,
              this.eventObject.time_end
            ];
            this.taskEditData.serverIp = newVal.ip_ports;
            this.taskEditData.urls = newVal.urls;
            this.taskEditData.lineWay = newVal.link_type;
            this.taskEditData.eventTxt = newVal.rule_text;
            this.taskEditData.radioValue = newVal.is_satisfy_all ? "1" : "2";
            if (!this.taskEditData.urls) {
              this.$set(this.taskEditData, "urls", [])
            }
            //this.taskEditData.push_set = this.eventObject.push_set;
            if (!this.eventObject.push_set.length) {
              this.$set(this.taskEditData, "push_set", this.pushFields)
            } else {
              this.$set(this.taskEditData, "push_set", this.eventObject.push_set)
            }
            if (newVal.rules) {
              newVal.rules.forEach(element => {
                let newRule = Object.assign(JSON.parse(JSON.stringify(this.baseRule)), element)
                this.dataList.push(newRule)
                this.selectTopic(newRule);
                this.selectOperator(newRule);
              })
            }
          }
        }
      },
      deep: true
    },
    tempPushSet: {
      handler(n, o) {
        let _this = this;
        let flag = false;
        n.forEach(configObj => {
          let notChecked = configObj.children.find(param => !param.checked);
          if (!notChecked) {
            configObj.checked = true;
          } else {
            configObj.checked = false;
          }
          let someoneChecked = configObj.children.find(param => param.checked);
          if (someoneChecked) {
            flag = true
          }
        });
        if (flag) {
          this.disabledPushFieldSet = false;
        } else {
          this.disabledPushFieldSet = true;
        }
      },
      deep: true
    }
  },
  created() {
    this.reAdd();
  },
  mounted() {
    // 加载字典
    this.findByType();
    this.getCameras();
    this.getTasks();
    this.getPushFields();
  },
  methods: {
    openPushSetDialog() {
      this.pushFieldDialog = true;
      this.tempPushSet = JSON.parse(JSON.stringify(this.taskEditData.push_set));
      this.checkFlag()
    },
    checkFlag() {
      // debugger
      let flag = true
      this.tempPushSet.forEach(item => {
        if (item.checked == false) {
          flag = false
        }
      });
      this.allFieldChecked = flag
    },
    checkChildren(val) {
      console.log(val, 12121);
      if (val == false) {
        this.allFieldChecked = false
      } else if (val == true && this.allFieldChecked == false) {
        this.$nextTick(() => {
          this.checkFlag()
        })
      }
    },
    varifyField(param) {
      var reg = /^[A-Za-z]+[0-9-_]?$/;
      if (!reg.test(param.alias)) {
        this.$message('请输入合法字段名');
        param.error = true;
      } else {
        param.error = false;
      }
      // this.pushFields.forEach(configObj => {
      //   configObj.children.find(param => param.error)
      // })
    },
    canclePushFieldSet() {
      this.pushFieldDialog = false;
    },
    allCheckChange(val) {
      this.tempPushSet.forEach(function (item) {
        item.checked = val
        item.children.forEach(function (child) {
          child.checked = val
        })
      })
    },
    submitPushFieldSet() {
      let flag = false;
      //this.pushFields.forEach(configObj => {
      this.tempPushSet.forEach(configObj => {
        let errorOne = configObj.children.find(param => param.checked && param.error);
        if (errorOne) {
          this.$notify({
            type: 'error',
            message: '请将选中字段输入合法字段名'
          })
          flag = true
        }
      });
      if (flag) {
        //NO SUBMIT
        return
      }
      this.taskEditData.push_set = this.tempPushSet;
      this.pushFieldDialog = false;
      // 保存规则
      this.eventPushsSave()
    },
    toggleConfigCheck(configObj) {
      configObj.children.forEach(child => {
        child.checked = configObj.checked
      })
      this.checkFlag()
    },
    getPushFields() {
      let _this = this;
      getPushSet().then(res => {
        _this.pushFields = res.data;
      })
      // this.pushFields = [
      //   {          id: 'sxjxx', name: '摄像机信息', checked: false, alias: '',
      //     children: [
      //       { name: '摄像机ID', checked: false, alias: 'cameraID', id: 'cameraID', children: null },
      //       { name: '摄像机名称', checked: false, alias: 'cameraName', id: 'cameraName', children: null },
      //       { name: '摄像机地址', checked: false, alias: 'cameraAddr', id: 'cameraAddr', children: null },
      //       { name: '摄像机址', checked: false, alias: 'cameraAdr', id: 'cameraAdr', children: null }
      //     ]        },
      //   {          id: 'cjxx', name: '场景信息', checked: false, alias: '',
      //     children: [{ name: '场景ID', checked: false, alias: 'taskId', id: 'tskId', children: null }]        },
      // ];
    },
    addUrl() {
      this.taskEditData.urls.push({
        checked: true,
        hash: Math.random().toString(36).substr(2),
        url: "",
      });
    },
    delUrl(index) {
      this.$set(this.taskEditData.urls, index, this.baseRule);
      this.taskEditData.urls.splice(index, 1);
    },
    // 保存
    async eventPushsSave() {
      // 判断保存的ip是否符合格式要求
      if (this.taskEditData.urls.length < 1) {
        this.$notify({
          type: "warning",
          message: "请配置至少一台推送服务器"
        });
        return;
      }
      for (let i = 0; i < this.taskEditData.urls.length; i++) {
        if (this.taskEditData.urls[i].url.length < 1) {
          this.$notify({
            type: "warning",
            message: "接口URL地址不允许为空"
          });
          return;
        }
      }
      // 拼接字符串
      let ruleDesc = []
      this.dataList.forEach(i => {
        let str = "";
        if (i.topic_type) {
          str += this.getNameByValue(i.topicTypeOptions, i.topic_type);
        }
        if (i.topic_arg) {
          str += this.getNameByValue(i.topicArgOptions, i.topic_arg);
        }
        if (i.operator === '==') {
          str += ' = ';
        }
        if (i.rule_value === "all*all") {
          str += "全部";
        } else if (i.rule_value === "null*null") {
          str += "空";
        } else {
          str += i.rule_value;
        }
        if (str.length > 0) {
          ruleDesc.push(str);
        }
      });
      // 处理规则列表数据结构
      let ruleList = this.dataList.map(i => {
        return {
          topic_type: i.topic_type,
          topic_arg: i.topic_arg,
          operator: i.operator,
          operator_type: i.operator_type,
          rule_value: i.rule_value
        }
      });
      let json = {
        enable: this.taskEditData.enable,
        id: this.taskEditData.id,
        ip_ports: this.taskEditData.serverIp,
        name: this.taskEditData.name,
        rule_text: ruleDesc.join("<br/>"),
        rules: ruleList,
        time_start: this.taskEditData.time[0],
        time_end: this.taskEditData.time[1],
        urls: this.taskEditData.urls,
        is_satisfy_all: this.taskEditData.radioValue === "1",
        link_type: this.taskEditData.lineWay,
        push_set: this.taskEditData.push_set
      };
      let res = await eventPushsSave(json);
      if (res && res.success) {
        this.taskEditData.eventTxt = ruleDesc.join("<br/>");
        this.$emit("updateList", res.data.id);
        this.$notify({
          type: "success",
          message: "保存成功"
        });
      }
    },
    // 查找字典
    async findByType() {
      let res = await findDictionaryByType();
      if (res && res.success) {
        this.dictionary = Object.assign(this.dictionary, res.data)
        this.baseRule.topicTypeOptions = this.dictionary.EVENTRULETOPIC
        this.baseRule.operatorTypeOpionts = this.dictionary.EVENTTYPECOMPUTE
        this.dictionary['alarmLevel'] = this.dictionary.ALARMLEVEL.map(el => {
          return {
            name: el.name,
            value: el.name
          }
        })
      }
    },
    async getCameras() {
      let rsp = await findByEventTopic({ topic: 'camera', type: 'name' });
      if (rsp && rsp.success) {
        this.dictionary['camera'] = rsp.data;
      }
      rsp = await findByEventTopic({ topic: 'dbtable' });
      if (rsp && rsp.success) {
        this.dictionary['dbtable'] = rsp.data.map(el => {
          return {
            name: el.name,
            value: el.name
          }
        })
      }
    },
    async getTasks() {
      this.dictionary['task'] = []
      let rsp = await getTaskList();
      if (rsp && rsp.success) {
        let hash = {}
        rsp.data.forEach(task => {
          if (!task.isDelete && !hash[task.name]) {
            this.dictionary['task'].push({
              value: task.name,
              name: task.name
            })
            hash[task.name] = true;
          }
        })
      }
    },
    // 新建配置
    createSet() {
      this.dataList.push(JSON.parse(JSON.stringify(this.baseRule)));
    },
    cleanSet() {
      this.dataList.splice(0, this.dataList.length);
    },
    // 添加子规则
    addRule() {
      this.dataList.push(JSON.parse(JSON.stringify(this.baseRule)));
    },
    // 删除子规则
    delRule(index) {
      this.dataList.splice(index, 1);
    },
    // 规则中下拉框的选择回调
    selectTopic(rule, resetNext = false) {
      rule.topicTypeOptions.forEach(element => {
        if (element.value === rule.topic_type) {
          rule.topicArgOptions = element.children;
          if (resetNext) {
            rule.topic_arg = rule.topicArgOptions[0].value;
            this.selectArg(rule, resetNext);
          }
        }
      });
    },
    selectArg(rule, resetNext = false) {
      debugger
      let argInfo = rule.topicArgOptions.filter(arg => {
        return arg.value === rule.topic_arg;
      })
      if (argInfo.length > 0) {
        let desc = argInfo[0].description.split(",");
        if (desc.length > 0) {
          rule.operatorTypeOpionts = this.dictionary.EVENTTYPECOMPUTE.filter(el => {
            return desc.indexOf(el.value) >= 0;
          })
        }
      }
      if (resetNext) {
        rule.operator_type = rule.operatorTypeOpionts[rule.operatorTypeOpionts.length - 1].value;
        this.selectOperator(rule, resetNext);
      }
    },
    selectOperator(rule, resetNext = false) {
      if (rule.operator_type === "option") {
        rule.ruleValueOptions = this.dictionary[rule.topic_type] ? this.dictionary[rule.topic_type] : [];
        if (rule.rule_value != "") {
          rule.rule_values = rule.rule_value.split(",");
        }
        // 处理 全部/空
        for (let i = 0; i < rule.rule_values.length; i++) {
          if (rule.rule_values[i] === "all*all") {
            rule.rule_values[i] = "全部";
          }
          if (rule.rule_values[i] === "null*null") {
            rule.rule_values[i] = "空";
          }
        }
        this.setOptionsDisable(rule);
      }
      if (resetNext) {
        rule.rule_value = "";
        rule.rule_values = [];
      }
    },
    selectValue(rule, val) {
      if (rule.operator_type === "option") {
        this.setOptionsDisable(rule);
        if (val.indexOf("全部") >= 0) {
          rule.rule_value = "all*all";
          return;
        }
        if (val.indexOf("空") >= 0) {
          rule.rule_value = "null*null";
          return;
        }
      }
      rule.rule_value = val.join(",");
    },
    setOptionsDisable(rule) {
      let isAllSelect = (rule.rule_values.indexOf("全部") >= 0);
      let isNullSelect = (rule.rule_values.indexOf("空") >= 0);
      rule.ruleValueOptions.forEach(opt => {
        if (!rule.rule_values.length) {
          opt.disabled = false;
          return
        }
        if (opt.name === "全部") {
          opt.disabled = !isAllSelect;
          return
        }
        if (opt.name === "空") {
          opt.disabled = !isNullSelect;
          return
        }
        opt.disabled = (isAllSelect || isNullSelect);
      })
    },
    // 根据value返回对应的name
    getNameByValue(arr, value) {
      let s = arr.find(item => {
        return item.value === value;
      });
      return s.name;
    },
    // 清空重新新增
    reAdd() {
      this.taskEditData = {
        id: "",
        name: "",
        time: [
          this.$moment().format("YYYY-MM-DD 00:00:00"),
          this.$moment().format("YYYY-MM-DD HH:mm:ss")
        ],
        serverIp: [
          {
            enable: true,
            server_ip: "",
            port: 0
          }
        ],
        urls: [
        ],
        lineWay: "",
        lineOptions: [
          {
            value: "001",
            label: "IP广播"
          }
        ],
        radioValue: "1",
        eventTxt: "",
        push_set: this.pushFields
      };
      this.dataList = [];
    },
    onCancle() {
      this.$emit('onCancle')
    }
  }
};
</script>
<style lang="scss">
.s-event-push-right {
  text-align: left;
  font-size: 14px;
  i {
    cursor: pointer;
  }
  .s-right-config {
    padding: 10px 40px;
  }
  .el-form-item__label {
    text-align: left;
  }
  .s-right-mid {
    height: 10px;
    background-color: #e9ebf2;
    width: 100%;
    //position: absolute;
  }
  .s-right-rule {
    padding: 20px 40px;
    margin-top: 17px;
    .rule-title {
      border-bottom: 1px solid #e0e0e0;
    }
    .rule-title2 {
      margin-top: 20px;
    }
    .div-border {
      width: 995px;
      padding: 10px;
      margin-top: 15px;
      min-height: 80px;
      background: #fafafa;
      border: 1px solid #f2f2f2;
    }
    .rule-edit-btn {
      font-size: 18px;
      line-height: 38px;
    }
    .save-btn {
      // float: right;
      margin-top: 20px;
      margin-left: 895px;
    }
  }
  .config-item {
    margin: 20px 0;
    b {
      margin-right: 10px;
    }
  }
  .el-button--text {
    text-decoration: unset;
  }
  .icon-btn {
    i {
      font-size: 18px;
      position: relative;
      top: 2px;
    }
    span {
      font-size: 14px;
    }
    display: inline;
    color: #3d68e1;
    line-height: 38px;
    margin-left: 10px;
    cursor: pointer;
  }
  .server-url {
    padding-top: 25px;
  }
  .server-add {
    font-size: 18px;
    margin-left: 8px;
    color: #3d68e1;
    line-height: 39px;
  }
  .dialog-push-field {
    .el-button--primary.is-disabled,
    .el-button--primary.is-disabled:hover {
      background-color: #9eb4f0 !important;
      border-color: #9eb4f0 !important;
    }
    .el-dialog {
      width: 910px;
      height: 700px;
      .el-dialog__body {
        padding-top: 14px;
        height: 540px;
        overflow-y: auto;
      }
    }
    .text-center {
      text-align: center;
    }
    .slot-title {
      position: relative;
      .right {
        position: absolute;
        top: 0;
        right: 30px;
      }
    }
    .check-area {
      padding-bottom: 10px;
      .header {
        position: relative;
        background: #efefef;
        line-height: 30px;
        margin-bottom: 14px;
        font-weight: bold;
        .title {
          border-left: 3px solid #2481fa;
          padding-left: 10px;
        }
        .right {
          position: absolute;
          top: 0;
          right: 30px;
        }
      }
      .flex-box.flex-wrap {
        flex-wrap: wrap;
      }
      .param.flex-box {
        word-break: keep-all;
        align-items: center;
        margin: 0 10px;
        min-width: 260px;
        margin-bottom: 10px;
        .param-name {
          margin: 0 5px;
        }
        .el-input {
          border-color: #dcdfe6;
          color: #606266;
          .el-input__inner {
            color: inherit;
            border-color: inherit;
          }
        }
      }
    }
  }
}
</style>
<template>
  <div class="s-event-push-right">
    <div class="s-right-config">
      <el-form>
        <el-form-item label="名称">
          <el-input
            v-model="taskEditData.name"
            placeholder="请输入名称"
            size="small"
            style="width: 400px"
          ></el-input>
        </el-form-item>
        <el-form-item label="时间">
          <el-date-picker
            v-model="taskEditData.time"
            format="yyyy-MM-dd HH:mm:ss"
            value-format="yyyy-MM-dd HH:mm:ss"
            type="datetimerange"
            range-separator="至"
            start-placeholder="开始日期"
            end-placeholder="结束日期"
            size="small"
          ></el-date-picker>
        </el-form-item>
        <span style="line-height: 38px">推送服务器</span>
        <div class="icon-btn" v-if="urls.length < 1" @click="addUrl()">
          <i class="el-icon-circle-plus-outline"></i>
          <span>&nbsp;添加接口地址</span>
        </div>
        <div
          v-for="(item, index) in urls"
          :key="item.hash"
          class="flex-box server-url"
        >
          <div>
            <el-checkbox v-model="item.enable"></el-checkbox>
            <span class="ml20">{{ "URL&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;" }}</span>
            <el-input
              v-model="item.url"
              style="width: 360px; margin-left: 0px"
              size="small"
            ></el-input>
          </div>
          <div class="server-add">
            <i
              class="el-icon-remove-outline"
              @click="delUrl(index)"
              style="color: red; margin-right: 10px"
            />
            <i class="el-icon-circle-plus-outline" @click="addUrl()"></i>
          </div>
        </div>
        <el-form-item label="联动方式" style="margin-top: 20px; width: 100">
          <el-select
            v-model="taskEditData.lineWay"
            placeholder="请选择"
            size="small"
          >
            <el-option
              v-for="item in taskEditData.lineOptions"
              :key="item.value"
              :label="item.label"
              :value="item.value"
            ></el-option>
          </el-select>
        </el-form-item>
        <el-form-item label="标签">
          <el-radio v-model="taskEditData.radioValue" label="1"
            >满足全部</el-radio
          >
          <el-radio v-model="taskEditData.radioValue" label="2"
            >满足任意一个</el-radio
          >
        </el-form-item>
      </el-form>
    </div>
    <div class="s-right-mid"></div>
    <div class="s-right-rule">
      <div class="rule-title">
        <b style="margin-right: 20px">任务配置</b>
        <div class="icon-btn" v-if="dataList.length === 0" @click="createSet">
          <i class="el-icon-circle-plus-outline"></i>
          <span>&nbsp;新增</span>
        </div>
        <div class="icon-btn" v-if="dataList.length > 0" @click="cleanSet">
          <i class="el-icon-remove-outline"></i>
          <span>&nbsp;清空</span>
        </div>
      </div>
      <div
        v-for="(rule, index) in dataList"
        :key="index"
        style="margin-top: 10px"
      >
        <el-row :gutter="20">
          <!-- 主题 -->
          <el-col :span="4">
            <el-select
              v-model="rule.topic_type"
              placeholder="请选择"
              @change="selectTopic(rule, true)"
              size="small"
            >
              <el-option
                v-for="item in rule.topicTypeOptions"
                :key="item.id"
                :label="item.name"
                :value="item.value"
              ></el-option>
            </el-select>
          </el-col>
          <!-- 过滤值 -->
          <el-col :span="4">
            <el-select
              v-model="rule.topic_arg"
              placeholder="请选择"
              @change="selectArg(rule, true)"
              size="small"
            >
              <el-option
                v-for="item in rule.topicArgOptions"
                :key="item.id"
                :label="item.name"
                :value="item.value"
              ></el-option>
            </el-select>
          </el-col>
          <!-- 操作符 -->
          <el-col :span="4">
            <el-select
              v-model="rule.operator"
              placeholder="请选择"
              size="small"
            >
              <el-option label="==" value="="></el-option>
            </el-select>
          </el-col>
          <!-- 值类型 -->
          <el-col :span="4">
            <el-select
              v-model="rule.operator_type"
              placeholder="请选择"
              @change="selectOperator(rule, true)"
              size="small"
            >
              <el-option
                v-for="item in rule.operatorTypeOpionts"
                :key="item.id"
                :label="item.name"
                :value="item.value"
              ></el-option>
            </el-select>
          </el-col>
          <!-- 过滤值 -->
          <el-col :span="4">
            <div v-if="rule.operator_type === 'custom'">
              <el-input
                v-model="rule.rule_value"
                placeholder="请输入内容"
                size="small"
              ></el-input>
            </div>
            <div v-else>
              <el-select
                v-model="rule.rule_values"
                multiple
                collapse-tags
                placeholder="请选择"
                size="small"
                @change="selectValue(rule, $event)"
              >
                <el-option
                  v-for="item in rule.ruleValueOptions"
                  :key="item.id"
                  :label="item.name"
                  :disabled="item.disabled"
                  :value="item.value"
                ></el-option>
              </el-select>
            </div>
          </el-col>
          <el-col :span="4">
            <div class="rule-edit-btn">
              <i
                v-show="dataList.length > 1"
                class="el-icon-remove-outline"
                @click="delRule(index)"
                style="color: red; margin-right: 10px"
              />
              <i
                v-show="index === dataList.length - 1"
                class="el-icon-circle-plus-outline"
                @click="addRule()"
                style="color: #3d68e1"
              ></i>
            </div>
          </el-col>
        </el-row>
        <el-row></el-row>
      </div>
      <div class="rule-title2">
        <b>规则</b>
        <div class="div-border" v-html="taskEditData.eventTxt"></div>
      </div>
      <div class="config-item">
        <b>推送字段</b>
        <el-button type="primary" size="mini" @click="openPushSetDialog"
          >设置</el-button
        >
      </div>
      <div class="save-btn">
        <el-button
          type="info"
          size="small"
          @click="onCancle"
          style="color: #222"
          >取消</el-button
        >
        <el-button type="primary" @click="eventPushsSave" size="small"
          >保存</el-button
        >
      </div>
    </div>
    <el-dialog
      :visible="pushFieldDialog"
      :append-to-body="false"
      :close-on-click-modal="false"
      class="dialog-push-field"
      @close="pushFieldDialog = false"
    >
      <div slot="title" class="slot-title">
        <p>请选择想要推送的字段</p>
        <div class="right">
          <el-checkbox
            v-model="allFieldChecked"
            @change="allCheckChange"
          ></el-checkbox>
        </div>
      </div>
      <div
        class="check-area"
        v-for="configObj in tempPushSet"
        :key="configObj.id"
      >
        <div class="header">
          <div class="title">{{ configObj.name }}</div>
          <div class="right">
            <el-checkbox
              v-model="configObj.checked"
              @change="toggleConfigCheck(configObj)"
              >全选</el-checkbox
            >
          </div>
        </div>
        <div class="flex-box flex-wrap">
          <div
            class="param flex-box"
            v-for="param in configObj.children"
            :key="param.id"
          >
            <el-checkbox
              v-model="param.checked"
              @change="checkChildren"
            ></el-checkbox>
            <span class="param-name">{{ param.name }}</span>
            <el-input
              v-model="param.alias"
              size="mini"
              :ref="`input_${param.id}`"
              @input="varifyField(param)"
              :style="{
                color: param.error ? 'red' : '',
                borderColor: param.error ? 'red' : '',
              }"
            ></el-input>
          </div>
        </div>
      </div>
      <div slot="footer" class="text-center">
        <el-button size="small" @click="canclePushFieldSet">取消</el-button>
        <el-button
          size="small"
          type="primary"
          :disabled="disabledPushFieldSet"
          @click="submitPushFieldSet"
          >保存</el-button
        >
      </div>
    </el-dialog>
  </div>
</template>
<script>
import { eventPushsSave, findByEventTopic, getPushSet } from "@/api/event";
import { findDictionaryByType, findDictionaryByID } from "@/api/dictionary";
import { getTaskList } from "@/api/search";
export default {
  name: "rightEvent",
  props: {
    eventObject: {
      type: Object,
      default: () => {
        return {};
      },
    },
  },
  computed: {
    urls() {
      return this.taskEditData.urls;
    },
  },
  data() {
    return {
      taskEditData: {},
      dataList: [],
      dictionary: [],
      cameras: [],
      tasks: [],
      tables: [],
      baseRule: {
        event_push_id: "",
        id: "",
        operator: "==",
        operator_type: "",
        rule_value: "",
        rule_values: [],
        topic_arg: "",
        topic_type: "",
        topicTypeOptions: {},
        topicArgOptions: {},
        operatorOptions: {},
        operatorTypeOpionts: {},
        ruleValueOptions: [],
      },
      pushFieldDialog: false,
      tempPushSet: [],
      pushFields: [],
      allFieldChecked: false,
      disabledPushFieldSet: true,
    };
  },
  watch: {
    eventObject: {
      handler(newVal, oldVal) {
        this.taskEditData.enable = this.eventObject.enable;
        if (newVal !== oldVal) {
          if (this.taskEditData.id !== newVal.id) {
            this.dataList = [];
            this.taskEditData.id = newVal.id;
            this.taskEditData.name = newVal.name;
            this.taskEditData.time = [
              this.eventObject.time_start,
              this.eventObject.time_end,
            ];
            this.taskEditData.serverIp = newVal.ip_ports;
            this.taskEditData.urls = newVal.urls;
            this.taskEditData.lineWay = newVal.link_type;
            this.taskEditData.eventTxt = newVal.rule_text;
            this.taskEditData.radioValue = newVal.is_satisfy_all ? "1" : "2";
            if (!this.taskEditData.urls) {
              this.$set(this.taskEditData, "urls", []);
            }
            //this.taskEditData.push_set = this.eventObject.push_set;
            if (!this.eventObject.push_set.length) {
              this.$set(this.taskEditData, "push_set", this.pushFields);
            } else {
              this.$set(
                this.taskEditData,
                "push_set",
                this.eventObject.push_set
              );
            }
            if (newVal.rules) {
              newVal.rules.forEach((element) => {
                let newRule = Object.assign(
                  JSON.parse(JSON.stringify(this.baseRule)),
                  element
                );
                this.dataList.push(newRule);
                this.selectTopic(newRule);
                this.selectOperator(newRule);
              });
            }
          }
        }
      },
      deep: true,
    },
    tempPushSet: {
      handler(n, o) {
        let _this = this;
        let flag = false;
        n.forEach((configObj) => {
          let notChecked = configObj.children.find((param) => !param.checked);
          if (!notChecked) {
            configObj.checked = true;
          } else {
            configObj.checked = false;
          }
          let someoneChecked = configObj.children.find(
            (param) => param.checked
          );
          if (someoneChecked) {
            flag = true;
          }
        });
        if (flag) {
          this.disabledPushFieldSet = false;
        } else {
          this.disabledPushFieldSet = true;
        }
      },
      deep: true,
    },
  },
  created() {
    this.reAdd();
  },
  mounted() {
    // 加载字典
    this.findByType();
    this.getCameras();
    this.getTasks();
    this.getPushFields();
  },
  methods: {
    openPushSetDialog() {
      this.pushFieldDialog = true;
      this.tempPushSet = JSON.parse(JSON.stringify(this.taskEditData.push_set));
      this.checkFlag();
    },
    checkFlag() {
      // debugger
      let flag = true;
      this.tempPushSet.forEach((item) => {
        if (item.checked == false) {
          flag = false;
        }
      });
      this.allFieldChecked = flag;
    },
    checkChildren(val) {
      console.log(val, 12121);
      if (val == false) {
        this.allFieldChecked = false;
      } else if (val == true && this.allFieldChecked == false) {
        this.$nextTick(() => {
          this.checkFlag();
        });
      }
    },
    varifyField(param) {
      var reg = /^[A-Za-z]+[0-9-_]?$/;
      if (!reg.test(param.alias)) {
        this.$message("请输入合法字段名");
        param.error = true;
      } else {
        param.error = false;
      }
      // this.pushFields.forEach(configObj => {
      //   configObj.children.find(param => param.error)
      // })
    },
    canclePushFieldSet() {
      this.pushFieldDialog = false;
    },
    allCheckChange(val) {
      this.tempPushSet.forEach(function (item) {
        item.checked = val;
        item.children.forEach(function (child) {
          child.checked = val;
        });
      });
    },
    submitPushFieldSet() {
      let flag = false;
      //this.pushFields.forEach(configObj => {
      this.tempPushSet.forEach((configObj) => {
        let errorOne = configObj.children.find(
          (param) => param.checked && param.error
        );
        if (errorOne) {
          this.$notify({
            type: "error",
            message: "请将选中字段输入合法字段名",
          });
          flag = true;
        }
      });
      if (flag) {
        //NO SUBMIT
        return;
      }
      this.taskEditData.push_set = this.tempPushSet;
      this.pushFieldDialog = false;
      // 保存规则
      this.eventPushsSave();
    },
    toggleConfigCheck(configObj) {
      configObj.children.forEach((child) => {
        child.checked = configObj.checked;
      });
      this.checkFlag();
    },
    getPushFields() {
      let _this = this;
      getPushSet().then((res) => {
        _this.pushFields = res.data;
      });
      // this.pushFields = [
      //   {          id: 'sxjxx', name: '摄像机信息', checked: false, alias: '',
      //     children: [
      //       { name: '摄像机ID', checked: false, alias: 'cameraID', id: 'cameraID', children: null },
      //       { name: '摄像机名称', checked: false, alias: 'cameraName', id: 'cameraName', children: null },
      //       { name: '摄像机地址', checked: false, alias: 'cameraAddr', id: 'cameraAddr', children: null },
      //       { name: '摄像机址', checked: false, alias: 'cameraAdr', id: 'cameraAdr', children: null }
      //     ]        },
      //   {          id: 'cjxx', name: '场景信息', checked: false, alias: '',
      //     children: [{ name: '场景ID', checked: false, alias: 'taskId', id: 'tskId', children: null }]        },
      // ];
    },
    addUrl() {
      this.taskEditData.urls.push({
        checked: true,
        hash: Math.random().toString(36).substr(2),
        url: "",
      });
    },
    delUrl(index) {
      this.$set(this.taskEditData.urls, index, this.baseRule);
      this.taskEditData.urls.splice(index, 1);
    },
    // 保存
    async eventPushsSave() {
      // 判断保存的ip是否符合格式要求
      if (this.taskEditData.urls.length < 1) {
        this.$notify({
          type: "warning",
          message: "请配置至少一台推送服务器",
        });
        return;
      }
      for (let i = 0; i < this.taskEditData.urls.length; i++) {
        if (this.taskEditData.urls[i].url.length < 1) {
          this.$notify({
            type: "warning",
            message: "接口URL地址不允许为空",
          });
          return;
        }
      }
      // 拼接字符串
      let ruleDesc = [];
      this.dataList.forEach((i) => {
        let str = "";
        if (i.topic_type) {
          str += this.getNameByValue(i.topicTypeOptions, i.topic_type);
        }
        if (i.topic_arg) {
          str += this.getNameByValue(i.topicArgOptions, i.topic_arg);
        }
        if (i.operator === "==") {
          str += " = ";
        }
        if (i.rule_value === "all*all") {
          str += "全部";
        } else if (i.rule_value === "null*null") {
          str += "空";
        } else {
          str += i.rule_value;
        }
        if (str.length > 0) {
          ruleDesc.push(str);
        }
      });
      // 处理规则列表数据结构
      let ruleList = this.dataList.map((i) => {
        return {
          topic_type: i.topic_type,
          topic_arg: i.topic_arg,
          operator: i.operator,
          operator_type: i.operator_type,
          rule_value: i.rule_value,
        };
      });
      let json = {
        enable: this.taskEditData.enable,
        id: this.taskEditData.id,
        ip_ports: this.taskEditData.serverIp,
        name: this.taskEditData.name,
        rule_text: ruleDesc.join("<br/>"),
        rules: ruleList,
        time_start: this.taskEditData.time[0],
        time_end: this.taskEditData.time[1],
        urls: this.taskEditData.urls,
        is_satisfy_all: this.taskEditData.radioValue === "1",
        link_type: this.taskEditData.lineWay,
        push_set: this.taskEditData.push_set,
      };
      let res = await eventPushsSave(json);
      if (res && res.success) {
        this.taskEditData.eventTxt = ruleDesc.join("<br/>");
        this.$emit("updateList", res.data.id);
        this.$notify({
          type: "success",
          message: "保存成功",
        });
      }
    },
    // 查找字典
    async findByType() {
      let res = await findDictionaryByType();
      if (res && res.success) {
        this.dictionary = Object.assign(this.dictionary, res.data);
        this.baseRule.topicTypeOptions = this.dictionary.EVENTRULETOPIC;
        this.baseRule.operatorTypeOpionts = this.dictionary.EVENTTYPECOMPUTE;
        this.dictionary["alarmLevel"] = this.dictionary.ALARMLEVEL.map((el) => {
          return {
            name: el.name,
            value: el.name,
          };
        });
      }
    },
    async getCameras() {
      let rsp = await findByEventTopic({ topic: "camera", type: "name" });
      if (rsp && rsp.success) {
        this.dictionary["camera"] = rsp.data;
      }
      rsp = await findByEventTopic({ topic: "dbtable" });
      if (rsp && rsp.success) {
        this.dictionary["dbtable"] = rsp.data.map((el) => {
          return {
            name: el.name,
            value: el.name,
          };
        });
      }
    },
    async getTasks() {
      this.dictionary["task"] = [];
      let rsp = await getTaskList();
      if (rsp && rsp.success) {
        let hash = {};
        rsp.data.forEach((task) => {
          if (!task.isDelete && !hash[task.name]) {
            this.dictionary["task"].push({
              value: task.name,
              name: task.name,
            });
            hash[task.name] = true;
          }
        });
      }
    },
    // 新建配置
    createSet() {
      this.dataList.push(JSON.parse(JSON.stringify(this.baseRule)));
    },
    cleanSet() {
      this.dataList.splice(0, this.dataList.length);
    },
    // 添加子规则
    addRule() {
      this.dataList.push(JSON.parse(JSON.stringify(this.baseRule)));
    },
    // 删除子规则
    delRule(index) {
      this.dataList.splice(index, 1);
    },
    // 规则中下拉框的选择回调
    selectTopic(rule, resetNext = false) {
      rule.topicTypeOptions.forEach((element) => {
        if (element.value === rule.topic_type) {
          rule.topicArgOptions = element.children;
          if (resetNext) {
            rule.topic_arg = rule.topicArgOptions[0].value;
            this.selectArg(rule, resetNext);
          }
        }
      });
    },
    selectArg(rule, resetNext = false) {
      debugger;
      let argInfo = rule.topicArgOptions.filter((arg) => {
        return arg.value === rule.topic_arg;
      });
      if (argInfo.length > 0) {
        let desc = argInfo[0].description.split(",");
        if (desc.length > 0) {
          rule.operatorTypeOpionts = this.dictionary.EVENTTYPECOMPUTE.filter(
            (el) => {
              return desc.indexOf(el.value) >= 0;
            }
          );
        }
      }
      if (resetNext) {
        rule.operator_type =
          rule.operatorTypeOpionts[rule.operatorTypeOpionts.length - 1].value;
        this.selectOperator(rule, resetNext);
      }
    },
    selectOperator(rule, resetNext = false) {
      if (rule.operator_type === "option") {
        rule.ruleValueOptions = this.dictionary[rule.topic_type]
          ? this.dictionary[rule.topic_type]
          : [];
        if (rule.rule_value != "") {
          rule.rule_values = rule.rule_value.split(",");
        }
        // 处理 全部/空
        for (let i = 0; i < rule.rule_values.length; i++) {
          if (rule.rule_values[i] === "all*all") {
            rule.rule_values[i] = "全部";
          }
          if (rule.rule_values[i] === "null*null") {
            rule.rule_values[i] = "空";
          }
        }
        console.log("-----------");
        this.setOptionsDisable(rule);
      }
      if (resetNext) {
        rule.rule_value = "";
        rule.rule_values = [];
      }
    },
    selectValue(rule, val) {
      if (rule.operator_type === "option") {
        this.setOptionsDisable(rule);
        if (val.indexOf("全部") >= 0) {
          rule.rule_value = "all*all";
          return;
        }
        if (val.indexOf("空") >= 0) {
          rule.rule_value = "null*null";
          return;
        }
      }
      rule.rule_value = val.join(",");
    },
    setOptionsDisable(rule) {
      let isAllSelect = rule.rule_values.indexOf("全部") >= 0;
      let isNullSelect = rule.rule_values.indexOf("空") >= 0;
      console.log(rule.rule_values);
      rule.ruleValueOptions.forEach((opt) => {
        if (!rule.rule_values.length) {
          opt.disabled = false;
          return;
        }
        if (opt.name === "空") {
          opt.disabled = !isNullSelect;
          return;
        }
        opt.disabled = isAllSelect || isNullSelect;
      });
    },
    // 根据value返回对应的name
    getNameByValue(arr, value) {
      let s = arr.find((item) => {
        return item.value === value;
      });
      return s.name;
    },
    // 清空重新新增
    reAdd() {
      this.taskEditData = {
        id: "",
        name: "",
        time: [
          this.$moment().format("YYYY-MM-DD 00:00:00"),
          this.$moment().format("YYYY-MM-DD HH:mm:ss"),
        ],
        serverIp: [
          {
            enable: true,
            server_ip: "",
            port: 0,
          },
        ],
        urls: [],
        lineWay: "",
        lineOptions: [
          {
            value: "001",
            label: "IP广播",
          },
        ],
        radioValue: "1",
        eventTxt: "",
        push_set: this.pushFields,
      };
      this.dataList = [];
    },
    onCancle() {
      this.$emit("onCancle");
    },
  },
};
</script>
<style lang="scss">
.s-event-push-right {
  text-align: left;
  font-size: 14px;
  i {
    cursor: pointer;
  }
  .s-right-config {
    padding: 10px 40px;
  }
  .el-form-item__label {
    text-align: left;
  }
  .s-right-mid {
    height: 10px;
    background-color: #e9ebf2;
    width: 100%;
    //position: absolute;
  }
  .s-right-rule {
    padding: 20px 40px;
    margin-top: 17px;
    .rule-title {
      border-bottom: 1px solid #e0e0e0;
    }
    .rule-title2 {
      margin-top: 20px;
    }
    .div-border {
      width: 995px;
      padding: 10px;
      margin-top: 15px;
      min-height: 80px;
      background: #fafafa;
      border: 1px solid #f2f2f2;
    }
    .rule-edit-btn {
      font-size: 18px;
      line-height: 38px;
    }
    .save-btn {
      // float: right;
      margin-top: 20px;
      margin-left: 895px;
    }
  }
  .config-item {
    margin: 20px 0;
    b {
      margin-right: 10px;
    }
  }
  .el-button--text {
    text-decoration: unset;
  }
  .icon-btn {
    i {
      font-size: 18px;
      position: relative;
      top: 2px;
    }
    span {
      font-size: 14px;
    }
    display: inline;
    color: #3d68e1;
    line-height: 38px;
    margin-left: 10px;
    cursor: pointer;
  }
  .server-url {
    padding-top: 25px;
  }
  .server-add {
    font-size: 18px;
    margin-left: 8px;
    color: #3d68e1;
    line-height: 39px;
  }
  .dialog-push-field {
    .el-button--primary.is-disabled,
    .el-button--primary.is-disabled:hover {
      background-color: #9eb4f0 !important;
      border-color: #9eb4f0 !important;
    }
    .el-dialog {
      width: 910px;
      height: 700px;
      .el-dialog__body {
        padding-top: 14px;
        height: 540px;
        overflow-y: auto;
      }
    }
    .text-center {
      text-align: center;
    }
    .slot-title {
      position: relative;
      .right {
        position: absolute;
        top: 0;
        right: 30px;
      }
    }
    .check-area {
      padding-bottom: 10px;
      .header {
        position: relative;
        background: #efefef;
        line-height: 30px;
        margin-bottom: 14px;
        font-weight: bold;
        .title {
          border-left: 3px solid #2481fa;
          padding-left: 10px;
        }
        .right {
          position: absolute;
          top: 0;
          right: 30px;
        }
      }
      .flex-box.flex-wrap {
        flex-wrap: wrap;
      }
      .param.flex-box {
        word-break: keep-all;
        align-items: center;
        margin: 0 10px;
        min-width: 260px;
        margin-bottom: 10px;
        .param-name {
          margin: 0 5px;
        }
        .el-input {
          border-color: #dcdfe6;
          color: #606266;
          .el-input__inner {
            color: inherit;
            border-color: inherit;
          }
        }
      }
    }
  }
}
</style>
src/pages/desktop/index/components/Tools.vue
@@ -120,6 +120,7 @@
      :visible.sync="showPasswdForm"
      :append-to-body="true"
      width="500px"
      @close="cancelPasswordChange"
    >
      <el-form
        :model="passwdForm"
@@ -153,7 +154,7 @@
        </el-form-item>
      </el-form>
      <div slot="footer" class="dialog-footer">
        <el-button type="info" @click="showPasswdForm = false" size="small"
        <el-button type="info" size="small" @click="cancelPasswordChange"
          >取 消</el-button
        >
        <el-button type="primary" @click="submitForm('ruleForm')" size="small"
@@ -343,7 +344,7 @@
  },
  mounted() {
    document.addEventListener("click", (e) => {
      if (this.showFastPath||this.showWifi) {
      if (this.showFastPath || this.showWifi) {
        this.showFastPath = false;
        this.showWifi = false;
      }
@@ -384,10 +385,7 @@
      );
    },
    updateSysNow() {
      window.parent.postMessage(
        { msg: `toVindicate?autoUpdate=1` },
        "*"
      );
      window.parent.postMessage({ msg: `toVindicate?autoUpdate=1` }, "*");
    },
    delaySysRemind(sec) {
      delayUpgradeNotice({
@@ -436,7 +434,12 @@
      });
    },
    toggleShowWifi() {
      this.notificationCenterVisible = false;
      this.showWifi = !this.showWifi;
      this.$store.commit(
        "desktop/changeNotificationCenterVisible",
        this.notificationCenterVisible
      );
    },
    submitForm(formName) {
      this.$refs[formName].validate((valid) => {
@@ -445,15 +448,22 @@
            oldPwd: this.passwdForm.oldPwd,
            newPwd: this.passwdForm.checkPwd,
          };
          updatePwd(json).then((res) => {
            this.$notify({
              type: res.success ? "success" : "error",
              message: res.msg,
          updatePwd(json)
            .then((res) => {
              this.$notify({
                type: res.success ? "success" : "error",
                message: res.msg,
              });
              if (res.success) {
                this.cancelPasswordChange();
              }
            })
            .catch((err) => {
              this.$notify({
                type: "error",
                message: err.msg,
              });
            });
            if (res.success) {
              this.showPasswdForm = false;
            }
          });
        } else {
          console.log("error submit!!");
          return false;
@@ -537,6 +547,14 @@
          console.log("退出失败");
        });
    },
    cancelPasswordChange() {
      this.showPasswdForm = false;
      this.passwdForm = {
        oldPwd: "",
        newPwd: "",
        checkPwd: "",
      };
    },
  },
};
</script>
src/pages/settings/views/clusterManagement.vue
@@ -2,7 +2,7 @@
  <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>
@@ -205,18 +205,6 @@
              </el-input>
            </el-form-item>
          </el-form>
          <div class="clu-list">
            <!-- :class="pickedNodeI == index ? 'clu-item-active' : ''" -->
            <div
              class="clu-item"
              v-for="(item, index) in members"
              :key="index"
              @click="pickNode(index)"
            >
              <i class="iconfont">&#xe727;</i>
              {{ item.Address }}
            </div>
          </div>
          <div class="btns">
            <div class="ok" @click="join('joinForm')">加入集群</div>
          </div>
@@ -238,7 +226,7 @@
  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";
@@ -246,15 +234,15 @@
export default {
  data() {
    const checkPwd = (rule, value, callback) => {
      if (value=="") {
      if (value == "") {
        return callback(new Error("密码不能为空"));
      }
      // setTimeout(() => {
        if (value.length != 6) {
          callback(new Error("密码应为6位!"));
        } else {
          callback();
        }
      if (value.length != 6) {
        callback(new Error("密码应为6位!"));
      } else {
        callback();
      }
      // }, 1000);
    };
    const checkID = (rule, value, callback) => {
@@ -303,18 +291,18 @@
        clustername: [
          { required: true, message: "请输入集群名称", trigger: "blur" },
        ],
        clusterpwd: [{ validator: checkPwd, required: true,trigger: "blur" }],
        clusterpwd: [{ validator: checkPwd, required: true, trigger: "blur" }],
        virtualIp: [{ required: true, validator: isIPv4, trigger: "change" }],
      },
      joinExistRules: {
        clusterid: [{ validator: checkID, trigger: "blur" }],
        clusterip: [{ validator: isIPv4, trigger: "blur" }],
        clusterpwd: [{ validator: checkPwd, required: true,trigger: "blur" }],
        clusterpwd: [{ validator: checkPwd, required: true, trigger: "blur" }],
      },
    };
  },
  components: {
    // cloudNode,
    cloudNode,
    NetNode,
    ipInput,
  },
@@ -424,9 +412,12 @@
      });
    },
    join(formName) {
      debugger;
      let _this = this;
      this.$refs[formName].validate((valid) => {
        debugger;
        if (valid) {
          debugger;
          _this.joinLoading = true;
          let data = {
            clusterId: _this.joinForm.clusterid,
@@ -903,7 +894,7 @@
      left: 20px;
    }
    .el-form-item {
          margin-bottom: 16px;
      margin-bottom: 10px;
      .el-input__inner {
        background-color: #ffffff;
        border: 2px solid transparent;