zhangzengfei
2022-08-06 e018e23189eb9520f6f28ae515b17333351267ff
完善推送管理功能
1个文件已添加
6个文件已修改
1019 ■■■■ 已修改文件
src/api/event.ts 58 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/report.ts 57 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/giantTree/zTree/ztree.vue 429 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/report/components/DevList.vue 153 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/report/components/FormArea.vue 301 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/report/components/SettingBox.vue 17 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/report/index.vue 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/event.ts
@@ -1,18 +1,5 @@
import request from "@/scripts/httpRequest";
import qs from "qs";
/**
 * 事件推送保存
 */
export const eventPushsSave = (query: any) => {
  return request({
    url: "/data/api-v/eventPush/save",
    method: "post",
    data: query
  });
};
import request from "@/scripts/httpRequest"
import qs from "qs"
/**
 * 根据事件推送主题的一级和二级选项获取最后下拉菜单列表
 */
@@ -21,19 +8,8 @@
    url: "/data/api-v/eventPush/findByEventTopic",
    method: "get",
    params: query
  });
};
/**
 * 查询事件列表
 */
export const findAll = (query: any) => {
  return request({
    url: "/data/api-v/eventPush/findAll",
    method: "get",
    params: query
  });
};
  })
}
/**
 * 改变enable状态
@@ -43,9 +19,8 @@
    url: "/data/api-v/eventPush/changeStatus",
    method: "post",
    data: query
  });
};
  })
}
/**
 * 根据事件id获取事件详情
@@ -55,8 +30,8 @@
    url: "/data/api-v/eventPush/getById",
    method: "get",
    params: query
  });
};
  })
}
/**
 * 根据id删除
@@ -66,18 +41,16 @@
    url: "/data/api-v/eventPush/delete",
    method: "post",
    data: qs.stringify(query)
  });
};
  })
}
//获取事件声音列表
export const getSoundList = () => {
  return request({
    url: "/saas/api-s/voice/findAll",
    method: "get"
  })
}
export const uploadSound = (data: any) => {
  return request({
@@ -87,19 +60,18 @@
  })
}
//获取所有的推送字段配置
export const getPushSet = ()=>{
export const getPushSet = () => {
  return request({
    url:'/data/api-v/eventPush/getPushSet',
    method:'get'
    url: "/data/api-v/eventPush/getPushSet",
    method: "get"
  })
}
export const deleteSound = (q:any) => {
export const deleteSound = (q: any) => {
  return request({
    url: "/data/api-v/voice/del",
    method: "get",
    params:q
    params: q
  })
}
src/api/report.ts
New file
@@ -0,0 +1,57 @@
import request from "@/scripts/httpRequest"
import qs from "qs"
/**
 * 查询任务列表
 */
export const findAllTask = (query: any) => {
  return request({
    url: "/api-a/v1/task/list",
    method: "get",
    params: query
  })
}
/**
 * 事件推送新增
 */
export const createTask = (query: any) => {
  return request({
    url: "/api-a/v1/task/create",
    method: "post",
    data: query
  })
}
/**
 * 事件推送修改
 */
export const updateTask = (query: any) => {
  return request({
    url: "/api-a/v1/task/update",
    method: "post",
    data: query
  })
}
/**
 * 事件推送修改
 */
export const deleteTask = (query: any) => {
  return request({
    url: "/api-a/v1/task/delete",
    method: "get",
    params: query
  })
}
/**
 * 推送历史查询
 */
export const findTaskLogs = (query: any) => {
  return request({
    url: "/api-a/v1/log/list",
    method: "get",
    params: query
  })
}
src/components/giantTree/zTree/ztree.vue
@@ -1,17 +1,8 @@
<template>
  <div>
    <div class="searchTree">
      <el-input
        placeholder="搜索"
        v-model="keyWord"
        size="mini"
        v-show="search"
      >
        <i
          slot="suffix"
          class="el-input__icon el-icon-search"
          :id="searchBtnId"
        ></i>
      <el-input placeholder="搜索" v-model="keyWord" size="mini" v-show="search">
        <i slot="suffix" class="el-input__icon el-icon-search" :id="searchBtnId"></i>
      </el-input>
    </div>
    <div class="ztree" :id="ztreeId"></div>
