sd
2025-07-28 84f19ab0d37599400959e85e63cfda5df4869bc8
src/pages/cameraAccess/components/SeparateRules.vue
@@ -6,78 +6,56 @@
          <div v-show="cameraType === 'camera'">
            <span>
              <span class="label">视频分析处理</span>
              <el-switch
                style="margin-left: 10px"
                v-model="Camera.analytics"
                @change="pollEnable"
                :disabled="!Camera.cameraId"
              ></el-switch>
              <el-switch style="margin-left: 10px" v-model="Camera.analytics" @change="pollEnable"
                :disabled="!Camera.cameraId"></el-switch>
            </span>
          </div>
          <div v-if="Camera.analytics && isShowPolling === 'show'" class="flex-box" v-show="cameraType === 'camera'">
            <span class="label">处理方式</span>
            <toggle-button
              :value="Camera.dealWay"
              :width="60"
              :labels="{ checked: '实时', unchecked: '轮询' }"
              :color="{
                checked: '#3D68E1',
                unchecked: '#FF7733',
                disabled: '#CCCCCC'
              }"
              :sync="true"
              @change="changePoll"
            />
            <toggle-button  :width="60" :labels="{ checked: '实时', unchecked: '实时' }" :color="{
              checked: '#3D68E1',
              unchecked: '#3D68E1',
              disabled: '#CCCCCC'
            }" :sync="true"/>
            <!-- <toggle-button :value="Camera.dealWay" :width="60" :labels="{ checked: '实时', unchecked: '轮询' }" :color="{
              checked: '#3D68E1',
              unchecked: '#FF7733',
              disabled: '#CCCCCC'
            }" :sync="true" @change="changePoll" /> -->
          </div>
          <div v-if="Camera.analytics" class="flex-box" v-show="cameraType === 'camera'">
            <span class="label">处理状态: {{ camStatus }}</span>
          </div>
          <div v-if="Camera.analytics" class="flex-box" v-show="cameraType === 'camera'">
            <span class="label"
              >分辨率:
            <span class="label">分辨率:
              {{
                Camera.camearInfo.resolution_width == 0 || Camera.camearInfo.resolution_height == 0
                  ? "本机分辨率"
                  : `${Camera.camearInfo.resolution_width} * ${Camera.camearInfo.resolution_height}`
              }}</span
            >
              }}</span>
          </div>
          <div v-if="Camera.analytics" class="flex-box">
            <span class="label">SmartAI节点: {{ Camera.runServerName }}</span>
          </div>
          <div v-if="Camera.analytics" class="flex-box">
          <!-- <div v-if="Camera.analytics" class="flex-box">
            <span class="label">算法快速通道</span>
            <div class="channel flex-box">
              <el-tooltip effect="dark" content="复制此摄像机算法规则" placement="bottom" popper-class="atooltip">
                <span
                  style="color: #3d68e1; cursor: pointer; font-size: 23px"
                  @click="ctrlC"
                  class="iconfont iconfuzhiguize"
                ></span>
                <span style="color: #3d68e1; cursor: pointer; font-size: 23px" @click="ctrlC"
                  class="iconfont iconfuzhiguize"></span>
              </el-tooltip>
              <el-tooltip
                effect="dark"
                :content="
                  !TreeDataPool.ctrlCameraId ? '粘贴算法规则' : `粘贴算法规则,来源:${TreeDataPool.ctrlCameraName}`
                "
                placement="bottom"
                popper-class="atooltip"
              >
                <span
                  :style="
                    !TreeDataPool.ctrlCameraId
                      ? 'cursor: not-allowed;font-size:23px;'
                      : 'color:#3D68E1;font-size:23px;cursor: pointer;'
                  "
                  @click="ctrlV"
                  class="iconfont iconniantie ml5"
                ></span>
              <el-tooltip effect="dark" :content="!TreeDataPool.ctrlCameraId ? '粘贴算法规则' : `粘贴算法规则,来源:${TreeDataPool.ctrlCameraName}`
                " placement="bottom" popper-class="atooltip">
                <span :style="!TreeDataPool.ctrlCameraId
                  ? 'cursor: not-allowed;font-size:23px;'
                  : 'color:#3D68E1;font-size:23px;cursor: pointer;'
                  " @click="ctrlV" class="iconfont iconniantie ml5"></span>
              </el-tooltip>
            </div>
          </div>
          </div> -->
        </div>
      </div>
    </div>
