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.

220 lines
6.9 KiB
Vue

<template>
<view class="container">
<picker mode="selector" :range="cameras" range-key="name" @change="handleCameraChange">
<button>{{ currentCamera ? currentCamera.name : '选择相机' }}</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/l_u.png"
:style="{ width: isFullscreen ? '40px' : '40px', height: isFullscreen ? '40px' : '40px', opacity: activeButton === 'leftUp' ? 0.7 : 1 }"
@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/r_u.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/l_d.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/r_d.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 ipAddres = uni.getStorageSync('IP_ADDRESS');
const isH5 = uni.getSystemInfoSync().platform === 'h5';
const protocol = isH5 ? 'http' : 'rtmp';
const ext = isH5 ? '.m3u8' : '';
this.streamUrl = `${protocol}://${ipAddres}/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();
},
// 云台控制方法
async handleControl(action, state) {
console.log(`${action}-${state}`);
const data = {
id: this.currentCamera.id
};
const res = await request({
url: '/admin-api/camera/control/' + action + '/' + state,
method: 'POST',
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>