zhangzengfei
2021-12-23 8de8ffd91ab6f96f35cf1357fd025051471ad4af
完善国标树配置功能
3个文件已修改
234 ■■■■ 已修改文件
src/components/giantTree/index.vue 13 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/giantTree/zTree/ztree.vue 49 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pages/gb28181/index/App.vue 172 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/giantTree/index.vue
@@ -6,9 +6,11 @@
      :readonly="TreeDataPool.readonly"
      :gb28181="gb28181"
      :setting="setting"
      :search="search"
      @onCreated="handleCreated"
      @onClick="itemClick"
      @onCheck="itemCheck"
      @onAfterSearch="itemCheck"
      @onDblClick="onDblClick"
      @onAddNode="addNode"
      @onRemoveNode="delNode"
@@ -58,6 +60,10 @@
      default: ""
    },
    gb28181: {
      type: Boolean,
      default: false
    },
    search: {
      type: Boolean,
      default: false
    },
@@ -154,7 +160,7 @@
      }
    },
    onDblClick(evt, treeId, item) {
      if (item.type !== "4" || this.app !== "Camera") {
      if (!item || item.type !== "4" || this.app !== "Camera") {
        return
      }
      // console.log('activeForceChoose', this.TreeDataPool.activeForceChoose)
@@ -286,7 +292,9 @@
    //   this.TreeDataPool.updateZTreeCheckNodes([treeNode]);
    // },
    itemCheck(evt, treeId, treeNode) {
      this.TreeDataPool.selectedNode = treeNode
      if (treeNode) {
        this.TreeDataPool.selectedNode = treeNode
      }
      this.TreeDataPool.treeType = this.treeName
      // 多选
@@ -299,6 +307,7 @@
      // 保存一份数据
      this.TreeDataPool.activeTreeData = this.ztreeObj.getNodes()
      this.$emit("itemChecked", treeNode)
    },
    //展开
    itemExpand(e, id, node) {
src/components/giantTree/zTree/ztree.vue
@@ -1,8 +1,8 @@
<template>
  <div>
    <div class="search">
      <el-input placeholder="搜索" v-model="keyWord">
        <i slot="suffix" class="el-input__icon el-icon-search" id="key"></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>
@@ -26,6 +26,7 @@
    showCheckbox: { type: Boolean, default: false },
    readonly: { type: Boolean, default: true },
    gb28181: { type: Boolean, default: false },
    search: { type: Boolean, default: false },
    setting: {
      type: Object,
      require: false,
@@ -44,8 +45,10 @@
  data() {
    return {
      ztreeId: "ztree_" + parseInt(Math.random() * 1e10),
      searchBtnId: "search_" + parseInt(Math.random() * 1e10),
      ztreeObj: null,
      list: [],
      loading: false,
      ztreeSetting: {
        view: {
          showLine: true,
@@ -127,7 +130,7 @@
            Object.assign({}, this.ztreeSetting, this.setting),
            this.list
          )
          this.fuzzySearch(this.ztreeObj, "#key", null, true) //初始化模糊搜索方法
          this.fuzzySearch(this.ztreeObj, this.searchBtnId, false, true) //初始化模糊搜索方法
          this.$emit("onCreated", this.ztreeObj)
        })
      },
@@ -382,6 +385,7 @@
        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)
      }
      /**
@@ -412,33 +416,37 @@
      }
      //listen to change in input element
      $(searchField).bind("click", function() {
        _this.options.target = document.querySelector("#" + _this.ztreeId).parentNode.parentNode
      $("#" + searchField).bind("click", function() {
        // _this.options.target = document.querySelector("#" + _this.ztreeId).parentNode.parentNode
        // console.log(_this.options.target);
        let loadingInstance = Loading.service(_this.options)
        // 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
        loadingInstance.close()
        // loadingInstance.close()
        setTimeout(() => {
          $("#" + searchField).removeClass("el-icon-loading")
          $("#" + searchField).addClass("el-icon-search")
        }, 300)
      })
      var timeoutId = null
      var lastKeyword = ""
      // excute lazy load once after input change, the last pending task will be cancled
      function searchNodeLazy(_keywords) {
        if (timeoutId) {
          //clear pending task
          clearTimeout(timeoutId)
        if (lastKeyword === _keywords) {
          return
        }
        timeoutId = setTimeout(function() {
          if (lastKeyword === _keywords) {
            return
          }
          ztreeFilter(zTreeObj, _keywords) //lazy load ztreeFilter function
          // $(searchField).focus();//focus input field again after filtering
          lastKeyword = _keywords
        }, 500)
        ztreeFilter(zTreeObj, _keywords) //lazy load ztreeFilter function
        // $(searchField).focus();//focus input field again after filtering
        lastKeyword = _keywords
      }
    },
    handleSearch() {
      this.loading = true
      searchNodeLazy(this.keyWord) //call lazy load
      this.loading = false
    }
  }
}
@@ -777,7 +785,8 @@
<style scoped lang="scss">
.search {
  width: 300px;
  width: 280px;
  margin: 5px 5px;
  ::v-deep .el-input__suffix {
    right: 0;
src/pages/gb28181/index/App.vue
@@ -9,7 +9,7 @@
        type="border-card"
        @tab-click="hanleTabClick"
      >
        <el-tab-pane label="国标ID" name="gb28181">
        <el-tab-pane label="国标服务" name="gb28181">
          <div style="width: 775px">
            <!-- GB28181设置 -->
            <el-form :model="gb28181" :rules="rules" label-width="130px" class="alarmSetting" ref="gb28181">
@@ -17,7 +17,7 @@
                  <ip-input :ip="gb28181.ServerIp" @on-blur="gb28181.ServerIp = arguments[0]"></ip-input>
              </el-form-item>-->
              <div style="text-align: left; margin-bottom: 16px">
              <div style="text-align: left;margin-bottom: 16px;">
                <el-radio-group v-model="gb28181.idType">
                  <el-radio :label="0">输入已有ID</el-radio>
                  <el-radio :label="1">生成新的ID</el-radio>
@@ -116,12 +116,8 @@
            border
            fit
            highlight-current-row
            style="width: 100%; color: #000"
            :header-cell-style="{
              background: '#f8f8f8',
              color: '#222222',
              height: '30px'
            }"
            style="width: 100%; color:#000"
            :header-cell-style="{ background: '#f8f8f8', color: '#222222', height: '30px' }"
          >
            <el-table-column type="index" label="序号" align="center" width="50"></el-table-column>
            <el-table-column prop="name" label="名称" align="center"></el-table-column>
@@ -138,29 +134,55 @@
          </el-table>
        </el-tab-pane>
        <el-tab-pane label="国标摄像机" name="cameras">
          <div style="text-align: left">
          <div style="text-align:left">
            <el-button type="primary" size="small" @click="updateCamerasFromVideosvr">刷新</el-button>
          </div>
          <div class="camera-title">
            <b>国标摄像机配置</b>
            <span>(最多勾选500路摄像机)</span>
          </div>
          <tree-menu
            ref="tree"
            app="gb28181"
            treeName="localTree"
            :node="TreeDataPool.treeData"
            :height="treeHeight"
            :setting="treeSettings"
            clickType="multiple"
            style="width: 600px; min-height: 500px"
          />
          <div class="base-image" v-loading="TreeDataPool.baseImageLoading">
            <span>{{ TreeDataPool.cameraNameForBaseImage }}</span>
            <div class="camera-image" v-show="TreeDataPool.cameraNameForBaseImage.length">
              <img :src="'data:image/png;base64,' + TreeDataPool.gb28181CameraBaseImage" width="450px" alt />
          <div class="tree-container">
            <div class="tree-box">
              <div class="camera-title">
                <b>国标摄像机</b>
              </div>
              <tree-menu
                ref="ztree"
                app="gb28181"
                treeName="localTree"
                clickType="multiple"
                :node="TreeDataPool.treeData"
                :height="treeHeight"
                :setting="treeSettings"
                @itemChecked="onItemCheck"
                search
                style="width:500px;min-height:500px"
              />
            </div>
            <div class="tree-box">
              <div class="camera-title">
                <b>已选摄像机</b>
                <span>(最多勾选500路摄像机)</span>
              </div>
              <!-- <tree-menu
                ref="dstTree"
                treeName="localTree"
                :node="dstTreeData"
                :height="treeHeight"
                :setting="treeSettingsSelect"
                style="width:500px;min-height:500px"
              /> -->
              <div class="select-tree-menu" :style="`max-height:${750 - 200}px;`">
                <z-tree :nodes="dstTreeData" :show-checkbox="false" :gb28181="true" search />
              </div>
            </div>
            <div class="base-image" v-loading="TreeDataPool.baseImageLoading">
              <span>{{ TreeDataPool.cameraNameForBaseImage }}</span>
              <div class="camera-image" v-show="TreeDataPool.cameraNameForBaseImage.length">
                <img :src="'data:image/png;base64,' + TreeDataPool.gb28181CameraBaseImage" width="450px" alt />
              </div>
            </div>
          </div>
          <el-divider></el-divider>
          <span class="camera-seleted-text">
@@ -188,11 +210,13 @@
import TreeMenu from "@/components/giantTree/index"
import { isPort, isIPv4 } from "@/scripts/validate"
import bus from "@/plugin/bus"
import ZTree from "@/components/giantTree/zTree/ztree"
export default {
  name: "Gb28181Setting",
  components: {
    TreeMenu
    TreeMenu,
    ZTree
  },
  directives: {
    focus: {
@@ -215,6 +239,11 @@
      treeSettings: {
        check: {
          enable: true
        }
      },
      treeSettingsSelect: {
        check: {
          enable: false
        }
      },
      rules: {
@@ -258,7 +287,8 @@
        provinceOptions: [],
        cityOptions: [],
        countyOptions: []
      }
      },
      dstTreeData: []
    }
  },
  mounted() {
@@ -283,16 +313,23 @@
      } else if (this.activeName == "cameras") {
        this.getCamerasFromVideosvr()
      }
      // this.TreeDataPool.fetchGbTree()
      // this.dstTreeData = this.TreeDataPool.gb28181Data
    },
    async getCamerasFromVideosvr() {
      this.loading = true
      await this.TreeDataPool.fetchVideosvrCameras(false)
      this.dstTreeData = this.TreeDataPool.newTreeByChecked(this.TreeDataPool.treeData)
      this.loading = false
    },
    async updateCamerasFromVideosvr() {
      this.loading = true
      await this.TreeDataPool.fetchVideosvrCameras(true)
      this.loading = false
    },
    onItemCheck() {
      this.dstTreeData = this.TreeDataPool.newTreeByChecked(this.TreeDataPool.activeTreeData)
    },
    saveChecked() {
      localStorage.setItem("ztree_fold_list", JSON.stringify(this.TreeDataPool.foldNodeList))
@@ -507,16 +544,6 @@
    text-decoration: underline;
  }
  .camera-title {
    text-align: left;
    padding: 0px 10px;
    margin: 5px 0px;
    height: 33px;
    background-color: #e4e2e2;
    line-height: 33px;
    font-size: 14px;
  }
  .camera-seleted-text {
    margin-right: 20px;
@@ -525,15 +552,64 @@
    }
  }
  .base-image {
    position: absolute;
    top: 18%;
    left: 57%;
    width: 450px;
  .tree-container {
    display: flex;
    .tree-box {
      width: 500px;
      margin: 5px 10px 0px 0px;
      border: 1px solid #e4e2e2;
    .camera-image {
      background-color: black;
      height: 254px;
      .camera-title {
        text-align: left;
        padding: 0px 10px;
        margin: 0px 0px;
        height: 33px;
        background-color: #e4e2e2;
        line-height: 33px;
        font-size: 14px;
      }
    }
    .base-image {
      margin: 140px 10px;
      width: 450px;
      height: 300px;
      .camera-image {
        background-color: black;
        height: 254px;
      }
    }
    .select-tree-menu {
      // max-width: 350px;
      overflow-x: hidden;
      overflow-y: hidden;
      margin-bottom: 4px;
    }
    .select-tree-menu::-webkit-scrollbar {
      /*滚动条整体样式*/
      width: 4px; /*高宽分别对应横竖滚动条的尺寸*/
      height: 4px;
    }
    .select-tree-menu::-webkit-scrollbar-thumb {
      /*滚动条里面小方块*/
      border-radius: 5px;
      -webkit-box-shadow: inset 0 0 5px rgba(157, 165, 183, 0);
      background: rgb(202, 201, 201);
    }
    .select-tree-menu::-webkit-scrollbar-track {
      /*滚动条里面轨道*/
      -webkit-box-shadow: inset 0 0 5px rgba(157, 165, 183, 0);
      border-radius: 0;
      background: rgb(235, 234, 234);
    }
    .select-tree-menu::-webkit-scrollbar-thumb:hover {
      background: rgba(0, 0, 0, 0.4);
    }
    .select-tree-menu:hover {
      overflow-x: visible;
      overflow-y: auto;
      margin-bottom: 0px;
    }
  }
}