feat: 完成监控相关UI+逻辑

This commit is contained in:
范鹏 2025-04-06 18:17:50 +08:00
parent 5954c8a838
commit abbbec9cdb
9 changed files with 72 additions and 177 deletions

View File

@ -5,7 +5,7 @@ import request from '../utils/request'
// 获取p2pInfo
export function getP2pInfo(data) {
return request({
url: '/v1/tencentYun/getDeviceDetail',
url: '/passthrough',
method: 'POST',
data
})

View File

@ -29,15 +29,6 @@
"version": "latest",
"provider": "wx1319af22356934bf",
"export": "exportForXp2pPlugin.js"
},
"wechat-p2p-player": {
"version": "latest",
"provider": "wx9e8fbc98ceac2628",
"export": "exportForPlayerPlugin.js"
},
"wmpf-voip": {
"version": "latest",
"provider": "wxf830863afde621eb"
}
}
},

View File

@ -16,6 +16,7 @@
"style": {
"navigationStyle": "custom",
"navigationBarTitleText": "监控",
"disableScroll": true,
"mp-weixin": {
"usingComponents": {
"iot-p2p-player-with-mjpg": "plugin://xp2p/iot-p2p-player-with-mjpg",
@ -23,8 +24,26 @@
}
}
}
},
{
"path": "authorizeWechat",
"style": {
"navigationBarTitleText": "微信授权",
"disableScroll": true
}
}
]
],
"plugins": {
"wechat-p2p-player": {
"version": "latest",
"provider": "wx9e8fbc98ceac2628",
"export": "exportForPlayerPlugin.js"
},
"wmpf-voip": {
"version": "latest",
"provider": "wxf830863afde621eb"
}
}
},
{
"root": "pages/addDevice",

View File

@ -221,6 +221,16 @@
></image>
<view>消息提醒</view>
</view>
<view
class="menu-main-view transform-scale-105"
@click="$basic.routeJump({ name: 'p2pPlayer' })"
>
<image
class="menu-main-image"
src="https://oss-lock.xhjcn.ltd/mp/icon_wechat_call.png"
></image>
<view>微信呼叫</view>
</view>
</view>
</view>
<view class="setting" @click="$basic.routeJump({ name: 'setting' })">

View File

@ -1,20 +1,31 @@
<template>
<view>
<iot-p2p-player-with-mjpg
v-if="deviceInfo"
id="playerRef"
:deviceInfo="deviceInfo"
:xp2pInfo="xp2pInfo"
:rotate="90"
:muted="isMute"
mode="RTC"
:acceptPlayerEvents="true"
soundMode="speaker"
sceneType="live"
streamQuality="high"
:minCache="0.2"
:maxCache="0.8"
:fill="true"
orientation="horizontal"
@statechange="handleStateChange"
@playsuccess="handlePlaySuccess"
>
</iot-p2p-player-with-mjpg>
<image
v-if="!isVideoLoaded"
src="https://oss-lock.xhjcn.ltd/mp/background_monitor.png"
class="w-full h-full absolute top-0 left-0"
></image>
<iot-p2p-voice
v-if="deviceInfo"
id="voiceComponent"
:deviceInfo="deviceInfo"
:xp2pInfo="xp2pInfo"
@ -23,6 +34,7 @@
</iot-p2p-voice>
<view
v-if="isVideoLoaded"
class="fixed bottom-[calc(32rpx+env(safe-area-inset-bottom))] bg-[rgba(0,0,0,0.3)] rounded-xl p-4 shadow-lg mx-4 w-622"
>
<view class="flex items-center justify-around mx-10">
@ -72,11 +84,22 @@
</view>
</view>
</view>
<view
v-if="!isVideoLoaded"
class="fixed bottom-[calc(48rpx+env(safe-area-inset-bottom))] w-full flex justify-center"
>
<up-loading-icon
size="70rpx"
:vertical="true"
textSize="28rpx"
text="连接中"
mode="circle"
></up-loading-icon>
</view>
</view>
</template>
<script setup>
import { getXp2pManager } from './xp2pManager'
import { useBluetoothStore } from '@/stores/bluetooth'
import { useBasicStore } from '@/stores/basic'
import { onMounted, ref } from 'vue'
@ -86,36 +109,30 @@
const $bluetooth = useBluetoothStore()
const $basic = useBasicStore()
let xp2pManager = null
const deviceInfo = ref()
const xp2pInfo = ref()
const isVoice = ref(false)
const isMute = ref(false)
const isVideoLoaded = ref(false)
onMounted(async () => {
if (!xp2pManager) {
xp2pManager = getXp2pManager()
}
const { code, data, message } = await getP2pInfo({
lockId: $bluetooth.currentLockInfo.lockId
request_method: 'GET',
request_uri: '/api/v1/tencentYun/getDeviceDetailData',
post_args: {
lockId: $bluetooth.currentLockInfo.lockId
}
})
if (code === 0) {
deviceInfo.value = {
deviceId: `${data.productId}/${data.deviceId}`,
deviceId: `${data.productId}/${data.deviceName}`,
productId: data.productId,
deviceName: data.deviceName
}
xp2pInfo.value = data.xp2pInfo
await xp2pManager.startP2PService({
deviceInfo: deviceInfo.value,
xp2pInfo: xp2pInfo.value,
caller: 1
})
} else {
$basic.backAndToast(message)
}
@ -180,8 +197,8 @@
voice.stopVoice()
}
const handleStateChange = state => {
console.log(11111111, state)
const handlePlaySuccess = () => {
isVideoLoaded.value = true
}
</script>

View File

@ -1,29 +0,0 @@
export const getUserId = () => {
return 1
}
export function compareVersion(ver1, ver2) {
const v1 = ver1.split('.')
const v2 = ver2.split('.')
const len = Math.max(v1.length, v2.length)
while (v1.length < len) {
v1.push('0')
}
while (v2.length < len) {
v2.push('0')
}
for (let i = 0; i < len; i++) {
const num1 = parseInt(v1[i])
const num2 = parseInt(v2[i])
if (num1 > num2) {
return 1
} else if (num1 < num2) {
return -1
}
}
return 0
}

View File

@ -1,118 +0,0 @@
import { getUserId, compareVersion } from './utils'
let xp2pManager = null
export const getXp2pManager = () => {
if (!xp2pManager) {
let xp2pPlugin = requirePlugin('xp2p')
console.log(11111, xp2pPlugin)
const iotExports = xp2pPlugin.iot
const app = getApp()
// 用户id微信用户在此小程序中的唯一标识
iotExports?.setUserId?.(getUserId() || 'demo')
// 开发版才打插件log
if (app.pluginLogger && uni.getAccountInfoSync().miniProgram.envVersion === 'develop') {
iotExports?.setPluginLogger?.(app.pluginLogger)
}
// 设置优先使用的打洞协议
if (
compareVersion(uni.getSystemInfoSync().SDKVersion, '3.4.1') >= 0 &&
xp2pPlugin.p2p.setTcpFirst
) {
const tcpFirstKey = 'tcpFirst'
const tcpFirstTime = parseInt(uni.getStorageSync(tcpFirstKey), 10)
const tcpFirst = !!(tcpFirstTime && Date.now() - tcpFirstTime < 3600000 * 24) // 24小时内有效
console.log('tcpFirst', tcpFirst)
xp2pPlugin.p2p.setTcpFirst(tcpFirst)
// 给index页用方便测试时调整tcpFirst
app.tcpFirst = tcpFirst
app.toggleTcpFirst = async () => {
const modalRes = await uni.showModal({
title: '确定切换 tcpFirst 吗?',
content: '切换后需要重新进入小程序'
})
if (!modalRes || !modalRes.confirm) {
return
}
uni.setStorageSync(tcpFirstKey, tcpFirst ? '' : Date.now())
app.restart()
}
}
// 设置是否连接对端stun
if (xp2pPlugin.p2p.setCrossStunTurn) {
const crossStunTurnKey = 'crossStunTurn'
const crossStunTurnTime = parseInt(uni.getStorageSync(crossStunTurnKey), 10)
const crossStunTurn = !!(crossStunTurnTime && Date.now() - crossStunTurnTime < 3600000 * 24) // 24小时内有效
xp2pPlugin.p2p.setCrossStunTurn(crossStunTurn)
// 给index页用方便测试时调整crossStunTurn
app.crossStunTurn = crossStunTurn
app.toggleCrossStunTurn = async () => {
const modalRes = await uni.showModal({
title: '确定切换 crossStunTurn 吗?',
content: '切换后需要重新进入小程序'
})
if (!modalRes || !modalRes.confirm) {
return
}
uni.setStorageSync(crossStunTurnKey, crossStunTurn ? '' : Date.now())
app.restart()
}
}
// 设置切换端口
if (xp2pPlugin.p2p.updateStunPort) {
const portKey = 'STUN_PORT'
const stunPort = uni.getStorageSync(portKey) || 20002
xp2pPlugin.p2p.updateStunPort(stunPort)
app.stunPort = stunPort
app.togglePort = async port => {
const modalRes = await uni.showModal({
title: '确定切换 stunPort 吗?',
content: '切换后需要重新进入小程序'
})
if (!modalRes || !modalRes.confirm) {
return
}
uni.setStorageSync(portKey, port)
app.restart()
}
}
// 设置切换配置跟随
if (xp2pPlugin.p2p.setUseDeliveryConfig) {
const useDeliveryConfigKey = 'useDeliveryConfig'
const useDeliveryConfigTime = parseInt(uni.getStorageSync(useDeliveryConfigKey), 10)
const useDeliveryConfig = !!(
useDeliveryConfigTime && Date.now() - useDeliveryConfigTime < 3600000 * 24
) // 24小时内有效
xp2pPlugin.p2p.setUseDeliveryConfig(useDeliveryConfig)
app.useDeliveryConfig = useDeliveryConfig
app.toggleUseDeliveryConfig = async () => {
const modalRes = await uni.showModal({
title: '确定切换 使用设备跟随 吗?',
content: '切换后需要重新进入小程序'
})
if (!modalRes || !modalRes.confirm) {
return
}
uni.setStorageSync(useDeliveryConfigKey, useDeliveryConfig ? '' : Date.now())
app.restart()
}
}
xp2pManager = iotExports.getXp2pManager()
app.logger?.log('xp2pManager', {
P2PPlayerVersion: xp2pManager.P2PPlayerVersion,
XP2PVersion: xp2pManager.XP2PVersion,
// uuid插件随机生成的id存储在小程序本地删除小程序后会重新生成
uuid: xp2pManager.uuid
})
}
return xp2pManager
}

View File

@ -391,6 +391,11 @@ const pages = [
name: 'p2pPlayer',
path: '/pages/p2p/p2pPlayer',
tabBar: false
},
{
name: 'authorizeWechat',
path: '/pages/p2p/authorizeWechat',
tabBar: false
}
]

View File

@ -29,13 +29,13 @@ const request = config => {
const timestamp = new Date().getTime()
timer = setTimeout(() => {
resolve({ code: -1, message: '网络访问失败,请检查网络是否正常' })
}, 7200)
}, 30200)
uni.request({
url: URL,
method,
header,
data,
timeout: 7000,
timeout: 30000,
async success(res) {
const { statusCode, data } = res
if (timer) {