瀏覽代碼

摄像头绑定

ChenSir 1 年之前
父節點
當前提交
37617bb1ea

+ 52 - 0
aidex-quartz/src/main/java/com/aidex/quartz/task/cameraTask.java

@@ -0,0 +1,52 @@
+package com.aidex.quartz.task;
+
+import cn.hutool.core.date.DateUtil;
+import com.aidex.common.core.redis.RedisCache;
+import com.aidex.common.utils.StringUtils;
+import com.aidex.system.domain.SysShip;
+import com.aidex.system.mapper.SysCameraAlarmMapper;
+import com.aidex.system.service.SysShipService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import java.util.concurrent.TimeUnit;
+
+/**
+ * 摄像头定时任务
+ *
+ * @author ChenSir
+ */
+@Component("cameraTask")
+public class cameraTask
+{
+    protected static final Logger logger = LoggerFactory.getLogger(cameraTask.class);
+
+    @Autowired
+    private SysCameraAlarmMapper sysCameraAlarmMapper;
+
+    @Autowired
+    private SysShipService sysShipService;
+
+    @Autowired
+    private RedisCache redisCache;
+
+    public void getShipSurplusSeat(String shipId, String beforeTime, String redisKey)
+    {
+        logger.info("执行摄像头剩余座位数定时任务----------开始,船只id--{},定时任务插入时间---{},存入的RedisKey值---{}", shipId, beforeTime, redisKey);
+        int shipSurplusSeat = sysCameraAlarmMapper.getShipSurplusSeat(shipId, beforeTime, DateUtil.now());
+        SysShip sysShip = sysShipService.get(shipId);
+        // 剩余座位数
+        long all = sysShip.getNuclearLoadNum();
+        if (StringUtils.isNotEmpty(redisKey)) {
+            // 剩余座位数
+            long surplus = all - shipSurplusSeat >0 ? all - shipSurplusSeat  :  0;
+            redisCache.setCacheObject(redisKey, (int)surplus, 5, TimeUnit.MINUTES);
+            logger.info("执行摄像头剩余座位数定时任务----------结束,船只--{},剩余座位数---{}", sysShip.getShipNanme(), surplus);
+        }
+
+    }
+
+
+}

+ 35 - 0
aidex-system/src/main/java/com/aidex/system/domain/SysCameraAlarm.java

@@ -0,0 +1,35 @@
+package com.aidex.system.domain;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import javax.validation.constraints.NotBlank;
+import java.util.Date;
+
+/**
+ * @author :ChenSir
+ * @date :Created in 2024/3/29 9:24
+ * @description:预约记录
+ */
+@Data
+@AllArgsConstructor
+@NoArgsConstructor()
+public class SysCameraAlarm {
+
+	@ApiModelProperty(value = "摄像头报警id")
+	private String id;
+
+	@ApiModelProperty(value = "摄像头报警时间")
+	private Date dataTime;
+
+	@ApiModelProperty(value = "摄像头设备号")
+	private String deviceSn;
+
+	@ApiModelProperty(value = "当前报警人数")
+	private int personNum;
+
+
+}

+ 31 - 0
aidex-system/src/main/java/com/aidex/system/domain/SysShipCamera.java

@@ -0,0 +1,31 @@
+package com.aidex.system.domain;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.util.Date;
+
+/**
+ * @author :ChenSir
+ * @date :Created in 2024/3/29 9:24
+ * @description:船只绑定设备
+ */
+@Data
+@AllArgsConstructor
+@NoArgsConstructor()
+public class SysShipCamera {
+
+	@ApiModelProperty(value = "船只id")
+	private String shipId;
+
+	@ApiModelProperty(value = "摄像头设备号")
+	private String cameraDeviceSn;
+
+	@ApiModelProperty(value = "摄像头名称")
+	private String cameraDeviceName;
+
+	@ApiModelProperty(value = "船只名称")
+	private String shipName;
+}

+ 22 - 0
aidex-system/src/main/java/com/aidex/system/mapper/SysCameraAlarmMapper.java

