video.vue 7.84 KB
<script lang="ts" setup>
  import { Tooltip } from 'ant-design-vue';
  import { ref, unref } from 'vue';
  import { QuestionCircleOutlined } from '@ant-design/icons-vue';
  import {
    CaretUpOutlined,
    CaretRightOutlined,
    PauseOutlined,
    CaretDownOutlined,
    CaretLeftOutlined,
    ZoomInOutlined,
    ZoomOutOutlined,
  } from '@ant-design/icons-vue';
  import { Button, Slider } from 'ant-design-vue';
  import { controlling } from '/@/api/camera/cameraManager';
  import { setEzvizControl, setVideoControl } from '/@/api/device/videoChannel';
  import XGPlayer from '/@/components/Video/src/XGPlayer.vue';
  import { EzvizVideoControlEnum, VideoCancelModalParamsType, VideoControlEnum } from './config';
  import { VideoPlatformEnum } from '/@/views/camera/manage/config.data';

  const props = defineProps<{
    playUrl?: string;
    options?: VideoCancelModalParamsType;
  }>();

  const playerRef = ref<InstanceType<typeof XGPlayer>>();

  // 控制云台控制速度
  const sliderValue = ref<number>(123);

  const isPlay = ref(false);

  //播放/暂停
  const handleClick = () => {
    const playerInstance = unref(playerRef)?.getPlayerInstance();
    if (playerInstance && playerInstance.paused) {
      unref(playerRef)?.getPlayerInstance()?.play();
      isPlay.value = true;
    } else {
      unref(playerRef)?.getPlayerInstance()?.pause();
      isPlay.value = false;
    }
  };

  const handleControl = (action: number, direction: string) => {
    const { options } = props;
    controlling({ cameraIndexCode: options?.id, action, command: direction });
  };

  // 国标控制
  const handleGBTControl = (command: string, action?: number | string) => {
    const { tbDeviceId, channelId } = props.options || {};
    setVideoControl(tbDeviceId, channelId, {
      command,
      horizonSpeed: action,
      verticalSpeed: action,
      zoomSpeed: action,
    });
  };

  const handleEzvizControl = (actionType: string, start: boolean) => {
    const { id } = props.options || {};
    const action = EzvizVideoControlEnum[actionType as VideoControlEnum];
    setEzvizControl({ entityId: id!, action, controllingType: Number(!start) });
  };

  //长按开始
  const moveStart = (action: string) => {
    if (unref(props.options?.isGBT)) {
      handleGBTControl(action, unref(sliderValue));
      return;
    }

    if (props.options?.videoPlatformType === VideoPlatformEnum.FLUORITE) {
      handleEzvizControl(action, true);
      return;
    }

    handleControl(0, action);
  };

  // 长按结束
  const moveStop = (action: string) => {
    if (unref(props.options?.isGBT)) {
      handleGBTControl('STOP', unref(sliderValue));
      return;
    }

    if (props.options?.videoPlatformType === VideoPlatformEnum.FLUORITE) {
      setTimeout(() => {
        handleEzvizControl(action, false);
      }, 1000);
      return;
    }

    handleControl(1, action);
  };

  const handleVideoStatus = (flag: boolean) => {
    isPlay.value = flag;
  };
</script>

