ZZJ
2022-06-10 58bf48cea61c6c5b4381a4b8ff5b4a39eb4671eb
国标摄像机信息接口
9个文件已修改
1516 ■■■■■ 已修改文件
src/Pool/VideoRuleData.ts 33 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/camera.ts 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/player/index.vue 158 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/wasmPlayer/index.vue 478 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pages/cameraAccess/components/CameraInfo.vue 129 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pages/cameraAccess/components/LinkageRule.vue 161 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pages/cameraAccess/components/SeparateRules.vue 427 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pages/cameraAccess/index/VideoManage.vue 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
vue.config.js 107 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/Pool/VideoRuleData.ts
@@ -1,4 +1,4 @@
import { getCameraInfo } from "@/api/camera";
import { getCameraInfo,getGB28181CameraInfo } from "@/api/camera";
import { getAllPolygon } from "@/api/polygon";
import { getDirDetails, findAllFileByStackId } from "@/api/localVedio";
import { getCameraSceneRule } from '@/api/scene'
@@ -23,7 +23,7 @@
  public selectResolution: string;
  public hasCtrlC: boolean;
  constructor(id: string) {
  constructor(id: string,isGB:boolean) {
    this.loading = false;
    this.baseImg = "";
    this.cameraId = id ? id : "";
@@ -44,7 +44,7 @@
    this.rules = [];
    if (id && id !== "") {
      this.update();
      this.update(isGB);
    }
    this.resolutionOption = [
@@ -65,23 +65,40 @@
    this.hasCtrlC = false
  }
  public async update() {
    await this.getInfo();
  public async update(isGB) {
    await this.getInfo(isGB);
    await this.getSceneRule();
    await this.getPolygon();
  }
  public async getInfo() {
  public async getInfo(isGB) {
    // 判断选中的是摄像机还是数据栈
    if (this.cameraId.indexOf("stack") === -1) {
      try {
        const rsp: any = await getCameraInfo(this.cameraId);
      //处理国标摄像机
      if(isGB) {
        try {
        const rsp: any = await getGB28181CameraInfo(this.cameraId);
        if (rsp.success) {
          this.cameraName = rsp.data.name ? rsp.data.name : "";
        }
      } catch {
        this.cameraName = "";
      }
      }
      else {
        try {
        const rsp: any = await getCameraInfo(this.cameraId);
        if (rsp.success) {
          this.cameraName = rsp.data.name ? rsp.data.name : "";
        }
        } catch {
          this.cameraName = "";
        }
      }
    } else {
      const rsp: any = await findAllFileByStackId({ stackId: this.cameraId });
      if (rsp.success && rsp.data.dataList.length) {
src/api/camera.ts
@@ -26,6 +26,14 @@
  });
};
export const getGB28181CameraInfo = (id: string) => {
  return request({
    url: "/data/api-v/gb28181/camera/show",
    method: "get",
    params: { cid: id }
  });
};
export const delCamera = (id: string) => {
  return request({
    url: "/data/api-v/camera/del",
src/components/player/index.vue
@@ -1,6 +1,12 @@
<template>
  <div class="video-player">
    <canvas v-show="showArea" id="area-canvas" ref="areaCanvas" width="960" height="540"></canvas>
    <canvas
      v-show="showArea"
      id="area-canvas"
      ref="areaCanvas"
      width="960"
      height="540"
    ></canvas>
    <video ref="videoPlayer" :poster="poster" preload="auto" muted></video>
    <div class="controls">
      <!-- 全屏 -->
@@ -20,36 +26,39 @@
    wsAddr: {
      type: String,
      // default: "ws://192.168.1.182:10101/ws"
      default: `${location.protocol === "https" ? "wss" : "ws"}://${location.host}/ws`
      default: `${location.protocol === "https" ? "wss" : "ws"}://${
        location.host
      }/ws`,
    },
    cameraName: {
      type: String,
      default: ""
      default: "",
    },
    cameraID: {
      type: String,
      default: "C4668FD0-3CAE-C31F-C21E-28B7001243C4"
      default: "C4668FD0-3CAE-C31F-C21E-28B7001243C4",
    },
    rtspUrl: {
      type: String,
      default: "rtsp://admin:a1234567@192.168.1.201:554/h264/ch1/main/av_stream"
      default:
        "rtsp://admin:a1234567@192.168.1.201:554/h264/ch1/main/av_stream",
    },
    isRunning: {
      type: Boolean,
      default: false
      default: false,
    },
    isGb: {
      type: Boolean,
      default: false
      default: false,
    },
    showArea: {
      type: Boolean,
      default: false
      default: false,
    },
    hasPoster:{
    hasPoster: {
      type: Boolean,
      default: true
    }
      default: true,
    },
  },
  computed: {
@@ -62,13 +71,13 @@
      wfs: {},
      poster: "/images/player/player_poster.gif?t=" + Math.random(),
      wfsId: 0,
      Camera: new VideoRuleData(),
      Camera: new VideoRuleData(this.isGb),
      showCanvas: true,
      canvasData: {
        line: [],
        rect: [], // {id:'uuid', name: '矩形1', location: [{ x: 20, y: 30 }, { x: 20, y: 60 }, { x: 100, y: 60 }, { x: 100, y: 30 }] }
        arrow: [],
        polygon: []
        polygon: [],
      },
      //showProportion: 3.2,
      //showProportionY: 3.58,
@@ -80,7 +89,7 @@
      ctx: null,
      canvasWidth: 0,
      canvasHeight: 0,
      algoDataSocket: null
      algoDataSocket: null,
    };
  },
  watch: {
@@ -89,14 +98,14 @@
      if (newVal !== oldVal) {
        if (this.wfs.config) {
          this.wfs.destroy();
          !!this.algoDataSocket && this.algoDataSocket.close()
          !!this.algoDataSocket && this.algoDataSocket.close();
        }
        this.$nextTick(() => {
          this.clickStart();
          this.poster = "/images/player/player_poster.gif?t=" + Math.random()
          this.poster = "/images/player/player_poster.gif?t=" + Math.random();
        });
      }
    }
    },
  },
  mounted() {
    this.clickStart();
@@ -105,34 +114,33 @@
      this.ctx = this.canvas.getContext("2d");
      this.ctx.lineWidth = 1;
      this.initArea();
    })
    });
  },
  beforeDestroy() {
    this.wfs.destroy();
    this.wfsId = "";
    !!this.algoDataSocket && this.algoDataSocket.close()
    !!this.algoDataSocket && this.algoDataSocket.close();
  },
  methods: {
    checkConnect(id) {
      // console.log(this.wfs)
      if (id !== this.wfsId) {
        return
        return;
      }
      if (this.wfs.websocketLoader && this.wfs.websocketLoader.client) {
        if (this.wfs.websocketLoader.client.disconnected) {
          this.clickStart();
          console.log("实时视频已断开,正在重连")
          return
          console.log("实时视频已断开,正在重连");
          return;
        }
      }
      let _this = this;
      setTimeout(() => {
        _this.checkConnect(id)
      }, 10000)
        _this.checkConnect(id);
      }, 10000);
    },
    clickStart() {
      if (this.rtspUrl == "") {
@@ -149,7 +157,7 @@
          cameraID: cameraId,
          rtspUrl: this.rtspUrl,
          isRunning: this.isRunning,
          isGb28181: this.isGb
          isGb28181: this.isGb,
        };
        // let camera = document.getElementById(this.cameraID);
@@ -159,7 +167,7 @@
        this.wfsId = randomId;
        this.wfs.attachMedia(camera, "chX", "H264Raw", wsAddr, cameraInfo);
        this.checkConnect(randomId)
        this.checkConnect(randomId);
      }
    },
    getUuid() {
@@ -185,22 +193,42 @@
      _this.canvasData.line.forEach(function (v, i) {
        _this.ctx.strokeStyle = "yellow";
        _this.ctx.beginPath();
        _this.ctx.moveTo(v.location[0].x / _this.showProportion, v.location[0].y / _this.showProportion);
        _this.ctx.lineTo(v.location[1].x / _this.showProportion, v.location[1].y / _this.showProportion);
        _this.ctx.moveTo(
          v.location[0].x / _this.showProportion,
          v.location[0].y / _this.showProportion
        );
        _this.ctx.lineTo(
          v.location[1].x / _this.showProportion,
          v.location[1].y / _this.showProportion
        );
        _this.ctx.stroke();
        _this.canvas.style.cursor = "default";
      });
      _this.canvasData.rect.forEach(function (v, i) {
        _this.ctx.strokeStyle = "yellow";
        _this.ctx.beginPath();
        _this.ctx.moveTo(v.location[0].x / _this.showProportion, v.location[0].y / _this.showProportion);
        _this.ctx.lineTo(v.location[1].x / _this.showProportion, v.location[1].y / _this.showProportion);
        _this.ctx.lineTo(v.location[2].x / _this.showProportion, v.location[2].y / _this.showProportion);
        _this.ctx.lineTo(v.location[3].x / _this.showProportion, v.location[3].y / _this.showProportion);
        _this.ctx.lineTo(v.location[0].x / _this.showProportion, v.location[0].y / _this.showProportion);
        _this.ctx.moveTo(
          v.location[0].x / _this.showProportion,
          v.location[0].y / _this.showProportion
        );
        _this.ctx.lineTo(
          v.location[1].x / _this.showProportion,
          v.location[1].y / _this.showProportion
        );
        _this.ctx.lineTo(
          v.location[2].x / _this.showProportion,
          v.location[2].y / _this.showProportion
        );
        _this.ctx.lineTo(
          v.location[3].x / _this.showProportion,
          v.location[3].y / _this.showProportion
        );
        _this.ctx.lineTo(
          v.location[0].x / _this.showProportion,
          v.location[0].y / _this.showProportion
        );
        _this.ctx.stroke();
        _this.canvas.style.cursor = "default";
      });
      _this.canvasData.arrow.forEach(function (v, i) {
        _this.ctx.strokeStyle = "yellow";
@@ -215,7 +243,6 @@
          "yellow"
        );
        _this.canvas.style.cursor = "default";
      });
      _this.canvasData.polygon.forEach(function (v, i) {
        if (v.location.length === 0) {
@@ -223,19 +250,34 @@
        }
        _this.ctx.strokeStyle = "yellow";
        _this.ctx.beginPath();
        _this.ctx.moveTo(v.location[0].x / _this.showProportion, v.location[0].y / _this.showProportionY);
        _this.ctx.moveTo(
          v.location[0].x / _this.showProportion,
          v.location[0].y / _this.showProportionY
        );
        for (let i = 1; i < v.location.length; i++) {
          _this.ctx.lineTo(v.location[i].x / _this.showProportion, v.location[i].y / _this.showProportionY);
          _this.ctx.lineTo(
            v.location[i].x / _this.showProportion,
            v.location[i].y / _this.showProportionY
          );
        }
        _this.ctx.closePath();
        _this.ctx.stroke();
        _this.canvas.style.cursor = "default";
      });
    },
    // 箭头绘制函数
    drawArrow(ctx, fromX, fromY, toX, toY, theta = 30, headlen = 10, width = 1, color = "yellow") {
    drawArrow(
      ctx,
      fromX,
      fromY,
      toX,
      toY,
      theta = 30,
      headlen = 10,
      width = 1,
      color = "yellow"
    ) {
      // ctx:Canvas绘图环境
      // fromX, fromY:起点坐标(也可以换成p1,只不过它是一个数组)
      // toX, toY:终点坐标 (也可以换成p2,只不过它是一个数组)
@@ -288,7 +330,7 @@
    getCanvasData(data) {
      let polyon = { ...data };
      polyon.camera_id = this.Camera.cameraId;
      savePolygon(polyon).then(rsp => {
      savePolygon(polyon).then((rsp) => {
        this.Camera.getPolygon();
        this.Camera.getCameraTask();
      });
@@ -296,35 +338,37 @@
    setWidthHeight() {
      this.canvasWidth = this.$refs.videoPlayer.offsetWidth;
      this.canvasHeight = this.$refs.videoPlayer.offsetHeight;
      console.log(this.canvasWidth, this.canvasHeight)
      console.log(this.canvasWidth, this.canvasHeight);
    },
    async initArea() {
      console.log('init')
      const res = await getAllPolygon({ cameraId: this.TreeDataPool.selectedNode.id });
      console.log("init");
      const res = await getAllPolygon({
        cameraId: this.TreeDataPool.selectedNode.id,
      });
      this.canvasData.line = res.data.line;
      this.canvasData.rect = res.data.rect;
      this.canvasData.arrow = res.data.arrow;
      this.canvasData.polygon = res.data.polygon;
      console.log(this.canvasData)
      console.log(this.canvasData);
      this.clickSelect(this.canvasData);
    },
    initAlgoDataWebScoket() {
      if (typeof (WebSocket) === "undefined") {
        console.log("error,您的浏览器不支持socket")
      if (typeof WebSocket === "undefined") {
        console.log("error,您的浏览器不支持socket");
      } else {
        this.algoDataSocket = new WebSocket()
        this.algoDataSocket = new WebSocket();
        this.algoDataSocket.onopen = () => {
          console.log("socket连接成功")
        }
          console.log("socket连接成功");
        };
        this.algoDataSocket.onerror = () => {
          console.log("连接错误")
        }
        this.algoDataSocket.onmessage = msg => {
          console.log(msg)
        }
          console.log("连接错误");
        };
        this.algoDataSocket.onmessage = (msg) => {
          console.log(msg);
        };
      }
    }
  }
    },
  },
};
</script>
src/components/wasmPlayer/index.vue
@@ -1,6 +1,12 @@
<template>
  <div class="video-player">
    <canvas v-show="showArea" id="area-canvas" ref="areaCanvas" width="960" height="540"></canvas>
    <canvas
      v-show="showArea"
      id="area-canvas"
      ref="areaCanvas"
      width="960"
      height="540"
    ></canvas>
    <div class="container" id="videoPlayer">
      <div class="canvasDiv">
        <div