@@ -86,17 +64,13 @@
    <div class="top">
      <p class="task-css">
        <b style="font-size: 14px; line-height: 18px">场景</b>
        <b style="font-size: 14px; line-height: 18px">督查任务</b>
      </p>
      <div class="clearfix">
        <slide-scene :sceneData="Camera.rules"></slide-scene>
        <div class="top-right">
          <sysinfo
            :showRealPoll="cameraType === 'camera'"
            :ShowLocalVedio="cameraType === 'dataStack'"
            v-if="showSysInfo"
            style="margin-top: -10px"
          />
          <sysinfo :showRealPoll="cameraType === 'camera'" :ShowLocalVedio="cameraType === 'dataStack'"
            v-if="showSysInfo" style="margin-top: -10px" />
        </div>
      </div>
    </div>
@@ -119,61 +93,28 @@
            </div>
            <div class="img-box">
              <template v-if="TreeDataPool.treeActiveName == 'camera'">
                <polygon-canvas
                  class="cavas"
                  ref="canvas"
                  v-if="showCanvas"
                  v-loading="loading"
                  element-loading-text="刷新中,请稍等..."
                  element-loading-background="rgba(0, 0, 0, 0.8)"
                  :isShowDrawArrow="false"
                  :disabled="false"
                  :snapshot_url="Camera.baseImg"
                  :canvasDataShow="Camera.canvasData"
                  :currentCameraId="Camera.cameraId"
                  :loading="Camera.loading"
                  :canvasWidth="canvasWidth"
                  :canvasHeight="canvasHeight"
                  :isGB28181="Camera.gb28181"
                  @fromCanvas="getCanvasData"
                  @changeLoading="changeLoading"
                  @refresh="refresh"
                >
                <polygon-canvas class="cavas" ref="canvas" v-if="showCanvas" v-loading="loading"
                  element-loading-text="刷新中,请稍等..." element-loading-background="rgba(0, 0, 0, 0.8)"
                  :isShowDrawArrow="false" :disabled="false" :snapshot_url="Camera.baseImg"
                  :canvasDataShow="Camera.canvasData" :currentCameraId="Camera.cameraId" :loading="Camera.loading"
                  :canvasWidth="canvasWidth" :canvasHeight="canvasHeight" :isGB28181="Camera.gb28181"
                  @fromCanvas="getCanvasData" @changeLoading="changeLoading" @refresh="refresh">
                </polygon-canvas>
              </template>
              <template v-else>
                <div style="width: 100%" v-loading="getStackFileLoading">
                  <swiper
                    ref="swiper"
                    :auto-update="true"
                    :options="canvasSwiperOption"
                    @slideChange="swiperSlideChange"
                    class="swiper-box-container2"
                    style="width: 100%"
                  >
                  <swiper ref="swiper" :auto-update="true" :options="canvasSwiperOption"
                    @slideChange="swiperSlideChange" class="swiper-box-container2" style="width: 100%">
                    <swiper-slide v-for="(data, index) in swipercanvasData" :key="index">
                      <div>
                        <b class="video-title" style="font-size: 14px; margin-top: -10px">{{ data.name }}</b>
                        <polygon-canvas
                          class="cavas"
                          ref="canvas"
                          v-if="showCanvas"
                          v-loading="loading"
                          element-loading-text="刷新中,请稍等..."
                          element-loading-background="rgba(0, 0, 0, 0.8)"
                          :isShowDrawArrow="false"
                          :isShowRefresh="false"
                          :sourceType="data.type"
                          :disabled="false"
                          :snapshot_url="data.baseImg"
                          :canvasDataShow="Camera.canvasData"
                          :currentCameraId="data.stackId"
                          :loading="data.loading"
                          :canvasWidth="canvasWidth"
                          :canvasHeight="canvasHeight"
                          @fromCanvas="getCanvasData"
                          @changeLoading="changeLoading"
                        ></polygon-canvas>
                        <polygon-canvas class="cavas" ref="canvas" v-if="showCanvas" v-loading="loading"
                          element-loading-text="刷新中,请稍等..." element-loading-background="rgba(0, 0, 0, 0.8)"
                          :isShowDrawArrow="false" :isShowRefresh="false" :sourceType="data.type" :disabled="false"
                          :snapshot_url="data.baseImg" :canvasDataShow="Camera.canvasData"
                          :currentCameraId="data.stackId" :loading="data.loading" :canvasWidth="canvasWidth"
                          :canvasHeight="canvasHeight" @fromCanvas="getCanvasData"
                          @changeLoading="changeLoading"></polygon-canvas>
                      </div>
                    </swiper-slide>
                  </swiper>
