Просмотр исходного кода

视频监控云台控制和预置点列表调整

fan 2 недель назад
Родитель
Сommit
a44b76ee7c

+ 8 - 1
src/API/custom.js

@@ -80,7 +80,14 @@ export const getCameraCruiseRouteOptions = data =>
     data,
     notShowLoading: true,
   })
-
+//保存预置位
+export const savePreset = data =>
+  $http({
+    url: 'camera/Config/SavePreset',
+    method: 'post',
+    data
+  })
+  
 //获取人员信息
 export const getPersonList = data =>
   $http({

+ 3 - 3
src/components/ImageVideo/CanvasVideo.vue

@@ -100,14 +100,14 @@ export default {
   },
 
   beforeDestroy() {
-    this.cleanup()
+    this.$EventBus.$off("updateSendParam");
+    this.cleanup();
   },
 
   methods: {
     // 初始化事件监听
     initEventListeners() {
-      this.$EventBus.$off('updateSendParam')
-      this.$EventBus.$on('updateSendParam', this.handleParamUpdate)
+      this.$EventBus.$on("updateSendParam", this.handleParamUpdate);
     },
 
     // 处理参数更新

+ 55 - 4
src/views/videoMonitor/components/VideoControl.vue

@@ -18,8 +18,19 @@
           </el-select>
         </el-form-item>
         <el-form-item label="预置点" prop="presetIndex">
-          <el-select class="myInput" size="mini" v-model="presetIndex" placeholder="请选择预置点" style="width: 100%">
-            <el-option v-for="item in Array.from({ length: 255 }, (item, index) => index + 1)" :key="item" :label="item" :value="item"></el-option>
+          <el-select
+            class="myInput"
+            size="mini"
+            v-model="presetIndex"
+            placeholder="请选择预置点"
+            style="width: 100%"
+          >
+            <el-option
+              v-for="(item, index) in cameraPresetList"
+              :key="index"
+              :label="item.label"
+              :value="item.value"
+            ></el-option>
           </el-select>
         </el-form-item>
         <div class="btn_box">
@@ -39,7 +50,8 @@
 </template>
 
 <script>
-import Dayjs from 'dayjs'
+import Dayjs from "dayjs";
+import { getCameraPresetOptions, savePreset } from "@/API/custom";
 export default {
   name: 'VideoControl',
   props: {
@@ -76,10 +88,49 @@ export default {
       speed: 5,
       presetIndex: 1,
       // 视频控制 end
+      // 预置位列表
+      cameraPresetList: [],
+    };
+  },
+  mounted() {
+    if (this.curVideoData.id) {
+      this.getCameraPresetList();
+    } else {
+      this.$watch("curVideoData.id", (newId) => {
+        if (newId) {
+          this.getCameraPresetList();
+        }
+      });
     }
   },
-  mounted() {},
   methods: {
+    async getCameraPresetList() {
+      try {
+        const res = await getCameraPresetOptions({
+          id: this.curVideoData.id,
+        });
+        if (res.code === 20000) this.cameraPresetList = res.data.content;
+        // console.log("获取预置位列表", this.cameraPresetList);
+      } catch (error) {
+        console.log("getCameraPreset error", error);
+      }
+    },
+    async savePresetData(item) {
+      try {
+        let res = await savePreset({
+          cameraId: this.cameraData.id,
+          preset: item.value,
+          name: item.label,
+        });
+        if (res.code === 20000) {
+          // console.log("预置位设置成功", res);
+          //摄像头预置位设置
+          this.changePtzPresetParam(8);
+          //重新获取预置位
+          this.getCameraPresetList();
+        }
+      } catch (error) {}
+    },
     changePtzCommParam(comm, stop) {
       if (!comm) return
       if (!this.curVideoData.id) {

+ 0 - 184
src/views/videoMonitorORI/components/StationSelect.vue

@@ -1,184 +0,0 @@
-<template>
-  <div class="stationSelect-container">
-    <div class="search-box">
-      <el-input v-model="stationName" placeholder="请输入查询内容" />
-      <div class="search-btn">
-        <img :src="require('@/assets/imgs/video/icon_sousuo_sel@2x.png')" alt="" />
-      </div>
-    </div>
-    <div class="stationTree-box">
-      <el-tree
-        :data="stationData"
-        :props="defaultProps"
-        node-key="id"
-        accordion
-        @node-click="handleNodeClick"
-        :filter-node-method="filterNode"
-        ref="tree"
-      ></el-tree>
-    </div>
-  </div>
-</template>
-
-<script>
-export default {
-  name: "StationSelect",
-  props: {
-    videoList: {
-      type: Array,
-      default: () => [],
-    },
-    selectedVideo: {
-      type: String,
-      default: "",
-    },
-  },
-  data() {
-    return {
-      stationName: "",
-      defaultProps: {
-        children: "children",
-        label: "label",
-        id: "id",
-      },
-    };
-  },
-  computed: {
-    stationData() {
-      return this.videoList.map((item) => {
-        return {
-          id: item.id,
-          label: item.name,
-        };
-      });
-    },
-  },
-  watch: {
-    stationName(val) {
-      this.$nextTick(() => {
-        this.$refs.tree.filter(val);
-      });
-    },
-    selectedVideo: {
-      handler(val) {
-        this.$nextTick(() => {
-          this.$refs.tree.setCurrentKey(val);
-        });
-      },
-    },
-  },
-  methods: {
-    handleNodeClick(data) {
-      console.log(data);
-      this.$emit("update:selectedVideo", data.id);
-    },
-    filterNode(value, data) {
-      if (!value) return true;
-      return data.label.indexOf(value) !== -1;
-    },
-  },
-};
-</script>
-<style lang="less" scoped>
-.stationSelect-container {
-  width: 306px;
-  // height: 862px;
-  min-height: 862px;
-  height: calc(100vh - 218px);
-  background: #001f54;
-  border: 1px solid #5bd6ff;
-  .search-box {
-    width: 100%;
-    padding: 10px;
-    display: flex;
-    // justify-content: space-between;
-    ::v-deep .el-input__inner {
-      // width: 110px;
-      height: 30px;
-      border-radius: 0;
-      background: rgba(0, 20, 23, 0.2);
-      border: 0.5px solid #5bd6ff;
-      color: #fff;
-      // padding-right: 35px;
-    }
-    ::v-deep .el-input__inner:focus {
-      border: 0.5px solid #5bd6ff !important;
-    }
-    ::v-deep .el-input.is-focus .el-input__inner {
-      border: 0.5px solid #5bd6ff !important;
-    }
-    ::v-deep .el-input__suffix {
-      right: 5px;
-    }
-    ::v-deep .el-input__icon {
-      line-height: 30px;
-    }
-    .search-btn {
-      width: 30px;
-      height: 30px;
-      margin-left: 10px;
-      cursor: pointer;
-      flex-shrink: 0;
-      img {
-        width: 100%;
-        height: 100%;
-      }
-    }
-  }
-  .stationTree-box {
-    padding: 0 10px;
-    height: calc(100% - 50px);
-    overflow-y: auto;
-    .el-tree {
-      background-color: transparent;
-      color: #fff;
-      /deep/ .el-tree-node__expand-icon.expanded {
-        -webkit-transform: rotate(0deg);
-        transform: rotate(0deg);
-      }
-      //有子节点 且未展开
-      /deep/ .el-icon-caret-right:before {
-        background: url("~@/assets/imgs/video/unfold.png") no-repeat 0 0;
-        content: "";
-        display: block;
-        width: 16px;
-        height: 16px;
-        font-size: 16px;
-        background-size: 16px;
-      }
-      //有子节点 且已展开
-      /deep/ .el-tree-node__expand-icon.expanded.el-icon-caret-right:before {
-        background: url("~@/assets/imgs/video/fold.png") no-repeat 0 0;
-        content: "";
-        display: block;
-        width: 16px;
-        height: 16px;
-        font-size: 16px;
-        background-size: 16px;
-      }
-      //没有子节点
-      /deep/.el-tree-node__expand-icon.is-leaf::before {
-        background: url("~@/assets/imgs/video/camera.png") no-repeat 0 0;
-        content: "";
-        display: block;
-        width: 16px;
-        height: 16px;
-        font-size: 16px;
-        background-size: 16px;
-      }
-      /deep/ .el-tree-node.is-current > .el-tree-node__content {
-        background-color: transparent;
-        color: #73ffd2;
-      }
-      /deep/ .el-tree-node:focus > .el-tree-node__content {
-        background-color: transparent;
-        color: #73ffd2;
-      }
-      /deep/ .el-tree-node__content:hover {
-        background-color: transparent;
-        color: #73ffd2;
-      }
-    }
-  }
-}
-</style>

+ 0 - 274
src/views/videoMonitorORI/components/VideoConfig.vue

@@ -1,274 +0,0 @@
-<template>
-  <div class="videoConfig-container">
-    <div class="codestream-box">
-      <div class="item-label">码流类型:</div>
-      <div class="codestream-main">
-        <el-select class="myInput" v-model="selectedCodeStreamType" @change="updateCodeStreamType">
-          <el-option value="1" label="主码流"></el-option>
-          <el-option value="2" label="子码流"></el-option>
-          <el-option value="3" label="辅码流"></el-option>
-        </el-select>
-        <div class="search-btn">
-          <img :src="require('@/assets/imgs/video/icon_sousuo_sel@2x.png')" alt="" />
-        </div>
-      </div>
-    </div>
-    <div class="splitScreen-box">
-      <div class="item-label">分屏方式:</div>
-      <div class="splitScreen-main">
-        <el-select
-          class="myInput"
-          v-model="selectedSplitScreenType"
-          @change="updateSplitScreenType"
-        >
-          <el-option
-            v-for="item of screenConfig"
-            :key="item.type"
-            :value="item.type"
-            :label="item.name"
-          ></el-option>
-        </el-select>
-      </div>
-    </div>
-    <div class="polling-box">
-      <div class="item-label">轮询设置:</div>
-      <div class="polling-main">
-        <div class="polling-item">
-          <span>速率</span>
-          <el-input-number
-            class="myInput"
-            v-model="pollingConfig.freq"
-            :step="1"
-            controls-position="right"
-            size="mini"
-            @change="updatePolling"
-          />
-        </div>
-        <div class="polling-item">
-          <span>开启</span>
-          <el-switch
-            v-model="pollingConfig.open"
-            active-color="#13ce66"
-            inactive-color="#C0C4CC"
-            :active-value="true"
-            :inactive-value="false"
-            @change="openPolling"
-          >
-          </el-switch>
-        </div>
-        <div class="polling-item">
-          <span>大屏</span>
-          <el-switch
-            v-model="isAllScreen"
-            active-color="#13ce66"
-            inactive-color="#C0C4CC"
-            :active-value="true"
-            :inactive-value="false"
-            @change="setAllScreen"
-          >
-          </el-switch>
-        </div>
-      </div>
-    </div>
-    <div class="video-ptz-box">
-      <div class="item-label">
-        视频操作:
-        <el-tag v-if="curVideoData.name" size="small" closable @close="updateVideoData">
-          {{ curVideoData.name }}
-        </el-tag>
-        <span v-else>无</span>
-      </div>
-      <div class="video-ptz-main">
-        <video-control :curVideoData="curVideoData" />
-      </div>
-    </div>
-  </div>
-</template>
-
-<script>
-import VideoControl from "./VideoControl";
-export default {
-  name: "VideoConfig",
-  components: { VideoControl },
-  props: {
-    curSplitScreenType: {
-      type: String,
-      default: "1",
-    },
-    curCodeStreamType: {
-      type: String,
-      default: "1",
-    },
-    screenConfig: {
-      type: Array,
-      default: () => [],
-    },
-    curVideoData: {
-      type: Object,
-      default: () => ({}),
-    },
-    pollingConfig: {
-      type: Object,
-      default: () => ({ open: false, freq: 10 }),
-    },
-    screenModel: {
-      type: String,
-      default: "large",
-    },
-  },
-  data() {
-    return {
-      selectedCodeStreamType: "1",
-      selectedSplitScreenType: "9",
-      isAllScreen: false,
-    };
-  },
-  watch: {
-    screenModel(val) {
-      this.isAllScreen = val === "full";
-    },
-  },
-  methods: {
-    updateSplitScreenType(type) {
-      this.$emit("update:curSplitScreenType", type);
-      this.updateVideoData();
-    },
-    updateCodeStreamType(data) {
-      this.$emit("update:curCodeStreamType", data);
-    },
-    updateVideoData() {
-      this.$emit("update:curVideoData", {});
-    },
-    openPolling(value) {
-      if (value) {
-        this.$parent.startLoop();
-      } else {
-        this.$parent.stopLoop();
-      }
-    },
-    updatePolling(val) {
-      if (this.$parent.timer) {
-        this.$parent.stopLoop();
-        setTimeout(() => {
-          this.$parent.startLoop();
-        }, 500);
-      }
-    },
-    setAllScreen(value) {
-      if (value) {
-        this.$emit("update:screenModel", "full");
-      }
-    },
-  },
-};
-</script>
-<style lang="less" scoped>
-.videoConfig-container {
-  width: 258px;
-  // height: 862px;
-  min-height: 862px;
-  height: calc(100vh - 218px);
-  background: #001f54;
-  border: 1px solid #5bd6ff;
-  padding: 0 8px;
-  .codestream-box {
-    .codestream-main {
-      display: flex;
-      .search-btn {
-        width: 30px;
-        height: 30px;
-        margin-left: 6px;
-        cursor: pointer;
-        flex-shrink: 0;
-        img {
-          width: 100%;
-          height: 100%;
-        }
-      }
-    }
-  }
-  .splitScreen-box {
-    .splitScreen-main {
-      display: flex;
-      flex-direction: column;
-      align-items: flex-start;
-      .splitScreen-item {
-        width: 138px;
-        height: 47px;
-        cursor: pointer;
-        img {
-          width: 100%;
-          height: 100%;
-        }
-      }
-    }
-  }
-  .polling-box {
-    .polling-main {
-      padding: 0 10px;
-      .polling-item {
-        display: flex;
-        align-items: center;
-        margin-bottom: 10px;
-        span {
-          width: 50px;
-          color: #5bd6ff;
-          text-align: center;
-        }
-      }
-    }
-  }
-  .myInput.el-select,
-  .myInput.el-input-number {
-    ::v-deep .el-input__inner {
-      // width: 110px;
-      height: 30px;
-      border-radius: 0;
-      background: rgba(0, 20, 23, 0.2);
-      border: 0.5px solid #5bd6ff;
-      color: #5bd6ff;
-      // padding-right: 35px;
-    }
-    ::v-deep .el-input__inner:focus {
-      border: 0.5px solid #5bd6ff !important;
-    }
-    ::v-deep .el-input.is-focus .el-input__inner {
-      border: 0.5px solid #5bd6ff !important;
-    }
-    ::v-deep .el-input__suffix {
-      right: 5px;
-    }
-    ::v-deep .el-input__icon {
-      line-height: 30px;
-    }
-    ::v-deep .el-input-number__decrease,
-    ::v-deep .el-input-number__increase {
-      border-radius: 0;
-      background: rgba(0, 60, 57, 0.3);
-      border-color: #5bd6ff;
-      color: #fff;
-    }
-  }
-  .item-label {
-    height: 48px;
-    line-height: 48px;
-    font-size: 14px;
-    color: #5bd6ff;
-    letter-spacing: 0;
-    font-weight: 400;
-    .el-tag {
-      border-radius: 0;
-      background: rgba(0, 20, 23, 0.2);
-      border: 0.5px solid #5bd6ff;
-      color: #5bd6ff;
-      /deep/ .el-tag__close {
-        color: #5bd6ff;
-        &:hover {
-          color: #fff;
-          background-color: #5bd6ff;
-        }
-      }
-    }
-  }
-}
-</style>

+ 0 - 253
src/views/videoMonitorORI/components/VideoControl.vue

@@ -1,253 +0,0 @@
-<template>
-  <div class="videoControl-container">
-    <div class="comm-panel">
-      <div class="btn-box" v-for="item of commandConfig.direction" :key="item.type">
-        <el-button
-          type="primary"
-          :icon="`el-icon-${item.type}`"
-          size="mini"
-          @mousedown.native="changePtzCommParam(item.command, false)"
-          @mouseup.native="changePtzCommParam(item.command, true)"
-        ></el-button>
-      </div>
-    </div>
-    <div class="zoom-panel">
-      <div class="btn-box" v-for="item of commandConfig.zoom" :key="item.type">
-        <el-button
-          type="primary"
-          :icon="`el-icon-${item.type}`"
-          size="mini"
-          @mousedown.native="changePtzCommParam(item.command, false)"
-          @mouseup.native="changePtzCommParam(item.command, true)"
-        ></el-button>
-      </div>
-    </div>
-    <div class="speed-panel">
-      <span class="form-label">速度:</span>
-      <el-select class="myInput" size="mini" v-model="speed" placeholder="请选择速度">
-        <el-option
-          v-for="item in Array.from({ length: 10 }, (item, index) => index + 1)"
-          :key="item"
-          :label="item"
-          :value="item"
-        ></el-option>
-      </el-select>
-    </div>
-    <div class="preset-panel">
-      <span class="form-label">预置点:</span>
-      <el-select class="myInput" size="mini" v-model="presetIndex" placeholder="请选择预置点">
-        <el-option
-          v-for="item in Array.from({ length: 255 }, (item, index) => index + 1)"
-          :key="item"
-          :label="item"
-          :value="item"
-        ></el-option>
-      </el-select>
-      <el-button type="primary" size="mini" @click="changePtzPresetParam(8)">设置</el-button>
-      <el-button type="primary" size="mini" @click="changePtzPresetParam(39)">转到</el-button>
-    </div>
-    <div class="playback-panel">
-      <span class="form-label">时间:</span>
-      <el-date-picker
-        style="max-width: 170px"
-        class="myInput"
-        v-model="startTime"
-        type="datetime"
-        placeholder="选择回放开始时间"
-        size="mini"
-      ></el-date-picker>
-      <el-button type="success" size="mini" @click="changePlayTypeParam(true)" :disabled="!startTime">回放</el-button>
-      <el-button type="primary" size="mini" @click="changePlayTypeParam(false)" :disabled="!startTime">实时</el-button>
-    </div>
-  </div>
-</template>
-
-<script>
-import Dayjs from "dayjs";
-export default {
-  name: "VideoControl",
-  props: {
-    curVideoData: {
-      type: Object,
-      require: true,
-      default: () => ({}),
-    },
-  },
-  data() {
-    return {
-      // 视频控制相关 start
-      commandConfig: {
-        //视频控制开关配置
-        direction: [
-          //方向
-          { type: "top-left", name: "左上", command: 25 },
-          { type: "top", name: "上", command: 21 },
-          { type: "top-right", name: "右上", command: 26 },
-          { type: "back", name: "左", command: 23 },
-          { type: "rank", name: "中", command: 0 },
-          { type: "right", name: "右", command: 24 },
-          { type: "bottom-left", name: "左下", command: 27 },
-          { type: "bottom", name: "下", command: 22 },
-          { type: "bottom-right", name: "右下", command: 28 },
-        ],
-        zoom: [
-          //放大缩小
-          { type: "zoom-in", name: "放大", command: 11 },
-          { type: "zoom-out", name: "缩小", command: 12 },
-        ],
-      },
-      startTime: null,
-      speed: 5,
-      presetIndex: 1,
-      // 视频控制 end
-    };
-  },
-  mounted() {
-    console.log(this.curVideoData);
-  },
-  methods: {
-    changePtzCommParam(comm, stop) {
-      if (!comm) return;
-      if (!this.curVideoData.id) {
-        stop && this.$message.warning("请先选择视频窗口!");
-        return;
-      }
-      let param = {
-        id: this.curVideoData.id,
-        ptzCommand: comm,
-        ptzStop: stop,
-        ptzSpeed: this.speed,
-        canControl: this.curVideoData.ptzEnable,
-      };
-      this.$EventBus.$emit("updateSendParam", param);
-    },
-    changePtzPresetParam(comm) {
-      if (!comm) return;
-      if (!this.curVideoData.id) {
-        this.$message.warning("请先选择视频窗口!");
-        return;
-      }
-      let param = {
-        id: this.curVideoData.id,
-        ptzPreset: comm,
-        ptzPresetIndex: this.presetIndex,
-        canControl: this.curVideoData.ptzEnable,
-      };
-      this.$EventBus.$emit("updateSendParam", param);
-    },
-    /**
-     * state  true代表回放模式
-     */
-    changePlayTypeParam(state) {
-      let param = { id: this.curVideoData.id };
-      if (!this.curVideoData.id) {
-        this.$message.warning("请先选择视频窗口!");
-        return;
-      }
-      if (state) {
-        if (!this.startTime) {
-          this.$message.warning("请选择回放开始时间!");
-          return;
-        }
-        param["startTime"] = Dayjs(this.startTime).format("YYYY-MM-DD HH:mm:ss");
-      }
-      this.$EventBus.$emit("updateSendParam", param, true);
-    },
-  },
-};
-</script>
-<style lang="less" scoped>
-.videoControl-container {
-  display: flex;
-  flex-direction: column;
-  align-items: center;
-  padding: 0 10px;
-  .comm-panel {
-    width: 180px;
-    display: flex;
-    flex-wrap: wrap;
-    .el-button {
-      background: #007ccc;
-      border-color: #007ccc;
-    }
-  }
-  .zoom-panel {
-    width: 120px;
-    display: flex;
-    .el-button {
-      background: #007ccc;
-      border-color: #007ccc;
-    }
-  }
-  .speed-panel {
-    margin-top: 15px;
-    display: flex;
-    align-items: center;
-  }
-  .preset-panel {
-    margin-top: 15px;
-    display: flex;
-    align-items: center;
-    flex-wrap: wrap;
-    .el-select {
-      max-width: 170px;
-    }
-    .el-button {
-      margin-top: 15px;
-      background: rgba(0, 60, 57, 0.3);
-      border: 1px solid #5bd6ff;
-      color: #c9f1ff;
-    }
-  }
-  .playback-panel {
-    margin-top: 15px;
-    display: flex;
-    align-items: center;
-    flex-wrap: wrap;
-    .el-button {
-      margin-top: 15px;
-      background: rgba(0, 60, 57, 0.3);
-      border: 1px solid #5bd6ff;
-      color: #c9f1ff;
-    }
-  }
-  .btn-box {
-    flex-shrink: 0;
-    width: 60px;
-    height: 40px;
-    display: flex;
-    justify-content: center;
-    align-items: center;
-  }
-  .form-label {
-    color: #5bd6ff;
-    display: inline-block;
-    width: 50px;
-    flex-shrink: 0;
-    // text-align: right;
-  }
-  .myInput {
-    ::v-deep .el-input__inner {
-      // width: 110px;
-      height: 30px;
-      border-radius: 0;
-      background: rgba(0, 20, 23, 0.2);
-      border: 0.5px solid #007ccc;
-      color: #5bd6ff;
-      // padding-right: 35px;
-    }
-    ::v-deep .el-input__inner:focus {
-      border: 0.5px solid #007ccc !important;
-    }
-    ::v-deep .el-input.is-focus .el-input__inner {
-      border: 0.5px solid #007ccc !important;
-    }
-    ::v-deep .el-input__suffix {
-      right: 5px;
-    }
-    ::v-deep .el-input__icon {
-      line-height: 30px;
-    }
-  }
-}
-</style>

+ 0 - 146
src/views/videoMonitorORI/components/VideoWindow.vue

@@ -1,146 +0,0 @@
-<template>
-  <div
-    class="videoWindow-container"
-    :style="gridStyle"
-    :class="{
-      small: screenModel === 'small',
-      large: screenModel === 'large',
-      full: screenModel === 'full',
-    }"
-    @dblclick="zoomWindow"
-  >
-    <div
-      v-for="item of showVideoList"
-      :key="item.id"
-      class="videoWindow-item"
-      :class="{
-        unequal: unequal,
-        selected: curVideoData.id === item.id,
-      }"
-      @click="chooseWindow(item)"
-    >
-      <!-- :src="require(`@/assets/imgs/video/${item.url}`)" -->
-      <video-content :cameraData="item" :curVideoId="curVideoData.id" />
-    </div>
-  </div>
-</template>
-
-<script>
-import VideoContent from "./videoContent.vue";
-export default {
-  name: "VideoWindow",
-  components: { VideoContent },
-  props: {
-    showVideoList: {
-      type: Array,
-      default: () => [],
-    },
-    curSplitScreenType: {
-      type: String,
-      default: "1",
-    },
-    screenConfig: {
-      type: Array,
-      default: () => [],
-    },
-    curVideoData: {
-      type: Object,
-      default: () => ({}),
-    },
-    screenModel: {
-      type: String,
-      default: "large",
-    },
-  },
-  data() {
-    return {
-      socketList: {},
-      clickTime: null,
-    };
-  },
-  computed: {
-    // grid布局样式
-    gridStyle() {
-      let { row, col } = this.screenConfig.find((item) => item.type === this.curSplitScreenType);
-      return `grid-template-columns: repeat(${row}, 1fr);grid-template-rows: repeat(${col}, 1fr);`;
-    },
-    // 是否主次屏
-    unequal() {
-      const { unequal } = this.screenConfig.find((item) => item.type === this.curSplitScreenType);
-      return unequal;
-    },
-  },
-
-  methods: {
-    handleChange() {},
-    chooseWindow(item) {
-      clearTimeout(this.clickTime);
-      this.clickTime = setTimeout(() => {
-        if (this.curVideoData.id === item.id) {
-          // item.canControl
-          this.$emit("update:curVideoData", {});
-        } else {
-          this.$emit("update:curVideoData", item);
-        }
-      }, 300);
-    },
-    zoomWindow() {
-      // console.log("111");
-      clearTimeout(this.clickTime);
-      if (this.screenModel === "full") {
-        this.$emit("update:screenModel", "small");
-      } else if (this.screenModel === "large") {
-        this.$emit("update:screenModel", "small");
-      } else if (this.screenModel === "small") {
-        this.$emit("update:screenModel", "large");
-      }
-    },
-  },
-};
-</script>
-<style lang="less" scoped>
-.videoWindow-container {
-  background: #001f54;
-  border: 1px solid #5bd6ff;
-  padding: 10px;
-  display: grid;
-  // grid-template-columns: repeat(3, 1fr);
-  // grid-template-rows: repeat(3, 1fr);
-  gap: 10px;
-  &.small {
-    width: 1138px;
-    // height: 862px;
-    min-height: 862px;
-    height: calc(100vh - 218px);
-  }
-  &.large {
-    width: 100%;
-    min-height: 902px;
-    height: calc(100vh - 178px);
-  }
-  &.full {
-    width: 100vw;
-    height: 100vh;
-    padding: 3px;
-    gap: 3px;
-  }
-  .videoWindow-item {
-    background: rgba(0, 20, 23, 0.2);
-    border: 2px solid #5bd6ff;
-    color: #fff;
-    font-size: 20px;
-    display: flex;
-    justify-content: center;
-    align-items: center;
-    cursor: pointer;
-    overflow: hidden;
-    &.unequal:first-child {
-      grid-column-start: span 2;
-      grid-row-start: span 2;
-    }
-    &.selected {
-      border-color: orangered;
-    }
-  }
-}
-</style>

+ 0 - 147
src/views/videoMonitorORI/components/videoContent.vue

@@ -1,147 +0,0 @@
-<template>
-  <div class="img-container">
-    <img :src="url" v-if="url" />
-    <div class="image-slot" v-else>
-      <i class="el-icon-video-camera"></i>
-      <span>无信号</span>
-      <span>{{ cameraData.name }}</span>
-    </div>
-  </div>
-</template>
-<script>
-export default {
-  props: {
-    cameraData: {
-      type: Object,
-      default: () => ({}),
-    },
-    curVideoId: {
-      type: String,
-      default: "",
-    },
-  },
-  data() {
-    return {
-      id: "",
-      url: "",
-      lastUrl: "",
-      ws: null,
-      startTime: null,
-      speed: 4,
-      presetIndex: 1,
-    };
-  },
-  watch: {
-    cameraData: {
-      handler(val) {
-        if (val.id) {
-          this.updateEvent({ id: val.id }, true);
-        }
-      },
-      deep: true,
-      immediate: true,
-    },
-  },
-  mounted() {
-    this.$EventBus.$off("updateSendParam");
-    this.$EventBus.$on("updateSendParam", (data, state) => {
-      if (data.id === this.cameraData.id) {
-        this.updateEvent(data, state);
-      }
-    });
-  },
-  beforeDestroy() {
-    this.closeHandler();
-  },
-  methods: {
-    init(str) {
-      // this.socketList[`ws_${this.cameraData.id}`];
-      this.ws = new WebSocket(VUE_APP_BASE_WS() + "/VideoOverWebSocket");
-      // this.ws = new WebSocket("wss://" + window.location.host + BASE_URL + "/VideoOverWebSocket");
-      // this.ws = new WebSocket("ws://" + window.location.host + BASE_URL + "/VideoOverWebSocket");
-      this.ws.onmessage = (evt) => {
-        if (typeof evt.data === "string") {
-          console.log(JSON.parse(evt.data).Msg);
-        } else {
-          let _this = this;
-          // const updateUrl = _.debounce(function () {
-          let currUrl = URL.createObjectURL(evt.data);
-          if (_this.lastUrl) URL.revokeObjectURL(_this.lastUrl);
-          _this.lastUrl = currUrl;
-          _this.url = currUrl;
-          // }, 500);
-          // updateUrl();
-        }
-      };
-      this.handleSend(str);
-      // console.log(window);
-    },
-    handleSend(str) {
-      if (this.ws.readyState === WebSocket.OPEN) {
-        this.ws.send(str);
-      } else if (this.ws.readyState == WebSocket.CONNECTING) {
-        // Wait for the open event, maybe do something with promises
-        // depending on your use case. I believe in you developer!
-        this.ws.addEventListener("open", () => this.handleSend(str));
-      } else {
-        // etc.
-      }
-    },
-    updateEvent(data, state) {
-      const param = JSON.stringify(data);
-      if (this.ws && this.ws.readyState == 1) {
-        this.handleSend(param);
-      } else {
-        this.init(param);
-      }
-      if (state) {
-        setTimeout(() => {
-          this.url = "";
-          if (this.lastUrl) URL.revokeObjectURL(this.lastUrl);
-          this.lastUrl = "";
-        }, 500);
-      }
-    },
-    closeHandler() {
-      this.ws && this.ws.close();
-      setTimeout(() => {
-        if (this.url) URL.revokeObjectURL(this.url);
-        this.url = "";
-        this.lastUrl = "";
-        this.ws.onclose = (evt) => {
-          // this.ws = null;
-          console.log("websocket已关闭");
-        };
-      }, 500);
-    },
-  },
-};
-</script>
-
-<style lang="less" scoped>
-.img-container {
-  width: 100%;
-  height: 100%;
-  img {
-    width: 100%;
-    height: 100%;
-    object-fit: fill;
-    // display: block;
-  }
-  .image-slot {
-    width: 100%;
-    height: 100%;
-    // background-color: #f5f7fa;
-    color: #5bd6ff;
-    font-size: 24px;
-    display: flex;
-    flex-direction: column;
-    justify-content: center;
-    align-items: center;
-    font-weight: 500;
-    span {
-      font-size: 16px;
-    }
-  }
-}
-</style>

+ 0 - 218
src/views/videoMonitorORI/index.vue

@@ -1,218 +0,0 @@
-<template>
-  <div class="videoMonitor-container" :class="{ full: screenModel === 'full' }">
-    <div class="btns-container" v-show="screenModel === 'small'">
-      <div class="btn-box" v-for="btn of btnConfig" :key="btn.type" @click="curVideoType = btn.type">
-        <img
-          :src="require(`@/assets/imgs/video/btn_${btn.type}_${btn.type === curVideoType ? 'sel' : 'nor'}@2x.png`)"
-          alt=""
-        />
-      </div>
-    </div>
-    <div class="videoMonitor-main">
-      <station-select :videoList="videoList" :selectedVideo.sync="selectedVideo" v-show="screenModel === 'small'" />
-      <video-window
-        ref="videoWindow"
-        :curSplitScreenType="curSplitScreenType"
-        :screenConfig="screenConfig"
-        :curVideoData.sync="curVideoData"
-        :showVideoList="showVideoList"
-        :screenModel.sync="screenModel"
-      />
-      <video-config
-        v-show="screenModel === 'small'"
-        :screenConfig="screenConfig"
-        :curCodeStreamType.sync="curCodeStreamType"
-        :curSplitScreenType.sync="curSplitScreenType"
-        :curVideoData.sync="curVideoData"
-        :pollingConfig="pollingConfig"
-        :screenModel.sync="screenModel"
-      />
-    </div>
-    <!-- <div class="placeHolder">建设中</div> -->
-    <!-- <el-image :src="require('@/assets/imgs/test.png')" /> -->
-  </div>
-</template>
-
-<script>
-import StationSelect from './components/StationSelect'
-import VideoConfig from './components/VideoConfig.vue'
-import VideoWindow from './components/VideoWindow.vue'
-import { getCameraList } from '@/API/custom.js'
-export default {
-  name: 'videoMonitor',
-  components: {
-    VideoWindow,
-    VideoConfig,
-    StationSelect,
-  },
-  data() {
-    return {
-      screenConfig: [
-        { type: '1', name: '一分屏', row: 1, col: 1 },
-        { type: '4', name: '四分屏', row: 2, col: 2 },
-        { type: '9', name: '九分屏', row: 3, col: 3 },
-        {
-          type: '6',
-          name: '9分主次屏',
-          row: 3,
-          col: 3,
-          unequal: true,
-        },
-        { type: '16', name: '16分屏', row: 4, col: 4 },
-        {
-          type: '13',
-          name: '16分主次屏',
-          row: 4,
-          col: 4,
-          unequal: true,
-        },
-      ],
-      btnConfig: [
-        { name: '实时视频', type: 'realtime' },
-        { name: '视频回放', type: 'playback' },
-        { name: '视频轮询', type: 'rotationpatrol' },
-      ],
-      videoList: Array.from({ length: 30 }, (item, index) => ({
-        id: index + '',
-        name: '视频' + index,
-      })), //所有摄像头
-      showVideoList: [], //当前展示的摄像头
-      selectedVideo: '', //左边树当前选中的摄像头
-      curVideoType: 'realtime', //当前视频模式
-      curSplitScreenType: '9', //当前分屏模式
-      curCodeStreamType: '1', // 当前码流格式
-      curVideoData: {}, //当前选中的视频窗口
-      timer: null,
-      curIndex: 0,
-      screenModel: 'large', // 窗口展示大小模式  full/large/small
-      pollingConfig: {
-        open: true,
-        freq: 10,
-      },
-    }
-  },
-  watch: {
-    curSplitScreenType(val) {
-      this.buildVideoList(true)
-    },
-    selectedVideo(id) {
-      this.curIndex = this.videoList.findIndex(item => item.id === id)
-      this.buildVideoList(true)
-    },
-    screenModel(val) {
-      this.$parent.fullScreen = val === 'full'
-    },
-  },
-  mounted() {
-    this.getCameraList()
-    this.buildVideoList()
-    this.$once('hook:beforeDestroy', () => {
-      this.stopLoop()
-    })
-  },
-  methods: {
-    getCameraList() {
-      getCameraList({}).then(res => {
-        let content = res.data.content || []
-        // 暂时屏蔽掉没信号的摄像头,否则会导致服务崩溃
-        // let tData = content.filter((c) => {
-        //   return !["静海06BR越站区"].includes(c.name);
-        // });
-        this.videoList = content
-        // this.videoList = [content[8]];
-        this.selectedVideo = this.videoList[0]?.id
-        this.buildVideoList()
-        // 如果轮询默认开启、自动开始轮询
-        this.pollingConfig.open && this.startLoop()
-      })
-    },
-    startLoop() {
-      // 视频总数大于窗口总数时开始轮询
-      if (this.videoList.length <= +this.curSplitScreenType) {
-        this.$message.warning('当前分屏下无需轮询!')
-        return
-      }
-      if (!this.timer) {
-        this.timer = setInterval(() => {
-          this.selectedVideo = this.videoList[this.curIndex].id
-          this.buildVideoList(true)
-        }, this.pollingConfig.freq * 1000)
-      }
-    },
-    stopLoop() {
-      console.log('???')
-      this.timer && clearTimeout(this.timer)
-      this.timer = null
-    },
-    /**
-     * flog:是否轮询
-     */
-    buildVideoList(flog) {
-      let videoList = []
-      let start = this.curIndex //当前序号
-      let range = +this.curSplitScreenType //跨度
-      let next = start + range
-      let listLength = this.videoList.length //总数
-      if (range < listLength) {
-        if (flog) {
-          if (next === listLength) {
-            this.curIndex = 0
-            videoList = this.videoList.slice(start, start + range)
-          } else {
-            if (next < listLength) {
-              videoList = this.videoList.slice(start, start + range)
-              this.curIndex += range
-            } else {
-              let leftArr = this.videoList.slice(start, listLength)
-              let rightArr = this.videoList.slice(0, next - listLength)
-              videoList = [...leftArr, ...rightArr]
-              this.curIndex = next - listLength
-            }
-          }
-        } else {
-          videoList = this.videoList.slice(start, start + range)
-        }
-      } else {
-        videoList = this.videoList
-      }
-      this.showVideoList = videoList
-    },
-  },
-}
-</script>
-
-<style lang="less" scoped>
-.videoMonitor-container {
-  width: 100%;
-  height: 100%;
-  padding: 100px 90px 0;
-  // background: #001012;
-  pointer-events: auto;
-  &.full {
-    padding: 0;
-    .videoMonitor-main {
-      margin: 0;
-    }
-  }
-  .btns-container {
-    width: 100%;
-    height: 40px;
-    display: flex;
-    .btn-box {
-      width: 147px;
-      height: 40px;
-      margin-right: 10px;
-      cursor: pointer;
-      img {
-        width: 100%;
-        height: 100%;
-      }
-    }
-  }
-  .videoMonitor-main {
-    margin-top: 20px;
-    display: flex;
-    justify-content: space-between;
-  }
-}
-</style>

+ 46 - 9
src/views/videoMonitorType/components/VideoControl.vue

@@ -56,13 +56,10 @@
             style="width: 100%"
           >
             <el-option
-              v-for="item in Array.from(
-                { length: 255 },
-                (item, index) => index + 1
-              )"
-              :key="item"
-              :label="item"
-              :value="item"
+              v-for="(item, index) in cameraPresetList"
+              :key="index"
+              :label="item.label"
+              :value="item.value"
             ></el-option>
           </el-select>
         </el-form-item>
@@ -110,6 +107,7 @@
 
 <script>
 import Dayjs from "dayjs";
+import { getCameraPresetOptions, savePreset } from "@/API/custom";
 export default {
   name: "VideoControl",
   props: {
@@ -144,12 +142,51 @@ export default {
       },
       startTime: null,
       speed: 5,
-      presetIndex: 1,
+      presetIndex: null,
       // 视频控制 end
+      // 预置位列表
+      cameraPresetList: [],
     };
   },
-  mounted() {},
+  mounted() {
+    if (this.curVideoData.id) {
+      this.getCameraPresetList();
+    } else {
+      this.$watch("curVideoData.id", (newId) => {
+        if (newId) {
+          this.getCameraPresetList();
+        }
+      });
+    }
+  },
   methods: {
+    async getCameraPresetList() {
+      try {
+        const res = await getCameraPresetOptions({
+          id: this.curVideoData.id,
+        });
+        if (res.code === 20000) this.cameraPresetList = res.data.content;
+        // console.log("获取预置位列表", this.cameraPresetList);
+      } catch (error) {
+        console.log("getCameraPreset error", error);
+      }
+    },
+    async savePresetData(item) {
+      try {
+        let res = await savePreset({
+          cameraId: this.cameraData.id,
+          preset: item.value,
+          name: item.label,
+        });
+        if (res.code === 20000) {
+          // console.log("预置位设置成功", res);
+          //摄像头预置位设置
+          this.changePtzPresetParam(8);
+          //重新获取预置位
+          this.getCameraPresetList();
+        }
+      } catch (error) {}
+    },
     changePtzCommParam(comm, stop) {
       if (!comm) return;
       if (!this.curVideoData.id) {

+ 4 - 3
vue.config.js

@@ -17,7 +17,8 @@ module.exports = {
     },
     proxy: {
       '/yapi': {
-        target: 'https://10.0.0.201:8080/prod-api/', // 托克托现场
+        target: 'http://192.168.18.200:18082/prod-api/', // 托克托现场
+        // target: 'https://10.0.0.201:8080/prod-api/', // 托克托现场
         // target: 'http://172.168.0.62:8080/prod-api/', // 托克托现场
         // target: 'http://192.168.195.136:8080/prod-api/', // 托克托本地虚拟机
 
@@ -28,9 +29,9 @@ module.exports = {
         },
       },
       '/model': {
-        target: 'https://10.0.0.201:8081/model/', //托克托模型现场服务器
+        // target: 'https://10.0.0.201:8081/model/', //托克托模型现场服务器
         // target: 'http://172.168.0.62:8081/model/', //托克托模型现场服务器
-        // target: 'http://192.168.195.136:8081/model/', //托克托模型虚拟机
+        target: 'http://192.168.195.136:8081/model/', //托克托模型虚拟机
         changeOrigin: true,
         pathRewrite: {
           '^/model': '/',