You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

176 lines
6.5 KiB
Vue

<template>
<view class="container">
<picker mode="selector" :range="cameras" range-key="name" @change="handleCameraChange">
<button>选择相机</button>
</picker>
<video id="myVideo" ref="videoPlayer" :src="streamUrl" autoplay muted controls
style="width: 100%; height: 50%;" @fullscreenchange="handleFullscreenChange"></video>
<!-- 云台控制面板 -->
<view class="ptz-control" :class="{ 'ptz-control-fullscreen': isFullscreen }">
<view class="direction-list">
<view class="operation-item">
<u-icon name="minus" :size=" 40" @touchstart="handleControl('zoomSub', 'start')" @touchend="handleControl('zoomSub', 'stop')" @touchcancel="handleControl('zoomSub', 'stop')"></u-icon>
</view>
<span>变倍</span>
<view class="operation-item">
<u-icon name="plus" :size="isFullscreen ? 40 : 40" @touchstart="handleControl('zoomAdd', 'start')" @touchend="handleControl('zoomAdd', 'stop')" @touchcancel="handleControl('zoomAdd', 'stop')"></u-icon>
</view>
<view class="operation-item">
<u-icon name="minus" :size="isFullscreen ? 40 : 40" @touchstart="handleControl('focusSub', 'start')" @touchend="handleControl('focusSub', 'stop')" @touchcancel="handleControl('focusSub', 'stop')"></u-icon>
</view>
<span>变焦</span>
<view class="operation-item">
<u-icon name="plus" :size="isFullscreen ? 40 : 40" @touchstart="handleControl('focusAdd', 'start')" @touchend="handleControl('focusAdd', 'stop')" @touchcancel="handleControl('focusAdd', 'stop')"></u-icon>
</view>
<view class="direction-item">
<image src="@/static/tabbar/icon/箭头_左上.png" :style="{ width: isFullscreen ? '40px' : '40px', height: isFullscreen ? '40px' : '40px' }" @touchstart="handleControl('leftUp', 'start')" @touchend="handleControl('leftUp', 'stop')" @touchcancel="handleControl('leftUp', 'stop')"></image>
</view>
<view class="direction-item">
<u-icon name="arrow-up" :size="isFullscreen ? 40 : 40" @touchstart="handleControl('up', 'start')" @touchend="handleControl('up', 'stop')" @touchcancel="handleControl('up', 'stop')"></u-icon>
</view>
<view class="direction-item">
<image src="@/static/tabbar/icon/箭头_右上.png" :style="{ width: isFullscreen ? '40px' : '40px', height: isFullscreen ? '40px' : '40px' }" @touchstart="handleControl('rightUp', 'start')" @touchend="handleControl('rightUp', 'stop')" @touchcancel="handleControl('rightUp', 'stop')"></image>
</view>
<view class="direction-item">
<u-icon name="arrow-left" :size="isFullscreen ? 40 : 40" @touchstart="handleControl('left', 'start')" @touchend="handleControl('left', 'stop')" @touchcancel="handleControl('left', 'stop')"></u-icon>
</view>
<view class="direction-item">
<u-icon :size="isFullscreen ? 40 : 40" @click="refresh"></u-icon>
</view>
<view class="direction-item">
<u-icon name="arrow-right" :size="isFullscreen ? 40 : 40" @touchstart="handleControl('right', 'start')" @touchend="handleControl('right', 'stop')" @touchcancel="handleControl('right', 'stop')"></u-icon>
</view>
<view class="direction-item">
<image src="@/static/tabbar/icon/箭头_左下.png" :style="{ width: isFullscreen ? '40px' : '40px', height: isFullscreen ? '40px' : '40px' }" @touchstart="handleControl('leftDown', 'start')" @touchend="handleControl('leftDown', 'stop')" @touchcancel="handleControl('leftDown', 'stop')"></image>
</view>
<view class="direction-item">
<u-icon name="arrow-down" :size="isFullscreen ? 40 : 40" @touchstart="handleControl('down', 'start')" @touchend="handleControl('down', 'stop')" @touchcancel="handleControl('down', 'stop')"></u-icon>
</view>
<view class="direction-item">
<image src="@/static/tabbar/icon/箭头_右下.png" :style="{ width: isFullscreen ? '40px' : '40px', height: isFullscreen ? '40px' : '40px' }" @touchstart="handleControl('rightDown', 'start')" @touchend="handleControl('rightDown', 'stop')" @touchcancel="handleControl('rightDown', 'stop')"></image>
</view>
</view>
</view>
</view>
</template>
<script>
import request from '@/utils/request';
export default {
data() {
return {
streamUrl: '',
cameras: [{
name: '相机1',
id: 1,
streamName: 'stream123'
},
{
name: '相机2',
id: 2,
streamName: 'stream456'
}
],
currentCamera: {},
videoPlayer: null,
isFullscreen: false
}
},
async mounted() {
console.log(uni.getSystemInfoSync().platform)
this.videoPlayer = uni.createVideoContext('myVideo', this);
await this.fetchCameraList();
},
methods: {
async fetchCameraList() {
try {
const res = await request({
url: '/admin-api/logistics/camera/list'
});
console.log(res);
this.cameras = res.data.data;
this.currentCamera = this.cameras[0];
this.updateStreamUrl();
} catch (error) {
uni.showToast({
title: '加载相机列表失败',
icon: 'none'
});
}
},
updateStreamUrl() {
const currentIp = window.location.hostname;
const isH5 = uni.getSystemInfoSync().platform === 'h5';
const protocol = isH5 ? 'http' : 'rtmp';
const ext = isH5 ? '.m3u8' : '';
this.streamUrl = `${protocol}://${currentIp}/live/camera${this.currentCamera.id}${ext}`;
console.log(this.streamUrl)
this.$nextTick(() => {
this.videoPlayer.play();
});
},
handleCameraChange(e) {
this.videoPlayer.stop();
this.currentCamera = this.cameras[e.detail.value];
this.updateStreamUrl();
},
// 云台控制方法
handleControl(action, state) {
console.log(`${action}-${state}`);
const data = { id: this.currentCamera.id };
},
// 刷新画面
refresh() {
this.videoPlayer.stop();
this.updateStreamUrl();
},
// 全屏状态变化
handleFullscreenChange(e) {
this.isFullscreen = e.detail.fullScreen;
}
}
}
</script>
<style>
.container {
width: 100%;
height: 85vh;
}
/* 云台控制面板样式 */
.ptz-control {
margin-top: 10px;
background-color: rgba(255, 255, 255, 0.8);
border: 1px solid #ccc;
padding: 5px;
border-radius: 5px;
}
.ptz-control-fullscreen {
position: fixed;
bottom: 10px;
left: 50%;
transform: translateX(-50%);
width: 80%;
z-index: 1000;
}
.direction-list {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 3px;
justify-items: center;
}
.operation-item, .direction-item {
display: flex;
flex-direction: column;
align-items: center;
margin: 3px;
}
.operation-item span, .direction-item span {
font-size: 10px;
margin-top: 3px;
}
</style>