@@ -0,0 +1,22 @@
+package com.aidex.system.mapper;
+
+import com.aidex.common.core.mapper.BaseMapper;
+import com.aidex.system.domain.SysAlarm;
+import com.aidex.system.domain.SysCameraAlarm;
+import org.apache.ibatis.annotations.Param;
+
+/**
+ * 报警信息Mapper接口
+ * @author ChenSir
+ * @email 914769835
+ * @date 2024-03-17
+ */
+public interface SysCameraAlarmMapper extends BaseMapper<SysCameraAlarm>
+{
+
+
+    int insertCameraAlarm(SysCameraAlarm sysCameraAlarm);
+
+    int getShipSurplusSeat(@Param("shipId") String shipId, @Param("startTime") String startTime, @Param("endTime") String endTime);
+
+}

+ 40 - 0
aidex-system/src/main/java/com/aidex/system/mapper/SysCameraAlarmMapper.xml

@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.aidex.system.mapper.SysCameraAlarmMapper">
+
+
+    <insert id="insertCameraAlarm" parameterType="com.aidex.system.domain.SysCameraAlarm">
+        INSERT INTO sys_camera_alarm(
+
+            id,
+
+            data_time,
+
+            device_sn,
+
+            person_num
+
+        ) VALUES (
+
+            #{id},
+
+            #{dataTime},
+
+            #{deviceSn},
+
+            #{personNum}
+        )
+    </insert>
+
+    <select id="getShipSurplusSeat" resultType="java.lang.Integer">
+        SELECT
+            coalesce(MAX(a.person_num),0)
+        FROM
+            sys_camera_alarm a
+        WHERE
+            a.device_sn IN ( SELECT camera_device_sn FROM sys_ship_camera WHERE ship_id = #{shipId} )
+            and a.data_time &gt;=#{startTime} and a.data_time &lt;=#{endTime}
+    </select>
+
+
+</mapper>

+ 180 - 0
aidex-ui/src/views/system/sysship/modules/SysShipCamera.vue

@@ -0,0 +1,180 @@
+<template>
+  <ant-modal
+    modalWidth="576"
+    modalHeight="500"
+    :visible="cameraOpen"
+    :modal-title="cameraTitle"
+    :adjust-size="true"
+    @cancel="cancel"
+  >
+    <a-card :bordered="false" slot="content" style="margin-bottom: 10px;">
+      <!-- 条件搜索 -->
+      <div class="table-page-search-wrapper">
+        <a-form :labelCol="labelCol" :wrapperCol="wrapperCol" ref="queryForm">
+          <a-row :gutter="32">
+            <a-col :span="16">
+              <a-form layout="inline">
+                <a-form-item label="摄像头" v-model="cameraDeviceSn">
+                  <a-select v-model="cameraDeviceSn" style="width: 180px;">
+                    <a-select-option v-for="item in cameraList" :value="item.deviceSn" :key="item.deviceSn">{{ item.deviceName }}</a-select-option>
+                  </a-select>
+                </a-form-item>
+              </a-form>
+            </a-col>
+            <a-col>
+              <span class="table-page-search-submitButtons" style="float: right;">
+                <a-button type="primary" @click="bind"><a-icon type="search" />绑定</a-button>
+              </span>
+            </a-col>
+          </a-row>
+        </a-form>
+      </div>
+    </a-card>
+    <a-card :bordered="false" slot="content" class="table-card">
+      <advance-table
+        title="监控绑定"
+        tableKey="base-sysShip-index-table"
+        size="middle"
+        @refresh="getShipCameraList"
+        :columns="cameraColumns"
+        :data-source="sysShipCameraList"
+        :loading="loading"
+        :format-conditions="true"
+      >
+        <span slot="operation" slot-scope="{text, record}">
+          <a @click="unbind(record)">
+            解绑
+          </a>
+        </span>
+      </advance-table>
+    </a-card>
+    <template slot="footer">
+      <a-button :disabled="disabled" @click="cancel">
+        关闭
+      </a-button>
+    </template>
+  </ant-modal>
+</template>
+<script>
+import AntModal from '@/components/pt/dialog/AntModal.vue'
+import AdvanceTable from '@/components/pt/table/AdvanceTable.vue'
+import { bindCamera, unbindCamera, getShipCameraList } from '@/api/system/sysShip'
+import { list } from '@/api/camera/camera'
+
+export default {
+  name: 'SysShipCamera',
+  props: {
+    shipId: {
+      type: String,
+      required: true
+    }
+  },
+  components: {
+    AdvanceTable,
+    AntModal
+  },
+  data () {
+    return {
+      cameraOpen: false,
+      closeDialog: true,
+      spinning: false,
+      delayTime: 100,
+      labelCol: { span: 2 },
+      wrapperCol: { span: 14 },
+      loading: false,
+      disabled: false,
+      total: 0,
+      cameraDeviceSn: '',
+      cameraTitle: '监控绑定',
+      // 表单参数
+      sysShipCameraList: [],
+      cameraList: [],
+      cameraColumns: [
+        {
+          title: '船只名称',
+          dataIndex: 'shipName',
+          align: 'center'
+        },
+        {
+          title: '摄像头',
+          dataIndex: 'cameraDeviceName',
+          align: 'center'
+        },
+        {
+          title: '操作',
+          dataIndex: 'operation',
+          align: 'center',
+          width: '15%',
+          scopedSlots: { customRender: 'operation' }
+        }
+      ]
+    }
+  },
+  mounted() {
+    if (this.shipId) {
+      this.getShipCameraList()
+    }
+    this.getCameraList()
+  },
+  created() {
+    // this.getCameraList()
+  },
+  methods: {
+    getCameraList() {
+      const param = {
+        pageNum: 1,
+        pageSize: 50
+      }
+      this.cameraList = []
+      list(param).then(response => {
+        this.cameraList = response.data.records.filter(item => {
+          return !this.sysShipCameraList.find(camera => camera.cameraDeviceSn === item.deviceSn)
+        })
+      })
+    },
+    openBind() {
+      this.cameraOpen = true
+    },
+    cancel() {
+      this.cameraOpen = false
+      this.$emit('close')
+    },
+    getShipCameraList() {
+      this.loading = true
+      this.sysShipCameraList = []
+      getShipCameraList(this.shipId).then(response => {
+        this.sysShipCameraList = response.data
+        this.loading = false
+      })
+    },
+    bind() {
+      const camera = this.cameraList.find(item => item.deviceSn === this.cameraDeviceSn)
+      const param = {
+        shipId: this.shipId,
+        cameraDeviceSn: this.cameraDeviceSn,
+        cameraDeviceName: camera.deviceName
+      }
+      bindCamera(param).then(response => {
+        this.$message.success(
+          '绑定成功',
+          3
+        )
+        this.getShipCameraList()
+      })
+    },
+    unbind(row) {
+      const param = {
+        shipId: row.shipId,
+        cameraDeviceSn: row.cameraDeviceSn
+      }
+      unbindCamera(param).then(response => {
+        this.$message.success(
+          '解绑成功',
+          3
+        )
+        this.getShipCameraList()
+      })
+    }
+  }
+}
+</script>

+ 197 - 0
aidex-ui/src/views/system/sysship/modules/SysShipCameraLive.vue

@@ -0,0 +1,197 @@
+<template>
+  <ant-modal
+    modalWidth="1500"
+    modalHeight="600"
+    :visible="cameraOpen"
+    :modal-title="cameraTitle"
+    :adjust-size="true"
+    @cancel="cancel"
+  >
+    <div slot="content" style="padding: 10px;height: 100%;width: 100%;">
+      <a-row :gutter="2" style="height: 80%;width: 100%;" v-if="sysShipCameraList.length > 0">
+        <a-col :span="12" v-for="item in sysShipCameraList" :key="item.shipId +'_'+item.cameraDeviceSn">
+          <a-card :title="item.cameraDeviceName" :bordered="false">
+            <div class="videoPlayer">
+              <div class="play-videos">
+                <div :id="item.shipId +'_'+item.cameraDeviceSn" style="width: 100% !important;height: 100% !important; position:relative" class="xgPlayer"></div>
+              </div>
+            </div>
+          </a-card>
+        </a-col>
+      </a-row>
+      <a-row :gutter="2" style="height: 80%;width: 100%;" v-else>
+        <a-col :span="12">
+          <a-card title="未绑定摄像头" :bordered="false">
+            <div class="videoPlayer">
+              <div class="play-videos">
+                <div  class="xgPlayer">未绑定摄像头</div>
+              </div>
+            </div>
+          </a-card>
+        </a-col>
+        <a-col :span="12" >
+          <a-card title="未绑定摄像头"  :bordered="false">
+            <div class="videoPlayer">
+              <div class="play-videos">
+                <div class="xgPlayer">未绑定摄像头</div>
+              </div>
+            </div>
+          </a-card>
+        </a-col>
+      </a-row>
+    </div>
+    <template slot="footer">
+      <a-button :disabled="disabled" @click="cancel">
+        关闭
+      </a-button>
+    </template>
+  </ant-modal>
+</template>
+<script>
+import AntModal from '@/components/pt/dialog/AntModal.vue'
+import { getShipCameraList } from '@/api/system/sysShip'
+import { getLive } from '@/api/camera/camera'
+import Player from 'xgplayer'
+import FlvPlugin from 'xgplayer-flv'
+import HlsPlugin from 'xgplayer-hls'
+import 'xgplayer/dist/index.min.css'
+
+export default {
+  name: 'SysShipCameraLive',
+  props: {
+    shipId: {
+      type: String,
+      required: true
+    }
+  },
+  components: {
+    AntModal
+  },
+  data () {
+    return {
+      cameraOpen: false,
+      closeDialog: true,
+      spinning: false,
+      delayTime: 100,
+      labelCol: { span: 2 },
+      wrapperCol: { span: 14 },
+      loading: false,
+      disabled: false,
+      total: 0,
+      cameraDeviceSn: '',
+      cameraTitle: '视频查看',
+      // 表单参数
+      sysShipCameraList: [],
+      player: null, // 实例
+      xOptions: {
+        id: '', // 播放器容器
+        isLive: true,
+        fluid: false,
+        fitVideoSize: 'auto',
+        videoFillMode: 'auto',
+        enableContextmenu: true,
+        loop: false, // 是否自动循环
+        lang: 'zh-cn', // 语言,'en', 'zh-cn', 'zh-tw'
+        screenShot: {// 是否允许截图(按钮)
+          saveImg: true,
+          quality: 0.92,
+          type: 'image/png',
+          format: '.png'
+        },
+        playsinline: false,
+        keyShortcut: 'true',
+        controls: {
+          autoHide: true,
+          mode: 'bottom'
+        },
+        cssullScreen: {
+          disable: true
+        },
+        ignores: ['cssfullscreen', 'playbackrate'],
+        playbackrate: {
+          disable: true
+        },
+        videoInit: true, // 自动预加载
+        volume: 0.7, // 初始化音量
+        autoplay: true,
+        url: ''
+      },
+      initVolume: 0.5
+    }
+  },
+  mounted() {
+    if (this.shipId) {
+      this.getShipCameraList()
+    }
+  },
+  created() {
+  },
+  methods: {
+    open() {
+      this.cameraOpen = true
+    },
+    cancel() {
+      this.cameraOpen = false
+      this.$emit('close')
+    },
+    getShipCameraList() {
+      this.loading = true
+      this.sysShipCameraList = []
+      getShipCameraList(this.shipId).then(response => {
+        this.sysShipCameraList = response.data
+        this.loading = false
+        this.getLiveUrl()
+      })
+    },
+    getLiveUrl() {
+      this.sysShipCameraList.forEach(item => {
+        const param = {
+          deviceSn: item.cameraDeviceSn,
+          channelNo: 1
+        }
+        getLive(param).then((response) => {
+          // 初始话播放器
+          // item.videoUrl = response.data.url
+          this.initPlayer(response.data.url, item.shipId + '_' + item.cameraDeviceSn)
+        })
+      })
+    },
+    // =========================1,设置播放器必要参数===================
+    initPlayer(url, id) {
+      console.log('初始化播放器!')
+      if (!url) return console.warn('url is not esist')
+      if (url) {
+        this.xOptions.url = url
+        if (this.url.toLowerCase().indexOf('.flv') > 0) {
+          this.xOptions.plugins = [FlvPlugin]
+        } else {
+          this.xOptions.plugins = [HlsPlugin]
+        }
+        this.xOptions.id = id
+        this.xOptions.volume = this.initVolume
+        this.player = new Player(this.xOptions)
+      }
+    }
+  }
+}
+</script>
+<style scoped>
+.videoPlayer{
+  height: 100%;
+  width: 100%;
+  position: absolute;
+  left: 10;
+  top: 18;
+  z-index: 99;
+}
+.play-videos {
+  width: 100%;
+  height: 380px;
+  background: black;
+  margin: 5px auto 1px 0;
+  .xgPlayer .dplayer-video-wrap {
+    width: 100% !important;
+    height: 100% !important;
+  }
+}
+</style>