zhangzengfei
2021-05-17 317d3e5116240d8b849857f5d737bcf61884285b
优化国标配置
7个文件已修改
730 ■■■■ 已修改文件
src/Pool/TreeData.ts 222 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/LeftNav.vue 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/giantTree/index.vue 22 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/giantTree/zTree/ztree.vue 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pages/gb28181/index/App.vue 428 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pages/gb28181/index/api.ts 39 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pages/gb28181/index/main.ts 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/Pool/TreeData.ts
@@ -8,10 +8,11 @@
  refreshGB28181Tree,
  updateCameraArea
} from '@/api/area'
import { findAllFile, show, changeEnable } from '@/api/localVedio'
export default class TreeDataPool {
  public openeds: Array<boolean>
  public activeTreeData: Array<object>
  public treeData: Array<object>
  public clusterData: Array<object>
  public gb28181Data: Array<object>
@@ -37,20 +38,6 @@
  public foldNodeList: object
  //记录左侧tab:activeName
  public treeActiveName: string
  //本地视频:视频分析处理
  public vedioAnaliyseSwitch: boolean
  //本地视频列表
  public localVedioList: Array<any>
  //本地视频当前页
  public localCurrentPage: number
  //本地视频每页查询20条
  public localPageSize: number
  //本地视频总条数
  public localTotal: number
  //勾选的本地视频
  public checkedLocalVedio: Array<any>
  //当前选中的本地视频
  public clickLocalVideo: object
  //控制开始、暂停按钮显示状态
  public btnStaus: string
  //本地视频类型
@@ -60,10 +47,19 @@
  //记录复制的摄像机name
  public ctrlCameraName: string
  // 是否使用ztree
  public zTree: boolean
  public checkedTreeNode: Array<object>
  // 选中的摄像机个数
  public gb28181CheckedCount: number
  // 总摄像机个数
  public gb28181ChildNodeCount: number
  constructor() {
    this.openeds = [true, true, false]
    this.activeTreeData = []
    this.treeData = []
    this.gb28181Data = []
    this.clusterData = []
@@ -84,20 +80,17 @@
    this.selectedNode = {}
    this.treeType = ''
    this.foldNodeList = {}
    this.vedioAnaliyseSwitch = false
    this.treeActiveName = 'camera'
    this.searchLocalType = 0
    this.localVedioList = []
    this.checkedLocalVedio = []
    this.clickLocalVideo = {}
    //1:暂停状态;2:等待状态;3:置灰
    this.btnStaus = '3'
    this.localCurrentPage = 1
    this.localPageSize = 20
    this.localTotal = 0
    this.ctrlCameraId = ''
    this.ctrlCameraName = ''
    this.zTree = false
    this.checkedTreeNode = []
    this.gb28181CheckedCount = 0
    this.gb28181ChildNodeCount = 0
  }
  setVideoArr(index: number, value: object, vue: any): void {
@@ -261,8 +254,6 @@
    this.isFold(this.gb28181Data)
    this.selectedNodes = []
    this.selectedNode = {}
    this.cleanLocalVedio()
  }
  cleanTree(tree) {
@@ -397,8 +388,6 @@
    if (this.openeds[1]) {
      this.fetchGbTree()
    }
    this.findAllFile({})
  }
  async add(name: string, parent: string) {
@@ -434,109 +423,84 @@
    // this.fetchGbTree()
  }
  async findAllFile(params: any) {
    ; (params.fileName = this.searchInput), (params.type = this.searchLocalType)
    params.page = this.localCurrentPage
    params.size = this.localPageSize
    let res: any = await findAllFile(params)
    if (res && res.success) {
      let list = res.data.dataList.map(i => {
        let obj: any = {}
        Object.assign(obj, i)
        if (i.ruleType == 0) {
          obj.iconStatus2 = '0'
        } else {
          obj.iconStatus2 = '1'
        }
        if (!i.snapshot_url) {
          // obj.snapshot_url = require('@/assets/nobody.png')
          obj.snapshot_url = ''
        } else {
          obj.snapshot_url = '/httpImage/' + obj.snapshot_url
        }
        if (i.is_running) {
          obj.iconStatus1 = '1'
        } else if (i.progress == 100) {
          obj.iconStatus1 = '2'
        } else if (i.status == 1 && i.progress == 0 && i.hasRule) {
          obj.iconStatus1 = '3'
        } else if (!i.hasRule && i.progress == 0) {
          obj.iconStatus1 = '4'
        }
        obj.checkStatus = false
        obj.clickStatus = false
        obj.showCheckBox = false
        return obj
      })
      this.localVedioList = list
      this.localTotal = res.data.total
      // console.log(this.localVedioList,this.searchInput,'本地视频列表')
    }
  }
  async show() {
    let res: any = await show()
    if (res && res.success) {
      this.vedioAnaliyseSwitch = res.data.videoEnable
    }
  }
  async changeEnable() {
    let res: any = await changeEnable({
      enable: this.vedioAnaliyseSwitch
    })
  }
  getCheckedFiles() {
    this.checkedLocalVedio = this.localVedioList.filter(i => {
      return i.checkStatus
    })
    this.clickLocalVideo = this.localVedioList.filter(i => {
      return i.clickStatus
    })[0]
    if (this.checkedLocalVedio.length === 0) {
      this.btnStaus = '3'
      return false
    }
    this.checkedLocalVedio.every((i, index) => {
      let t = ''
      if (i.status == 0 && i.hasRule) {
        t = '1'
      } else if (i.status == 1 && i.hasRule && !i.is_running) {
        t = '2'
      } else {
        t = '3'
      }
      if (index == 0) {
        this.btnStaus = t
      } else {
        if (this.btnStaus !== t) {
          this.btnStaus = '3'
          return false
        }
      }
    })
  }
  filterLocalVideoWell() {
    if (this.localVedioList.length !== 0) {
      this.localVedioList = this.localVedioList.filter(i => {
        return i.progress == 100
      })
    }
  }
  cleanLocalVedio() {
    this.localVedioList.map(i => {
      i.checkStatus = false
      i.clickStatus = false
    })
    this.checkedLocalVedio = []
    this.btnStaus = '3'
  }
  async dropNode(cameraId, areaId) {
  async dropNode(cameraId: string, areaId: string) {
    await updateCameraArea({ cameraId: cameraId, areaId: areaId })
  }
  getAllChildrenNodes(treeNode, arr) {
    for (var i = 0; i < treeNode.length; i++) {
      var sonList = treeNode[i].children;
      if (!sonList) {
        if (treeNode[i].type == "camera") {
          arr.push(treeNode[i]);
          if (treeNode[i].checked) {
            this.gb28181CheckedCount += 1;
          }
        }
      } else {
        this.getAllChildrenNodes(sonList, arr);
      }
    }
    return arr;
  }
  countChildrenNodes(treeNode) {
    let arry = []
    this.getAllChildrenNodes(treeNode, arry)
    return arry.length
  }
  async fetchVideosvrCameras() {
    const rsp: any = await refreshGB28181Tree()
    if (rsp && rsp.success) {
      this.selectedNode = {}
      this.treeData = rsp.data ? rsp.data : []
      if (this.treeData && this.treeData.length > 0) {
        this.sortTreeData(this.treeData)
      }
      // 设置禁止拖拽摄像机到摄像机节点
      this.setDropDisable(this.treeData)
      this.isFold(this.treeData)
      this.activeTreeData = this.treeData
      this.gb28181CheckedCount = 0;
      this.gb28181ChildNodeCount = this.countChildrenNodes(this.treeData)
    }
  }
  removeNoCheckedNode(nodes: Array<any>) {
    for (let i = 0; i < nodes.length;) {
      if (!nodes[i].checked) {
        nodes.splice(i, 1)
        continue
      }
      if (nodes[i].children && nodes[i].children.length) {
        this.removeNoCheckedNode(nodes[i].children)
      }
      i++
    }
  }
  countCheckedNodes(nodes: Array<any>) {
    let count = 0
    nodes.forEach(n => {
      if (n.type == "camera") {
        count++
      }
    })
    this.gb28181CheckedCount = count
  }
  newTreeByChecked(nodes: Array<object>) {
    let newTree = JSON.parse(JSON.stringify(nodes))
    this.removeNoCheckedNode(newTree)
    return newTree
  }
}
src/components/LeftNav.vue
@@ -123,14 +123,14 @@
              </template>
              <!-- 国标刷新图标 -->
              <div class="tree-edit gb-refresh" v-show="!TreeDataPool.gbReadonly">
              <!-- <div class="tree-edit gb-refresh" v-show="!TreeDataPool.gbReadonly">
                <el-tooltip content="刷新" placement="top" popper-class="atooltip">
                  <button @click="refreshGB">
                    <i v-if="loadingGBTree" class="el-icon-loading" style="font-size:16px"></i>
                    <i v-else class="el-icon-refresh" style="font-size:16px"></i>
                  </button>
                </el-tooltip>
              </div>
              </div>-->
              <div class="tree-edit gb-lock" v-show="showLock">
                <button @click="gbLockSwitch">
                  <i v-if="TreeDataPool.gbReadonly" class="el-icon-lock" style="font-size:16px"></i>
src/components/giantTree/index.vue
@@ -5,6 +5,7 @@
      :show-checkbox="TreeDataPool.multiple"
      :readonly="TreeDataPool.readonly"
      :gb28181="gb28181"
      :setting="setting"
      @onCreated="handleCreated"
      @onClick="itemClick"
      @onCheck="itemCheck"
@@ -66,7 +67,14 @@
    height: {
      type: Number,
      default: 0
    }
    },
    setting: {
      type: Object,
      require: false,
      default: function () {
        return {};
      },
    },
  },
  data() {
    return {
@@ -117,13 +125,10 @@
        //摄像机信息更新信息后,如果节点位置有变tId就不准了,this.TreeDataPool.selectedNode此时还是旧的信息
        let ztreeNodes = ztreeObj.getNodes();
        //var curNodeTid = '';
        console.log(ztreeNodes)
        _this.findTidByIdFromArr(ztreeNodes);
        console.log('curNodeTid', _this.curNodeTid)
        this.TreeDataPool.selectedNode.tId = _this.curNodeTid;
        let node = this.ztreeObj.getNodeByTId(this.TreeDataPool.selectedNode.tId)
        console.log('selecBode', this.TreeDataPool.selectedNode)
        console.log('selectedNode.tId', this.TreeDataPool.selectedNode.tId)
        // 多选时, 选中单选单击的节点
        if (this.TreeDataPool.multiple) {
          this.ztreeObj.checkAllNodes(false);
@@ -266,7 +271,6 @@
      this.showDialog = true;
    },
    itemClick(evt, treeId, treeNode) {
      console.log(evt, treeId)
      this.TreeDataPool.selectedNode = treeNode;
      this.TreeDataPool.treeType = this.treeName;
@@ -301,6 +305,12 @@
      // this.ztreeObj.checkNode(treeNode, true, false, false);
      let checkedNodes = this.ztreeObj.getCheckedNodes(true);
      this.TreeDataPool.updateZTreeCheckNodes(checkedNodes);
      // 实时统计选中个数
      this.TreeDataPool.countCheckedNodes(checkedNodes);
      // 保存一份数据
      this.TreeDataPool.activeTreeData = this.ztreeObj.getNodes()
    },
    //展开
    itemExpand(e, id, node) {
src/components/giantTree/zTree/ztree.vue
@@ -112,7 +112,6 @@
            Object.assign({}, this.ztreeSetting, this.setting),
            this.list
          );
          console.log('onCreated,ztr')
          this.$emit("onCreated", this.ztreeObj);
        });
      },
