Newer
Older
safe_production_front / src / views / ycjg / ssjk / control-isc.vue
<script lang="ts" setup name="videoControl">
import type { FormInstance, FormRules } from 'element-plus'
import { ElMessage, ElMessageBox } from 'element-plus'
import type { Ref } from 'vue'
import {getCurrentInstance, nextTick, reactive, ref} from 'vue'
import dayjs from 'dayjs'
import useWebsocketStore from '@/store/modules/websocket'
import { getDevInfo, restartDev } from '@/api/ptz/dev'
import controlImg from '@/assets/images/control.png'
import {
  devControl,
  devControlWithSpeed,
  devToPosition,
} from '@/api/ptz/control'
import { getPicListPage, pictureAdd } from '@/api/ycjg/ssjk'
import { base64ToBlob, exportFile } from '@/utils/exportUtils'
import { log } from '@/utils/log'
import { getPreviewUrl } from '@/utils/hik'
const { proxy } = getCurrentInstance() as any
const width = ref(0)
const height = ref(0)
const player = ref(null)

const websocket = useWebsocketStore()
const $route = useRoute()
const deviceData: Ref<any> = ref({})
const realh = ref('****')
const realv = ref('****')
const instance = getCurrentInstance()

const videoControl = ref('videoControl')

const controlSpeed = ref(7)

const loading = ref(false)
const total = ref(0)
const list = ref([])

const divPlugin = ref(null)
const lineList: Ref<any[]> = ref([])
const timeRange = ref<[any, any]>(['', ''])

const listQuery = ref({
  devId: '',
  startTime: '',
  endTime: '',
  offset: 1,
  limit: 6,
})
// socket更新数据
const unwatch = watch(websocket, (newVal) => {
})

// 搜索重置
function fetchData() {
  search()
}

function search(isNowPage = false) {
  if (!isNowPage) {
    // 是否显示当前页,否则跳转第一页
    listQuery.value.offset = 1
  }
  loading.value = true
  getPicListPage(listQuery.value).then((res: any) => {
    list.value = res.data.rows.map((item: any) => {
      item.url = `${window.localStorage.getItem('baseurl-safe')}/picture/download/${item.url}?token=${window.localStorage.getItem('token')}`
      return item
    })
    total.value = res.data.total
    loading.value = false
  }).catch(() => {
    loading.value = false
  })
}

function createPlayer() {
  player.value = new window.JSPlugin({
    szId: 'player',
    szBasePath: './',
    iMaxSplit: 1,
    iCurrentSplit: 2,
    openDebug: true,
    iWidth: width.value,
    iHeight: height.value,
    oStyle: {
      borderSelect: '#FFCC00',
    },
  })
}

// 调整大小
const resize = () => {
  width.value = window.innerWidth - 580
  height.value = window.innerHeight - 230
  if (player.value !== null) {
    player.value!.JS_Resize()
  }
}

// 抓拍
async function takePhoto() {
  const time = dayjs().format('YYYYMMDDHHmm')
  player.value!.JS_CapturePicture(0, `${deviceData.value.monitorName}_${time}.jpg`, 'JPEG', (imageData: any) => {
    // log('视频抓拍', `开始播报时间:${time}`)
    pictureAdd({
      devId: $route.query.id,
      picture: imageData,
    }).then((res: any) => {
      // 本地
      const blob = base64ToBlob(imageData)
      exportFile(blob, `${deviceData.value.monitorName}_${time}.jpg`)
      ElMessage.success('抓图成功')
      search()
    })
  })
}

/* 预览&对讲 */
async function realplay() {
  const playUrl = await getPreviewUrl(deviceData.value.cameraIndexCode)
  player.value!.JS_Play(playUrl, { playURL: playUrl, mode: 0 }, 0).then(
    () => { console.log('realplay success') },
    (e: any) => { console.error(e) },
  )
}
function stopPlay() {
  player.value!.JS_Stop().then(
    () => { console.log('stop realplay success') },
    (e: any) => { console.error(e) },
  )
}

// 放大
function zoomIn(action: string) {
  const params = {
    cameraIndexCode: deviceData.value.cameraIndexCode,
    command: 'ZOOM_IN',
    action,
  }
  devControl(params).then(() => {
    // ElMessage.success('放大成功')
  })
}

// 缩小
function zoomOut(action: string) {
  const params = {
    cameraIndexCode: deviceData.value.cameraIndexCode,
    command: 'ZOOM_OUT',
    action,
  }
  devControl(params).then(() => {
    // ElMessage.success('缩小成功')
  })
}