@@ -8,24 +14,46 @@
          element-loading-background="rgba(0, 0, 0, 0.8)"
          style="position: unset !important"
        ></div>
        <canvas ref="playCanvas" id="paly-canvas" width="960" height="540"></canvas>
        <canvas
          ref="playCanvas"
          id="paly-canvas"
          width="960"
          height="540"
        ></canvas>
      </div>
      <transition name="fade">
        <div class="popuptext" id="myPopup" v-if="fullScreenNotice">资源下载中,请稍后...</div>
        <div class="popuptext" id="myPopup" v-if="fullScreenNotice">
          资源下载中,请稍后...
        </div>
      </transition>
      <!-- 控制条 -->
      <section class="jsmodern-video-panel" :style="{ display: isStream ? 'none' : 'block' }">
      <section
        class="jsmodern-video-panel"
        :style="{ display: isStream ? 'none' : 'block' }"
      >
        <!-- 播放/暂停 -->
        <b :class="playerStatus == 0 ? 'jsmodern-video-play' : 'jsmodern-video-pause'" @click="playVideo"></b>
        <b
          :class="
            playerStatus == 0 ? 'jsmodern-video-play' : 'jsmodern-video-pause'
          "
          @click="playVideo"
        ></b>
        <!-- 时间 -->
        <span class="jsmodern-video-start" ref="timeLabel">00:00:00/00:00:00</span>
        <span class="jsmodern-video-start" ref="timeLabel"
          >00:00:00/00:00:00</span
        >
        <!-- 进度条 -->
        <div>
          <input class="jsmodern-video-linebox" ref="timeTrack" type="range" value="0" />
          <input
            class="jsmodern-video-linebox"
            ref="timeTrack"
            type="range"
            value="0"
          />
        </div>
        <!-- 声音 -->
@@ -36,15 +64,25 @@
        </div> -->
        <!-- 全屏 -->
        <b class="jsmodern-video-fullin" @click="fullScreen" :disable="false"></b>
        <b
          class="jsmodern-video-fullin"
          @click="fullScreen"
          :disable="false"
        ></b>
        <!-- 下载 -->
        <i class="el-icon-download jsmodern-video-download" @click="downLoad" v-show="!isStream"></i>
        <i
          class="el-icon-download jsmodern-video-download"
          @click="downLoad"
          v-show="!isStream"
        ></i>
      </section>
      <!-- 大播放按钮 -->
      <div v-show="!isStream">
        <span class="video-btn" v-show="playerStatus == 0" @click="playVideo"><img src="./wasm/img/bo1.png"/></span>
        <span class="video-btn" v-show="playerStatus == 0" @click="playVideo"
          ><img src="./wasm/img/bo1.png"
        /></span>
        <!-- 上一个 -->
        <span class="video-prve" v-show="showPrev">
@@ -58,7 +96,7 @@
        <!-- 播放失败 -->
        <span class="video-error" v-show="playerStatus == -1">
          <i class="el-icon-warning-outline" style="font-size:40px"></i>
          <i class="el-icon-warning-outline" style="font-size: 40px"></i>
          <br />
          视频加载失败 无效的视频地址
        </span>