src/pages/gb28181/index/App.vue
@@ -1,20 +1,15 @@
<template>
  <div class="s-basic-setting" @contextmenu.prevent="toOpenMenuList">
    <el-menu
      :default-openeds="openeds"
      background-color="#fff"
      text-color="#303133"
      active-text-color="#409EFF"
      style="height: 100%;"
      class="menu-css"
      @open="menuOpen"
      @close="menuClose"
  <div class="s-system-manage">
    <div class="s-basic-setting">
      <el-tabs
        id="e-basic-setting"
        v-model="activeName"
        v-loading="loading"
        :element-loading-text="loadingText"
        type="border-card"
        @tab-click="hanleTabClick"
    >
      <el-submenu index="0">
        <template slot="title">
          <b class="tree-font">国际ID</b>
        </template>
        <el-menu-item-group class="item-group">
        <el-tab-pane label="国标ID" name="gb28181">
          <!-- GB28181设置 -->
          <el-form
            :model="gb28181"
@@ -115,16 +110,11 @@
              <el-button type="primary" @click="submitGB28281" size="small">保存</el-button>
            </el-form-item>
          </el-form>
        </el-menu-item-group>
      </el-submenu>
      <el-submenu index="1">
        <template slot="title">
          <b class="tree-font">接入平台列表</b>
        </template>
        <el-menu-item-group class="item-group">
          <div>
        </el-tab-pane>
        <el-tab-pane label="接入平台列表" name="subordinates">
            <el-table
              :data="tableList"
            :data="subDevTable"
              border
              fit
              highlight-current-row
