feat: 视频播放组件封装
This commit is contained in:
parent
86ff238df7
commit
8a3acd57ee
|
@ -1,6 +1,6 @@
|
|||
import server from '@/utils/request';
|
||||
import { LocalStore } from '@/utils/comm';
|
||||
import { TOKEN_KEY } from '@/utils/variable';
|
||||
import { BASE_API_PATH, TOKEN_KEY } from '@/utils/variable';
|
||||
|
||||
export default {
|
||||
// 列表
|
||||
|
@ -19,7 +19,7 @@ export default {
|
|||
// ========== 视频播放 ==========
|
||||
// 开始直播
|
||||
ptzStart: (deviceId: string, channelId: string, type: string) =>
|
||||
`/media/device/${deviceId}/${channelId}/live.${type}?:X_Access_Token=${LocalStore.get(TOKEN_KEY)}`,
|
||||
`${BASE_API_PATH}/media/device/${deviceId}/${channelId}/live.${type}?:X_Access_Token=${LocalStore.get(TOKEN_KEY)}`,
|
||||
|
||||
// 云台控制-停止
|
||||
ptzStop: (deviceId: string, channelId: string) => server.post(`/media/device/${deviceId}/${channelId}/_ptz/STOP`),
|
||||
|
|
|
@ -1,25 +1,36 @@
|
|||
<!-- 视频播放 -->
|
||||
<template>
|
||||
<vue3videoPlay
|
||||
v-bind="options"
|
||||
poster="https://cdn.jsdelivr.net/gh/xdlumia/files/video-play/ironMan.jpg"
|
||||
/>
|
||||
<vue3videoPlay v-bind="options" />
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import 'vue3-video-play/dist/style.css';
|
||||
import vue3videoPlay from 'vue3-video-play';
|
||||
|
||||
const props = defineProps({
|
||||
src: { type: String, default: '' },
|
||||
type: { type: String, default: 'mp4' },
|
||||
});
|
||||
|
||||
watch(
|
||||
() => props.src,
|
||||
(val: string) => {
|
||||
options.src = val;
|
||||
},
|
||||
);
|
||||
|
||||
const options = reactive({
|
||||
...props,
|
||||
width: '500px', //播放器高度
|
||||
height: '280px', //播放器高度
|
||||
color: '#409eff', //主题色
|
||||
title: '', //视频名称
|
||||
src: 'https://cdn.jsdelivr.net/gh/xdlumia/files/video-play/IronMan.mp4', //视频源
|
||||
// src: props.src,
|
||||
// type: props.type,
|
||||
muted: false, //静音
|
||||
webFullScreen: false,
|
||||
speedRate: ['0.75', '1.0', '1.25', '1.5', '2.0'], //播放倍速
|
||||
autoPlay: false, //自动播放
|
||||
autoPlay: true, //自动播放
|
||||
loop: false, //循环播放
|
||||
mirror: false, //镜像画面
|
||||
ligthOff: false, //关灯模式
|
||||
|
@ -37,5 +48,3 @@ const options = reactive({
|
|||
], //显示所有按钮,
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped></style>
|
||||
|
|
|
@ -2,16 +2,32 @@
|
|||
<template>
|
||||
<div class="live-player-tools">
|
||||
<div class="direction">
|
||||
<div class="direction-item up">
|
||||
<div
|
||||
class="direction-item up"
|
||||
@mousedown="emit('onMouseDown', 'UP')"
|
||||
@mouseup="emit('onMouseUp', 'UP')"
|
||||
>
|
||||
<AIcon class="direction-icon" type="CaretUpOutlined" />
|
||||
</div>
|
||||
<div class="direction-item right">
|
||||
<div
|
||||
class="direction-item right"
|
||||
@mousedown="emit('onMouseDown', 'RIGHT')"
|
||||
@mouseup="emit('onMouseUp', 'RIGHT')"
|
||||
>
|
||||
<AIcon class="direction-icon" type="CaretRightOutlined" />
|
||||
</div>
|
||||
<div class="direction-item left">
|
||||
<div
|
||||
class="direction-item left"
|
||||
@mousedown="emit('onMouseDown', 'LEFT')"
|
||||
@mouseup="emit('onMouseUp', 'LEFT')"
|
||||
>
|
||||
<AIcon class="direction-icon" type="CaretLeftOutlined" />
|
||||
</div>
|
||||
<div class="direction-item down">
|
||||
<div
|
||||
class="direction-item down"
|
||||
@mousedown="emit('onMouseDown', 'DOWN')"
|
||||
@mouseup="emit('onMouseUp', 'DOWN')"
|
||||
>
|
||||
<AIcon class="direction-icon" type="CaretDownOutlined" />
|
||||
</div>
|
||||
<div class="direction-audio">
|
||||
|
@ -19,17 +35,31 @@
|
|||
</div>
|
||||
</div>
|
||||
<div class="zoom">
|
||||
<div class="zoom-item zoom-in">
|
||||
<div
|
||||
class="zoom-item zoom-in"
|
||||
@mousedown="emit('onMouseDown', 'ZOOM_IN')"
|
||||
@mouseup="emit('onMouseUp', 'ZOOM_IN')"
|
||||
>
|
||||
<AIcon type="PlusOutlined" />
|
||||
</div>
|
||||
<div class="zoom-item zoom-out">
|
||||
<div
|
||||
class="zoom-item zoom-out"
|
||||
@mousedown="emit('onMouseDown', 'ZOOM_OUT')"
|
||||
@mouseup="emit('onMouseUp', 'ZOOM_OUT')"
|
||||
>
|
||||
<AIcon type="MinusOutlined" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts"></script>
|
||||
<script setup lang="ts">
|
||||
type Emits = {
|
||||
(e: 'onMouseDown', type: string): void;
|
||||
(e: 'onMouseUp', type: string): void;
|
||||
};
|
||||
const emit = defineEmits<Emits>();
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
@import './mediaTool.less';
|
||||
|
|
|
@ -6,13 +6,14 @@
|
|||
cancelText="取消"
|
||||
okText="确定"
|
||||
width="800px"
|
||||
:maskClosable="false"
|
||||
@ok="_vis = false"
|
||||
@cancel="_vis = false"
|
||||
>
|
||||
<div class="media-live">
|
||||
<div class="media-live-video">
|
||||
<div class="media-tool">
|
||||
<div class="tool-item">
|
||||
<div class="tool-item" @click.stop="handleRecord">
|
||||
{{
|
||||
isRecord === 0
|
||||
? '开始录像'
|
||||
|
@ -22,17 +23,24 @@
|
|||
}}
|
||||
</div>
|
||||
<div class="tool-item">刷新</div>
|
||||
<div class="tool-item">重置</div>
|
||||
<div class="tool-item" @click.stop="handleReset">重置</div>
|
||||
</div>
|
||||
<LivePlayer :url="url" />
|
||||
<LivePlayer :src="src" :type="mediaType" />
|
||||
</div>
|
||||
<MediaTool />
|
||||
<MediaTool
|
||||
@onMouseDown="handleMouseDown"
|
||||
@onMouseUp="handleMouseUp"
|
||||
/>
|
||||
</div>
|
||||
<div class="media-live-tool">
|
||||
<a-radio-group v-model:value="mediaType" button-style="solid">
|
||||
<a-radio-group
|
||||
v-model:value="mediaType"
|
||||
button-style="solid"
|
||||
@change="mediaStart"
|
||||
>
|
||||
<a-radio-button value="mp4">MP4</a-radio-button>
|
||||
<a-radio-button value="flv">FLV</a-radio-button>
|
||||
<a-radio-button value="hls">HLS</a-radio-button>
|
||||
<a-radio-button value="m3u8">HLS</a-radio-button>
|
||||
</a-radio-group>
|
||||
</div>
|
||||
</a-modal>
|
||||
|
@ -42,6 +50,7 @@
|
|||
import { PropType } from 'vue';
|
||||
import LivePlayer from '@/components/Player/index.vue';
|
||||
import MediaTool from '@/components/Player/mediaTool.vue';
|
||||
import channelApi from '@/api/media/channel';
|
||||
|
||||
type Emits = {
|
||||
(e: 'update:visible', data: boolean): void;
|
||||
|
@ -61,14 +70,89 @@ const _vis = computed({
|
|||
set: (val) => emit('update:visible', val),
|
||||
});
|
||||
|
||||
// 视频地址
|
||||
const src = ref('');
|
||||
// 视频类型
|
||||
const mediaType = ref('mp4');
|
||||
/**
|
||||
* 媒体开始播放
|
||||
*/
|
||||
const mediaStart = () => {
|
||||
src.value = channelApi.ptzStart(
|
||||
props.data.deviceId,
|
||||
props.data.channelId,
|
||||
mediaType.value,
|
||||
);
|
||||
};
|
||||
|
||||
// 录像状态
|
||||
const isRecord = ref(0); // 0:停止录像; 1:请求录像中; 2:开始录像
|
||||
/**
|
||||
* 查询录像状态
|
||||
*/
|
||||
const getIsRecord = async () => {
|
||||
const { result } = await channelApi.ptzIsRecord(
|
||||
props.data.deviceId,
|
||||
props.data.channelId,
|
||||
);
|
||||
isRecord.value = result ? 2 : 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* 点击录像/停止录像
|
||||
*/
|
||||
const handleRecord = async () => {
|
||||
if (isRecord.value === 0) {
|
||||
isRecord.value = 1;
|
||||
const res = await channelApi.recordStart(
|
||||
props.data.deviceId,
|
||||
props.data.channelId,
|
||||
{ local: false },
|
||||
);
|
||||
if (res.success) {
|
||||
isRecord.value = 2;
|
||||
} else {
|
||||
isRecord.value = 0;
|
||||
}
|
||||
} else if (isRecord.value === 2) {
|
||||
const res = await channelApi.recordStop(
|
||||
props.data.deviceId,
|
||||
props.data.channelId,
|
||||
{ local: false },
|
||||
);
|
||||
if (res.success) {
|
||||
isRecord.value = 0;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 重置
|
||||
*/
|
||||
const handleReset = async () => {
|
||||
channelApi.mediaStop(props.data.deviceId, props.data.channelId);
|
||||
};
|
||||
|
||||
/**
|
||||
* 点击控制按钮
|
||||
* @param type 控制类型
|
||||
*/
|
||||
const handleMouseDown = (type: string) => {
|
||||
channelApi.ptzTool(props.data.deviceId, props.data.channelId, type);
|
||||
};
|
||||
const handleMouseUp = () => {
|
||||
channelApi.ptzStop(props.data.deviceId, props.data.channelId);
|
||||
};
|
||||
|
||||
watch(
|
||||
() => _vis.value,
|
||||
(val: boolean) => {},
|
||||
(val: boolean) => {
|
||||
if (val) {
|
||||
mediaStart();
|
||||
getIsRecord();
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
const isRecord = ref(0);
|
||||
const url = ref('');
|
||||
const mediaType = ref('mp4');
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
@import './index.less';
|
||||
|
|
|
@ -83,7 +83,7 @@
|
|||
:channelData="channelData"
|
||||
@submit="listRef.reload()"
|
||||
/>
|
||||
<Live v-model:visible="playerVis" />
|
||||
<Live v-model:visible="playerVis" :data="channelData" />
|
||||
</page-container>
|
||||
</template>
|
||||
|
||||
|
@ -205,6 +205,7 @@ const getActions = (
|
|||
},
|
||||
icon: 'VideoCameraOutlined',
|
||||
onClick: () => {
|
||||
channelData.value = cloneDeep(data);
|
||||
playerVis.value = true;
|
||||
},
|
||||
},
|
||||
|
|
Loading…
Reference in New Issue