电话咨询
This commit is contained in:
@@ -169,6 +169,9 @@ const consultId = ref('')
|
||||
const miniProgramReturnUrl = ref('')
|
||||
const cloudLawApiBase = ref('')
|
||||
const cloudLawToken = ref('')
|
||||
// 调用方角色:'law' = 律师端(接单端),其余/空 = 用户端(applet)。
|
||||
// 律师为参会者(非主持人),结束会议走 /api/law/voiceCall/{callId}/end;用户端默认 /api/applet/voiceConnection。
|
||||
const cloudLawRole = ref('')
|
||||
const callMode = ref('video')
|
||||
const joining = ref(false)
|
||||
const joinError = ref('')
|
||||
@@ -209,6 +212,9 @@ const audioEnabled = computed(() => !!meetingStore.localAudioEnabled)
|
||||
const videoEnabled = computed(() => !!meetingStore.localVideoEnabled)
|
||||
const speakingMap = computed(() => meetingStore.speakingMap || {})
|
||||
const isVoiceMode = computed(() => callMode.value === 'voice')
|
||||
const isLawRole = computed(() => String(cloudLawRole.value).toLowerCase() === 'law')
|
||||
// 结束会议接口基址:律师端 /api/law/voiceCall,用户端 /api/applet/voiceConnection
|
||||
const voiceEndBase = computed(() => isLawRole.value ? '/api/law/voiceCall' : '/api/applet/voiceConnection')
|
||||
const cameraIcon = computed(() => videoEnabled.value ? videoOnIcon : videoOffIcon)
|
||||
const micIcon = computed(() => audioEnabled.value ? voiceOnIcon : voiceOffIcon)
|
||||
const speakerIcon = computed(() => speakerMuted.value ? speakerOffIcon : speakerOnIcon)
|
||||
@@ -403,7 +409,7 @@ const notifyCloudLawEnd = () => {
|
||||
if (!callId.value || !cloudLawApiBase.value) return Promise.resolve()
|
||||
return new Promise(resolve => {
|
||||
uni.request({
|
||||
url: resolveCloudLawApiUrl(`/api/applet/voiceConnection/${encodeURIComponent(callId.value)}/end`),
|
||||
url: resolveCloudLawApiUrl(`${voiceEndBase.value}/${encodeURIComponent(callId.value)}/end`),
|
||||
method: 'POST',
|
||||
data: {},
|
||||
header: cloudLawToken.value ? { 'Content-Type': 'application/json', token: `Bearer ${cloudLawToken.value}` } : { 'Content-Type': 'application/json' },
|
||||
@@ -499,6 +505,8 @@ const pollCommandsOnce = async () => {
|
||||
}
|
||||
|
||||
const startCommandPolling = () => {
|
||||
// 律师端(接单端)无 publicCommands 远程指令通道,跳过轮询避免无谓 404
|
||||
if (isLawRole.value) return
|
||||
if (!callId.value || commandPollHandle) return
|
||||
pollCommandsOnce()
|
||||
commandPollHandle = setInterval(pollCommandsOnce, 1200)
|
||||
@@ -840,21 +848,34 @@ const hangup = async () => {
|
||||
leaving.value = true
|
||||
stopCommandPolling()
|
||||
try {
|
||||
// 先通知云律后端结束本次通话:
|
||||
// - 用户端:/api/applet/voiceConnection/{callId}/end
|
||||
// - 律师端:/api/law/voiceCall/{callId}/end → 后端 CloudLawEndMeeting 结束会议(双方都收到 room.ended)
|
||||
await notifyCloudLawEnd()
|
||||
// 云律视频咨询:发起人(小程序端用户)在 CreateRoomForInternal 时被加成 host,
|
||||
// 用户挂机 = 咨询结束,无条件 endMeeting 让律师 iframe 收到 room.ended 自动退出。
|
||||
// 不依赖 meetingStore.isHost(host_id/userId 偶发类型不一致导致误判 false 只走 leave,
|
||||
// 表现就是"用户端挂机后 PC 还停在会议里")。
|
||||
console.log('[CloudLawVideoCall] hangup -> endMeeting', {
|
||||
roomCode: meetingStore.currentRoom?.room_code,
|
||||
hostId: meetingStore.currentRoom?.host_id,
|
||||
myUserId: userStore.userInfo?.id || userStore.userInfo?.user_id,
|
||||
isHostComputed: meetingStore.isHost
|
||||
})
|
||||
await meetingStore.endMeeting()
|
||||
if (isLawRole.value) {
|
||||
// 律师为参会者(非主持人),EndRoom 是 host-only。会议已由上面的 /end 在后端结束,
|
||||
// 这里仅本地离会即可(直接 endMeeting 会因非主持人 403,徒增一次失败请求)。
|
||||
console.log('[CloudLawVideoCall] hangup(law) -> backend end + local leave', {
|
||||
roomCode: meetingStore.currentRoom?.room_code,
|
||||
callId: callId.value
|
||||
})
|
||||
await meetingStore.leave().catch(() => {})
|
||||
} else {
|
||||
// 云律视频咨询:发起人(小程序端用户)在 CreateRoomForInternal 时被加成 host,
|
||||
// 用户挂机 = 咨询结束,无条件 endMeeting 让律师端收到 room.ended 自动退出。
|
||||
// 不依赖 meetingStore.isHost(host_id/userId 偶发类型不一致导致误判 false 只走 leave,
|
||||
// 表现就是"用户端挂机后 PC 还停在会议里")。
|
||||
console.log('[CloudLawVideoCall] hangup -> endMeeting', {
|
||||
roomCode: meetingStore.currentRoom?.room_code,
|
||||
hostId: meetingStore.currentRoom?.host_id,
|
||||
myUserId: userStore.userInfo?.id || userStore.userInfo?.user_id,
|
||||
isHostComputed: meetingStore.isHost
|
||||
})
|
||||
await meetingStore.endMeeting()
|
||||
}
|
||||
} catch (err) {
|
||||
console.warn('[CloudLawVideoCall] endMeeting failed, fallback leave', err)
|
||||
// endMeeting 失败时兜底 leave,至少自己先退出,避免卡死
|
||||
console.warn('[CloudLawVideoCall] end/hangup failed, fallback leave', err)
|
||||
// 失败时兜底 leave,至少自己先退出,避免卡死
|
||||
try { await meetingStore.leave() } catch (leaveErr) { console.warn('[CloudLawVideoCall] fallback leave failed', leaveErr) }
|
||||
} finally {
|
||||
ended.value = true
|
||||
@@ -871,6 +892,7 @@ onLoad(query => {
|
||||
miniProgramReturnUrl.value = query?.miniProgramReturnUrl || query?.mini_program_return_url || ''
|
||||
cloudLawApiBase.value = query?.cloudLawApiBase || query?.cloud_law_api_base || ''
|
||||
cloudLawToken.value = query?.cloudLawToken || query?.cloud_law_token || ''
|
||||
cloudLawRole.value = query?.cloudLawRole || query?.cloud_law_role || ''
|
||||
const mode = String(query?.mode || query?.callType || query?.type || '').toLowerCase()
|
||||
callMode.value = mode === 'voice' || mode === 'audio' ? 'voice' : 'video'
|
||||
joinMeeting()
|
||||
|
||||
Reference in New Issue
Block a user