@@ -19,16 +10,16 @@
</template>
<script>
import * as $ from "jquery";
import { Loading } from "element-ui";
import * as $ from "jquery"
import { Loading } from "element-ui"
if (!window.jQuery) {
  window.jQuery = $;
  window.jQuery = $
}
// require("@ztree/ztree_v3/js/jquery.ztree.all");
require("./ztree_v3/jquery.ztree.all");
require("./ztree_v3/jquery.ztree.exhide");
require("./ztree_v3/jquery.ztree.all")
require("./ztree_v3/jquery.ztree.exhide")
export default {
  props: {
@@ -39,17 +30,17 @@
    setting: {
      type: Object,
      require: false,
      default: function () {
        return {};
      },
      default: function() {
        return {}
      }
    },
    nodes: {
      type: Array,
      require: true,
      default: function () {
        return [];
      },
    },
      default: function() {
        return []
      }
    }
  },
  data() {
    return {
@@ -63,120 +54,120 @@
          showLine: true,
          showIcon: true, // default to hide icon
          addHoverDom: this.addHoverDom,
          removeHoverDom: this.removeHoverDom,
          removeHoverDom: this.removeHoverDom
        },
        check: {
          chkboxType: { Y: "", N: "" },
          enable: this.showCheckbox,
          chkboxType: { Y: "ps", N: "ps" },
          enable: this.showCheckbox
        },
        callback: {
          onAsyncError: (...arg) => {
            this.$emit("onAsyncError", ...arg);
            this.$emit("onAsyncError", ...arg)
          },
          onAsyncSuccess: (...arg) => {
            this.$emit("onAsyncSuccess", ...arg);
            this.$emit("onAsyncSuccess", ...arg)
          },
          onCheck: (...arg) => {
            this.$emit("onCheck", ...arg);
            this.$emit("onCheck", ...arg)
          },
          onClick: (...arg) => {
            this.$emit("onClick", ...arg);
            this.removeHoverIcon(...arg);
            this.$emit("onClick", ...arg)
            this.removeHoverIcon(...arg)
          },
          onCollapse: (...arg) => {
            this.$emit("onCollapse", ...arg);
            this.$emit("onCollapse", ...arg)
          },
          onDblClick: (...arg) => {
            this.$emit("onDblClick", ...arg);
            this.$emit("onDblClick", ...arg)
          },
          onDrag: (...arg) => {
            this.$emit("onDrag", ...arg);
            this.$emit("onDrag", ...arg)
          },
          onDragMove: (...arg) => {
            this.$emit("onDragMove", ...arg);
            this.$emit("onDragMove", ...arg)
          },
          onDrop: (...arg) => {
            this.$emit("onDrop", ...arg);
            this.$emit("onDrop", ...arg)
          },
          onExpand: (...arg) => {
            this.$emit("onExpand", ...arg);
            this.$emit("onExpand", ...arg)
          },
          onMouseDown: (...arg) => {
            this.$emit("onMouseDown", ...arg);
            this.$emit("onMouseDown", ...arg)
          },
          onMouseUp: (...arg) => {
            this.$emit("onMouseUp", ...arg);
            this.$emit("onMouseUp", ...arg)
          },
          onRemove: (...arg) => {
            this.$emit("onRemove", ...arg);
            this.$emit("onRemove", ...arg)
          },
          onRename: (...arg) => {
            this.$emit("onRename", ...arg);
            this.$emit("onRename", ...arg)
          },
          onRightClick: (...arg) => {
            this.$emit("onRightClick", ...arg);
          },
        },
            this.$emit("onRightClick", ...arg)
          }
        }
      },
      keyWord: "",
      options: {
        target: "",
      },
    };
        target: ""
      }
    }
  },
  watch: {
    nodes: {
      handler: function (nodes) {
        this.list = nodes;
      handler: function(nodes) {
        this.list = nodes
        // update tree
        if (this.ztreeObj) {
          this.ztreeObj.destroy();
          this.ztreeObj.destroy()
        }
        this.$nextTick(() => {
          this.ztreeObj = $.fn.zTree.init(
            $("#" + this.ztreeId),
            Object.assign({}, this.ztreeSetting, this.setting),
            this.list
          );
          this.fuzzySearch(this.ztreeObj, this.searchBtnId, false, true); //初始化模糊搜索方法
          this.$emit("onCreated", this.ztreeObj);
        });
          )
          this.fuzzySearch(this.ztreeObj, this.searchBtnId, false, true) //初始化模糊搜索方法
          this.$emit("onCreated", this.ztreeObj)
        })
      },
      deep: true,
      immediate: true,
      immediate: true
    },
    showCheckbox: {
      handler: function () {
      handler: function() {
        let top = $("#" + this.ztreeId)
          .parent()
          .scrollTop();
          .scrollTop()
        this.ztreeSetting.check.enable = this.showCheckbox;
        this.ztreeSetting.check.enable = this.showCheckbox
        if (this.ztreeObj) {
          this.list = this.ztreeObj.getNodes();
          this.ztreeObj.destroy();
          this.list = this.ztreeObj.getNodes()
          this.ztreeObj.destroy()
        }
        this.$nextTick(() => {
          this.ztreeObj = $.fn.zTree.init(
            $("#" + this.ztreeId),
            Object.assign({}, this.ztreeSetting, this.setting),
            this.list
          );
          )
          $("#" + this.ztreeId)
            .parent()
            .scrollTop(top);
          this.$emit("onCreated", this.ztreeObj);
        });
            .scrollTop(top)
          this.$emit("onCreated", this.ztreeObj)
        })
      },
      immediate: true,
    },
      immediate: true
    }
  },
  methods: {
    addHoverDom(treeid, treeNode) {
      let _vue = this;
      const item = document.getElementById(`${treeNode.tId}_a`);
      let _vue = this
      const item = document.getElementById(`${treeNode.tId}_a`)
      // 文件夹新增按钮
      if (
@@ -186,18 +177,18 @@
        !this.readonly &&
        !this.gb28181
      ) {
        const btn = document.createElement("i");
        btn.id = `${treeid}_${treeNode.id}_btn`;
        btn.classList.add("el-icon-circle-plus-outline");
        btn.classList.add("primary");
        const btn = document.createElement("i")
        btn.id = `${treeid}_${treeNode.id}_btn`
        btn.classList.add("el-icon-circle-plus-outline")
        btn.classList.add("primary")
        // btn.innerText = '删除';
        btn.addEventListener("click", (e) => {
          e.stopPropagation();
          e.stopPropagation()
          // this.clickRemove(treeNode)
          _vue.$emit("onAddNode", treeNode);
        });
          _vue.$emit("onAddNode", treeNode)
        })
        item.appendChild(btn);
        item.appendChild(btn)
      }
      // 文件夹删除按钮