@@ -133,27 +123,47 @@
            >
              <el-table-column type="index" label="序号" align="center" width="50"></el-table-column>
              <el-table-column prop="name" label="名称" align="center"></el-table-column>
              <el-table-column prop="id" label="ID" align="center"></el-table-column>
            <el-table-column prop="publicid" label="ID" align="center"></el-table-column>
              <el-table-column prop="ip" label="IP" align="center"></el-table-column>
              <el-table-column prop="status" label="状态" align="center"></el-table-column>
            <el-table-column prop="status" label="状态" align="center">
              <template slot-scope="scope">
                <span
                  :style="scope.row.active ? `color:#047d19` : 'color:#f11a1a;' "
                >{{scope.row.active ? "在线": "离线"}}</span>
              </template>
            </el-table-column>
              <el-table-column prop="mark" label="备注" align="center"></el-table-column>
            </el-table>
        </el-tab-pane>
        <el-tab-pane label="国标摄像机" name="cameras">
          <div style="text-align:left">
            <el-button type="primary" size="small" @click="getCamerasFromVideosvr">刷新</el-button>
          </div>
        </el-menu-item-group>
      </el-submenu>
      <el-submenu index="2">
        <template slot="title">
          <b class="tree-font">国际摄像机</b>
        </template>
        <el-menu-item-group class="item-group">
          <div>
            <div>
              <el-button type="primary" size="small">刷新</el-button>
          <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"
          />
          <el-divider></el-divider>
          <span class="camera-seleted-text">
            已选择 (
            <b>{{TreeDataPool.gb28181CheckedCount}}</b>
            / {{TreeDataPool.gb28181ChildNodeCount}} ) 路
          </span>
          <el-button type="primary" size="small" @click="saveChecked">保存</el-button>
        </el-tab-pane>
      </el-tabs>
          </div>
        </el-menu-item-group>
      </el-submenu>
    </el-menu>
  </div>