@@ -71,77 +109,80 @@
/*
  2021.09.22 添加多个录像地址的处理, 与录像模块约定, 用 || 分割多个视频地址, 前端处理播放.
*/
import { Player } from "./wasm/player"
import VideoRuleData from "@/Pool/VideoRuleData"
import { getAllPolygon } from "@/api/polygon"
import { Player } from "./wasm/player";
import VideoRuleData from "@/Pool/VideoRuleData";
import { getAllPolygon } from "@/api/polygon";
export default {
  name: "CameraPlayer",
  props: {
    videoUrl: {
      type: String,
      // default: "ws://192.168.1.182:10101/ws"
      default: `${location.protocol === "https" ? "wss" : "ws"}://${location.host}/ws`
      default: `${location.protocol === "https" ? "wss" : "ws"}://${
        location.host
      }/ws`,
    },
    cameraName: {
      type: String,
      default: ""
      default: "",
    },
    cameraID: {
      type: String,
      default: "C4668FD0-3CAE-C31F-C21E-28B7001243C4"
      default: "C4668FD0-3CAE-C31F-C21E-28B7001243C4",
    },
    rtspUrl: {
      type: String,
      default: "rtsp://admin:a1234567@192.168.1.201:554/h264/ch1/main/av_stream"
      default:
        "rtsp://admin:a1234567@192.168.1.201:554/h264/ch1/main/av_stream",
    },
    isRunning: {
      type: Boolean,
      default: false
      default: false,
    },
    isGb: {
      type: Boolean,
      default: false
      default: false,
    },
    showArea: {
      type: Boolean,
      default: false
      default: false,
    },
    isStream: {
      type: Boolean,
      default: true
      default: true,
    },
    autoPlay: {
      type: Boolean,
      default: false
      default: false,
    },
    preload: {
      type: Boolean,
      default: true
    }
      default: true,
    },
  },
  computed: {
    poster() {
      return "/images/player/player_poster.gif?t=" + Math.random()
      return "/images/player/player_poster.gif?t=" + Math.random();
    },
    showPrev() {
      return this.playerIndex - 1 >= 0
      return this.playerIndex - 1 >= 0;
    },
    showNext() {
      return this.playerIndex + 1 < this.videoUrls.length
    }
      return this.playerIndex + 1 < this.videoUrls.length;
    },
  },
  data() {
    return {
      player: null,
      playerId: 0,
      Camera: new VideoRuleData(),
      Camera: new VideoRuleData(isGb),
      showCanvas: true,
      canvasData: {
        line: [],
        rect: [], // {id:'uuid', name: '矩形1', location: [{ x: 20, y: 30 }, { x: 20, y: 60 }, { x: 100, y: 60 }, { x: 100, y: 30 }] }
        arrow: [],
        polygon: []
        polygon: [],
      },
      //showProportion: 3.2,
      //showProportionY: 3.58,
@@ -161,90 +202,111 @@
      videoLoading: false,
      loadUrl: "",
      isFullScreen: false,
      fullScreenNotice: false
    }
      fullScreenNotice: false,
    };
  },
  watch: {
    rtspUrl: function(newVal, oldVal) {
    rtspUrl: function (newVal, oldVal) {
      if (newVal !== oldVal) {
        if (this.player) {
          this.player.stop()
          !!this.algoDataSocket && this.algoDataSocket.close()
          this.player.stop();
          !!this.algoDataSocket && this.algoDataSocket.close();
        }
        this.$nextTick(() => {
          this.playVideo()
        })
          this.playVideo();
        });
      }
    },
    videoUrl: function(newVal, oldVal) {
    videoUrl: function (newVal, oldVal) {
      if (newVal !== oldVal) {
        if (this.player) {
          this.player.stop()
          this.player.stop();
        }
        this.$nextTick(() => {
          this.player.preloadFlag = 0
          this.playVideo()
        })
          this.player.preloadFlag = 0;
          this.playVideo();
        });
      }
    }
    },
  },
  mounted() {
    this.player = new Player()
    this.player.preload = this.preload
    this.player.statusCallback = this.setPlayerStatus
    this.player = new Player();
    this.player.preload = this.preload;
    this.player.statusCallback = this.setPlayerStatus;
    if (this.isStream) {
      this.playVideo()
      this.playVideo();
      this.$nextTick(() => {
        this.canvas = this.$refs.areaCanvas
        this.ctx = this.canvas.getContext("2d")
        this.ctx.lineWidth = 1
        this.initArea()
      })
        this.canvas = this.$refs.areaCanvas;
        this.ctx = this.canvas.getContext("2d");
        this.ctx.lineWidth = 1;
        this.initArea();
      });
    } else {
      // 录像URL处理, 可能存在多个录像地址
      if (this.videoUrl === "") {
        this.playerStatus = -1
        return
        this.playerStatus = -1;
        return;
      }
      this.videoUrls = this.videoUrl.split("||")
      this.videoUrls = this.videoUrl.split("||");
      if (this.autoPlay || this.preload) {
        this.playVideo()
        this.playVideo();
      }
    }
  },
  beforeDestroy() {
    this.player.stop()
    this.player.stop();
  },
  methods: {
    // 回显cavas数据
    // 点击选中变色 将当前页面所有路径重绘判断当前鼠标的坐标在哪个图形内 如果不传坐标参数就是回显的方法
    clickSelect(e) {
      this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height)
      let _this = this // 集合中遍历需要将this转存一下使用
      _this.canvasData.line.forEach(function(v, i) {
        _this.ctx.strokeStyle = "yellow"
        _this.ctx.beginPath()
        _this.ctx.moveTo(v.location[0].x / _this.showProportion, v.location[0].y / _this.showProportion)
        _this.ctx.lineTo(v.location[1].x / _this.showProportion, v.location[1].y / _this.showProportion)
        _this.ctx.stroke()
        _this.canvas.style.cursor = "default"
      })
      _this.canvasData.rect.forEach(function(v, i) {
        _this.ctx.strokeStyle = "yellow"
        _this.ctx.beginPath()
        _this.ctx.moveTo(v.location[0].x / _this.showProportion, v.location[0].y / _this.showProportion)
        _this.ctx.lineTo(v.location[1].x / _this.showProportion, v.location[1].y / _this.showProportion)
        _this.ctx.lineTo(v.location[2].x / _this.showProportion, v.location[2].y / _this.showProportion)
        _this.ctx.lineTo(v.location[3].x / _this.showProportion, v.location[3].y / _this.showProportion)
        _this.ctx.lineTo(v.location[0].x / _this.showProportion, v.location[0].y / _this.showProportion)
        _this.ctx.stroke()
        _this.canvas.style.cursor = "default"
      })
      _this.canvasData.arrow.forEach(function(v, i) {
        _this.ctx.strokeStyle = "yellow"
      this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
      let _this = this; // 集合中遍历需要将this转存一下使用
      _this.canvasData.line.forEach(function (v, i) {
        _this.ctx.strokeStyle = "yellow";
        _this.ctx.beginPath();
        _this.ctx.moveTo(
          v.location[0].x / _this.showProportion,
          v.location[0].y / _this.showProportion
        );
        _this.ctx.lineTo(
          v.location[1].x / _this.showProportion,
          v.location[1].y / _this.showProportion
        );
        _this.ctx.stroke();
        _this.canvas.style.cursor = "default";
      });
      _this.canvasData.rect.forEach(function (v, i) {
        _this.ctx.strokeStyle = "yellow";
        _this.ctx.beginPath();
        _this.ctx.moveTo(
          v.location[0].x / _this.showProportion,
          v.location[0].y / _this.showProportion
        );
        _this.ctx.lineTo(
          v.location[1].x / _this.showProportion,
          v.location[1].y / _this.showProportion
        );
        _this.ctx.lineTo(
          v.location[2].x / _this.showProportion,
          v.location[2].y / _this.showProportion
        );
        _this.ctx.lineTo(
          v.location[3].x / _this.showProportion,
          v.location[3].y / _this.showProportion
        );
        _this.ctx.lineTo(
          v.location[0].x / _this.showProportion,
          v.location[0].y / _this.showProportion
        );
        _this.ctx.stroke();
        _this.canvas.style.cursor = "default";
      });
      _this.canvasData.arrow.forEach(function (v, i) {
        _this.ctx.strokeStyle = "yellow";
        _this.drawArrow(
          _this.ctx,
          v.location[0].x / _this.showProportion,
@@ -254,28 +316,44 @@
          20,
          30,
          "yellow"
        )
        _this.canvas.style.cursor = "default"
      })
      _this.canvasData.polygon.forEach(function(v, i) {
        );
        _this.canvas.style.cursor = "default";
      });
      _this.canvasData.polygon.forEach(function (v, i) {
        if (v.location && v.location.length === 0) {
          return
          return;
        }
        _this.ctx.strokeStyle = "yellow"
        _this.ctx.beginPath()
        _this.ctx.moveTo(v.location[0].x / _this.showProportion, v.location[0].y / _this.showProportionY)
        _this.ctx.strokeStyle = "yellow";
        _this.ctx.beginPath();
        _this.ctx.moveTo(
          v.location[0].x / _this.showProportion,
          v.location[0].y / _this.showProportionY
        );
        for (let i = 1; i < v.location.length; i++) {
          _this.ctx.lineTo(v.location[i].x / _this.showProportion, v.location[i].y / _this.showProportionY)
          _this.ctx.lineTo(
            v.location[i].x / _this.showProportion,
            v.location[i].y / _this.showProportionY
          );
        }
        _this.ctx.closePath()
        _this.ctx.stroke()
        _this.canvas.style.cursor = "default"
      })
        _this.ctx.closePath();
        _this.ctx.stroke();
        _this.canvas.style.cursor = "default";
      });
    },
    // 箭头绘制函数
    drawArrow(ctx, fromX, fromY, toX, toY, theta = 30, headlen = 10, width = 1, color = "yellow") {
    drawArrow(
      ctx,
      fromX,
      fromY,
      toX,
      toY,
      theta = 30,
      headlen = 10,
      width = 1,
      color = "yellow"
    ) {
      // ctx:Canvas绘图环境
      // fromX, fromY:起点坐标(也可以换成p1,只不过它是一个数组)
      // toX, toY:终点坐标 (也可以换成p2,只不过它是一个数组)
@@ -288,110 +366,110 @@
      // width = typeof width !== "undefined" ? width : 1;
      // color = typeof color !== "undefined" ? color : "yellow";
      // 计算各角度和对应的P2,P3坐标
      let angle = (Math.atan2(fromY - toY, fromX - toX) * 180) / Math.PI
      let angle1 = ((angle + theta) * Math.PI) / 180
      let angle2 = ((angle - theta) * Math.PI) / 180
      let topX = headlen * Math.cos(angle1)
      let topY = headlen * Math.sin(angle1)
      let botX = headlen * Math.cos(angle2)
      let botY = headlen * Math.sin(angle2)
      let angle = (Math.atan2(fromY - toY, fromX - toX) * 180) / Math.PI;
      let angle1 = ((angle + theta) * Math.PI) / 180;
      let angle2 = ((angle - theta) * Math.PI) / 180;
      let topX = headlen * Math.cos(angle1);
      let topY = headlen * Math.sin(angle1);
      let botX = headlen * Math.cos(angle2);
      let botY = headlen * Math.sin(angle2);
      ctx.save()
      ctx.beginPath()
      let arrowX = fromX - topX
      let arrowY = fromY - topY
      ctx.moveTo(arrowX, arrowY)
      ctx.moveTo(fromX, fromY)
      ctx.lineTo(toX, toY)
      arrowX = toX + topX
      arrowY = toY + topY
      ctx.moveTo(arrowX, arrowY)
      ctx.lineTo(toX, toY)
      arrowX = toX + botX
      arrowY = toY + botY
      ctx.lineTo(arrowX, arrowY)
      ctx.strokeStyle = color
      ctx.lineWidth = width
      ctx.stroke()
      ctx.restore()
      ctx.save();
      ctx.beginPath();
      let arrowX = fromX - topX;
      let arrowY = fromY - topY;
      ctx.moveTo(arrowX, arrowY);
      ctx.moveTo(fromX, fromY);
      ctx.lineTo(toX, toY);
      arrowX = toX + topX;
      arrowY = toY + topY;
      ctx.moveTo(arrowX, arrowY);
      ctx.lineTo(toX, toY);
      arrowX = toX + botX;
      arrowY = toY + botY;
      ctx.lineTo(arrowX, arrowY);
      ctx.strokeStyle = color;
      ctx.lineWidth = width;
      ctx.stroke();
      ctx.restore();
    },
    // 回显图形备注
    showRemarks(x, y, remarks) {
      this.ctx.moveTo(x, y - 10) // 因为放大之后是y-20,所以缩小版的为y-10
      this.ctx.fillStyle = "green" // 设置填充颜色为绿色
      this.ctx.font = '10px "微软雅黑"' // 设置字体
      this.ctx.textBaseline = "bottom" // 设置字体底线对齐绘制基线
      this.ctx.textAlign = "left" // 设置字体对齐的方式
      this.ctx.fillText(remarks, x, y - 10) // 填充文字
      this.ctx.moveTo(x, y - 10); // 因为放大之后是y-20,所以缩小版的为y-10
      this.ctx.fillStyle = "green"; // 设置填充颜色为绿色
      this.ctx.font = '10px "微软雅黑"'; // 设置字体
      this.ctx.textBaseline = "bottom"; // 设置字体底线对齐绘制基线
      this.ctx.textAlign = "left"; // 设置字体对齐的方式
      this.ctx.fillText(remarks, x, y - 10); // 填充文字
    },
    getCanvasData(data) {
      let polyon = { ...data }
      polyon.camera_id = this.Camera.cameraId
      let polyon = { ...data };
      polyon.camera_id = this.Camera.cameraId;
      savePolygon(polyon).then((rsp) => {
        this.Camera.getPolygon()
        this.Camera.getCameraTask()
      })
        this.Camera.getPolygon();
        this.Camera.getCameraTask();
      });
    },
    setWidthHeight() {
      this.canvasWidth = this.$refs.videoPlayer.offsetWidth
      this.canvasHeight = this.$refs.videoPlayer.offsetHeight
      this.canvasWidth = this.$refs.videoPlayer.offsetWidth;
      this.canvasHeight = this.$refs.videoPlayer.offsetHeight;
    },
    async initArea() {
      if (!this.showCanvas) {
        return
        return;
      }
      const res = await getAllPolygon({
        cameraId: this.TreeDataPool.selectedNode.id
      })
      this.canvasData.line = res.data.line
      this.canvasData.rect = res.data.rect
      this.canvasData.arrow = res.data.arrow
      this.canvasData.polygon = res.data.polygon
      this.clickSelect(this.canvasData)
        cameraId: this.TreeDataPool.selectedNode.id,
      });
      this.canvasData.line = res.data.line;
      this.canvasData.rect = res.data.rect;
      this.canvasData.arrow = res.data.arrow;
      this.canvasData.polygon = res.data.polygon;
      this.clickSelect(this.canvasData);
    },
    initAlgoDataWebScoket() {
      if (typeof WebSocket === "undefined") {
        console.log("error,您的浏览器不支持socket")
        console.log("error,您的浏览器不支持socket");
      } else {
        this.algoDataSocket = new WebSocket()
        this.algoDataSocket = new WebSocket();
        this.algoDataSocket.onopen = () => {
          console.log("socket连接成功")
        }
          console.log("socket连接成功");
        };
        this.algoDataSocket.onerror = () => {
          console.log("连接错误")
        }
          console.log("连接错误");
        };
        this.algoDataSocket.onmessage = (msg) => {
          console.log(msg)
        }
          console.log(msg);
        };
      }
    },
    playVideo() {
      if (this.isStream && this.rtspUrl == "") {
        return
        return;
      }
      let payload = ""
      let url = ""
      let payload = "";
      let url = "";
      if (this.isStream) {
        if (this.cameraID == "") {
          this.cameraID = this.getUuid()
          this.cameraID = this.getUuid();
        }
        payload = JSON.stringify({
          cameraID: this.cameraID,
          rtspUrl: this.rtspUrl,
          isRunning: this.isRunning,
          isGb28181: this.isGb
        })
          isGb28181: this.isGb,
        });
        url = this.videoUrl
        url = this.videoUrl;
      } else {
        url = "/httpImage/" + this.videoUrls[this.playerIndex]
        url = "/httpImage/" + this.videoUrls[this.playerIndex];
      }
      this.videoLoading = true
      this.videoLoading = true;
      if (this.player.hPlayer == 0) {
        this.player.play(
          url,
@@ -401,48 +479,48 @@
          this.$refs.timeLabel,
          payload,
          () => {
            this.videoLoading = false
            this.videoLoading = false;
          }
        )
        );
      } else if (this.player.PlayOrPause == 0) {
        this.player.resume()
        this.videoLoading = false
        this.player.resume();
        this.videoLoading = false;
      } else {
        this.player.pause()
        this.videoLoading = false
        this.player.pause();
        this.videoLoading = false;
      }
      this.playerStatus = this.player.PlayOrPause
      this.playerStatus = this.player.PlayOrPause;
      this.loadUrl = url
      this.loadUrl = url;
    },
    setPlayerStatus(stat) {
      this.videoLoading = false
      this.videoLoading = false;
      // 控制加载后的播放按钮状态,实时流为自动播放,视频为preload
      this.playerStatus = this.isStream ? 1 : 0
      this.playerStatus = this.isStream ? 1 : 0;
    },
    stopVideo() {
      if (this.player.hPlayer == 0) return
      if (this.player.hPlayer == 0) return;
      this.player.stop()
      this.player.stop();
    },
    fullScreen() {
      if (!this.isFullScreen) {
        this.player.fullscreen()
        this.player.fullscreen();
      } else {
        this.player.exitfullscreen()
        this.player.exitfullscreen();
      }
      this.isFullScreen = !this.isFullScreen
      this.isFullScreen = !this.isFullScreen;
    },
    async downLoad() {
      if (!this.loadUrl) {
        this.$notify.info({
          title: "消息",
          message: "下载失败,无效的视频地址"
        })
        return
          message: "下载失败,无效的视频地址",
        });
        return;
      }
      if (this.isFullScreen) {
@@ -452,29 +530,29 @@
         p.appendChild(txt);
       p.classList.add("downloadNotice");
         screen.appendChild(p); */
        this.fullScreenNotice = true
        this.fullScreenNotice = true;
        setTimeout(() => {
          this.fullScreenNotice = false
        }, 2000)
          this.fullScreenNotice = false;
        }, 2000);
      } else {
        this.$notify.info({
          title: "消息",
          message: `资源下载中,请稍后...`
        })
          message: `资源下载中,请稍后...`,
        });
      }
      let url = "http://" + window.location.host + this.loadUrl
      let url = "http://" + window.location.host + this.loadUrl;
      // let url = "http://localhost:8080/httpImage/192.168.20.189:6700/283,2f49bf283ad7?collection=2021-09-28-DSVAD010120190703-video"
      let name = url.substring(url.lastIndexOf("/") + 1)
      let responsePromise = await fetch(url)
      let blob = await responsePromise.blob()
      let objectURL = window.URL.createObjectURL(blob)
      let a = document.createElement("a")
      a.href = objectURL
      a.download = name
      a.click()
      a.remove()
      let name = url.substring(url.lastIndexOf("/") + 1);
      let responsePromise = await fetch(url);
      let blob = await responsePromise.blob();
      let objectURL = window.URL.createObjectURL(blob);
      let a = document.createElement("a");
      a.href = objectURL;
      a.download = name;
      a.click();
      a.remove();
      /*  let url = 'http:/'+this.loadUrl.substring(10)
    let link = document.createElement("a"); //创建a标签
    let name = url.substring(url.lastIndexOf("/") + 1) 
@@ -486,18 +564,18 @@
    },
    playPrev() {
      this.playerIndex--
      this.player.stop()
      this.playVideo()
      this.playerIndex--;
      this.player.stop();
      this.playVideo();
    },
    playNext() {
      this.playerIndex++
      this.player.stop()
      this.playVideo()
    }
  }
}
      this.playerIndex++;
      this.player.stop();
      this.playVideo();
    },
  },
};
</script>
<style lang="scss">
src/pages/cameraAccess/components/CameraInfo.vue
@@ -230,6 +230,7 @@
  createCamera,
  updateCameraInfo,
  getCameraInfo,
  getGB28181CameraInfo,
  delCamera,
} from "@/api/camera";
import { getSoundList } from "@/api/event";
@@ -367,49 +368,99 @@
      this.$refs.addForm.resetFields();
      this.voice = null;
      console.log(node);
      // this.initFormData();
      // this.$refs.addForm.clearValidate();
      if (node.type === "4") {
        getCameraInfo(node.id).then((res) => {
          if (res.success) {
            // console.log(res, '获取摄像机信息')
            if (res.data.resolutions) {
              let list = res.data.resolutions.map((i) => {
                let obj = {};
                if (i.width == 0 && i.height == 0) {
                  obj.label = "本机分辨率";
                  obj.value = "0*0";
                } else {
                  obj.label = i.width + "*" + i.height;
                  obj.value = i.width + "*" + i.height;
                }
                return obj;
              });
              this.resolutionList = list;
              this.sensors = res.data.sensors;
              console.log(list);
            }
            this.$nextTick(() => {
              this.initFormData();
              Object.assign(this.form, res.data);
              this.soundList.forEach((element) => {
                if (this.form.voiceId == element.id) {
                  this.voice = element;
                }
              });
              if (this.form.run_type !== -1) {
                this.form.isAI = true;
              } else {
                this.form.isAI = false;
        // 国标摄像机
        if (node.cameraType === 1) {
          getGB28181CameraInfo(node.id).then((res) => {
            if (res.success) {
              // console.log(res, '获取摄像机信息')
              if (res.data.resolutions) {
                let list = res.data.resolutions.map((i) => {
                  let obj = {};
                  if (i.width == 0 && i.height == 0) {
                    obj.label = "本机分辨率";
                    obj.value = "0*0";
                  } else {
                    obj.label = i.width + "*" + i.height;
                    obj.value = i.width + "*" + i.height;
                  }
                  return obj;
                });
                this.resolutionList = list;
                this.sensors = res.data.sensors;
                console.log(list);
              }
              this.form.resolution =
                this.form.resolution_width + "*" + this.form.resolution_height;
            });
          }
        });
              this.$nextTick(() => {
                this.initFormData();
                Object.assign(this.form, res.data);
                this.soundList.forEach((element) => {
                  if (this.form.voiceId == element.id) {
                    this.voice = element;
                  }
                });
                if (this.form.run_type !== -1) {
                  this.form.isAI = true;
                } else {
                  this.form.isAI = false;
                }
                this.form.resolution =
                  this.form.resolution_width +
                  "*" +
                  this.form.resolution_height;
              });
            }
          });
        } else {
          getCameraInfo(node.id).then((res) => {
            if (res.success) {
              // console.log(res, '获取摄像机信息')
              if (res.data.resolutions) {
                let list = res.data.resolutions.map((i) => {
                  let obj = {};
                  if (i.width == 0 && i.height == 0) {
                    obj.label = "本机分辨率";
                    obj.value = "0*0";
                  } else {
                    obj.label = i.width + "*" + i.height;
                    obj.value = i.width + "*" + i.height;
                  }
                  return obj;
                });
                this.resolutionList = list;
                this.sensors = res.data.sensors;
                console.log(list);
              }
              this.$nextTick(() => {
                this.initFormData();
                Object.assign(this.form, res.data);
                this.soundList.forEach((element) => {
                  if (this.form.voiceId == element.id) {
                    this.voice = element;
                  }
                });
                if (this.form.run_type !== -1) {
                  this.form.isAI = true;
                } else {
                  this.form.isAI = false;
                }
                this.form.resolution =
                  this.form.resolution_width +
                  "*" +
                  this.form.resolution_height;
              });
            }
          });
        }
      }
    },
    // 保存
src/pages/cameraAccess/components/LinkageRule.vue
@@ -20,14 +20,14 @@
    </div>-->
    <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="tableRuleList"></slide-scene>
        <div class="top-right">
          <sysinfo
            v-if="showSysInfo"
            style="margin-top: -10px;"
            style="margin-top: -10px"
            :ShowLocalVedio="this.TreeDataPool.treeActiveName !== 'camera'"
            :showRealPoll="this.TreeDataPool.treeActiveName == 'camera'"
          />
@@ -45,11 +45,19 @@
      <div class="bottom-right">
        <div class="draw-and-time-box">
          <div class="draw-box">
            <p style="text-align:left;padding: 10px 0px 0px 0px;box-sizing: border-box;">
            <p
              style="
                text-align: left;
                padding: 10px 0px 0px 0px;
                box-sizing: border-box;
              "
            >
              <b style="font-size: 14px">查看区域</b>
            </p>
            <div class="img-box">
              <span class="camera-tip" v-show="swipercanvasData.length == 0 ">暂无区域,请至少选择2个摄像机</span>
              <span class="camera-tip" v-show="swipercanvasData.length == 0"
                >暂无区域,请至少选择2个摄像机</span
              >
              <!-- swiper 展示 -->
              <swiper
                ref="swiper"
@@ -57,8 +65,15 @@
                @slideChange="swiperSlideChange"
                class="swiper-box-container2"
              >
                <swiper-slide v-for="(data, index) in swipercanvasData" :key="index">
                  <b class="video-title" style="font-size:14px;margin-top:-10px">{{ data.name }}</b>
                <swiper-slide
                  v-for="(data, index) in swipercanvasData"
                  :key="index"
                >
                  <b
                    class="video-title"
                    style="font-size: 14px; margin-top: -10px"
                    >{{ data.name }}</b
                  >
                  <polygon-canvas
                    ref="canvas"
                    v-loading="loading"
@@ -78,24 +93,34 @@
                  ></polygon-canvas>
                </swiper-slide>
              </swiper>
              <div class="swiper-local-prev" v-show="swipercanvasData.length>1">
              <div
                class="swiper-local-prev"
                v-show="swipercanvasData.length > 1"
              >
                <div class="icon-btn" slot="button-prev">
                  <i class="iconfont iconzuo"></i>
                </div>
              </div>
              <div class="swiper-local-next" v-show="swipercanvasData.length>1">
              <div
                class="swiper-local-next"
                v-show="swipercanvasData.length > 1"
              >
                <div class="icon-btn" slot="button-next">
                  <i class="iconfont iconyou1"></i>
                </div>
              </div>
            </div>
          </div>
          <div style="float:left;width:calc(10% - 90px);height:100%;"></div>
          <div style="float: left; width: calc(10% - 90px); height: 100%"></div>
          <div
            class="time-box"
            style="width:calc(90% + 90px - 576px);overflow-x:auto;overflow-y:hidden"
            style="
              width: calc(90% + 90px - 576px);
              overflow-x: auto;
              overflow-y: hidden;
            "
          >
            <p style="text-align:left;padding: 10px;box-sizing: border-box">
            <p style="text-align: left; padding: 10px; box-sizing: border-box">
              <b style="font-size: 14px">时间规则</b>
            </p>
            <time-slider ref="timeSlider" :type="'link'" />
@@ -117,10 +142,7 @@
</template>
<script>
import {
  saveLinkScene,
  getLinkSceneRule,
} from '@/api/scene'
import { saveLinkScene, getLinkSceneRule } from "@/api/scene";
import VideoRuleData from "@/Pool/VideoRuleData";
import polygonCanvas from "@/components/canvas";
@@ -136,19 +158,18 @@
    polygonCanvas,
    SceneRule,
    Sysinfo,
    SlideScene
    SlideScene,
  },
  computed: {
    selectedCameraIds() {
      return this.TreeDataPool.selectedNodes;
    }
    },
  },
  data() {
    return {
      loading: false,
      loadingRuleList: false,
      Carmeras: [],
      Camera: new VideoRuleData(),
      tasksTable: {},
      swipercanvasData: [],
      seqNumber: 0,
@@ -158,27 +179,27 @@
        grabCursor: true,
        pagination: {
          el: ".swiper-pagination",
          type: "fraction"
          type: "fraction",
        },
        navigation: {
          nextEl: ".swiper-local-next",
          prevEl: ".swiper-local-prev"
        }
          prevEl: ".swiper-local-prev",
        },
      },
      swiperTaskOption: {
        slidesPerView: 4,
        // spaceBetween: 10,
        pagination: {
          el: ".swiper-pagination",
          clickable: true
          clickable: true,
        },
        navigation: {
          nextEl: ".next-border",
          prevEl: ".pre-border"
        }
          prevEl: ".pre-border",
        },
      },
      showSysInfo: false,
      requestSeq: ""
      requestSeq: "",
    };
  },
  watch: {
@@ -186,26 +207,32 @@
      handler(newVal, oldVal) {
        this.setSwiperData();
      },
      deep: true
    }
      deep: true,
    },
  },
  methods: {
    swiperSlideChange() {
      this.swiperIndex = this.$refs.swiper.swiper.activeIndex;
    },
    initCameraData() {
    initCameraData(type) {
      this.$nextTick(() => {
        this.Carmeras = [];
        this.showSysInfo = true;
        this.selectedCameraIds.forEach(cid => {
          this.Carmeras.push(new VideoRuleData(cid));
        });
        if (type === 1) {
          this.selectedCameraIds.forEach((cid) => {
            this.Carmeras.push(new VideoRuleData(cid, true));
          });
        } else {
          this.selectedCameraIds.forEach((cid) => {
            this.Carmeras.push(new VideoRuleData(cid));
          });
        }
        this.$refs.timeSlider.activeTab = this.VideoManageData.TimeRules[0].id;
        this.showRules();
      })
      });
    },
    setSwiperData() {
      let swipers = [];
@@ -222,16 +249,15 @@
      this.swipercanvasData = swipers;
    },
    refresh(url, id) {
      this.swipercanvasData.forEach(data => {
      this.swipercanvasData.forEach((data) => {
        if (data.cameraId == id) {
          data.baseImg = url;
        }
      })
      });
      //this.Camera.baseImg = url
    },
    getCanvasData() { },
    getCanvasData() {},
    newUid() {
      let originStr = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx";
      let originChar = "0123456789abcdef";
      let len = originChar.length;
@@ -247,11 +273,10 @@
        let seq = this.newUid();
        this.requestSeq = seq;
        getLinkSceneRule({ cameraIds: this.selectedCameraIds }).then(
          rsp => {
        getLinkSceneRule({ cameraIds: this.selectedCameraIds })
          .then((rsp) => {
            this.loadingRuleList = false;
            if (rsp && rsp.success && seq === this.requestSeq) {
              this.tableRuleList = rsp.data;
              // 统一规则编辑的数据结构
@@ -260,52 +285,54 @@
              }
            }
            // this.TreeDataPool.fetchTreeData();
          }
        ).catch(() => {
          this.loadingRuleList = false;
        });
          })
          .catch(() => {
            this.loadingRuleList = false;
          });
      }
    },
    saveSceneRule(groupRule) {
      const payload = { ...groupRule }
      const payload = { ...groupRule };
      if (!payload.rules) {
        this.$message({
          type: "warning",
          message: "规则参数有误"
          message: "规则参数有误",
        });
        return
        return;
      }
      payload.cameraIds = this.selectedCameraIds;
      saveLinkScene(payload).then(rsp => {
        if (rsp && rsp.success) {
          //this.Camera.update();
          this.initCameraData();
          // this.showRules();
          this.$notify({
            type: "success",
            message: "任务保存成功!"
          });
        } else {
          this.$notify({
      saveLinkScene(payload)
        .then((rsp) => {
          if (rsp && rsp.success) {
            //this.Camera.update();
            this.initCameraData();
            // this.showRules();
            this.$notify({
              type: "success",
              message: "任务保存成功!",
            });
          } else {
            this.$notify({
              type: "error",
              message: rsp.data,
            });
          }
        })
        .catch((err) => {
          this.$message({
            type: "error",
            message: rsp.data
            message: "保存失败!",
          });
        }
      }).catch(err => {
        this.$message({
          type: "error",
          message: "保存失败!"
        });
      });
    },
    changeLoading(params) {
      this.loading = params
    }
  }
      this.loading = params;
    },
  },
};
</script>
<style lang="scss">
src/pages/cameraAccess/components/SeparateRules.vue
@@ -7,7 +7,7 @@
            <span>
              <span class="label">视频分析处理</span>
              <el-switch
                style="margin-left: 10px;"
                style="margin-left: 10px"
                v-model="Camera.analytics"
                @change="pollEnable"
                :disabled="!Camera.cameraId"
@@ -15,26 +15,44 @@
            </span>
          </div>
          <div v-if="Camera.analytics" class="flex-box" v-show="cameraType === 'camera'">
          <div
            v-if="Camera.analytics"
            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'}"
              :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"
            >分辨率: {{(Camera.camearInfo.resolution_width == 0 || Camera.camearInfo.resolution_height == 0) ? '本机分辨率': `${Camera.camearInfo.resolution_width} * ${Camera.camearInfo.resolution_height}` }}</span>
          <div
            v-if="Camera.analytics"
            class="flex-box"
            v-show="cameraType === 'camera'"
          >
            <span class="label"
              >分辨率:
              {{
                Camera.camearInfo.resolution_width == 0 ||
                Camera.camearInfo.resolution_height == 0
                  ? "本机分辨率"
                  : `${Camera.camearInfo.resolution_width} * ${Camera.camearInfo.resolution_height}`
              }}</span
            >
          </div>
          <div v-if="Camera.analytics" class="flex-box">
            <span class="label">SmartAI节点: {{ Camera.runServerName}}</span>
            <span class="label">SmartAI节点: {{ Camera.runServerName }}</span>
          </div>
          <div v-if="Camera.analytics" class="flex-box">
@@ -47,19 +65,27 @@
                popper-class="atooltip"
              >
                <span
                  style="color:#3D68E1;cursor: pointer;font-size:23px;"
                  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}`"
                :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;'"
                  :style="
                    !TreeDataPool.ctrlCameraId
                      ? 'cursor: not-allowed;font-size:23px;'
                      : 'color:#3D68E1;font-size:23px;cursor: pointer;'
                  "
                  @click="ctrlV"
                  class="iconfont iconniantie ml5"
                ></span>
@@ -74,7 +100,7 @@
    <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>
@@ -83,7 +109,7 @@
            :showRealPoll="cameraType === 'camera'"
            :ShowLocalVedio="cameraType === 'dataStack'"
            v-if="showSysInfo"
            style="margin-top:-10px"
            style="margin-top: -10px"
          />
        </div>
      </div>
@@ -99,15 +125,17 @@
              <span
                class="el-dropdown-link"
                @click="drawBaseImg"
                style="position: relative;top: 5px; cursor:pointer"
                style="position: relative; top: 5px; cursor: pointer"
              >
                <i class="iconfont iconbianji1" style="font-size: 28px; "></i>
                <i class="iconfont iconbianji1" style="font-size: 28px"></i>
              </span>
            </div>
            <div style="width:590px;height:16px;">
              <b
                style="font-size:14px"
              >{{ Camera.camearInfo.alias ? Camera.camearInfo.alias: Camera.camearInfo.name }}</b>
            <div style="width: 590px; height: 16px">
              <b style="font-size: 14px">{{
                Camera.camearInfo.alias
                  ? Camera.camearInfo.alias
                  : Camera.camearInfo.name
              }}</b>
            </div>
            <div class="img-box">
              <template v-if="TreeDataPool.treeActiveName == 'camera'">
@@ -132,21 +160,25 @@
                ></polygon-canvas>
              </template>
              <template v-else>
                <div style="width:100%" v-loading="getStackFileLoading">
                <div style="width: 100%" v-loading="getStackFileLoading">
                  <swiper
                    ref="swiper"
                    :auto-update="true"
                    :options="canvasSwiperOption"
                    @slideChange="swiperSlideChange"
                    class="swiper-box-container2"
                    style="width:100%"
                    style="width: 100%"
                  >
                    <swiper-slide v-for="(data, index) in swipercanvasData" :key="index">
                    <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>
                          style="font-size: 14px; margin-top: -10px"
                          >{{ data.name }}</b
                        >
                        <polygon-canvas
                          class="cavas"
                          ref="canvas"
@@ -172,7 +204,7 @@
                  </swiper>
                  <div
                    class="swiper-local-prev"
                    v-show="swipercanvasData.length>1"
                    v-show="swipercanvasData.length > 1"
                    @click="prevClick"
                  >
                    <div class="icon-btn" slot="button-prev">
@@ -181,7 +213,7 @@
                  </div>
                  <div
                    class="swiper-local-next"
                    v-show="swipercanvasData.length>1"
                    v-show="swipercanvasData.length > 1"
                    @click="nextClick"
                  >
                    <div class="icon-btn" slot="button-next">
@@ -192,12 +224,16 @@
              </template>
            </div>
          </div>
          <div style="float:left;width:calc(10% - 90px);height:100%;"></div>
          <div style="float: left; width: calc(10% - 90px); height: 100%"></div>
          <div
            class="time-box"
            style="width:calc(90% + 90px - 576px);overflow-x:auto;overflow-y:hidden"
            style="
              width: calc(90% + 90px - 576px);
              overflow-x: auto;
              overflow-y: hidden;
            "
          >
            <p style="text-align:left;padding: 10px;box-sizing: border-box">
            <p style="text-align: left; padding: 10px; box-sizing: border-box">
              <b style="font-size: 14px">时间段</b>
            </p>
            <time-slider ref="timeSlider" :type="'sep'" />
@@ -219,13 +255,9 @@
<script>
import { savePolygon } from "@/api/polygon";
import {
  pasteRules
} from '@/api/task';
import { pasteRules } from "@/api/task";
import {
  saveCameraScene,
} from '@/api/scene'
import { saveCameraScene } from "@/api/scene";
import { changeRunType } from "@/api/pollConfig";
import { findAllFileByStackId } from "@/api/localVedio";
@@ -243,19 +275,21 @@
    polygonCanvas,
    Sysinfo,
    SceneRule,
    SlideScene
    SlideScene,
  },
  directives: {
    focus: {
      inserted: function (el) {
        el.querySelector('input').focus()
      }
    }
        el.querySelector("input").focus();
      },
    },
  },
  computed: {
    cameraType() {
      return this.TreeDataPool.treeActiveName === 'camera' ? "camera" : "dataStack"
    }
      return this.TreeDataPool.treeActiveName === "camera"
        ? "camera"
        : "dataStack";
    },
  },
  data() {
    return {
@@ -268,12 +302,12 @@
        grabCursor: true,
        pagination: {
          el: ".swiper-pagination",
          type: "fraction"
          type: "fraction",
        },
        navigation: {
          nextEl: ".swiper-local-next",
          prevEl: ".swiper-local-prev"
        }
          prevEl: ".swiper-local-prev",
        },
      },
      // swiperOption: {
      //   slidesPerView: 5,
@@ -294,7 +328,7 @@
      showCanvas: true,
      canvasWidth: 576,
      canvasHeight: 324,
      stackId: '',
      stackId: "",
      swiperIndex: 0,
      swipercanvasData: [],
      stackFilesPage: 1,
@@ -304,10 +338,9 @@
  mounted() {
    this.mockAsync();
    this.PollData.statistics();
  },
  watch: {
    'Camera.cameraId': {
    "Camera.cameraId": {
      handler(n, o) {
        if (n) {
          if (this.TreeDataPool.treeActiveName == "dataStack") {
@@ -316,12 +349,12 @@
            this.stackId = n;
            if (this.stackId) {
              this.swipercanvasData = [];
              this.getStackFiles()
              this.getStackFiles();
            }
          }
        }
      }
    }
      },
    },
  },
  methods: {
    prevClick() {
@@ -331,11 +364,10 @@
          this.getStackFiles(true);
        } else {
          this.$message({
            type: 'info',
            message: '当前已是第一页'
            type: "info",
            message: "当前已是第一页",
          });
        }
      }
    },
    nextClick() {
@@ -347,41 +379,53 @@
    getStackFiles(onClick = false) {
      this.getStackFileLoading = true;
      let _this = this;
      findAllFileByStackId({ name: '', stackId: this.stackId, page: this.stackFilesPage, size: this.stackFilesSize, type: 0 }).then(res => {
        if (res && res.success) {
          if (res.data.dataList.length > 0) {
            this.swipercanvasData = [];
            this.swipercanvasData = res.data.dataList.map(item => {
              return {
                name: item.name,
                stackId: item.stack_id,
                baseImg: item.type == 2 ? `/files/${item.path.substr(item.path.lastIndexOf('/') + 1)}` : item.snapshot_url,
                type: item.type,
                id: item.id,
                loading: false
              }
            });
            this.swiperIndex = 0;
            this.$refs.swiper.swiper.activeIndex = 0;
          } else {
            if (onClick) {
              this.$message({
                type: 'warning',
                message: '已无更多数据!'
      findAllFileByStackId({
        name: "",
        stackId: this.stackId,
        page: this.stackFilesPage,
        size: this.stackFilesSize,
        type: 0,
      })
        .then((res) => {
          if (res && res.success) {
            if (res.data.dataList.length > 0) {
              this.swipercanvasData = [];
              this.swipercanvasData = res.data.dataList.map((item) => {
                return {
                  name: item.name,
                  stackId: item.stack_id,
                  baseImg:
                    item.type == 2
                      ? `/files/${item.path.substr(
                          item.path.lastIndexOf("/") + 1
                        )}`
                      : item.snapshot_url,
                  type: item.type,
                  id: item.id,
                  loading: false,
                };
              });
              this.swiperIndex = 0;
              this.$refs.swiper.swiper.activeIndex = 0;
            } else {
              if (onClick) {
                this.$message({
                  type: "warning",
                  message: "已无更多数据!",
                });
              }
            }
          } else {
            this.$message({
              type: "error",
              message: "数据请求失败,请稍后重试!",
            });
          }
        } else {
          this.$message({
            type: 'error',
            message: '数据请求失败,请稍后重试!'
          });
        }
        this.getStackFileLoading = false;
      }).catch(e => {
        this.getStackFileLoading = false;
      });
          this.getStackFileLoading = false;
        })
        .catch((e) => {
          this.getStackFileLoading = false;
        });
    },
    swiperSlideChange() {
      this.swiperIndex = this.$refs.swiper.swiper.activeIndex;
@@ -389,7 +433,11 @@
    mockAsync() {
      setTimeout(() => {
        this.mockSceneData = [
          { scenename: "name1", id: 1, icon: ["iconrenlianjiance", "icongetijingzhi"] },
          {
            scenename: "name1",
            id: 1,
            icon: ["iconrenlianjiance", "icongetijingzhi"],
          },
          { scenename: "name2", id: 2, icon: ["iconchouyan-copy"] },
          {
            scenename: "name3",
@@ -398,19 +446,23 @@
              "iconrenshukouzhao",
              "iconchouyan-copy",
              "iconrenlianjiance",
              "icongetijingzhi"
            ]
              "icongetijingzhi",
            ],
          },
          {
            scenename: "name4",
            id: 4,
            icon: ["iconchouyan-copy", "iconrenlianjiance", "icongetijingzhi"]
            icon: ["iconchouyan-copy", "iconrenlianjiance", "icongetijingzhi"],
          },
          { scenename: "name5", id: 5, icon: ["icongetijingzhi"] },
          { scenename: "name6", id: 6, icon: ["iconrenshukouzhao", "icongetijingzhi"] },
          { scenename: "name7", id: 7, icon: ["iconrenlianjiance"] }
          {
            scenename: "name6",
            id: 6,
            icon: ["iconrenshukouzhao", "icongetijingzhi"],
          },
          { scenename: "name7", id: 7, icon: ["iconrenlianjiance"] },
        ];
      }, 3000)
      }, 3000);
    },
    drawBaseImg() {
      if (Array.isArray(this.$refs.canvas)) {
@@ -424,51 +476,55 @@
    getCanvasData(data) {
      let polyon = { ...data };
      polyon.camera_id = this.Camera.cameraId;
      savePolygon(polyon).then(rsp => {
      savePolygon(polyon).then((rsp) => {
        this.Camera.getPolygon();
        //this.Camera.getCameraTask();
      });
    },
    refresh(url) {
      this.Camera.baseImg = url
      this.Camera.baseImg = url;
    },
    // 初始化摄像机信息,父组件调用
    async initCameraData(id) {
    async initCameraData(id, type) {
      this.Camera = new VideoRuleData();
      console.log("121212");
      console.log(type);
      if (id && id !== "") {
        this.loading = false;
        this.Camera.cameraId = id;
        await this.Camera.update();
        if (type === 1) {
          await this.Camera.update(true);
        } else {
          await this.Camera.update();
        }
      }
      this.$refs.timeSlider.activeTab = this.VideoManageData.TimeRules[0].id;
      this.showSysInfo = true
      this.showSysInfo = true;
      // 判断正在执行实时或者轮询任务
      this.PollData.CameraList.forEach(element => {
      this.PollData.CameraList.forEach((element) => {
        if (element.id === this.Camera.cameraId) {
          this.runType = element.run_type;
        }
      })
      });
    },
    saveSceneRule(groupRule) {
      const payload = { ...groupRule }
      const payload = { ...groupRule };
      payload.cameraIds = [this.Camera.cameraId];
      let _this = this;
      saveCameraScene(payload).then(rsp => {
      saveCameraScene(payload).then((rsp) => {
        if (rsp && rsp.success) {
          this.Camera.update();
          this.$notify({
            type: "success",
            message: "策略保存成功!"
            message: "策略保存成功!",
          });
          //刷新左侧树
          _this.$root.$children[0].$children[0].querySearchAsync('camera')
          _this.$root.$children[0].$children[0].querySearchAsync("camera");
        }
      });
    },
@@ -476,90 +532,93 @@
      this.Camera.update();
    },
    changeLoading(params) {
      this.loading = params
      this.loading = params;
    },
    //是否进行视频分析处理
    pollEnable(row) {
      let val = 0
      let val = 0;
      if (row) {
        if (this.PollData.RealTimeSum < this.PollData.channelTotal) {
          this.Camera.dealWay = true
          val = 1
          this.Camera.dealWay = true;
          val = 1;
        } else {
          this.Camera.dealWay = false
          val = 0
          this.Camera.dealWay = false;
          val = 0;
        }
      } else {
        this.Camera.dealWay = false
        val = -1
        this.Camera.dealWay = false;
        val = -1;
      }
      if (this.Camera.cameraId && this.Camera.cameraId !== undefined) {
      debugger
        changeRunType({ camera_ids: [this.Camera.cameraId], run_type: val }).then(
          rsp => {
            if (rsp && rsp.success) {
              this.$notify({
                type: "success",
                message: "配置成功"
              });
            } else {
              this.$notify({
                type: "error",
                message: "配置失败"
              });
            }
            this.TreeDataPool.fetchTreeData();
        debugger;
        changeRunType({
          camera_ids: [this.Camera.cameraId],
          run_type: val,
        }).then((rsp) => {
          if (rsp && rsp.success) {
            this.$notify({
              type: "success",
              message: "配置成功",
            });
          } else {
            this.$notify({
              type: "error",
              message: "配置失败",
            });
          }
        );
          this.TreeDataPool.fetchTreeData();
        });
      }
      this.PollData.statisticTaskInfo();
    },
    //实时、轮询切换
    changePoll(row) {
      //判断是新增还是更新
      debugger
      debugger;
      if (this.Camera.cameraId && this.Camera.cameraId !== undefined) {
        if (this.PollData.RealTimeSum < this.PollData.channelTotal) {
          if (row.value) {
            this.Camera.dealWay = true
            this.Camera.dealWay = true;
          } else {
            this.Camera.dealWay = false
            this.Camera.dealWay = false;
          }
      debugger
          changeRunType({ camera_ids: [this.Camera.cameraId], run_type: this.Camera.dealWay ? 1 : 0 }).then(
            rsp => {
          debugger;
          changeRunType({
            camera_ids: [this.Camera.cameraId],
            run_type: this.Camera.dealWay ? 1 : 0,
          }).then((rsp) => {
            if (rsp && rsp.success) {
              this.$notify({
                type: "success",
                message: "配置成功",
              });
            } else {
              this.$notify({
                type: "error",
                message: "配置失败",
              });
            }
          });
        } else {
          if (this.Camera.dealWay) {
            this.Camera.dealWay = false;
            debugger;
            changeRunType({
              camera_ids: [this.Camera.cameraId],
              run_type: this.Camera.dealWay ? 1 : 0,
            }).then((rsp) => {
              if (rsp && rsp.success) {
                this.$notify({
                  type: "success",
                  message: "配置成功"
                  message: "配置成功",
                });
              } else {
                this.$notify({
                  type: "error",
                  message: "配置失败"
                  message: "配置失败",
                });
              }
            }
          );
        } else {
          if (this.Camera.dealWay) {
            this.Camera.dealWay = false
      debugger
            changeRunType({ camera_ids: [this.Camera.cameraId], run_type: this.Camera.dealWay ? 1 : 0 }).then(
              rsp => {
                if (rsp && rsp.success) {
                  this.$notify({
                    type: "success",
                    message: "配置成功"
                  });
                } else {
                  this.$notify({
                    type: "error",
                    message: "配置失败"
                  });
                }
              }
            );
            });
          }
        }
        this.TreeDataPool.fetchTreeData();
@@ -572,41 +631,43 @@
      this.TreeDataPool.ctrlCameraName = this.Camera.cameraName;
      this.$notify({
        type: "success",
        message: "复制算法成功!"
      })
        message: "复制算法成功!",
      });
    },
    ctrlV() {
      if (this.Camera.cameraId === this.TreeDataPool.ctrlCameraId) {
        this.$notify({
          type: "warning",
          message: "不能粘贴本摄像机的算法到本摄像机!"
        })
          message: "不能粘贴本摄像机的算法到本摄像机!",
        });
        return false;
      }
      pasteRules({
        sourceId: this.TreeDataPool.ctrlCameraId,
        targetIds: [this.Camera.cameraId]
      }).then((res) => {
        if (res && res.success) {
          this.$notify({
            type: "success",
            message: "粘贴算法成功!"
          })
          this.initCameraData(this.Camera.cameraId)
        } else {
        targetIds: [this.Camera.cameraId],
      })
        .then((res) => {
          if (res && res.success) {
            this.$notify({
              type: "success",
              message: "粘贴算法成功!",
            });
            this.initCameraData(this.Camera.cameraId);
          } else {
            this.$notify({
              type: "error",
              message: "粘贴算法失败!",
            });
          }
        })
        .catch((err) => {
          this.$notify({
            type: "error",
            message: "粘贴算法失败!"
          })
        }
      }).catch(err => {
        this.$notify({
          type: "error",
          message: "粘贴算法失败!"
        })
      })
            message: "粘贴算法失败!",
          });
        });
    },
  }
  },
};
</script>
<style lang="scss">
src/pages/cameraAccess/index/VideoManage.vue
@@ -120,13 +120,15 @@
        }
      } else if (this.activeName === "separate-rule") {
        this.$refs.sepRule.Camera = {};
        this.$refs.sepRule.initCameraData(node.id);
        this.$refs.sepRule.initCameraData(node.id, node.cameraType);
      }
    },
    "TreeDataPool.selectedNodes": {
      handler(nodes) {
      handler() {
        if (this.activeName == "linkage-rule") {
          this.$refs.linkRule.initCameraData();
          this.$refs.linkRule.initCameraData(
            this.TreeDataPool.selectedNode.cameraType
          );
        }
      },
      deep: true,
@@ -223,12 +225,15 @@
        }
      } else if (tab.name === "separate-rule") {
        if (this.TreeDataPool.treeActiveName == "camera") {
          this.$refs.sepRule.initCameraData(this.TreeDataPool.selectedNode.id);
          this.$refs.sepRule.initCameraData(
            this.TreeDataPool.selectedNode.id,
            this.TreeDataPool.selectedNode.cameraType
          );
        } else if (this.TreeDataPool.treeActiveName == "dataStack") {
          this.$refs.sepRule.initCameraData(this.DataStackPool.selectedDir.id);
        }
      } else if (this.activeName == "linkage-rule") {
        this.$refs.linkRule.initCameraData();
        //   this.$refs.linkRule.initCameraData();
      } else if (this.activeName == "poll-setting") {
        this.$nextTick(() => {
          this.$refs.pullSetting.initLineChart();
vue.config.js
@@ -1,13 +1,13 @@
"use strict"
const glob = require("glob")
const { ExitStatus } = require("typescript")
const pages = {}
const IS_VENDOR = /[\\/]node_modules[\\/]/
const pageVendor = {}
"use strict";
const glob = require("glob");
const { ExitStatus } = require("typescript");
const pages = {};
const IS_VENDOR = /[\\/]node_modules[\\/]/;
const pageVendor = {};
const pkg = require("./package.json")
const timestamp = new Date().getTime()
const queryStr = `?v=${pkg.version}&t=${timestamp}`
const pkg = require("./package.json");
const timestamp = new Date().getTime();
const queryStr = `?v=${pkg.version}&t=${timestamp}`;
const basicApps = [
  "index",
@@ -21,32 +21,32 @@
  "library",
  "search",
  "settings",
  "syslog"
]
  "syslog",
];
const argv = process.env.npm_lifecycle_event
const argv = process.env.npm_lifecycle_event;
glob.sync("./src/pages/**/main.ts").forEach((path) => {
  const chunk = path.split("./src/pages/")[1].split("/main.ts")[0]
  const chunk = path.split("./src/pages/")[1].split("/main.ts")[0];
  // 仅编译基础应用
  if (argv == "release") {
    let app = chunk.split("/")
    let app = chunk.split("/");
    if (app.length < 0 || basicApps.indexOf(app[0]) < 0) {
      return
      return;
    }
  }
  const chunk_vendor = `${chunk}-vendors`
  const chunk_common = `${chunk}-common`
  const chunk_vendor = `${chunk}-vendors`;
  const chunk_common = `${chunk}-common`;
  pages[chunk] = {
    entry: path,
    template: "public/index.html",
    title: chunk == "desktop/index" ? "SmartAI" : chunk,
    chunks: [chunk_vendor, "chunk-common", chunk]
  }
    chunks: [chunk_vendor, "chunk-common", chunk],
  };
  if (chunk != "index") {
    pages[chunk].filename = "view/" + chunk + ".html"
    pages[chunk].filename = "view/" + chunk + ".html";
  }
  pageVendor[chunk_vendor] = {
@@ -54,8 +54,8 @@
    priority: -11,
    chunks: (c) => c.name === chunk,
    test: /\.js$/,
    enforce: true
  }
    enforce: true,
  };
  // pageVendor[chunk_common] = {
  //   name: chunk_common,