@@ -209,223 +200,194 @@
        !treeNode.children &&
        !this.gb28181
      ) {
        const btn = document.createElement("i");
        btn.id = `${treeid}_${treeNode.id}_btn`;
        btn.classList.add("el-icon-remove-outline");
        btn.classList.add("danger");
        const btn = document.createElement("i")
        btn.id = `${treeid}_${treeNode.id}_btn`
        btn.classList.add("el-icon-remove-outline")
        btn.classList.add("danger")
        // btn.innerText = '删除';
        btn.addEventListener("click", (e) => {
          e.stopPropagation();
          e.stopPropagation()
          // this.clickRemove(treeNode)
          _vue.$emit("onRemoveNode", treeNode);
        });
          _vue.$emit("onRemoveNode", treeNode)
        })
        item.appendChild(btn);
        item.appendChild(btn)
      }
      // 文件夹编辑按钮
      if (
        item &&
        !item.querySelector(".el-icon-edit") &&
        treeNode.isParent &&
        !this.readonly
      ) {
        const btn = document.createElement("i");
        btn.id = `${treeid}_${treeNode.id}_btn`;
        btn.classList.add("el-icon-edit");
        btn.classList.add("primary");
      if (item && !item.querySelector(".el-icon-edit") && treeNode.isParent && !this.readonly) {
        const btn = document.createElement("i")
        btn.id = `${treeid}_${treeNode.id}_btn`
        btn.classList.add("el-icon-edit")
        btn.classList.add("primary")
        // btn.innerText = '删除';
        btn.addEventListener("click", (e) => {
          e.stopPropagation();
          e.stopPropagation()
          // this.clickRemove(treeNode)
          _vue.$emit("onRenameNode", treeNode);
        });
          _vue.$emit("onRenameNode", treeNode)
        })
        item.appendChild(btn);
        item.appendChild(btn)
      }
      // 添加摄像机按钮
      if (
        item &&
        !item.querySelector(".iconshishishipin") &&
        treeNode.isParent &&
        !this.readonly &&
        !this.gb28181
      ) {
        const btn = document.createElement("i");
        btn.id = `${treeid}_${treeNode.id}_btn`;
        btn.classList.add("iconfont");
        btn.classList.add("iconshishishipin");
        btn.classList.add("primary");
        btn.classList.add("icon-fix");
      if (item && !item.querySelector(".iconshishishipin") && treeNode.isParent && !this.readonly && !this.gb28181) {
        const btn = document.createElement("i")
        btn.id = `${treeid}_${treeNode.id}_btn`
        btn.classList.add("iconfont")
        btn.classList.add("iconshishishipin")
        btn.classList.add("primary")
        btn.classList.add("icon-fix")
        // btn.innerText = '删除';
        btn.addEventListener("click", (e) => {
          e.stopPropagation();
          e.stopPropagation()
          // this.clickRemove(treeNode)
          _vue.$emit("onAddDevice", treeNode.id);
        });
        btn.innerHTML = "&#xe642;";
          _vue.$emit("onAddDevice", treeNode.id)
        })
        btn.innerHTML = "&#xe642;"
        item.appendChild(btn);
        item.appendChild(btn)
      }
      // 导入摄像机按钮
      if (
        item &&
        !item.querySelector(".icondaoru") &&
        treeNode.isParent &&
        !this.readonly &&
        !this.gb28181
      ) {
        const btn = document.createElement("i");
        btn.id = `${treeid}_${treeNode.id}_btn`;
        btn.classList.add("iconfont");
        btn.classList.add("icondaoru");
        btn.classList.add("primary");
        btn.classList.add("icon-fix");
      if (item && !item.querySelector(".icondaoru") && treeNode.isParent && !this.readonly && !this.gb28181) {
        const btn = document.createElement("i")
        btn.id = `${treeid}_${treeNode.id}_btn`
        btn.classList.add("iconfont")
        btn.classList.add("icondaoru")
        btn.classList.add("primary")
        btn.classList.add("icon-fix")
        // btn.innerText = '删除';
        btn.addEventListener("click", (e) => {
          e.stopPropagation();
          e.stopPropagation()
          // this.clickRemove(treeNode)
          _vue.$emit("onImport", treeNode.id);
        });
        btn.innerHTML = "&#xe643;";
          _vue.$emit("onImport", treeNode.id)
        })
        btn.innerHTML = "&#xe643;"
        item.appendChild(btn);
        item.appendChild(btn)
      }
      // 查看底图按钮
      if (
        item &&
        !item.querySelector(".el-icon-picture") &&
        treeNode.type == "camera"
      ) {
        const btn = document.createElement("i");
        btn.id = `${treeid}_${treeNode.id}_btn`;
        btn.classList.add("iconfont");
        btn.classList.add("el-icon-picture");
        btn.classList.add("primary");
        btn.classList.add("icon-fix");
      if (item && !item.querySelector(".el-icon-picture") && treeNode.type == "camera") {
        const btn = document.createElement("i")
        btn.id = `${treeid}_${treeNode.id}_btn`
        btn.classList.add("iconfont")
        btn.classList.add("el-icon-picture")
        btn.classList.add("primary")
        btn.classList.add("icon-fix")
        // btn.innerText = '删除';
        btn.addEventListener("click", (e) => {
          e.stopPropagation();
          e.stopPropagation()
          // this.clickRemove(treeNode)
          _vue.$emit("onShowPic", treeNode);
        });
          _vue.$emit("onShowPic", treeNode)
        })
        item.appendChild(btn);
        item.appendChild(btn)
      }
    },
    removeHoverIcon(evt, treeId, item) {
      this.removeHoverDom(treeId, item);
      this.removeHoverDom(treeId, item)
    },
    removeHoverDom(treeid, treeNode) {
      const item = document.getElementById(`${treeNode.tId}_a`);
      const item = document.getElementById(`${treeNode.tId}_a`)
      if (item) {
        let btn = item.querySelector(".el-icon-circle-plus-outline");
        let btn = item.querySelector(".el-icon-circle-plus-outline")
        if (btn) {
          item.removeChild(item.querySelector(".el-icon-circle-plus-outline"));
          item.removeChild(item.querySelector(".el-icon-circle-plus-outline"))
        }
        btn = item.querySelector(".el-icon-remove-outline");
        btn = item.querySelector(".el-icon-remove-outline")
        if (btn) {
          item.removeChild(item.querySelector(".el-icon-remove-outline"));
          item.removeChild(item.querySelector(".el-icon-remove-outline"))
        }
        btn = item.querySelector(".el-icon-edit");
        btn = item.querySelector(".el-icon-edit")
        if (btn) {
          item.removeChild(item.querySelector(".el-icon-edit"));
          item.removeChild(item.querySelector(".el-icon-edit"))
        }
        btn = item.querySelector(".iconshishishipin");
        btn = item.querySelector(".iconshishishipin")
        if (btn) {
          item.removeChild(item.querySelector(".iconshishishipin"));
          item.removeChild(item.querySelector(".iconshishishipin"))
        }
        btn = item.querySelector(".icondaoru");
        btn = item.querySelector(".icondaoru")
        if (btn) {
          item.removeChild(item.querySelector(".icondaoru"));
          item.removeChild(item.querySelector(".icondaoru"))
        }
        btn = item.querySelector(".el-icon-picture");
        btn = item.querySelector(".el-icon-picture")
        if (btn) {
          item.removeChild(item.querySelector(".el-icon-picture"));
          item.removeChild(item.querySelector(".el-icon-picture"))
        }
      }
    },
    fuzzySearch(zTreeObj, searchField, isHighLight, isExpand) {
      const _this = this;
      const _this = this
      if (!zTreeObj) {
        alert("fail to get ztree object");
        alert("fail to get ztree object")
      }
      var nameKey = zTreeObj.setting.data.key.name; //get the key of the node name
      isHighLight = isHighLight === false ? false : true; //default true, only use false to disable highlight
      isExpand = isExpand ? true : false; // not to expand in default
      zTreeObj.setting.view.nameIsHTML = isHighLight; //allow use html in node name for highlight use
      var nameKey = zTreeObj.setting.data.key.name //get the key of the node name
      isHighLight = isHighLight === false ? false : true //default true, only use false to disable highlight
      isExpand = isExpand ? true : false // not to expand in default
      zTreeObj.setting.view.nameIsHTML = isHighLight //allow use html in node name for highlight use
      var metaChar = "[\\[\\]\\\\^\\$\\.\\|\\?\\*\\+\\(\\)]"; //js meta characters
      var rexMeta = new RegExp(metaChar, "gi"); //regular expression to match meta characters
      var metaChar = "[\\[\\]\\\\^\\$\\.\\|\\?\\*\\+\\(\\)]" //js meta characters
      var rexMeta = new RegExp(metaChar, "gi") //regular expression to match meta characters
      // keywords filter function
      function ztreeFilter(zTreeObj, _keywords, callBackFunc) {
        if (!_keywords) {
          _keywords = ""; //default blank for _keywords
          _keywords = "" //default blank for _keywords
        }
        // function to find the matching node
        function filterFunc(node) {
          if (node && node.oldname && node.oldname.length > 0) {
            node[nameKey] = node.oldname; //recover oldname of the node if exist
            node[nameKey] = node.oldname //recover oldname of the node if exist
          }
          zTreeObj.updateNode(node); //update node to for modifications take effect
          zTreeObj.updateNode(node) //update node to for modifications take effect
          if (_keywords.length == 0) {
            //return true to show all nodes if the keyword is blank
            zTreeObj.showNode(node);
            zTreeObj.expandNode(node, isExpand);
            return true;
            zTreeObj.showNode(node)
            zTreeObj.expandNode(node, isExpand)
            return true
          }
          //transform node name and keywords to lowercase
          if (
            node[nameKey] &&
            node[nameKey].toLowerCase().indexOf(_keywords.toLowerCase()) != -1
          ) {
          if (node[nameKey] && node[nameKey].toLowerCase().indexOf(_keywords.toLowerCase()) != -1) {
            if (isHighLight) {
              //highlight process
              //a new variable 'newKeywords' created to store the keywords information
              //keep the parameter '_keywords' as initial and it will be used in next node
              //process the meta characters in _keywords thus the RegExp can be correctly used in str.replace
              var newKeywords = _keywords.replace(rexMeta, function (matchStr) {
              var newKeywords = _keywords.replace(rexMeta, function(matchStr) {
                //add escape character before meta characters
                return "\\" + matchStr;
              });
              node.oldname = node[nameKey]; //store the old name
              var rexGlobal = new RegExp(newKeywords, "gi"); //'g' for global,'i' for ignore case
                return "\\" + matchStr
              })
              node.oldname = node[nameKey] //store the old name
              var rexGlobal = new RegExp(newKeywords, "gi") //'g' for global,'i' for ignore case
              //use replace(RegExp,replacement) since replace(/substr/g,replacement) cannot be used here
              node[nameKey] = node.oldname.replace(
                rexGlobal,
                function (originalText) {
                  //highlight the matching words in node name
                  var highLightText =
                    '<span style="color: whitesmoke;background-color: darkred;">' +
                    originalText +
                    "</span>";
                  return highLightText;
                }
              );
              zTreeObj.updateNode(node); //update node for modifications take effect
              node[nameKey] = node.oldname.replace(rexGlobal, function(originalText) {
                //highlight the matching words in node name
                var highLightText =
                  '<span style="color: whitesmoke;background-color: darkred;">' + originalText + "</span>"
                return highLightText
              })
              zTreeObj.updateNode(node) //update node for modifications take effect
            }
            zTreeObj.showNode(node); //show node with matching keywords
            return true; //return true and show this node
            zTreeObj.showNode(node) //show node with matching keywords
            return true //return true and show this node
          }
          zTreeObj.hideNode(node); // hide node that not matched
          return false; //return false for node not matched
          zTreeObj.hideNode(node) // hide node that not matched
          return false //return false for node not matched
        }
        var nodesShow = zTreeObj.getNodesByFilter(filterFunc); //get all nodes that would be shown
        processShowNodes(nodesShow, _keywords); //nodes should be reprocessed to show correctly
        _this.$emit("onAfterSearch", null);
        var nodesShow = zTreeObj.getNodesByFilter(filterFunc) //get all nodes that would be shown
        processShowNodes(nodesShow, _keywords) //nodes should be reprocessed to show correctly
        _this.$emit("onAfterSearch", null)
      }
      /**
@@ -435,61 +397,61 @@
        if (nodesShow && nodesShow.length > 0) {
          //process the ancient nodes if _keywords is not blank
          if (_keywords.length > 0) {
            $.each(nodesShow, function (n, obj) {
              var pathOfOne = obj.getPath(); //get all the ancient nodes including current node
            $.each(nodesShow, function(n, obj) {
              var pathOfOne = obj.getPath() //get all the ancient nodes including current node
              if (pathOfOne && pathOfOne.length > 0) {
                //i < pathOfOne.length-1 process every node in path except self
                for (var i = 0; i < pathOfOne.length - 1; i++) {
                  zTreeObj.showNode(pathOfOne[i]); //show node
                  zTreeObj.expandNode(pathOfOne[i], true); //expand node
                  zTreeObj.showNode(pathOfOne[i]) //show node
                  zTreeObj.expandNode(pathOfOne[i], true) //expand node
                }
              }
            });
            })
          } else {
            //show all nodes when _keywords is blank and expand the root nodes
            var rootNodes = zTreeObj.getNodesByParam("level", "0"); //get all root nodes
            $.each(rootNodes, function (n, obj) {
              zTreeObj.expandNode(obj, true); //expand all root nodes
            });
            var rootNodes = zTreeObj.getNodesByParam("level", "0") //get all root nodes
            $.each(rootNodes, function(n, obj) {
              zTreeObj.expandNode(obj, true) //expand all root nodes
            })
          }
        }
      }
      //listen to change in input element
      $("#" + searchField).bind("click", function () {
      $("#" + searchField).bind("click", function() {
        // _this.options.target = document.querySelector("#" + _this.ztreeId).parentNode.parentNode
        // console.log(_this.options.target);
        // let loadingInstance = Loading.service(_this.options)
        // console.log(_this.keyWord);
        // var _keywords = $(this).val();
        $("#" + searchField).removeClass("el-icon-search");
        $("#" + searchField).addClass("el-icon-loading");
        searchNodeLazy(_this.keyWord); //call lazy load
        $("#" + searchField).removeClass("el-icon-search")
        $("#" + searchField).addClass("el-icon-loading")
        searchNodeLazy(_this.keyWord) //call lazy load
        // loadingInstance.close()
        setTimeout(() => {
          $("#" + searchField).removeClass("el-icon-loading");
          $("#" + searchField).addClass("el-icon-search");
        }, 300);
      });
          $("#" + searchField).removeClass("el-icon-loading")
          $("#" + searchField).addClass("el-icon-search")
        }, 300)
      })
      var lastKeyword = "";
      var lastKeyword = ""
      // excute lazy load once after input change, the last pending task will be cancled
      function searchNodeLazy(_keywords) {
        if (lastKeyword === _keywords) {
          return;
          return
        }
        ztreeFilter(zTreeObj, _keywords); //lazy load ztreeFilter function
        ztreeFilter(zTreeObj, _keywords) //lazy load ztreeFilter function
        // $(searchField).focus();//focus input field again after filtering
        lastKeyword = _keywords;
        lastKeyword = _keywords
      }
    },
    handleSearch() {
      this.loading = true;
      searchNodeLazy(this.keyWord); //call lazy load
      this.loading = false;
    },
  },
};
      this.loading = true
      searchNodeLazy(this.keyWord) //call lazy load
      this.loading = false
    }
  }
}
</script>
<style lang="scss">
@@ -593,8 +555,7 @@
}
.ztree li ul.line {
  /* background: url(/images/line_conn.gif) 0 0 repeat-y; */
  background: url(data:image/gif;base64,R0lGODlhCQACAIAAAMzMzP///yH5BAEAAAEALAAAAAAJAAIAAAIEjI9pUAA7)
    0 0 repeat-y;
  background: url(data:image/gif;base64,R0lGODlhCQACAIAAAMzMzP///yH5BAEAAAEALAAAAAAJAAIAAAIEjI9pUAA7) 0 0 repeat-y;
}
.ztree li a {
src/views/report/components/DevList.vue
@@ -1,21 +1,34 @@
<template>
  <div class="event-list">
    <div class="title">告警推送配置</div>
    <div class="empty" v-if="eventList.length === 0">
    <div class="title">
      <span>告警推送配置</span>
      <i
        class="el-icon-circle-plus-outline"
        style="cursor: pointer;margin-left:15px"
        v-show="taskList.length > 0"
        @click="handleAdd"
      ></i>
    </div>
    <div class="empty" v-show="taskList.length == 0">
      <img src="/images/search/1.png" alt="" />
      <div class="des">您还未添加添加告警事件推送任务</div>
      <div class="button add" @click="showSettingBox = true">
      <div class="button add" @click="handleAdd">
        立即添加
      </div>
    </div>
    <div class="list scroll">
      <el-table :data="eventList" style="width: 100%">
        <el-table-column label="序号" width="180"> </el-table-column>
        <el-table-column label="事件名称" width="180"> </el-table-column>
        <el-table-column label="事件等级" width="180"> </el-table-column>
        <el-table-column label="关联区域" width="180"> </el-table-column>
        <el-table-column label="责任人" width="180"> </el-table-column>
        <el-table-column label="推送方式" width="180"> </el-table-column>
      <el-table :data="taskList" style="width: 100%">
        <el-table-column label="序号" type="index" width="50"> </el-table-column>
        <el-table-column label="事件名称" width="180" prop="taskName"> </el-table-column>
        <el-table-column label="事件等级" width="120" prop="level"> </el-table-column>
        <el-table-column label="关联区域" prop="org"> </el-table-column>
        <el-table-column label="责任人" width="180" prop="person"> </el-table-column>
        <el-table-column label="手机号" width="180" prop="tel"> </el-table-column>
        <el-table-column label="状态" width="100" prop="enable">
          <template slot-scope="scope">
            <el-switch v-model="scope.row.enable" active-color="#13ce66" inactive-color="#bbbbbb"> </el-switch>
          </template>
        </el-table-column>
        <el-table-column label="操作">
          <template slot-scope="scope">
            <el-button size="mini" @click="handleEdit(scope.$index, scope.row)">编辑</el-button>
@@ -23,77 +36,101 @@
          </template>
        </el-table-column>
      </el-table>
      <!-- <div class="devItem" v-for="(item, index) in clusterList" :key="index">
        <div class="mainInfo">
          <img src="/images/hashrate/cluster.png" alt="" />
          <div class="right">
            <div class="name">{{ item.cluster_name }}</div>
            <div class="ip">{{ item.virtual_ip }}</div>
            <div class="number">设备总量:{{ item.nodeNum }}</div>
          </div>
          <div class="button set" @click="setting({ clusterId: item.cluster_id }, item.nodeList)">
            配置
          </div>
        </div>
      </div>
      <div class="devItem" v-for="(item, index) in devList" :key="index + 'dev'">
        <div class="mainInfo">
          <img src="/images/hashrate/equipment.png" alt="" />
          <div class="right">
            <div class="name">{{ item.devName }}</div>
            <div class="ip">{{ item.devIp }}</div>
          </div>
          <div class="button set" @click="setting({ devId: item.devId })">
            配置
          </div>
        </div>
      </div> -->
    </div>
    <SettingBox v-if="showSettingBox" @close="showSettingBox = false" :id="idObj" :nodeList="nodeList"></SettingBox>
    <SettingBox
      v-if="showSettingBox"
      @close="handleClose"
      :id="idObj"
      :node-list="editNode"
      :camera="cameraTree"
      :menu="menuTree"
    ></SettingBox>
  </div>
</template>
<script>
import SettingBox from "@/views/report/components/SettingBox"
import { getClusterDevList } from "@/api/clusterManage"
import { findAllTask, deleteTask } from "@/api/report"
import { getLocalCameraTree } from "@/api/area"
export default {
  components: {
    SettingBox
  },
  created() {
    this.getClusterDevList()
  },
  data() {
    return {
      eventList: [],
      clusterList: [],
      devList: [],
      taskList: [],
      showSettingBox: false,
      idObj: {},
      nodeList: []
      editNode: {},
      cameraTree: [],
      menuTree: []
    }
  },
  mounted() {
    this.getCameras()
    this.getTaskList()
  },
  methods: {
    async getClusterDevList() {
      const res = await getClusterDevList()
      if (res && res.success) {
        this.clusterList = res.data.clusterList
        this.devList = res.data.devList
    async getCameras() {
      let clusterId = ""
      let clusterReq = await getClusterDevList()
      if (clusterReq && clusterReq.success) {
        if (clusterReq.data.clusterList.length > 0) {
          clusterId = clusterReq.data.clusterList[0].cluster_id
        }
      }
      let camereReq = await getLocalCameraTree({ clusterId: clusterId })
      if (camereReq && camereReq.success) {
        this.cameraTree = camereReq.data.treeMenu
        let tmpTree = JSON.parse(JSON.stringify(camereReq.data.treeMenu))
        for (let i = 0; i < tmpTree.length; i++) this.clearNode(tmpTree[i])
        this.menuTree = tmpTree
      }
    },
    setting(id, nodeList) {
      this.idObj = id
      this.nodeList = nodeList ? nodeList : []
    clearNode(tree) {
      if (tree.children) {
        tree.children = tree.children.filter((item) => {
          return item.type == "MENU"
        })
      }
      if (tree.children && tree.children.length > 0) {
        for (let i = 0; i < tree.children.length; i++) this.clearNode(tree.children[i])
      } else {
        delete tree.children
      }
    },
    getTaskList() {
      findAllTask().then((rsp) => {
        if (rsp && rsp.success) {
          this.taskList = rsp.data
        }
      })
    },
    handleAdd() {
      this.idObj = ""
      this.editNode = {}
      this.showSettingBox = true
    },
    handleEdit(idx, row) {},
    handleDelete(idx, row) {}
    handleClose() {
      this.showSettingBox = false
      this.getTaskList()
    },
    handleEdit(idx, row) {
      console.log("edit", row)
      this.idObj = row.id
      this.editNode = row
      this.showSettingBox = true
    },
    handleDelete(idx, row) {
      deleteTask({ id: row.id }).then((rsp) => {
        if (rsp && rsp.success) {
          this.getTaskList()
        }
      })
    }
  }
}
</script>
@@ -104,7 +141,7 @@
  box-sizing: border-box;
  padding: 20px;
  width: 1280px;
  height: 770px;
  height: 100%;
  background-color: #fff;
  margin: 0 auto;
src/views/report/components/FormArea.vue
@@ -1,15 +1,8 @@
<template>
  <div class="FormArea">
    <el-form
      :model="gb28181"
      :rules="rules"
      label-position="left"
      label-width="90px"
      class="alarmSetting"
      ref="gb28181"
    >
    <el-form :model="reportTask" label-position="left" label-width="90px" class="alarmSetting" ref="report-task">
      <el-form-item class="selectItem" label="事件名称">
        <el-select class="h32" v-model="locationCity.province" size="small" placeholder="请选择事件">
        <el-select class="h32" v-model="reportTask.taskName" size="small" placeholder="请选择事件" style="width: 400px">
          <el-option
            v-for="item in eventsOptions"
            :key="item.value"
@@ -20,13 +13,7 @@
        </el-select>
      </el-form-item>
      <el-form-item class="selectItem" label="事件等级">
        <el-select
          class="h32"
          v-model="locationCity.level"
          size="small"
          placeholder="请选择"
          :disabled="gb28181.idType === 0"
        >
        <el-select class="h32" v-model="reportTask.level" size="small" placeholder="请选择" style="width: 400px">
          <el-option
            v-for="item in levelOptions"
            :key="item.value"
@@ -38,184 +25,178 @@
      </el-form-item>
      <el-form-item label="关联区域">
        <el-cascader
          size="mini"
          style="width:400px"
          v-model="tmpOrg"
          :options="menu"
          :props="{ value: 'id', label: 'name', checkStrictly: true }"
          collapse-tags
          clearable
          @change="handleTreeChange"
          ref="cascader"
        ></el-cascader>
      </el-form-item>
      <el-form-item label="责任人" prop="person">
        <el-input
          class="h32"
          v-model="gb28181.PublicId"
          v-model="reportTask.person"
          placeholder="请输入"
          size="small"
          :disabled="gb28181.idType === 1"
          style="width: 400px"
        ></el-input>
      </el-form-item>
      <el-form-item label="手机号" prop="tel">
        <el-input
          class="h32"
          v-model="reportTask.tel"
          placeholder="请输入"
          size="small"
          style="width: 400px"
        ></el-input>
      </el-form-item>
      <el-form-item label="责任人" prop="GbServerPort">
        <el-input
          class="h32"
          v-model.number="gb28181.GbServerPort"
          placeholder="请输入"
          size="small"
          style="width: 200px"
        ></el-input>
      </el-form-item>
      <el-form-item label="手机号" prop="GbServerPort">
        <el-input
          class="h32"
          v-model.number="gb28181.GbServerPort"
          placeholder="请输入"
          size="small"
          style="width: 200px"
        ></el-input>
      </el-form-item>
      <el-form-item label="推送方式">
        <el-input
          class="h32"
          v-model="gb28181.Password"
          placeholder="请输入"
          size="small"
          :disabled="!gb28181.IsAuth"
        ></el-input>
      <!-- <el-form-item label="推送方式">
        <el-select v-model="pushType" placeholder="请选择" style="width: 400px">
          <el-option label="短信" value="msg"> </el-option>
        </el-select>
      </el-form-item> -->
      <el-form-item label="开启任务">
        <el-switch v-model="reportTask.enable" active-color="#13ce66" inactive-color="#bbbbbb"> </el-switch>
      </el-form-item>
    </el-form>
    <div class="btnArea">
      <div class="button cancel" @click="$emit('close')">取消</div>
      <div class="button submit" @click="submitGB28281">保存</div>
      <div class="button submit" @click="submit">保存</div>
    </div>
  </div>
</template>
<script>
import { getGB28181Config, saveGB28181Config, getGb28181AreaList, newGb28181ID } from "@/api/Gb28181"
import { isPort, isIPv4 } from "@/scripts/validate"
import { createTask, updateTask } from "@/api/report"
export default {
  props: {
    id: {}
  },
  created() {
    this.initGB28181Conf()
    id: {
      type: String,
      default: ""
    },
    node: {},
    camera: {},
    menu: {}
  },
  data() {
    return {
      gb28181: {},
      rules: {
        ip: [
          {
            required: true,
            message: "请输入IP地址",
            trigger: "change"
          },
          { validator: isIPv4, trigger: "change" }
        ],
        ServerIp: [
          {
            required: true,
            message: "请输入IP地址",
            trigger: "change"
          },
          { validator: isIPv4, trigger: "change" }
        ],
        ServerPort: [
          {
            required: true,
            message: "请输入端口",
            trigger: "change"
          },
          { validator: isPort, trigger: "change" }
        ],
        GbServerPort: [
          {
            required: true,
            message: "请输入端口",
            trigger: "change"
          },
          { validator: isPort, trigger: "change" }
        ]
      },
      locationCity: {
        province: "",
        city: "",
        county: "",
        provinceOptions: [],
        cityOptions: [],
        countyOptions: []
      },
      reportTask: {},
      eventsOptions: [
        { value: "fire", label: "明 火" },
        { value: "smoke", label: "烟 雾" },
        { value: "work", label: "未穿工服" },
        { value: "head", label: "未戴安全帽" },
        { value: "dowork", label: "离岗" },
        { value: "juji", label: "人员聚集" }
        { value: "明火", label: "明火" },
        { value: "烟雾", label: "烟雾" },
        { value: "离岗", label: "离岗" },
        { value: "人员聚集", label: "人员聚集" },
        { value: "未穿工装", label: "未穿工装" },
        { value: "未戴安全帽", label: "未戴安全帽" }
      ],
      levelOptions: [
        { value: "1", label: "一级" },
        { value: "2", label: "二级" },
        { value: "3", label: "三级" },
        { value: "4", label: "四级" },
        { value: "5", label: "五级" }
      ]
        { value: "一级", label: "一级" },
        { value: "二级", label: "二级" },
        { value: "三级", label: "三级" },
        { value: "四级", label: "四级" },
        { value: "五级", label: "五级" }
      ],
      pushType: "msg",
      selectedOrg: {},
      tmpOrg: []
    }
  },
  mounted() {
    this.reportTask = this.node
  },
  methods: {
    initGB28181Conf() {
      getGB28181Config(this.id).then((rsp) => {
        if (rsp && rsp.success) {
          this.gb28181 = rsp.data
          //this.gb28181.idType = 0;
          this.$set(this.gb28181, "idType", 0)
          this.$refs["gb28181"].resetFields()
        }
      })
      getGb28181AreaList().then((rsp) => {
        if (rsp && rsp.success) {
          this.locationCity.provinceOptions = rsp.data.list
        }
      })
    handleTreeChange(value) {
      this.selectedOrg = value[value.length - 1]
    },
    submitGB28281() {
      this.$refs["gb28181"].validate((valid) => {
        if (valid) {
          saveGB28181Config(this.gb28181).then((rsp) => {
            if (rsp && rsp.success) {
              console.log("1212112")
              this.$notify({
                type: "success",
                message: "GB28181设置保存成功"
              })
            }
    collSelectedNodes() {
      let selectedNodeId = this.selectedOrg
      let selectedNode = {}
      let orgNodeIds = []
      if (this.selectedOrg == "") {
        return orgNodeIds
      }
      function findNode(node) {
        if (node.id == selectedNodeId) {
          selectedNode = node
          return
        }
        if (node.children) {
          node.children.forEach((n) => {
            findNode(n)
          })
        }
      }
      function collNode(node) {
        if (node.type != "MENU") {
          orgNodeIds.push(node.id)
          return
        }
        if (node.children) {
          node.children.forEach((n) => {
            collNode(n)
          })
        }
      }
      this.camera.forEach((n) => {
        findNode(n)
      })
      collNode(selectedNode)
      return orgNodeIds
    },
    submit() {
      if (this.reportTask.tel.length != 11) {
        this.$message.error("手机号码不正确")
        return
      }
      this.$refs["report-task"].validate((valid) => {
        if (valid) {
          if (this.tmpOrg.length > 0) {
            this.reportTask["cameraIds"] = this.collSelectedNodes().join(",")
            this.reportTask.org = this.$refs["cascader"].getCheckedNodes()[0].pathLabels.join("/")
          }
          if (this.id == "") {
            createTask(this.reportTask).then((rsp) => {
              if (rsp && rsp.success) {
                this.$notify({
                  type: "success",
                  message: "保存成功"
                })
                this.$emit("close")
              }
            })
          } else {
            updateTask(this.reportTask).then((rsp) => {
              if (rsp && rsp.success) {
                this.$notify({
                  type: "success",
                  message: "保存成功"
                })
                this.$emit("close")
              }
            })
          }
        } else {
          console.log("error submit!!")
          return false
        }
      })
    },
    changeProvince() {
      let pid = this.locationCity.province
      getGb28181AreaList({ parentId: pid }).then((rsp) => {
        if (rsp && rsp.success) {
          this.locationCity.cityOptions = rsp.data.list
          this.locationCity.city = this.locationCity.cityOptions[0].id
          this.changeCity()
        }
      })
    },
    changeCity() {
      let pid = this.locationCity.city
      getGb28181AreaList({ parentId: pid }).then((rsp) => {
        if (rsp && rsp.success) {
          this.locationCity.countyOptions = rsp.data.list
          this.locationCity.county = this.locationCity.countyOptions[0].id
        }
      })
    },
    newGBID() {
      let cCode = this.locationCity.county + ""
      newGb28181ID({ code: cCode }).then((rsp) => {
        if (rsp && rsp.success) {
          this.gb28181.PublicId = rsp.data.code
        }
      })
    }
src/views/report/components/SettingBox.vue
@@ -3,7 +3,14 @@
    <div class="title">事件推送配置</div>
    <div class="close iconfont" @click="$emit('close')">&#xe60f;</div>
    <div class="content">
      <FormArea :id="id" @close="$emit('close')" v-if="activeTab === 0"></FormArea>
      <FormArea
        :id="id"
        :node="nodeList"
        :camera="camera"
        :menu="menu"
        @close="$emit('close')"
        v-if="activeTab === 0"
      ></FormArea>
    </div>
  </div>
</template>
@@ -17,7 +24,9 @@
  },
  props: {
    id: {},
    nodeList: {}
    nodeList: {},
    camera: {},
    menu: {}
  },
  data() {
    return {
@@ -31,10 +40,10 @@
.SettingBox {
  position: fixed;
  top: 50%;
  left: 50%;
  left: 60%;
  margin-top: -354px;
  margin-left: -500px;
  width: 1000px;
  width: 700px;
  height: 708px;
  background-color: #fff;
  box-shadow: 0px 2px 16px 0px rgba(0, 43, 106, 0.25);
src/views/report/index.vue
@@ -6,7 +6,7 @@
    <div class="heart">
      <el-breadcrumb separator=">">
        <el-breadcrumb-item :to="{ path: '/manageCenter' }">管理中心</el-breadcrumb-item>
        <el-breadcrumb-item>告警管理</el-breadcrumb-item>
        <el-breadcrumb-item>推送管理</el-breadcrumb-item>
      </el-breadcrumb>
    </div>
@@ -38,7 +38,7 @@
.GB28181 {
  background-color: rgb(243, 245, 248);
  position: relative;
  min-height: 100vh;
  min-height: 200vh;
  .el-breadcrumb {
    margin-top: 48px;