</template>
@@ -162,13 +172,20 @@
  getGB28181Config,
  saveGB28181Config,
  getGb28181AreaList,
  newGb28181ID
  newGb28181ID,
  getLocalCameraTree,
  getAllSubServer,
  saveGb28181CamTree
} from './api'
import TreeMenu from "@/components/giantTree/index";
import { isPort, isIPv4 } from '@/scripts/validate'
import bus from '@/plugin/bus'
export default {
  name: 'Gb28181Setting',
  components: {
    TreeMenu
  },
  directives: {
    focus: {
      inserted: function (el) {
@@ -179,10 +196,19 @@
  data() {
    return {
      activeName: "gb28181",
      treeHeight: 750,
      loading: false,
      loadingText: "",
      openeds: ['0'],
      gb28181: {},
      tableList: [],
      subDevTable: [],
      idType: 1,
      treeSettings: {
        check: {
          enable: true
        }
      },
      rules: {
        ip: [
          {
@@ -228,12 +254,59 @@
    }
  },
  mounted() {
    this.TreeDataPool.multiple = true;
    //this.$nextTick(()=>{
    this.initGB28181Conf()
    //})
    this.initGB28181Conf();
  },
  methods: {
    hanleTabClick(tab, event) {
      if (this.activeName == "subordinates") {
        getAllSubServer().then(rsp => {
          if (rsp && rsp.success) {
            this.subDevTable = rsp.data;
          }
        })
      } else if (this.activeName == "cameras") {
        this.getCamerasFromVideosvr();
      }
    },
    async getCamerasFromVideosvr() {
      this.loading = true;
      await this.TreeDataPool.fetchVideosvrCameras();
      this.loading = false;
    },
    saveChecked() {
      if (this.TreeDataPool.gb28181CheckedCount > 500) {
        this.$message({
          type: "warning",
          message: "最多仅支持选择500路摄像机. 请重新选择"
        })
        return;
      }
      this.loading = true;
      let treeData = this.TreeDataPool.newTreeByChecked(this.TreeDataPool.activeTreeData)
      saveGb28181CamTree({ checkedMenus: treeData }).then(rsp => {
        if (rsp && rsp.success) {
          this.$message({
            type: "success",
            message: "保存成功"
          })
        }
        this.loading = false;
      }).catch(err => {
        this.$message({
          type: "error",
          message: "保存失败"
        })
        this.loading = false;
      })
    },
    initGB28181Conf() {
      getGB28181Config().then(rsp => {
        if (rsp && rsp.success) {
@@ -311,236 +384,119 @@
}
</script>
<style lang="scss">
.s-basic-setting {
.s-system-manage {
  width: 100% !important;
  min-width: 1067px;
  height: 100%;
  padding: 20px;
  box-sizing: border-box;
  .item-group {
    padding: 0 15px;
    margin-bottom: 15px;
  }
  .el-form {
    .el-form-item {
      text-align: left;
      margin-bottom: 16px;
      &:last-of-type {
        width: 490px;
      }
      .el-button {
        float: right;
      }
      .el-select {
        margin-right: 10px;
      }
      .el-form-item__content {
        text-align: left;
        input {
          max-width: 360px;
        }
        .el-date-editor.el-input,
        .el-date-editor.el-input__inner {
          width: 216px;
        }
        .el-checkbox__label {
          padding-left: 5px;
        }
  padding: 10px;
  background-color: #f8f9fb;
  .s-system-manage-breadcrumb {
    height: 5%;
    box-sizing: border-box;
    border: 1px solid #e4e7ed;
    box-shadow: #e4e7ed 0px 0px 9px inset;
    box-shadow: #e4e7ed 0px 0px 9px inset;
    border-radius: 5px;
      }
      .el-form-item__label {
        text-align: left;
      }
      &.el-form-item.is-required:not(.is-no-asterisk)
        > .el-form-item__label:before {
        margin-left: -9px;
      }
    }
  }
  .alarmSetting {
    .el-input {
      width: 100%;
      // padding-right: 10px;
    }
    .el-select {
      max-width: 113px;
    }
    .el-slider {
      width: calc(100% - 120px);
      display: inline-block;
      padding-right: 30px;
      box-sizing: border-box;
      vertical-align: middle;
    }
    .el-input-number {
      width: 100px;
      display: inline-block;
      .el-input {
        width: 100%;
      }
    }
  }
  .time-type {
    height: 25px;
    width: 413px;
    line-height: 28px;
    padding: 3px 23px;
    font-size: 14px;
    font-weight: 600;
    background-color: #e4e6ed;
  }
  #e-basic-setting {
  .el-tabs--border-card {
    border: 0px solid #dcdfe6;
    -webkit-box-shadow: none;
    box-shadow: none;
    .el-tabs__header {
      border: 0px solid #dcdfe6;
      .el-tabs__item {
        padding: 5px 50px;
        height: 50px;
        font-family: PingFangSC-Regular;
        font-size: 14px;
        font-size: 15px;
        color: #222222;
        text-align: center;
        border: 0px solid transparent;
      }
      .el-tabs__item:nth-child(2) {
        padding-left: 50px;
        padding-left: 50px !important;
      }
      .el-tabs__item:last-child {
        padding-right: 50px;
        padding-right: 50px !important;
      }
      .el-tabs__item.is-active {
        color: #ff7733;
        font-weight: bold;
        color: #3d68e1;
        // border-right-color: #fff;
        // border-left-color: #fff;
      }
      .el-tabs__item:not(.is-disabled):hover {
        color: #ff7733;
        color: #3d68e1;
      }
    }
    .el-tabs__active-bar {
      background-color: #ff7733;
    }
    .xiangqin-label {
      text-align: left;
      width: 85px;
      font-size: 14px;
      line-height: 30px;
  .el-tabs__header {
    margin-bottom: 0;
    }
    .xiangqing-info {
      text-align: left;
      font-size: 14px;
      line-height: 30px;
    }
  }
  #cut_min_duration {
    .el-slider__bar {
      background-color: #3d68e1;
    }
    .el-slider__button {
      width: 10px;
      height: 10px;
      border: 4px solid #3d68e1;
    }
  }
  #cut_max_duration {
    .el-slider__bar {
      background-color: #ff9e6e;
    }
    .el-slider__button {
      width: 10px;
      height: 10px;
      border: 4px solid #ff9e6e;
    }
  }
  .menu-css,
  .el-menu {
    border-right: none;
    list-style: none;
    position: relative;
    margin: 0;
    padding-left: 0;
    background-color: #ffffff;
    .el-submenu__title {
      height: 35px;
      line-height: 35px;
      font-size: 14px;
      color: #303133;
      padding: 0 20px;
      list-style: none;
      cursor: pointer;
      position: relative;
      -webkit-transition: border-color 0.3s, background-color 0.3s, color 0.3s;
      transition: border-color 0.3s, background-color 0.3s, color 0.3s;
      -webkit-box-sizing: border-box;
  .el-tabs__content {
    height: calc(100% - 64px);
      box-sizing: border-box;
      white-space: nowrap;
    }
    .tree-font {
      font-family: PingFangSC-Medium;
      font-size: 14px;
      color: #222222;
    overflow-y: auto;
    padding: 20px 40px !important;
    background: #fff;
    .el-tab-pane {
      width: 100%;
      .s-title {
      text-align: left;
    }
    li {
      text-align: left;
      .el-submenu__title {
        // border-bottom: solid 1px #e6e6e6;
        padding-left: 10px !important;
        background-color: #e4e6ed !important;
        border-radius: 2px;
        .el-submenu__icon-arrow {
          position: absolute;
          top: 50%;
          right: auto;
          left: 135px;
          margin-top: -7px;
          -webkit-transition: -webkit-transform 0.3s;
          transition: -webkit-transform 0.3s;
          transition: transform 0.3s;
          transition: transform 0.3s, -webkit-transform 0.3s;
          font-size: 12px;
        padding: 15px 0px;
        font-size: 16px;
        }
      }
    }
  }
  .save-btn {
    text-align: right;
    position: relative;
    right: 40px;
  }
}
</style>
<style lang="scss" scoped>
.menu-css,
.el-menu {
  border-right: none;
  list-style: none;
  position: relative;
  margin: 0;
  padding-left: 0;
  background-color: #ffffff;
  .tree-font {
    font-family: PingFangSC-Medium;
    font-size: 14px;
    color: #222222;
    text-align: left;
  .s-table {
    border: 1px solid #e8e8e9;
    margin-top: 40px;
  }
  li {
  .ui-top-title {
    padding-bottom: 10px;
    /* border-bottom: 1px solid #ebebeb; */
    position: relative;
    text-align: left;
    .el-submenu__title {
      .el-submenu__icon-arrow {
    padding-left: 15px;
    font-size: 16px;
    font-weight: bold;
  }
  .ui-top-title:before {
    content: " ";
    border-left: 4px solid #f53d3d;
    display: inline-block;
    height: 16px;
        position: absolute;
        top: 50%;
        right: 0;
        margin-top: -7px;
        -webkit-transition: -webkit-transform 0.3s;
        transition: -webkit-transform 0.3s;
        transition: transform 0.3s;
        transition: transform 0.3s, -webkit-transform 0.3s;
        font-size: 12px;
    left: 0;
    margin-top: -13px;
      }
  .el-button--text {
    color: #3d68e1;
    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;
    .b {
      color: #3d68e1;
    }
  }
}
src/pages/gb28181/index/api.ts
@@ -24,6 +24,14 @@
  });
};
export const getAllSubServer = (query: any) => {
  return request({
    url: "/data/api-v/gb28181/getAllSubServer",
    method: "get",
    params: query
  });
};
export const newGb28181ID = (query: any) => {
  return request({
    url: "/data/api-v/gb28181/newGbId",
@@ -31,3 +39,34 @@
    params: query
  });
};
export const getLocalCameraTree = (query: any) => {
  return request({
    url: "/data/api-v/area/localmenu",
    method: "get",
    params: query
  });
};
export const getGB28181CameraTree = (query: any) => {
  return request({
    url: "/data/api-v/area/gb28181Tree",
    method: "get",
    params: query
  });
};
export const refreshGB28181Tree = () => {
  return request({
    url: "/data/api-v/area/gb28181RefreshTree",
    method: "post",
  });
};
export const saveGb28181CamTree = (query: any) => {
  return request({
    url: "/data/api-v/gb28181/saveGb28181CamTree",
    method: "post",
    data: query
  });
};
src/pages/gb28181/index/main.ts
@@ -1,11 +1,25 @@
import Vue from 'vue';
import App from './App.vue';
import TreeDataPool from "@/Pool/TreeData";
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
import "@/assets/css/element-variables.scss";
Vue.use(ElementUI)
const onlyTreeDataPool = new TreeDataPool
const mixin = {
  data() {
    return {
      TreeDataPool: onlyTreeDataPool
    };
  },
};
Vue.mixin(mixin);
new Vue({
  el: '#app',
  render: h => h(App)