sd
2025-07-22 c1784a781aad8271cf6ebd25325aef785535f0a4
原有摄像机配置页面 把策略相关内容更换为督查任务
1个文件已添加
10个文件已修改
630 ■■■■■ 已修改文件
src/Pool/PollData.ts 43 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/Pool/VideoManageData.ts 36 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/Pool/VideoRuleData.ts 19 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/pollConfig.ts 9 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/scene.ts 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/selectRule.ts 40 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pages/analysisPower/index/App.vue 48 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pages/cameraAccess/components/CameraInfo.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pages/cameraAccess/components/SceneRule.vue 142 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pages/cameraAccess/components/SeparateRules.vue 271 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pages/cameraAccess/index/VideoManage.vue 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/Pool/PollData.ts
@@ -58,7 +58,6 @@
  public DiskUsePercent: number = 0;
  public barCharts: Array<any> = [];
  public Thresholds: Array<object> = [];
  public serverUrl: string = "";
  //算力配置中滑块数据
  public sliderList: Array<any> = [];
@@ -68,7 +67,6 @@
    this.fetchPollList();
    this.sysThresholds();
    this.statisticTaskInfo();
    this.fetchCameraInfo();
  }
  public async fetchPollConfig() {
@@ -80,31 +78,11 @@
      }
    }
  }
  public async fetchCameraInfo() {
    console.info("response:")
      const response = await fetch("/config.json");
      console.info("response:"+response)
      if (!response.ok) throw new Error(`请求失败: ${response.status}`);
      const responseData = await response.json();
      this.serverUrl = responseData.serverUrl;
      console.info("chatUrl:"+this.serverUrl);
    }
  public async fetchPollList() {
    console.info("搜索:"+this.serverUrl)
    this.CameraList = []
    // let rsp: any = await getCamerasByServer({ cameraName: this.SearchName });
    const response = await fetch("/api-v1/v1/videoCamera/list", {//http://192.168.1.235:8088
      method: "GET",
      headers: {
        "Content-Type": "application/json",
      },
    })
    if (!response.ok) {
      throw new Error(`请求失败: ${response.status}`);
    }
    let rsp: any = await response.json();
    if (rsp && rsp.status == 200) {
  public async fetchPollList() {
    this.CameraList = []
    let rsp: any = await getCamerasByServer({ cameraName: this.SearchName });
    if (rsp && rsp.success) {
      if (rsp.data) {
        this.CameraList = rsp.data.sort(function (obj1: any, obj2: any) {
          var val1 = obj1.run_type;
@@ -118,13 +96,12 @@
    const ipReg = /\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/;
    this.CameraList.forEach((cam: any) => {
      // 国标摄像机不显示ip
      if (cam.type && cam.type === 1) {
      if (cam.type === 1) {
        cam.ip = "-"
        return
      }
      let ip = ipReg.exec(cam.rtsp)
      console.info("ip:"+ip)
      if (ip && ip.length > 0) {
      if (ip.length > 0) {
        cam.ip = ip[0]
      }
    })
@@ -197,7 +174,7 @@
        }
        this.GpuUsedPercent = Number((gpuLoad / gpuTotal * 100).toFixed(2))
      }
      this.barCharts = [this.DiskUsePercent, this.CpuUsedPercent, this.GpuUsedPercent, this.MemUsedPercent]
      this.barCharts = [this.DiskUsePercent,this.CpuUsedPercent,this.GpuUsedPercent,this.MemUsedPercent]
    }
  }
@@ -233,17 +210,17 @@
      let totalCount = res.data.channelTotal
      let realCount = res.data.realValidCount
      let pollCount = res.data.pollChannelCount
      this.sliderList = [0, realCount, realCount + pollCount]
      this.sliderList = [0,realCount,realCount + pollCount]
      // if(realCount + pollCount == totalCount){
      //   this.sliderList = [0,realCount,realCount + pollCount]
      // }else{
      //   this.sliderList = [0,realCount,realCount + pollCount,totalCount]
      // }
    }
  }
  public async updateChannelCount(fileChannelCount, pollChannelCount) {
  public async updateChannelCount(fileChannelCount,pollChannelCount){
    let res: any = await updateChannelCount({
      videoChannelCount: fileChannelCount,
      pollChannelCount: pollChannelCount
src/Pool/VideoManageData.ts
@@ -1,6 +1,7 @@
import { getAllTimeRule, saveTimeRule } from "@/api/timeRule";
import { findDictionaryByType } from "@/api/dictionary";
import { findBaseByRuleEditor } from "@/api/es";
import { getCheckContents, getWarningRules,getKnowsList } from "@/api/selectRule";
const AllDayRule = [
  { day: 1, time_range: [{ start: "00:00", end: "24:00" }] },
@@ -15,6 +16,9 @@
export default class VideoManageData {
  public SepTasks: Array<object> = [];
  public TimeRules: Array<object> = [];
  public checkOptions: Array<object> = [];//检测内容
  public ruleOptions: Array<object> = [];//预警规则
  public knowsList: Array<object> = [];//知识库
  public Dictionary: object = {};
  public TagList: Array<object> = [];
  public TimeRuleSum: number = 0;
@@ -24,6 +28,38 @@
    this.getTimeRule();
    this.getDictionary();
    this.getTagList();
    this.getSelectRule();
  }
  public async getSelectRule() {
    let rspc: any = await getCheckContents(
      {
        page: 1,
        pageSize: 999
      }
    );
    if (rspc && rspc.status === 200) {
      this.checkOptions = rspc.data.list;
    }
    let rspw: any = await getWarningRules(
      {
        page: 1,
        pageSize: 999
      }
    );
    if (rspw && rspw.status === 200) {
      this.ruleOptions = rspw.data.list;
    }
    let rspk: any = await getKnowsList(
      {
        page: 1,
        pageSize: 999
      }
    );
    if (rspk && rspk.status === 200) {
      this.knowsList = rspk.data;
    }
    console.info("rspk:"+JSON.stringify(this.knowsList))
  }
  public async getTimeRule() {
src/Pool/VideoRuleData.ts
@@ -1,7 +1,7 @@
import { getCameraInfo, getGB28181CameraInfo } from "@/api/camera"
import { getAllPolygon } from "@/api/polygon"
import { getDirDetails, findAllFileByStackId } from "@/api/localVedio"
import { getCameraSceneRule } from "@/api/scene"
import { getCameraSceneRule,getCameraSceneRuleTwo } from "@/api/scene"
export default class VideoRuleData {
  public selectTask: Array<object>
@@ -153,11 +153,26 @@
    const rsp: any = await getCameraSceneRule({ cameraId: this.cameraId })
    if (rsp && rsp.success) {
      let rspData = rsp.data.taskList ? rsp.data.taskList : []
      this.rules = rsp.data.rules ? rsp.data.rules : []
      // this.rules = rsp.data.rules ? rsp.data.rules : []
      this.camearInfo = rsp.data.cameraInfo ? rsp.data.cameraInfo : {}
      this.analytics = rsp.data.cameraInfo.run_type !== -1 ? true : false
      this.dealWay = rsp.data.cameraInfo.run_type === 1 ? true : false
      this.runServerName = rsp.data.cameraInfo.runServerName
    }
    const rspTwo: any = await getCameraSceneRuleTwo({ videoId: this.cameraId })
    if (rspTwo && rspTwo.status === 200) {
      this.rules = rspTwo.data.list ? rspTwo.data.list.map(item => ({
        ...item,
        id:item.taskId,
        scene_name: item.taskName,
        desc:item.taskDescription,
        alarm_level:item.eventLevel,
        checkContents: item.checkContent ? item.checkContent.map(check => check.checkId) : [],
        warningRules: item.warningRule ? item.warningRule.map(rule => rule.ruleId) : [],
        workingTimes: item.workingTime ? item.workingTime.map(time => time.labelId)[0] : "",
      })) : []
    }
    // console.info("rules:"+JSON.stringify(rsp.data))
    // console.info("list:"+JSON.stringify(this.rules))
  }
}
src/api/pollConfig.ts
@@ -36,16 +36,9 @@
  })
}
// export const getCamerasByServer = (query: any) => {
//   return request({
//     url: "/data/api-v/camera/getAllCamerasByServer",
//     method: "get",
//     params: query
//   })
// }
export const getCamerasByServer = (query: any) => {
  return request({
    url: "/api-v1/v1/videoCamera/list",
    url: "/data/api-v/camera/getAllCamerasByServer",
    method: "get",
    params: query
  })
src/api/scene.ts
@@ -46,6 +46,13 @@
    params: query
  });
};
export const getCameraSceneRuleTwo = (query: any) => {
  return request({
    url: "/api-v1/v1/task/list",
    method: "get",
    params: query
  });
};
export const getLinkSceneRule = (params: any) => {
  return request({
@@ -62,3 +69,10 @@
    params: { groupId: id }
  });
};
export const deleteCameraSceneTwo = (params: any) => {
  return request({
    url: "/api-v1/v1/task/delete",
    method: "delete",
    params:params
  });
};
src/api/selectRule.ts
New file
@@ -0,0 +1,40 @@
import request from "@/scripts/httpRequest";
export const getCheckContents = (query: any) => {
  return request({
    url: "/api-v1/v1/checkContent/all",
    method: "get",
    params: query
  });
};
export const getWarningRules = (query: any) => {
  return request({
    url: "/api-v1/v1/warningRule/all",
    method: "get",
    params: query
  });
};
export const getKnowsList = (query: any) => {
  return request({
    url: "/api-v1/v1/task/getKnowOption",
    method: "get",
    params: query
  });
};
export const saveCameraAndTask = (params: any) => {
  return request({
    url: "/api-v1/v1/task/add",
    method: "post",
    data: params
  });
};
export const updateCameraAndTask = (params: any) => {
  return request({
    url: "/api-v1/v1/task/update",
    method: "put",
    data: params
  });
};
src/pages/analysisPower/index/App.vue
@@ -116,13 +116,15 @@
            </template>
          </el-table-column>
          <el-table-column
            label="督查任务"
            label="执行算法"
            align="center"
            show-overflow-tooltip
          >
            <template slot-scope="scope">
              <span v-if="scope.row.run_type === -1">-</span>
              <span v-else-if="scope.row.TaskNames != null">{{(scope.row.TaskNames || []).map(r => r.taskName).join('/') || ''}}</span>
              <span v-else-if="scope.row.tasks != null">{{
                scope.row.tasks | taskList
              }}</span>
              <span v-else>-</span>
            </template>
          </el-table-column>
@@ -134,7 +136,7 @@
          >
            <template slot-scope="scope">
              <span v-if="scope.row.run_type === -1">-</span>
              <span v-else>{{ scope.row.run_server_name }}</span>
              <span v-else>{{ scope.row.runServerName }}</span>
            </template>
          </el-table-column>
          <el-table-column
@@ -158,9 +160,7 @@
          >
            <template slot-scope="scope">
              <span v-if="scope.row.run_type === -1">-</span>
              <span v-else-if="scope.row.run_type === 1">{{ "轮询" }}</span>
              <span v-else>{{ "实时" }}</span>
              <!-- <toggle-button
              <toggle-button
                v-else
                :value="scope.row.run_type === 1"
                :width="60"
@@ -172,7 +172,7 @@
                }"
                :sync="true"
                @change="pollSwitch(scope.row)"
              /> -->
              />
            </template>
          </el-table-column>
        </el-table>
@@ -436,25 +436,25 @@
      }, 10 * 1000);
    },
    pollSwitch(row) {
      // changeRunType({ camera_ids: [row.id], run_type: row.run_type ^ 1 }).then(
      //   (rsp) => {
      //     if (rsp && rsp.success) {
      //       this.$notify({
      //         type: "success",
      //         message: "配置成功",
      //       });
      changeRunType({ camera_ids: [row.id], run_type: row.run_type ^ 1 }).then(
        (rsp) => {
          if (rsp && rsp.success) {
            this.$notify({
              type: "success",
              message: "配置成功",
            });
      //       row.run_type = row.run_type ^ 1;
      //     } else {
      //       this.$notify({
      //         type: "error",
      //         message: "配置失败",
      //       });
      //     }
            row.run_type = row.run_type ^ 1;
          } else {
            this.$notify({
              type: "error",
              message: "配置失败",
            });
          }
      //     // this.PollData.fetchPollList();
      //   }
      // );
          // this.PollData.fetchPollList();
        }
      );
    },
    initLineChart() {
      // console.log(this.barChart,'initLineChart')
src/pages/cameraAccess/components/CameraInfo.vue
@@ -94,7 +94,7 @@
      <el-row>
        <!-- 添加传感器 -->
        <CameraInfoEditor ref="cameraEditor" :Carmeras="form" :sensors="sensors"></CameraInfoEditor>
        <!-- <CameraInfoEditor ref="cameraEditor" :Carmeras="form" :sensors="sensors"></CameraInfoEditor> -->
      </el-row>
      <el-row style="padding-top: 15px">
src/pages/cameraAccess/components/SceneRule.vue
@@ -1,21 +1,21 @@
<template>
  <div class="scene-edit-container">
    <div class="scene-title">
      <b style="font-size: 14px; line-height: 18px">场景</b>
      <b style="font-size: 14px; line-height: 18px">督查任务</b>
      <el-button
        type="primary"
        size="mini"
        @click="handleCreate"
        style="margin-left: 90%"
        v-show="!editScene && TreeDataPool.selectedNode.type !== 'MENU'"
        >+ 添加场景</el-button
        >+ 添加任务</el-button
      >
    </div>
    <el-form ref="form" label-width="80px" v-show="editScene">
      <div class="flex-form">
        <div class="left">
          <el-form-item label="场景名称">
          <el-form-item label="任务名称">
            <el-input
              v-model="sceneForm.scene_name"
              size="mini"
@@ -38,7 +38,7 @@
          </el-form-item>
          <el-form-item label="时间段">
            <el-select
              v-model="sceneForm.time_rule_id"
              v-model="sceneForm.workingTimes"
              placeholder="请选择"
              size="mini"
            >
@@ -50,16 +50,39 @@
              ></el-option>
            </el-select>
          </el-form-item>
          <!-- 检测内容 -->
        <el-form-item label="检测内容">
          <el-select v-model="sceneForm.checkContents" multiple placeholder="请选择"
              size="mini">
            <el-option v-for="item in VideoManageData.checkOptions" :key="item.checkId" :label="item.fileName"
              :value="item.checkId"></el-option>
          </el-select>
        </el-form-item>
        <!-- 预警规则 -->
        <el-form-item label="预警规则">
          <el-select v-model="sceneForm.warningRules" placeholder="请选择"
              size="mini" multiple>
            <el-option v-for="item in VideoManageData.ruleOptions" :key="item.ruleId" :label="item.fileName"
              :value="item.ruleId"></el-option>
          </el-select>
        </el-form-item>
        <!-- 知识库 -->
        <!-- <el-form-item label="知识库"
              size="mini">
          <el-cascader v-model="sceneForm.knowsList" :options="VideoManageData.knowledgeOptions" :props="knowledgeProps" clearable
            filterable placeholder="请选择" class="knowledge-cascader" :show-all-levels="false"></el-cascader>
        </el-form-item> -->
        </div>
        <div class="right">
          <el-form-item label="场景描述">
          <el-form-item label="任务描述">
            <el-input
              v-model="sceneForm.desc"
              type="textarea"
              size="mini"
            ></el-input>
          </el-form-item>
          <el-form-item label="事件声音">
          <!-- <el-form-item label="事件声音">
            <el-select
              v-model="sceneForm.voice"
              placeholder="空"
@@ -90,17 +113,18 @@
                style="font-size: 26px; vertical-align: middle; color: #409eff"
              ></i>
            </span>
          </el-form-item>
          </el-form-item> -->
        </div>
      </div>
      <scene-editor
      <!-- <scene-editor
        ref="sceneEditor"
        :isLinkRule="linkRule"
        :Cameras="seletedCameras"
        :ruleList="templateRules"
        @sdkNameChange="getSceneName"
      ></scene-editor>
      ></scene-editor> -->
      <el-form-item style="width: 60%; min-width: 1048px">
        <el-button size="mini" @click="editScene = false">取消</el-button>
@@ -126,12 +150,17 @@
            align="center"
          ></el-table-column>
          <el-table-column
            label="场景名称"
            label="任务名称"
            prop="scene_name"
            align="center"
            show-overflow-tooltip
          ></el-table-column>
          <el-table-column
          <el-table-column label="事件等级" align="center">
            <template slot-scope="scope">
              <span>{{ scope.row.alarm_level | alarmLevel }}</span>
            </template>
          </el-table-column>
          <!-- <el-table-column
            label="策略"
            prop="group_text"
            align="center"
@@ -140,12 +169,43 @@
            <template slot-scope="scope">
              <span v-html="scope.row.group_text"></span>
            </template>
          </el-table-column>
          </el-table-column> -->
          <el-table-column
            label="时间段"
            prop="time_name"
            align="center"
          ></el-table-column>
          >
            <template slot-scope="scope">
            {{(scope.row.workingTime || []).map(r => r.labelName).join(' / ') || ''}}
              </template>
          </el-table-column>
          <el-table-column
            label="检测内容"
            prop="checkContent"
            align="center"
          >
            <template slot-scope="scope">
            {{(scope.row.checkContent || []).map(r => r.fileName).join(' / ') || ''}}
              </template>
          </el-table-column>
          <el-table-column
            label="预警规则"
            prop="warningRule"
            align="center"
          >
            <template slot-scope="scope">
            {{(scope.row.warningRule || []).map(r => r.fileName).join(' / ') || ''}}
              </template>
          </el-table-column>
          <el-table-column
            label="知识库"
            prop="knowledge"
            align="center"
          >
            <template slot-scope="scope">
            {{(scope.row.knowledge || []).map(r => r.fileName).join(' / ') || ''}}
              </template>
          </el-table-column>
          <el-table-column
            label="描述"
            prop="desc"
@@ -157,16 +217,11 @@
              <el-switch v-model="scope.row.defence_state" @change="updateDefence(scope.row)"></el-switch>
            </template>
          </el-table-column>-->
          <el-table-column label="事件声音" align="center">
          <!-- <el-table-column label="事件声音" align="center">
            <template slot-scope="scope">
              <span>{{ getSoundById(scope.row.voiceId) }}</span>
            </template>
          </el-table-column>
          <el-table-column label="事件等级" align="center">
            <template slot-scope="scope">
              <span>{{ scope.row.alarm_level | alarmLevel }}</span>
            </template>
          </el-table-column>
          </el-table-column> -->
          <el-table-column label="操作" fixed="right" align="center">
            <template slot-scope="scope">
              <el-tooltip
@@ -202,7 +257,7 @@
</template>
<script>
import { saveCameraScene, deleteCameraScene } from "@/api/scene";
import { saveCameraScene, deleteCameraScene,deleteCameraSceneTwo } from "@/api/scene";
import RuleEditor from "@/components/subComponents/RuleEditor";
import SceneEditor from "./scene/Editor";
import { getSoundList } from "@/api/event";
@@ -440,7 +495,7 @@
      if (!this.sceneForm.scene_name.trim()) {
        this.$notify({
          type: "warning",
          message: "场景名不能为空",
          message: "任务名不能为空",
        });
        return false;
      } else if (!this.sceneForm.alarm_level) {
@@ -449,7 +504,7 @@
          message: "事件等级不能为空",
        });
        return false;
      } else if (!this.sceneForm.time_rule_id) {
      } else if (!this.sceneForm.workingTimes) {
        this.$notify({
          type: "warning",
          message: "时间段不能为空",
@@ -462,27 +517,46 @@
      if (!this.validateForm()) {
        return;
      }
      let editorResp = this.$refs.sceneEditor.submitRule();
      if (!editorResp) {
        return;
      }
      this.sceneForm.rules = editorResp.rules;
      this.sceneForm.id = editorResp.id;
      this.sceneForm.group_text = editorResp.text;
      // let editorResp = this.$refs.sceneEditor.submitRule();
      // if (!editorResp) {
      //   return;
      // }
      // this.sceneForm.rules = editorResp.rules;
      // this.sceneForm.id = editorResp.id;
      // this.sceneForm.group_text = editorResp.text;
      const workTimes = [this.sceneForm.workingTimes].map(id => {
          const timeOption = this.VideoManageData.TimeRules.find(opt => opt.id === id)
          return {
            labelId: id,
            labelName: timeOption ? timeOption.name : ''
          }
        })
      this.sceneForm.taskName = this.sceneForm.scene_name
      this.sceneForm.eventLevel = this.sceneForm.alarm_level
      this.sceneForm.checks = this.sceneForm.checkContents
      this.sceneForm.rules = this.sceneForm.warningRules
      this.sceneForm.workTimes = workTimes
      this.sceneForm.taskDescription = this.sceneForm.desc
      this.onSaveScene(this.sceneForm);
    },
    handleDelScene(groupRule) {
      let _this = this;
      this.$confirm("提示:删除后,该条规则将失效,是否删除?", {
      this.$confirm("提示:删除后,该条任务将失效,是否删除?", {
        center: true,
        cancelButtonClass: "comfirm-class-cancle",
        confirmButtonClass: "comfirm-class-sure",
      })
        .then(() => {
          deleteCameraScene(groupRule.id).then((res) => {
          // console.info("groupRule:"+JSON.stringify(groupRule))
          deleteCameraSceneTwo(
            {
            taskId: groupRule.taskId
          }
          ).then((res) => {
            this.$emit("delete-rule");
            if (res && res.success) {
            if (res && res.status === 200) {
              // console.info("删除成功")
              this.$notify({
                type: "success",
                message: "删除成功",
src/pages/cameraAccess/components/SeparateRules.vue
@@ -6,42 +6,29 @@
          <div v-show="cameraType === 'camera'">
            <span>
              <span class="label">视频分析处理</span>
              <el-switch
                style="margin-left: 10px"
                v-model="Camera.analytics"
                @change="pollEnable"
                :disabled="!Camera.cameraId"
              ></el-switch>
              <el-switch style="margin-left: 10px" v-model="Camera.analytics" @change="pollEnable"
                :disabled="!Camera.cameraId"></el-switch>
            </span>
          </div>
          <div v-if="Camera.analytics && isShowPolling === 'show'" class="flex-box" v-show="cameraType === 'camera'">
            <span class="label">处理方式</span>
            <toggle-button
              :value="Camera.dealWay"
              :width="60"
              :labels="{ checked: '实时', unchecked: '轮询' }"
              :color="{
                checked: '#3D68E1',
                unchecked: '#FF7733',
                disabled: '#CCCCCC'
              }"
              :sync="true"
              @change="changePoll"
            />
            <toggle-button :value="Camera.dealWay" :width="60" :labels="{ checked: '实时', unchecked: '轮询' }" :color="{
              checked: '#3D68E1',
              unchecked: '#FF7733',
              disabled: '#CCCCCC'
            }" :sync="true" @change="changePoll" />
          </div>
          <div v-if="Camera.analytics" class="flex-box" v-show="cameraType === 'camera'">
            <span class="label">处理状态: {{ camStatus }}</span>
          </div>
          <div v-if="Camera.analytics" class="flex-box" v-show="cameraType === 'camera'">
            <span class="label"
              >分辨率:
            <span class="label">分辨率:
              {{
                Camera.camearInfo.resolution_width == 0 || Camera.camearInfo.resolution_height == 0
                  ? "本机分辨率"
                  : `${Camera.camearInfo.resolution_width} * ${Camera.camearInfo.resolution_height}`
              }}</span
            >
              }}</span>
          </div>
          <div v-if="Camera.analytics" class="flex-box">
@@ -52,29 +39,15 @@
            <span class="label">算法快速通道</span>
            <div class="channel flex-box">
              <el-tooltip effect="dark" content="复制此摄像机算法规则" placement="bottom" popper-class="atooltip">
                <span
                  style="color: #3d68e1; cursor: pointer; font-size: 23px"
                  @click="ctrlC"
                  class="iconfont iconfuzhiguize"
                ></span>
                <span style="color: #3d68e1; cursor: pointer; font-size: 23px" @click="ctrlC"
                  class="iconfont iconfuzhiguize"></span>
              </el-tooltip>
              <el-tooltip
                effect="dark"
                :content="
                  !TreeDataPool.ctrlCameraId ? '粘贴算法规则' : `粘贴算法规则,来源:${TreeDataPool.ctrlCameraName}`
                "
                placement="bottom"
                popper-class="atooltip"
              >
                <span
                  :style="
                    !TreeDataPool.ctrlCameraId
                      ? 'cursor: not-allowed;font-size:23px;'
                      : 'color:#3D68E1;font-size:23px;cursor: pointer;'
                  "
                  @click="ctrlV"
                  class="iconfont iconniantie ml5"
                ></span>
              <el-tooltip effect="dark" :content="!TreeDataPool.ctrlCameraId ? '粘贴算法规则' : `粘贴算法规则,来源:${TreeDataPool.ctrlCameraName}`
                " placement="bottom" popper-class="atooltip">
                <span :style="!TreeDataPool.ctrlCameraId
                  ? 'cursor: not-allowed;font-size:23px;'
                  : 'color:#3D68E1;font-size:23px;cursor: pointer;'
                  " @click="ctrlV" class="iconfont iconniantie ml5"></span>
              </el-tooltip>
            </div>
          </div>
@@ -86,17 +59,13 @@
    <div class="top">
      <p class="task-css">
        <b style="font-size: 14px; line-height: 18px">场景</b>
        <b style="font-size: 14px; line-height: 18px">督查任务</b>
      </p>
      <div class="clearfix">
        <slide-scene :sceneData="Camera.rules"></slide-scene>
        <div class="top-right">
          <sysinfo
            :showRealPoll="cameraType === 'camera'"
            :ShowLocalVedio="cameraType === 'dataStack'"
            v-if="showSysInfo"
            style="margin-top: -10px"
          />
          <sysinfo :showRealPoll="cameraType === 'camera'" :ShowLocalVedio="cameraType === 'dataStack'"
            v-if="showSysInfo" style="margin-top: -10px" />
        </div>
      </div>
    </div>
@@ -119,61 +88,28 @@
            </div>
            <div class="img-box">
              <template v-if="TreeDataPool.treeActiveName == 'camera'">
                <polygon-canvas
                  class="cavas"
                  ref="canvas"
                  v-if="showCanvas"
                  v-loading="loading"
                  element-loading-text="刷新中,请稍等..."
                  element-loading-background="rgba(0, 0, 0, 0.8)"
                  :isShowDrawArrow="false"
                  :disabled="false"
                  :snapshot_url="Camera.baseImg"
                  :canvasDataShow="Camera.canvasData"
                  :currentCameraId="Camera.cameraId"
                  :loading="Camera.loading"
                  :canvasWidth="canvasWidth"
                  :canvasHeight="canvasHeight"
                  :isGB28181="Camera.gb28181"
                  @fromCanvas="getCanvasData"
                  @changeLoading="changeLoading"
                  @refresh="refresh"
                >
                <polygon-canvas class="cavas" ref="canvas" v-if="showCanvas" v-loading="loading"
                  element-loading-text="刷新中,请稍等..." element-loading-background="rgba(0, 0, 0, 0.8)"
                  :isShowDrawArrow="false" :disabled="false" :snapshot_url="Camera.baseImg"
                  :canvasDataShow="Camera.canvasData" :currentCameraId="Camera.cameraId" :loading="Camera.loading"
                  :canvasWidth="canvasWidth" :canvasHeight="canvasHeight" :isGB28181="Camera.gb28181"
                  @fromCanvas="getCanvasData" @changeLoading="changeLoading" @refresh="refresh">
                </polygon-canvas>
              </template>
              <template v-else>
                <div style="width: 100%" v-loading="getStackFileLoading">
                  <swiper
                    ref="swiper"
                    :auto-update="true"
                    :options="canvasSwiperOption"
                    @slideChange="swiperSlideChange"
                    class="swiper-box-container2"
                    style="width: 100%"
                  >
                  <swiper ref="swiper" :auto-update="true" :options="canvasSwiperOption"
                    @slideChange="swiperSlideChange" class="swiper-box-container2" style="width: 100%">
                    <swiper-slide v-for="(data, index) in swipercanvasData" :key="index">
                      <div>
                        <b class="video-title" style="font-size: 14px; margin-top: -10px">{{ data.name }}</b>
                        <polygon-canvas
                          class="cavas"
                          ref="canvas"
                          v-if="showCanvas"
                          v-loading="loading"
                          element-loading-text="刷新中,请稍等..."
                          element-loading-background="rgba(0, 0, 0, 0.8)"
                          :isShowDrawArrow="false"
                          :isShowRefresh="false"
                          :sourceType="data.type"
                          :disabled="false"
                          :snapshot_url="data.baseImg"
                          :canvasDataShow="Camera.canvasData"
                          :currentCameraId="data.stackId"
                          :loading="data.loading"
                          :canvasWidth="canvasWidth"
                          :canvasHeight="canvasHeight"
                          @fromCanvas="getCanvasData"
                          @changeLoading="changeLoading"
                        ></polygon-canvas>
                        <polygon-canvas class="cavas" ref="canvas" v-if="showCanvas" v-loading="loading"
                          element-loading-text="刷新中,请稍等..." element-loading-background="rgba(0, 0, 0, 0.8)"
                          :isShowDrawArrow="false" :isShowRefresh="false" :sourceType="data.type" :disabled="false"
                          :snapshot_url="data.baseImg" :canvasDataShow="Camera.canvasData"
                          :currentCameraId="data.stackId" :loading="data.loading" :canvasWidth="canvasWidth"
                          :canvasHeight="canvasHeight" @fromCanvas="getCanvasData"
                          @changeLoading="changeLoading"></polygon-canvas>
                      </div>
                    </swiper-slide>
                  </swiper>
@@ -192,14 +128,11 @@
            </div>
          </div>
          <div style="float: left; width: calc(10% - 90px); height: 100%"></div>
          <div
            class="time-box"
            style="
          <div class="time-box" style="
              width: calc(90% + 90px - 576px);
              overflow-x: auto;
              overflow-y: hidden;
            "
          >
            ">
            <p style="text-align: left; padding: 10px; box-sizing: border-box">
              <b style="font-size: 14px">时间段</b>
            </p>
@@ -208,12 +141,8 @@
        </div>
        <!-- 场景规则 -->
        <scene-rule
          :seletedCameras="[Camera]"
          :tableRuleList="Camera.rules"
          :onSaveScene="saveSceneRule"
          @delete-rule="delScenRule"
        ></scene-rule>
        <scene-rule :seletedCameras="[Camera]" :tableRuleList="Camera.rules" :onSaveScene="saveSceneRule"
          @delete-rule="delScenRule"></scene-rule>
      </div>
    </div>
  </div>
@@ -226,6 +155,7 @@
import { getCameraInfo } from "@/api/camera"
import { getGB28181CameraInfo } from "@/api/camera"
import { saveCameraScene } from "@/api/scene"
import { saveCameraAndTask, updateCameraAndTask } from "@/api/selectRule";
import { changeRunType } from "@/api/pollConfig"
import { findAllFileByStackId } from "@/api/localVedio"
@@ -247,7 +177,7 @@
  },
  directives: {
    focus: {
      inserted: function(el) {
      inserted: function (el) {
        el.querySelector("input").focus()
      }
    }
@@ -469,19 +399,37 @@
    saveSceneRule(groupRule) {
      const payload = { ...groupRule }
      payload.cameraIds = [this.Camera.cameraId]
      payload.videoId = [this.Camera.cameraId][0]
      let _this = this
      saveCameraScene(payload).then((rsp) => {
        if (rsp && rsp.success) {
          this.Camera.update()
          this.$notify({
            type: "success",
            message: "策略保存成功!"
          })
          //刷新左侧树
          _this.$root.$children[0].$children[0].querySearchAsync("camera")
        }
      })
      if (payload.taskId) {
        updateCameraAndTask(payload).then((rsp) => {
          if (rsp && rsp.status === 200) {
            this.Camera.update()
            this.$notify({
              type: "success",
              message: "编辑成功!"
            })
            //刷新左侧树
            _this.$root.$children[0].$children[0].querySearchAsync("camera")
          }
        })
      } else {
        saveCameraAndTask(payload).then((rsp) => {
          if (rsp && rsp.status === 200) {
            this.Camera.update()
            this.$notify({
              type: "success",
              message: "保存成功!"
            })
            //刷新左侧树
            _this.$root.$children[0].$children[0].querySearchAsync("camera")
          }
        })
      }
    },
    delScenRule() {
      this.Camera.update()
@@ -628,6 +576,7 @@
.el-message--info .el-message__content {
  color: #999 !important;
}
.swiper-container {
  margin-left: auto;
  margin-right: auto;
@@ -637,6 +586,7 @@
  padding: 0;
  z-index: 1;
}
.swiper-local-prev,
.swiper-local-next {
  width: 40px;
@@ -647,6 +597,7 @@
  z-index: 99;
  border-radius: 4em;
  outline: none;
  .icon-btn {
    color: rgb(255, 255, 255);
    text-align: center;
@@ -654,48 +605,59 @@
    cursor: pointer;
  }
}
.swiper-local-prev {
  left: 10px;
}
.swiper-local-prev:hover {
  background: #666;
}
.swiper-local-next {
  left: 90%;
}
.swiper-local-next:hover {
  background: #666;
}
.s-separate-rules {
  width: 100%;
  padding: 13px 0 20px;
  .ai {
    //width: calc(100% + 76px);
    // height: 38px;
    // position: absolute;
    // left: -38px;
    height: 40px;
    .check-area {
      width: 100%;
      height: 100%;
      padding: 0 20px;
      -webkit-box-sizing: border-box;
      box-sizing: border-box;
      .ai-select {
        text-align: left;
        line-height: 30px;
        height: 30px;
        .flex-box {
          .label {
            & + label,
            & + div {
            &+label,
            &+div {
              margin-left: 10px;
              line-height: 1;
            }
          }
        }
      }
      .ai-select > div {
      .ai-select>div {
        display: inline-block;
        vertical-align: middle;
        margin-right: 30px;
@@ -707,14 +669,17 @@
      }
    }
  }
  .devide {
    height: 10px;
    background: #e9ebf2;
  }
  .top {
    width: 100%;
    padding: 10px 20px;
    box-sizing: border-box;
    .swiper-box {
      height: 100%;
      float: left;
@@ -722,14 +687,17 @@
      margin-top: -10px;
      position: relative;
    }
    .swiper-container {
      position: initial;
      min-width: 472px;
      width: 86%;
    }
    .swiper-slide {
      position: relative;
      width: 100%;
      .item-card {
        height: 110px !important;
        max-width: 126px;
@@ -745,6 +713,7 @@
        box-shadow: 0 5px 12px 0 rgba(0, 0, 0, 0.07);
        border-radius: 4px;
        cursor: pointer;
        .icon-xingzhuangcopy {
          position: relative;
          left: 0px;
@@ -764,16 +733,19 @@
          backdrop-filter: blur(1px) brightness(100%);
          display: none;
        }
        @media screen and (max-width: 1440px) {
          max-width: 110px;
        }
      }
      .item-card:hover {
        .mask {
          display: block;
        }
      }
    }
    .swiper-pre-border,
    .swiper-next-border {
      width: 40px;
@@ -784,6 +756,7 @@
      z-index: 99;
      border-radius: 4em;
      outline: none;
      .icon-btn {
        color: rgb(255, 255, 255);
        text-align: center;
@@ -791,15 +764,19 @@
        cursor: pointer;
      }
    }
    .swiper-pre-border {
      left: 10px;
    }
    .swiper-pre-border:hover {
      background: #666;
    }
    .swiper-next-border {
      right: 10px;
    }
    .swiper-next-border:hover {
      background: #666;
    }
@@ -808,24 +785,30 @@
      float: right;
      width: 54%;
      height: 144px;
      .card-box {
        width: 54% !important;
      }
      .eCharts-box {
        width: 45%;
        canvas {
          width: 98% !important;
        }
      }
    }
    .task-css {
      text-align: left;
      margin-bottom: 14px;
    }
  }
  .bottom {
    width: 100%;
    margin-bottom: 15px;
    .bottom-side {
      height: 100%;
      width: 250px;
@@ -835,6 +818,7 @@
      border-bottom: 1px solid #ccc;
      padding: 10px;
      box-sizing: border-box;
      .selectTask {
        margin: 10px auto;
        width: 140px;
@@ -842,6 +826,7 @@
        box-sizing: border-box;
        border: 1px solid #ccc;
        position: relative;
        .selectTaskDelete {
          position: absolute;
          right: 10px;
@@ -850,17 +835,21 @@
        }
      }
    }
    .bottom-right {
      padding: 10px 20px;
      box-sizing: border-box;
      .draw-and-time-box {
        height: 400px;
        width: 100%;
        //min-width: 1150px;
        .draw-box,
        .time-box {
          float: left;
          height: 100%;
          .img-box {
            height: calc(100% - 32px);
            //width: 90%;
@@ -871,48 +860,60 @@
            // align-items: center;
            position: relative;
            overflow: hidden;
            .refresh-btn {
              position: absolute;
              right: 10px;
              top: 10px;
            }
            img {
              width: 90%;
              padding: 5px;
              box-sizing: border-box;
            }
            .swiper-box-container {
              margin-top: -10px;
              text-align: left;
              padding: 0px 8px 0px 8px;
              .el-card__body {
                height: 100%;
                padding: 0px;
              }
              height: calc(100% - 10px);
              .info {
                width: 100%;
                height: 100%;
                .info-left {
                  width: 50%;
                  height: 100%;
                  float: left;
                  img {
                    width: 100%;
                  }
                }
                .info-right {
                  width: 50%;
                  height: 100%;
                  float: left;
                  box-sizing: border-box;
                  padding: 10px;
                  p {
                    padding: 4px 0px;
                  }
                  .infoIcon {
                    height: 24px;
                    cursor: pointer;
                    i {
                      margin: 5px;
                      font-size: 22px;
@@ -921,6 +922,7 @@
                }
              }
            }
            .pre-border,
            .next-border {
              width: 40px;
@@ -931,6 +933,7 @@
              z-index: 99;
              border-radius: 4em;
              outline: none;
              .icon-btn {
                color: rgb(255, 255, 255);
                text-align: center;
@@ -938,26 +941,33 @@
                cursor: pointer;
              }
            }
            .pre-border {
              left: -9px;
            }
            .pre-border:hover {
              background: #666;
            }
            .next-border {
              right: 10px;
            }
            .next-border:hover {
              background: #666;
            }
          }
        }
        .draw-box {
          width: 576px;
        }
        .draw-box-title {
          text-align: left;
          margin-top: -3px;
          .btn-css {
            position: relative;
            left: 514px;
@@ -966,6 +976,7 @@
        }
      }
    }
    .bottom-right::-webkit-scrollbar {
      width: 0 !important;
    }
@@ -977,9 +988,11 @@
    font-size: 14px;
    cursor: pointer;
  }
  .add-btn:hover {
    color: #2249b4;
  }
  .nocamera-css {
    cursor: not-allowed;
    color: #3d68e1;
@@ -995,22 +1008,25 @@
    margin-right: 7px;
    background: #3d68e1;
  }
  .loadingClass {
    text-align: center;
  }
  .el-loading-spinner-div {
  }
  .el-loading-spinner-div {}
}
</style>
<style lang="scss" scoped>
.el-dropdown-menu {
  width: 200px;
  .el-dropdown-menu__item {
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
  }
}
.el-loading-spinner {
  background: url("/images/cameraAccess/loading.gif") no-repeat;
  top: 50%;
@@ -1019,6 +1035,7 @@
  text-align: center;
  position: absolute;
  margin-left: 260px;
  .el-loading-text {
    color: #3d68e1;
    margin: 3px 0;
src/pages/cameraAccess/index/VideoManage.vue
@@ -28,7 +28,7 @@
        <data-stack-info ref="dataStackInfo" />
      </el-tab-pane>
      <el-tab-pane
        label="独立场景"
        label="督查任务"
        name="separate-rule"
        v-if="
          this.TreeDataPool.treeActiveName == 'camera' &&
@@ -49,7 +49,7 @@
        <separate-rules ref="sepRule" />
        <!-- <local-separate ref="localSeparate" v-else></local-separate> -->
      </el-tab-pane>
      <el-tab-pane
      <!-- <el-tab-pane
        label="联动场景"
        name="linkage-rule"
        v-if="
@@ -58,7 +58,7 @@
        "
      >
        <linkage-rule ref="linkRule" />
      </el-tab-pane>
      </el-tab-pane> -->
    </el-tabs>
  </div>
</template>