<template>
  <div class="!w-full h-full flex" style="min-height: 100%">
    <XGPlayer
      ref="playerRef"
      v-bind="options?.playerProps"
      :url="playUrl"
      auto-play
      :config="{ fluid: true }"
      @play="handleVideoStatus(true)"
      @pause="handleVideoStatus(false)"
      @ended="handleVideoStatus(false)"
    />

    <div
      v-if="options?.canControl"
      class="!w-2/10 px-4 bg-white flex justify-center items-center flex-col"
    >
      <Tooltip>
        <template #title>
          {{ t('deviceManagement.device.videoChannel.controlHelp') }}
        </template>
        <label class="validate-dot">
          {{ t('deviceManagement.device.videoChannel.console') }}
        </label>
        <QuestionCircleOutlined :style="{ fontSize: '14px', marginLeft: '5px' }" />
      </Tooltip>

      <div class="home mt-5">
        <Button class="front-sty-center child center" shape="circle" @click="handleClick()">
          <PauseOutlined v-if="isPlay" class="child-icon" style="color: #fffbfb" />
          <CaretRightOutlined v-else class="child-icon" style="color: #fffbfb" />
        </Button>

        <div class="box">
          <div>
            <Button
              class="left-top in-block"
              @mousedown="moveStart(VideoControlEnum.Up)"
              @mouseup="moveStop(VideoControlEnum.Up)"
            >
              <CaretUpOutlined class="icon-rotate child-icon" />
            </Button>
            <Button
              class="right-top in-block"
              @mousedown="moveStart(VideoControlEnum.Right)"
              @mouseup="moveStop(VideoControlEnum.Right)"
            >
              <CaretRightOutlined class="icon-rotate child-icon" />
            </Button>
          </div>
          <div>
            <Button
              class="left-bottom in-block"
              @mousedown="moveStart(VideoControlEnum.Left)"
              @mouseup="moveStop(VideoControlEnum.Left)"
            >
              <CaretLeftOutlined class="icon-rotate child-icon" />
            </Button>
            <Button
              class="right-bottom in-block"
              @mousedown="moveStart(VideoControlEnum.Down)"
              @mouseup="moveStop(VideoControlEnum.Down)"
            >
              <CaretDownOutlined class="icon-rotate child-icon" />
            </Button>
          </div>

          <Button class="circle" @click="handleClick" />
        </div>
      </div>
      <div class="mt-5" v-if="options.isGBT">
        <Slider v-model:value="sliderValue" :min="0" :max="255" style="width: 130px" />
      </div>
      <div class="flex justify-center mt-8">
        <Button
          class="button-icon"
          @mousedown="moveStart(VideoControlEnum.ZoomIn)"
          @mouseup="moveStop(VideoControlEnum.ZoomIn)"
          style="border-radius: 50%"
        >
          <ZoomInOutlined style="color: #315a9c; font-size: 1.5rem" />
        </Button>
        <Button
          class="ml-10 button-icon"
          @mousedown="moveStart(VideoControlEnum.ZoomOut)"
          @mouseup="moveStop(VideoControlEnum.ZoomOut)"
          style="border-radius: 50%"
        >
          <ZoomOutOutlined style="color: #315a9c; font-size: 1.5rem" />
        </Button>
      </div>
    </div>
  </div>
</template>

<style lang="less" scoped>
  .child {
    position: absolute;
    width: 3rem;
    height: 3rem;
    display: flex;
    justify-content: center;
    background: #e2dede;
    align-items: center;
    border: none;
  }

  .child-icon {
    font-size: 1.5rem;
    color: #fffbfb;
  }

  .button-icon {
    width: 3rem;
    height: 3rem;
    background: #f5f5f5;
    border: none;
    border-radius: 50% !important;
  }

  .center {
    top: 50%;
    left: 50%;
    width: 4rem;
    height: 4rem;
    transform: translate(-50%, -50%);
    border-radius: 50%;
    background: #5586d4;
  }

  .home {
    position: relative;
    width: 10rem;
    height: 10rem;
  }

  .box {
    transform: rotateZ(45deg);
    width: 10rem;
    height: 10rem;
  }

  .icon-rotate {
    transform: rotate(315deg);
  }

  .front-sty-center {
    position: absolute;
    top: 50%;
    z-index: 9999;
    left: 50%;
    transform: translate(-50%, -50%);
  }

  .circle {
    display: inline-block;
    border-radius: 50%;
    background-color: #5586d4;
    width: 4rem;
    height: 4rem;
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
  }

  .in-block {
    display: inline-block;
    position: relative;
  }

  .left-top {
    width: 5rem;
    height: 5rem;
    border-radius: 5rem 0 0 0;
    background-color: #e2dede;
  }

  .right-top {
    width: 5rem;
    height: 5rem;
    border-radius: 0 5rem 0 0;
    background-color: #e2dede;
  }

  .left-bottom {
    width: 5rem;
    height: 5rem;
    border-radius: 0 0 0 5rem;
    background-color: #e2dede;
  }

  .right-bottom {
    width: 5rem;
    height: 5rem;
    border-radius: 0 0 5rem 0;
    background-color: #e2dede;
  }

  :deep(.ant-slider-track) {
    background: #5586d4;
  }
</style>