@@ -65,32 +65,33 @@
  //   reuseExistingChunk: true,
  //   enforce: true
  // }
})
});
const serverUrl = "http://192.168.20.189:7009"
const iotdataServerUrl = "http://192.168.8.10:9000"
//const serverUrl = "http://192.168.20.189:7009"
const serverUrl = "http://192.168.20.116:7009";
const iotdataServerUrl = "http://192.168.8.10:9000";
// const cir = require("circular-dependency-plugin");
module.exports = {
  pages,
  chainWebpack: (config) => {
    config.plugins.delete("named-chunks")
    config.plugins.delete("named-chunks");
    if (process.env.NODE_ENV === "production") {
      config.output.filename("js/[name].js" + queryStr).end()
      config.output.chunkFilename("js/[name].js" + queryStr).end()
      config.output.filename("js/[name].js" + queryStr).end();
      config.output.chunkFilename("js/[name].js" + queryStr).end();
      // 修改生产配置
      config.plugin("extract-css").tap(() => [
        {
          filename: `css/[name].css${queryStr}`,
          chunkFilename: `css/[name].css${queryStr}`
        }
      ])
          chunkFilename: `css/[name].css${queryStr}`,
        },
      ]);
    }
    config.optimization.splitChunks({
      cacheGroups: pageVendor
    })
      cacheGroups: pageVendor,
    });
    // config.module.rule('fonts').use('url-loader').loader('file-loader').options({ name: 'fonts/[name].[ext]', publicPath: '../' })
    //config.module.rule('fonts').use('url-loader').loader('file-loader').options({ name: 'fonts/[name].[ext]', outputPath: '../' })
