feat: 完成twcall相关UI+逻辑

This commit is contained in:
范鹏 2025-04-07 17:01:22 +08:00
parent 920e5f3c33
commit 1c93dc914b
8 changed files with 364 additions and 15 deletions

20
App.vue
View File

@ -39,6 +39,8 @@
this.updateMiniProgram()
//
this.onBluetoothState()
// voip
this.setVoipConfig()
//
const checkResult = await this.checkSetting()
console.log(checkResult)
@ -65,6 +67,24 @@
'initAndListenBluetooth'
]),
...mapActions(useUserStore, ['updateLoginStatus']),
// voip
setVoipConfig() {
const wmpfVoip = requirePlugin('wmpf-voip').default
wmpfVoip.setUIConfig({
btnText: '去开门',
customBoxHeight: '75vh',
listenerUI: {
cameraRotation: 270,
objectFit: 'fill',
enableToggleCamera: false
}
})
wmpfVoip.setVoipEndPagePath({
url: '/pages/main/home',
key: 'Call',
routeType: 'switchTab'
})
},
//
updateMiniProgram() {
const updateManager = uni.getUpdateManager()

View File

@ -1,9 +1,9 @@
import request from '../utils/request'
// p2p 模块
// sdk 模块
// 获取p2pInfo
export function getP2pInfo(data) {
// 透传
export function passthrough(data) {
return request({
url: '/passthrough',
method: 'POST',

View File

@ -29,6 +29,15 @@
"version": "latest",
"provider": "wx1319af22356934bf",
"export": "exportForXp2pPlugin.js"
},
"wmpf-voip": {
"version": "latest",
"provider": "wxf830863afde621eb",
"genericsImplementation": {
"call-page-plugin": {
"custombox": "pages/main/customBox"
}
}
}
}
},

View File

@ -38,10 +38,6 @@
"version": "latest",
"provider": "wx9e8fbc98ceac2628",
"export": "exportForPlayerPlugin.js"
},
"wmpf-voip": {
"version": "latest",
"provider": "wxf830863afde621eb"
}
}
},
@ -579,6 +575,9 @@
{
"path": "pages/main/mine"
},
{
"path": "pages/main/customBox"
},
{
"path": "pages/main/notificationList",
"style": {

185
pages/main/customBox.vue Normal file
View File

@ -0,0 +1,185 @@
<template>
<view class="dialog">
<image
class="top-background"
src="https://oss-lock.xhjcn.ltd/mp/background_main.jpg"
mode="aspectFill"
></image>
<view class="switch" @click="openDoorOperate">
<SwitchLoading :size="220" ref="sLoading"></SwitchLoading>
</view>
<view class="switch-text">点击开锁</view>
</view>
</template>
<script setup>
import SwitchLoading from '@/components/SwitchLoading/SwitchLoading.vue'
import { useBluetoothStore } from '@/stores/bluetooth'
import { useBasicStore } from '@/stores/basic'
import { useUserStore } from '@/stores/user'
import { getLockDetailRequest, getLockNetTokenRequest } from '@/api/lock'
import { ref, onMounted } from 'vue'
const $bluetooth = useBluetoothStore()
const $basic = useBasicStore()
const $user = useUserStore()
const sLoading = ref(null)
const pending = ref(false)
const lockInfo = ref(null)
const onlineToken = ref('0')
const lockId = ref(19335)
const time = ref(0)
onMounted(async () => {
const { code, data, message } = await getLockDetailRequest({
lockId: lockId.value
})
if (code === 0) {
lockInfo.value = data
} else {
uni.showToast({
title: message,
icon: 'none'
})
}
await getServeTime()
})
const getServeTime = async () => {
const { code, data } = await $bluetooth.updateServerTimestamp()
if (code === 0) {
time.value = parseInt((data.date - new Date().getTime()) / 1000, 10)
}
}
const openDoorOperate = async () => {
const timestamp = new Date().getTime()
if (pending.value) {
return
}
const netWork = await $basic.getNetworkType()
if (!netWork) {
return
}
if (lockInfo.value.appUnlockOnline) {
const result = await getNetToken()
if (!result) {
sLoading.value.close()
pending.value = false
return
}
}
uni.vibrateLong()
pending.value = true
sLoading.value.open()
const openMode = lockInfo.value.appUnlockOnline ? 1 : 0
const { code } = await $bluetooth.openDoor({
name: lockInfo.value.name,
uid: $user.userInfo.uid.toString(),
openMode,
openTime: parseInt(new Date().getTime() / 1000, 10) + time.value,
onlineToken: onlineToken.value
})
$bluetooth
.syncRecord({
keyId: lockInfo.value.keyId.toString(),
uid: $user.userInfo.uid.toString()
})
.then(() => {
$bluetooth.closeBluetoothConnection()
})
uni.reportEvent('open_door', {
result: code,
duration: new Date().getTime() - timestamp
})
if (code === 0) {
uni.showToast({
title: `开门成功`,
icon: 'none'
})
} else if (code === 7) {
uni.showToast({
title: `钥匙过期`,
icon: 'none'
})
} else if (code === 13) {
uni.showToast({
title: `钥匙当前不可用`,
icon: 'none'
})
} else if (code === -1) {
uni.showToast({
title: `开锁失败`,
icon: 'none'
})
}
sLoading.value.close()
pending.value = false
}
const getNetToken = async () => {
const { code, data, message } = await getLockNetTokenRequest({
lockId: lockId.value
})
if (code === 0) {
onlineToken.value = data.token
return true
}
uni.showToast({
title: message,
icon: 'none'
})
return false
}
</script>
<style lang="scss" scoped>
.dialog {
position: relative;
display: flex;
align-items: center;
justify-content: center;
width: 100%;
height: 75vh;
background-color: #f3f3f3;
.top-background {
position: absolute;
width: 686rpx;
height: 464rpx;
border-radius: 32rpx;
}
.switch {
z-index: 99;
display: flex;
align-items: center;
justify-content: center;
width: 250rpx;
height: 250rpx;
margin-top: 20rpx;
background: #ffffff;
border-radius: 50%;
box-shadow: 0 8rpx 36rpx 0 rgba(0, 0, 0, 0.12);
}
.switch-text {
z-index: 99;
margin-top: 10rpx;
text-align: center;
}
}
</style>

View File

@ -223,7 +223,7 @@
</view>
<view
class="menu-main-view transform-scale-105"
@click="$basic.routeJump({ name: 'p2pPlayer' })"
@click="$basic.routeJump({ name: 'authorizeWechat' })"
>
<image
class="menu-main-image"

View File

@ -1,13 +1,149 @@
<template>
<view>
<view>授权微信</view>
<view class="mt-10 text-center text-base font-bold text-[#999]">授权后设备可呼叫该微信</view>
<view v-if="requestFinish">
<view
v-if="!isAuthorized"
class="bg-[#63b8af] text-white rounded-full text-center leading-88rpx h-88rpx w-686 mx-4 mt-10"
@click="handleAuthorize"
>
授权
</view>
<view v-else>
<view v-if="!reject" class="text-center text-lg font-bold mt-4">您已授权</view>
<view v-else>
<view class="text-center text-lg font-bold mt-4"> 您已拒绝授权请去设置中 </view>
<view class="text-center text-lg font-bold mt-4"> 打开语音视频通话提醒开关 </view>
<view
class="bg-[#63b8af] text-white rounded-full text-center leading-88rpx h-88rpx w-686 mx-4 mt-10"
@click="openSetting"
>
打开设置
</view>
</view>
</view>
</view>
</view>
</template>
<script setup>
import { onLoad } from '@dcloudio/uni-app'
import { onShow } from '@dcloudio/uni-app'
import { passthrough } from '@/api/sdk'
import { ref } from 'vue'
import { useBluetoothStore } from '@/stores/bluetooth'
onLoad(() => {
console.log(11111111)
const $bluetooth = useBluetoothStore()
const requestFinish = ref(false)
const isAuthorized = ref(false)
const list = ref([])
const reject = ref(false)
const pending = ref(false)
onShow(() => {
uni.showLoading({
title: '加载中...'
})
wx.getDeviceVoIPList({
async success(res) {
list.value = res.list
if (res.list.length > 0) {
const result = await getInfo()
if (result.code === 0) {
const data = list.value.find(
item => item.model_id === result.data.WXIoTDeviceInfo.ModelId
)
if (data) {
if (data.status === 1) {
reject.value = false
} else if (data.status === 0) {
reject.value = true
}
isAuthorized.value = true
requestFinish.value = true
uni.hideLoading()
} else {
requestFinish.value = true
uni.hideLoading()
}
} else {
uni.showToast({
title: result.message,
icon: 'none'
})
requestFinish.value = true
uni.hideLoading()
}
} else {
requestFinish.value = true
uni.hideLoading()
}
}
})
})
</script>
const openSetting = () => {
uni.openSetting({
success: res => {
console.log(res)
}
})
}
const getInfo = async () => {
const result = await passthrough({
request_method: 'GET',
request_uri: '/api/v1/tencentYun/getWechatDeviceTicket',
post_args: {
lockId: $bluetooth.currentLockInfo.lockId
}
})
return result
}
const handleAuthorize = async () => {
if (pending.value) return
pending.value = true
uni.showLoading({
title: '授权中...'
})
const result = await getInfo()
if (result.code === 0) {
wx.requestDeviceVoIP({
sn: result.data.WXIoTDeviceInfo.SN,
snTicket: result.data.WXIoTDeviceInfo.SNTicket,
modelId: result.data.WXIoTDeviceInfo.ModelId,
deviceName: '智能',
success() {
isAuthorized.value = true
uni.hideLoading()
pending.value = false
uni.showToast({
title: '授权成功',
icon: 'none'
})
},
fail() {
isAuthorized.value = true
reject.value = true
uni.hideLoading()
pending.value = false
uni.showToast({
title: '授权失败',
icon: 'none'
})
}
})
} else {
uni.hideLoading()
pending.value = false
uni.showToast({
title: result.message,
icon: 'none'
})
}
}
</script>

View File

@ -123,7 +123,7 @@
import { useBasicStore } from '@/stores/basic'
import { onMounted, ref } from 'vue'
import { onUnload } from '@dcloudio/uni-app'
import { getP2pInfo } from '@/api/p2p'
import { passthrough } from '@/api/sdk'
const $bluetooth = useBluetoothStore()
const $basic = useBasicStore()
@ -148,7 +148,7 @@
onMounted(async () => {
buttonInfo.value = await $basic.getButtonInfo()
const { code, data, message } = await getP2pInfo({
const { code, data, message } = await passthrough({
request_method: 'GET',
request_uri: '/api/v1/tencentYun/getDeviceDetailData',
post_args: {