电话咨询

This commit is contained in:
duoaohui
2026-06-04 12:40:04 +08:00
parent 46afcfe350
commit edda31e8bf

View File

@@ -16,7 +16,15 @@
-->
<template>
<view v-if="initializing || autoJoin" class="auto-join-page">
<text class="auto-join-title">正在进入会议</text>
<template v-if="autoJoinError">
<text class="auto-join-error-title">进入会议失败</text>
<text class="auto-join-error-msg">{{ autoJoinError }}</text>
<view class="auto-join-actions">
<button class="aj-btn aj-btn-primary" @click="retryAutoJoin">重试</button>
<button class="aj-btn aj-btn-secondary" @click="exitAutoJoin">返回</button>
</view>
</template>
<text v-else class="auto-join-title">正在进入会议</text>
</view>
<view v-else class="page">
<view class="container">
@@ -116,6 +124,9 @@ const joinCode = ref('')
const joinPassword = ref('')
const autoJoin = ref(false)
const initializing = ref(true)
// autoJoin 失败/超时的可见错误(替代无限"正在进入会议…"转圈)
const autoJoinError = ref('')
let autoJoinWatchdog = null
const modeLabel = computed(() => mode.value === 'create' ? '即将创建新会议' : `即将加入会议 ${joinCode.value}`)
@@ -363,6 +374,42 @@ const onCancel = () => {
uni.navigateBack()
}
// autoJoin 看门狗:若 15s 内既没进房也没报错(多见于 WS 连不上 / mediasoup 传输 ICE 不通而无限等待),
// 主动把无限转圈切换成可见的超时错误,便于真机定位与重试。
const startAutoJoinWatchdog = () => {
clearAutoJoinWatchdog()
autoJoinWatchdog = setTimeout(() => {
if (joining.value && !autoJoinError.value) {
autoJoinError.value = '连接会议服务器超时15s。可能是网络受限或会议服务WebSocket/媒体通道)暂不可达,请重试或检查网络。'
}
}, 15000)
}
const clearAutoJoinWatchdog = () => {
if (autoJoinWatchdog) { clearTimeout(autoJoinWatchdog); autoJoinWatchdog = null }
}
const retryAutoJoin = () => {
autoJoinError.value = ''
joining.value = false
startAutoJoinWatchdog()
onJoin({ skipMedia: true })
}
const exitAutoJoin = () => {
clearAutoJoinWatchdog()
// 云律小程序 web-view 内:返回到小程序;否则回上一步
try {
const embedded = typeof window !== 'undefined' && window.sessionStorage
&& window.sessionStorage.getItem('echo_cloud_law_meeting_embed') === '1'
const mp = typeof window !== 'undefined' && window.wx && window.wx.miniProgram ? window.wx.miniProgram : null
if (embedded && mp && typeof mp.navigateBack === 'function') {
mp.navigateBack({ delta: 1 })
return
}
} catch (e) {}
onCancel()
}
const onJoin = async (options = {}) => {
if (joining.value || !canJoin.value) return
joining.value = true
@@ -423,12 +470,17 @@ const onJoin = async (options = {}) => {
uni.redirectTo({ url: `/pages/meeting/room${roomCode ? `?code=${roomCode}` : ''}` })
} catch (err) {
const msg = err?.message || JSON.stringify(err)
// autoJoin 模式下把错误显式呈现在页面toast 一闪而过,真机很难看清)
if (autoJoin.value) {
autoJoinError.value = `加入失败:${msg}`
}
uni.showToast({ title: `加入失败:${msg}`, icon: 'none', duration: 3500 })
console.error('[Preview] 加入会议失败', err)
// 入会失败track 尚未转给 mediasoup 或刚拿到就失败,显式 stop 避免摄像头泄漏
try { audioTrack && audioTrack.stop && audioTrack.stop() } catch {}
try { videoTrack && videoTrack.stop && videoTrack.stop() } catch {}
} finally {
clearAutoJoinWatchdog()
joining.value = false
}
}
@@ -466,6 +518,7 @@ onLoad(async (query) => {
hasPermission: hasPermission.value,
permissionError: permissionError.value
})
startAutoJoinWatchdog()
onJoin({ skipMedia: true })
return
}
@@ -489,6 +542,7 @@ onBeforeUnmount(() => {
clearTimeout(changeDebounceTimer)
changeDebounceTimer = null
}
clearAutoJoinWatchdog()
stopPreviewStream()
stopAudioMeter()
})
@@ -499,13 +553,50 @@ onBeforeUnmount(() => {
min-height: 100vh;
background: #F8FAFC;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 0 48rpx;
}
.auto-join-title {
font-size: 30rpx;
color: #475569;
}
.auto-join-error-title {
font-size: 34rpx;
font-weight: 600;
color: #DC2626;
margin-bottom: 20rpx;
}
.auto-join-error-msg {
font-size: 26rpx;
line-height: 40rpx;
color: #475569;
text-align: center;
margin-bottom: 40rpx;
word-break: break-all;
}
.auto-join-actions {
display: flex;
gap: 24rpx;
}
.aj-btn {
min-width: 200rpx;
height: 80rpx;
line-height: 80rpx;
border-radius: 16rpx;
font-size: 28rpx;
text-align: center;
border: none;
}
.aj-btn-primary {
background: #3B82F6;
color: #FFFFFF;
}
.aj-btn-secondary {
background: #E2E8F0;
color: #334155;
}
.page { min-height: 100vh; background: #F8FAFC; padding: 24rpx; }
.container { max-width: 960rpx; margin: 0 auto; }
.title { font-size: 40rpx; font-weight: 600; color: #0F172A; display: block; margin: 24rpx 0 8rpx; }