@@ -192,14 +133,11 @@
            </div>
          </div>
          <div style="float: left; width: calc(10% - 90px); height: 100%"></div>
          <div
            class="time-box"
            style="
          <div class="time-box" style="
              width: calc(90% + 90px - 576px);
              overflow-x: auto;
              overflow-y: hidden;
            "
          >
            ">
            <p style="text-align: left; padding: 10px; box-sizing: border-box">
              <b style="font-size: 14px">时间段</b>
            </p>
@@ -208,12 +146,8 @@
        </div>
        <!-- 场景规则 -->
        <scene-rule
          :seletedCameras="[Camera]"
          :tableRuleList="Camera.rules"
          :onSaveScene="saveSceneRule"
          @delete-rule="delScenRule"
        ></scene-rule>
        <scene-rule :seletedCameras="[Camera]" :tableRuleList="Camera.rules" :onSaveScene="saveSceneRule"
          @delete-rule="delScenRule"></scene-rule>
      </div>
    </div>
  </div>
@@ -226,8 +160,9 @@
import { getCameraInfo } from "@/api/camera"
import { getGB28181CameraInfo } from "@/api/camera"
import { saveCameraScene } from "@/api/scene"
import { saveCameraAndTask, updateCameraAndTask } from "@/api/selectRule";
import { changeRunType } from "@/api/pollConfig"
import { changeRunType,changeRunTypeTwo } from "@/api/pollConfig"
import { findAllFileByStackId } from "@/api/localVedio"
import VideoRuleData from "@/Pool/VideoRuleData"
@@ -247,7 +182,7 @@
  },
  directives: {
    focus: {
      inserted: function(el) {
      inserted: function (el) {
        el.querySelector("input").focus()
      }
    }
@@ -440,6 +375,7 @@
    },
    refresh(url) {
      this.Camera.baseImg = url
      // console.info("url="+url)
    },
    // 初始化摄像机信息,父组件调用
    async initCameraData(id, type) {
@@ -469,19 +405,37 @@
    saveSceneRule(groupRule) {
      const payload = { ...groupRule }
      payload.cameraIds = [this.Camera.cameraId]
      payload.videoId = [this.Camera.cameraId][0]
      let _this = this
      saveCameraScene(payload).then((rsp) => {
        if (rsp && rsp.success) {
          this.Camera.update()
          this.$notify({
            type: "success",
            message: "策略保存成功!"
          })
          //刷新左侧树
          _this.$root.$children[0].$children[0].querySearchAsync("camera")
        }
      })
      if (payload.taskId) {
        updateCameraAndTask(payload).then((rsp) => {
          if (rsp && rsp.status === 200) {
            this.Camera.update()
            this.$notify({
              type: "success",
              message: "编辑成功!"
            })
            //刷新左侧树
            _this.$root.$children[0].$children[0].querySearchAsync("camera")
          }
        })
      } else {
        saveCameraAndTask(payload).then((rsp) => {
          if (rsp && rsp.status === 200) {
            this.Camera.update()
            this.$notify({
              type: "success",
              message: "保存成功!"
            })
            //刷新左侧树
            _this.$root.$children[0].$children[0].querySearchAsync("camera")
          }
        })
      }
    },
    delScenRule() {
      this.Camera.update()
@@ -491,6 +445,7 @@
    },
    //是否进行视频分析处理
    pollEnable(row) {
      // console.info("Camera.:"+JSON.stringify(this.Camera))
      let val = 0
      if (row) {
        if (this.PollData.RealTimeSum < this.PollData.channelTotal) {
@@ -504,80 +459,101 @@
        this.Camera.dealWay = false
        val = -1
      }
      console.info("isOpen:"+this.Camera.analytics?1:0)
      if (this.Camera.cameraId && this.Camera.cameraId !== undefined) {
        changeRunType({
          camera_ids: [this.Camera.cameraId],
          run_type: val,
          isGb: this.Camera.gb28181
        changeRunTypeTwo({
          videoId: this.Camera.cameraId,
          // isOpen: val
          isOpen: this.Camera.analytics?1:0
        }).then((rsp) => {
          this.getStatus()
          if (rsp && rsp.success) {
          if (rsp && rsp.status === 200) {
            this.$notify({
              type: "success",
              message: "配置成功"
            })
          } else {
            this.Camera.analytics = !this.Camera.analytics
            this.$notify({
              type: "error",
              message: "配置失败"
              message: rsp.msg
            })
          }
          this.TreeDataPool.fetchTreeData()
        })
        // changeRunType({
        //   camera_ids: [this.Camera.cameraId],
        //   run_type: val,
        //   isGb: this.Camera.gb28181
        // }).then((rsp) => {
        //   this.getStatus()
        //   if (rsp && rsp.success) {
        //     this.$notify({
        //       type: "success",
        //       message: "配置成功"
        //     })
        //   } else {
        //     this.$notify({
        //       type: "error",
        //       message: "配置失败"
        //     })
        //   }
        //   this.TreeDataPool.fetchTreeData()
        // })
      }
      this.PollData.statisticTaskInfo()
    },
    //实时、轮询切换
    changePoll(row) {
      //判断是新增还是更新
      if (this.Camera.cameraId && this.Camera.cameraId !== undefined) {
        if (this.PollData.RealTimeSum < this.PollData.channelTotal) {
          if (row.value) {
            this.Camera.dealWay = true
          } else {
            this.Camera.dealWay = false
          }
          changeRunType({
            camera_ids: [this.Camera.cameraId],
            run_type: this.Camera.dealWay ? 1 : 0,
            isGb: this.Camera.gb28181
          }).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
            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()
        this.PollData.statisticTaskInfo()
      }
      // if (this.Camera.cameraId && this.Camera.cameraId !== undefined) {
      //   if (this.PollData.RealTimeSum < this.PollData.channelTotal) {
      //     if (row.value) {
      //       this.Camera.dealWay = true
      //     } else {
      //       this.Camera.dealWay = false
      //     }
      //     changeRunType({
      //       camera_ids: [this.Camera.cameraId],
      //       run_type: this.Camera.dealWay ? 1 : 0,
      //       isGb: this.Camera.gb28181
      //     }).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
      //       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()
      //   this.PollData.statisticTaskInfo()
      // }
    },
    //复制
    ctrlC() {
@@ -628,6 +604,7 @@
.el-message--info .el-message__content {
  color: #999 !important;
}
.swiper-container {
  margin-left: auto;
  margin-right: auto;
@@ -637,6 +614,7 @@
  padding: 0;
  z-index: 1;
}
.swiper-local-prev,
.swiper-local-next {
  width: 40px;
@@ -647,6 +625,7 @@
  z-index: 99;
  border-radius: 4em;
  outline: none;
  .icon-btn {
    color: rgb(255, 255, 255);
    text-align: center;
@@ -654,48 +633,59 @@
    cursor: pointer;
  }
}
.swiper-local-prev {
  left: 10px;
}
.swiper-local-prev:hover {
  background: #666;
}
.swiper-local-next {
  left: 90%;
}
.swiper-local-next:hover {
  background: #666;
}
.s-separate-rules {
  width: 100%;
  padding: 13px 0 20px;
  .ai {
    //width: calc(100% + 76px);
    // height: 38px;
    // position: absolute;
    // left: -38px;
    height: 40px;
    .check-area {
      width: 100%;
      height: 100%;
      padding: 0 20px;
      -webkit-box-sizing: border-box;
      box-sizing: border-box;
      .ai-select {
        text-align: left;
        line-height: 30px;
        height: 30px;
        .flex-box {
          .label {
            & + label,
            & + div {
            &+label,
            &+div {
              margin-left: 10px;
              line-height: 1;
            }
          }
        }
      }
      .ai-select > div {
      .ai-select>div {
        display: inline-block;
        vertical-align: middle;
        margin-right: 30px;
@@ -707,14 +697,17 @@
      }
    }
  }
  .devide {
    height: 10px;
    background: #e9ebf2;
  }
  .top {
    width: 100%;
    padding: 10px 20px;
    box-sizing: border-box;
    .swiper-box {
      height: 100%;
      float: left;
@@ -722,14 +715,17 @@
      margin-top: -10px;
      position: relative;
    }
    .swiper-container {
      position: initial;
      min-width: 472px;
      width: 86%;
    }
    .swiper-slide {
      position: relative;
      width: 100%;
      .item-card {
        height: 110px !important;
        max-width: 126px;
@@ -745,6 +741,7 @@
        box-shadow: 0 5px 12px 0 rgba(0, 0, 0, 0.07);
        border-radius: 4px;
        cursor: pointer;
        .icon-xingzhuangcopy {
          position: relative;
          left: 0px;
@@ -764,16 +761,19 @@
          backdrop-filter: blur(1px) brightness(100%);
          display: none;
        }
        @media screen and (max-width: 1440px) {
          max-width: 110px;
        }
      }
      .item-card:hover {
        .mask {
          display: block;
        }
      }
    }
    .swiper-pre-border,
    .swiper-next-border {
      width: 40px;
@@ -784,6 +784,7 @@
      z-index: 99;
      border-radius: 4em;
      outline: none;
      .icon-btn {
        color: rgb(255, 255, 255);
        text-align: center;
@@ -791,15 +792,19 @@
        cursor: pointer;
      }
    }
    .swiper-pre-border {
      left: 10px;
    }
    .swiper-pre-border:hover {
      background: #666;
    }
    .swiper-next-border {
      right: 10px;
    }
    .swiper-next-border:hover {
      background: #666;
    }
@@ -808,24 +813,30 @@
      float: right;
      width: 54%;
      height: 144px;
      .card-box {
        width: 54% !important;
      }
      .eCharts-box {
        width: 45%;
        canvas {
          width: 98% !important;
        }
      }
    }
    .task-css {
      text-align: left;
      margin-bottom: 14px;
    }
  }
  .bottom {
    width: 100%;
    margin-bottom: 15px;
    .bottom-side {
      height: 100%;
      width: 250px;
@@ -835,6 +846,7 @@
      border-bottom: 1px solid #ccc;
      padding: 10px;
      box-sizing: border-box;
      .selectTask {
        margin: 10px auto;
        width: 140px;
@@ -842,6 +854,7 @@
        box-sizing: border-box;
        border: 1px solid #ccc;
        position: relative;
        .selectTaskDelete {
          position: absolute;
          right: 10px;
@@ -850,17 +863,21 @@
        }
      }
    }
    .bottom-right {
      padding: 10px 20px;
      box-sizing: border-box;
      .draw-and-time-box {
        height: 400px;
        width: 100%;
        //min-width: 1150px;
        .draw-box,
        .time-box {
          float: left;
          height: 100%;
          .img-box {
            height: calc(100% - 32px);
            //width: 90%;
@@ -871,48 +888,60 @@
            // align-items: center;
            position: relative;
            overflow: hidden;
            .refresh-btn {
              position: absolute;
              right: 10px;
              top: 10px;
            }
            img {
              width: 90%;
              padding: 5px;
              box-sizing: border-box;
            }
            .swiper-box-container {
              margin-top: -10px;
              text-align: left;
              padding: 0px 8px 0px 8px;
              .el-card__body {
                height: 100%;
                padding: 0px;
              }
              height: calc(100% - 10px);
              .info {
                width: 100%;
                height: 100%;
                .info-left {
                  width: 50%;
                  height: 100%;
                  float: left;
                  img {
                    width: 100%;
                  }
                }
                .info-right {
                  width: 50%;
                  height: 100%;
                  float: left;
                  box-sizing: border-box;
                  padding: 10px;
                  p {
                    padding: 4px 0px;
                  }
                  .infoIcon {
                    height: 24px;
                    cursor: pointer;
                    i {
                      margin: 5px;
                      font-size: 22px;
@@ -921,6 +950,7 @@
                }
              }
            }
            .pre-border,
            .next-border {
              width: 40px;
@@ -931,6 +961,7 @@
              z-index: 99;
              border-radius: 4em;
              outline: none;
              .icon-btn {
                color: rgb(255, 255, 255);
                text-align: center;
@@ -938,26 +969,33 @@
                cursor: pointer;
              }
            }
            .pre-border {
              left: -9px;
            }
            .pre-border:hover {
              background: #666;
            }
            .next-border {
              right: 10px;
            }
            .next-border:hover {
              background: #666;
            }
          }
        }
        .draw-box {
          width: 576px;
        }
        .draw-box-title {
          text-align: left;
          margin-top: -3px;
          .btn-css {
            position: relative;
            left: 514px;
@@ -966,6 +1004,7 @@
        }
      }
    }
    .bottom-right::-webkit-scrollbar {
      width: 0 !important;
    }
@@ -977,9 +1016,11 @@
    font-size: 14px;
    cursor: pointer;
  }
  .add-btn:hover {
    color: #2249b4;
  }
  .nocamera-css {
    cursor: not-allowed;
    color: #3d68e1;
@@ -995,22 +1036,25 @@
    margin-right: 7px;
    background: #3d68e1;
  }
  .loadingClass {
    text-align: center;
  }
  .el-loading-spinner-div {
  }
  .el-loading-spinner-div {}
}
</style>
<style lang="scss" scoped>
.el-dropdown-menu {
  width: 200px;
  .el-dropdown-menu__item {
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
  }
}
.el-loading-spinner {
  background: url("/images/cameraAccess/loading.gif") no-repeat;
  top: 50%;
@@ -1019,6 +1063,7 @@
  text-align: center;
  position: absolute;
  margin-left: 260px;
  .el-loading-text {
    color: #3d68e1;
    margin: 3px 0;