// 上下左右
function controlWithSpeed(event, type, action) {
  if (event.detail === 1) {
    const params = {
      cameraIndexCode: deviceData.value.cameraIndexCode,
      command: type,
      action,
    }
    devControl(params).then(() => {})
  }
}

function handleSizeChange(val: number) {
  listQuery.value.limit = val
  search(true)
}

// 改变当前页
function handleCurrentChange(val: number) {
  listQuery.value.offset = val
  search(true)
}

watch(timeRange, (val) => {
  if (val) {
    listQuery.value.startTime = `${val[0]}`
    listQuery.value.endTime = `${val[1]}`
  }
  else {
    listQuery.value.startTime = ''
    listQuery.value.endTime = ''
  }
})

onMounted(() => {
  console.log($route.query)
  // 从路由中获取页面类型参数
  if ($route.query && $route.query.id) {
    setTimeout(() => {
      window.addEventListener('resize', resize)
      resize()
      createPlayer()
      listQuery.value.devId = $route.query.id!.toString()
      getDevInfo(listQuery.value.devId).then((response) => {
        deviceData.value = response.data
        realplay()
      })
      fetchData()
    }, 500)
  }
})

onBeforeUnmount(() => {
  unwatch()
  window.removeEventListener('resize', resize)
})
</script>

<template>
  <div class="video-wrap">
    <div id="player" :style="`width:${width}px;height:${height}px;`" :class="videoControl"/>
    <div class="right" :style="`height:${height}px;`">
      <el-tabs tab-position="top" style="height: calc(100% - 30px);width: 100%;margin-bottom: 10px;margin-top: -10px">
        <el-tab-pane label="历史截图">
          <div style="display: flex;margin-bottom: 10px">
            <el-date-picker
              v-model="timeRange" type="daterange" clearable size="small"
              format="YYYY-MM-DD" value-format="YYYY-MM-DD"
              start-placeholder="开始时间" end-placeholder="结束时间" range-separator="到"
              style="margin-right: 20px"
            />
            <el-button type="primary" @click="fetchData" style="width: 60px" size="small">查 询</el-button>
          </div>
          <div style="background-color: white;overflow-y: hidden;overflow-x: scroll;width: 100%;display: flex;flex-wrap: wrap;">
            <div v-for="(item, index) in list" :key="index" style="height: 100px;width: 160px;margin: 5px">
              <el-image style="width: 160px; height: 100px;" :src="item.url" fit="fill" />
            </div>
          </div>
        </el-tab-pane>
      </el-tabs>
      <div style="z-index: 99999999;margin: 10px 10px 0;">
        <el-pagination
          small
          :current-page="listQuery.offset"
          :page-sizes="[6]"
          :page-size="listQuery.limit"
          :total="total"
          layout="total,prev,pager,next"
          @size-change="handleSizeChange"
          @current-change="handleCurrentChange"
        />
      </div>
    </div>
    <div class="bottom">
      <div class="control-title">设备控制</div>
      <div name="four" style="width: 150px; height: 130px;">
        <el-image style="width: 130px; height: 130px;position: absolute;top: 5px;left: 50px" :src="controlImg" fit="fill" />
        <div>
          <div class="round-btn" style="top: 8px;left: 95px" @mousedown="controlWithSpeed($event, 'UP', '0')" @mouseup="controlWithSpeed($event, 'UP', '1')" />
          <div class="round-btn" style="top: 90px;left: 95px" @mousedown="controlWithSpeed($event, 'DOWN', '0')" @mouseup="controlWithSpeed($event, 'DOWN', '1')" />
          <div class="round-btn" style="top: 48px;left: 53px" @mousedown="controlWithSpeed($event, 'LEFT', '0')" @mouseup="controlWithSpeed($event, 'LEFT', '1')" />
          <div class="round-btn" style="top: 48px;left: 135px" @mousedown="controlWithSpeed($event, 'RIGHT', '0')" @mouseup="controlWithSpeed($event, 'RIGHT', '1')" />
        </div>
      </div>
      <div style="display: flex;max-width: 250px;flex-wrap: wrap;margin: 0 20px">
        <el-button type="primary" class="btn" @click="stopPlay">
          <el-icon style="margin-right: 5px"><svg-icon name="icon-stop" /></el-icon>暂 停
        </el-button>
        <el-button type="primary" class="btn" @click="realplay">
          <el-icon style="margin-right: 5px"><svg-icon name="icon-play" /></el-icon>恢 复
        </el-button>
        <el-button type="primary" class="btn" @mousedown="zoomIn('0')" @mouseup="zoomIn('1')">
          <el-icon style="margin-right: 5px"><svg-icon name="icon-zoomin" /></el-icon>放 大
        </el-button>
        <el-button type="primary" class="btn" @mousedown="zoomOut('0')" @mouseup="zoomOut('1')">
          <el-icon style="margin-right: 5px"><svg-icon name="icon-zoomout" /></el-icon>缩 小
        </el-button>
        <el-button type="primary" class="btn" @click="takePhoto">
          <el-icon style="margin-right: 5px"><svg-icon name="icon-camera" /></el-icon>抓 拍</el-button>
      </div>
      <div style="width: calc(100% - 350px);height: 100%;display: flex;background-color: rgba(255,255,255,0.65);border-radius: 10px">
        <el-tabs v-if="deviceData !== {}" tab-position="left" style="height: 100%;width: 100%">
          <el-tab-pane label="设备信息">
            <el-descriptions style="flex: 1" class="margin-top" :column="3" border>
              <el-descriptions-item label="设备名称">{{deviceData.monitorName}}</el-descriptions-item>
              <el-descriptions-item label="设备类型">{{deviceData.deviceTypeName}}</el-descriptions-item>
              <el-descriptions-item label="所属单位">{{deviceData.deptName}}</el-descriptions-item>
              <el-descriptions-item label="所属区域">{{deviceData.areaName}}</el-descriptions-item>
              <el-descriptions-item label="经度" >{{deviceData.longitude}}</el-descriptions-item>
              <el-descriptions-item label="纬度" >{{deviceData.latitude}}</el-descriptions-item>
              <el-descriptions-item label="位置">{{deviceData.location}}</el-descriptions-item>
              <el-descriptions-item label="备注">{{deviceData.description}}</el-descriptions-item>
            </el-descriptions>
          </el-tab-pane>
        </el-tabs>
      </div>
    </div>
  </div>