@@ -100,69 +101,69 @@
  pwa: {
    iconPaths: {
      favicon32: "favicon.ico",
      favicon16: "favicon.ico"
    }
      favicon16: "favicon.ico",
    },
  },
  devServer: {
    proxy: {
      "/track": {
        target: serverUrl,
        // ws: true,
        changeOrigin: true
        changeOrigin: true,
      },
      "/ws": {
        target: serverUrl,
        // ws: true,
        changeOrigin: true
        changeOrigin: true,
      },
      "/data/api-v/app/findAllApp": {
        // target: '/',
        target: "http://localhost:8081/",
        target: "http://localhost:8080/",
        changeOrigin: true,
        pathRewrite: {
          "^/data/api-v/app/findAllApp": "apps.json"
        }
          "^/data/api-v/app/findAllApp": "apps.json",
        },
      },
      "/api-c": {
        target: serverUrl,
        changeOrigin: true
        changeOrigin: true,
      },
      "/api-v": {
        target: serverUrl,
        changeOrigin: true
        changeOrigin: true,
      },
      "/api-f": {
        target: serverUrl,
        // secure: false,
        changeOrigin: true
        changeOrigin: true,
      },
      "/api-p": {
        target: serverUrl,
        // secure: false,
        changeOrigin: true
        changeOrigin: true,
      },
      "/api-u": {
        target: serverUrl,
        changeOrigin: true
        changeOrigin: true,
      },
      "/httpImage": {
        target: serverUrl,
        changeOrigin: true // 图片代理
        changeOrigin: true, // 图片代理
      },
      "/files": {
        target: serverUrl,
        changeOrigin: true // 文件代理
        changeOrigin: true, // 文件代理
      },
      "/iotdata": {
        target: iotdataServerUrl,
        changeOrigin: true // iot服务,
        changeOrigin: true, // iot服务,
      },
      "/version": {
        target: serverUrl,
        changeOrigin: true // 版本检查,
      }
    }
  }
        changeOrigin: true, // 版本检查,
      },
    },
  },
  // configureWebpack: {
  //   plugins: [
  //     new cir({
@@ -181,4 +182,4 @@
      }
    }
  } */
}
};