</template>

<style lang="scss" scoped>
.video-wrap {
  display: flex;
  flex-wrap: wrap;
}
.videoControl {
  margin-left: 10px;
  margin-top: 10px;
  position: relative;
  background-color: #111111;
}
.right {
  height: calc(80vh - 90px);
  width: 360px;
  background-color: white;
  border-radius: 10px;
  padding: 10px;
  position: absolute;
  top: 10px;
  right: 10px;
}
.bottom {
  width: calc(100% - 10px);
  height: 140px;
  position: absolute;
  left: 0px;
  bottom: 5px;
  display: flex;
  overflow: hidden;
  border-radius: 10px;
  margin: 5px;
  box-shadow: 0 2px 12px 0 rgba(0,0,0,.1);
  overflow: hidden;
  padding: 5px;
  justify-content: space-between;
}
.control-title {
  color: white;
  background-color: #ff9f11;
  border-bottom-right-radius: 10px;
  border-top-right-radius: 10px;
  line-height: 30px;
  font-weight: bold;
  text-align: center;
  letter-spacing: 1px;
  font-family: Helvetica Neue,Helvetica,PingFang SC,Hiragino Sans GB,Microsoft YaHei,SimSun,sans-serif;
  writing-mode: vertical-rl;
  text-orientation: upright;
  width: 30px;
  height: 100px;

}
.b2 {
  height: 100%;
  width: 20%;
  text-align: center;
  overflow: hidden;
}
.btn {
  margin: 3px auto;
  width: 100px;
}
.control-row {
  display: flex;
  position: absolute;
  left: 260px;
  width: 60%;
  overflow: hidden;
  justify-content: flex-start;
  align-items: center;
}
.real-text {
  margin: 6px 10px;
  color: #6e6e6e;
}
.ppm-line {
  padding: 0;
  height: 100%;
  flex: 1;
}
.el-message-box {
  position: absolute !important;
  top: calc(50% - 68px) !important;
  left: 100px !important;
}
.ptz-control {
  width: 400px;
  position: absolute;
  right: 18%;
  top: 5px;
  display: flex;
  justify-content: center;
  align-items: flex-start;
  flex-wrap: wrap;
}
.round-btn {
  position: absolute;
  top: 14px;
  left: 129px;
  width: 42px;
  height: 42px;
  z-index: 111111;
  border-radius: 21px;
  cursor: pointer;
}
.round-btn:hover {
  background-color: rgba(61, 125, 254, 0.53);
}
.icon-button {
  background-color: #d6e5fc;
  border-color: #d6e5fc;
  padding: 6px;
  border-radius: 6px;
  color: #4384ff;

  :deep(.el-icon) {
    width: 18px;
    height: 18px;
  }

  //.icon-button-icon {
  //  width: 16px;
  //  height: 16px;
  //}

  &:hover {
    background-color: #c3dafd;
    color: #fff;
  }
}
.add-line {
  width: 250px;
  display: flex;
  margin-left: 10px;
  z-index: 1111111;
}
</style>