This commit is contained in:
Your Name
2026-04-10 14:43:58 +08:00
parent fdf714f833
commit 4909ec6daa
38 changed files with 6549 additions and 735 deletions
+109 -9
View File
@@ -729,11 +729,14 @@ const { proxy } = getCurrentInstance()
if(options.msg==1){
console.log('msg我进来了',options.msg)
await sendConfirmationMessage(); // 进入聊天时自动发送知情确认
await waitForIMReady(); // 确保 SDK 网络就绪后再发消息
await sendConfirmationMessage(); // 进入聊天时自动发送知情确认
}
loadDoctorInfo(); // 加载医生卡片信息(对方为医生时)
uni.$on('TUICall:callStart', onVideoCallStart);
uni.$on('TUICall:callEnd', onVideoCallEnd);
// 提前申请音视频权限,避免来电接通时才弹「去设置」提示
requestAVPermissions({ silent: true, scene: 'onLoad' });
//uni.showToast({ title: '聊天已就绪', icon: 'success' });
// #ifdef MP-WEIXIN
@@ -1136,18 +1139,25 @@ const { proxy } = getCurrentInstance()
}
}
/** 等待 IM SDK 网络握手完成,给 SDK 一段时间确保就绪后再发消息 */
function waitForIMReady() {
// 使用固定延迟代替事件监听:SDK_READY 事件可能在注册前已触发,
// 事件监听会等满 maxMs 超时,在微信小程序中引发 "Error: timeout"。
return new Promise((resolve) => setTimeout(resolve, 800));
}
async function sendConfirmationMessage() {
const alreadySent = messages.value.some(
(m) => m.type === 'confirmation' || (m.type === 'text' && isConfirmationMessageText(m.text))
);
if (alreadySent) return;
try {
const message = chat.createTextMessage({
to: targetUserID,
conversationType: TencentCloudChat.TYPES.CONV_C2C,
payload: { text: CONFIRMATION_MESSAGE }
});
await chat.sendMessage(message);
const pushSent = () => {
// 防止重复 push(relogin 后重试时再次检查)
const already = messages.value.some(
(m) => m.type === 'confirmation' || (m.type === 'text' && isConfirmationMessageText(m.text))
);
if (already) return;
messages.value.push({
type: 'confirmation',
text: CONFIRMATION_MESSAGE,
@@ -1157,8 +1167,27 @@ const { proxy } = getCurrentInstance()
});
scrollToBottom();
setTimeout(() => scrollToBottom(), 150);
};
const doSend = async () => {
const message = chat.createTextMessage({
to: targetUserID,
conversationType: TencentCloudChat.TYPES.CONV_C2C,
payload: { text: CONFIRMATION_MESSAGE }
});
await chat.sendMessage(message);
};
try {
await doSend();
pushSent();
} catch (error) {
console.error('发送确认信息失败:', error);
console.error('发送确认信息失败,尝试重新登录后重试:', error);
try {
await reloginIMChat();
await doSend();
pushSent();
} catch (e2) {
console.error('重登后确认信息仍发送失败:', e2);
}
}
}
@@ -1335,7 +1364,78 @@ const { proxy } = getCurrentInstance()
});
}
/**
* 申请摄像头 + 麦克风权限。
* silent=true 时仅静默尝试,不弹引导框(用于页面加载时提前申请)。
* silent=false 时若被拒绝主动引导用户去设置页开启。
* scene 标识触发场景(makeCall / incoming),用于日志分析。
*/
// #ifdef MP-WEIXIN
function requestAVPermissions({ silent = false, scene = 'unknown' } = {}) {
/** 上报权限被拒日志到后端 */
const logDenied = (deniedScope, action) => {
try {
const wxVersion = wx.getSystemInfoSync?.()?.SDKVersion || '';
proxy.apiUrl({
url: '/api/chat/logAvPermission',
method: 'POST',
data: {
patient_id: currentUserID || '',
doctor_id: targetUserID || '',
denied_scope: deniedScope,
scene,
action,
wx_version: wxVersion
}
}, false).catch(() => {});
} catch (_) {}
};
const guideToSetting = (deniedScope) => {
if (silent) {
// 静默模式:仅记录被拒,不弹弹窗
logDenied(deniedScope, 'silent_denied');
return;
}
uni.showModal({
title: '需要摄像头和麦克风权限',
content: '视频通话需要摄像头和麦克风权限,请点击「去设置」开启后重试',
confirmText: '去设置',
cancelText: '取消',
success: (res) => {
if (res.confirm) {
logDenied(deniedScope, 'open_setting');
wx.openSetting();
} else {
// 用户选择「取消」,记录日志
logDenied(deniedScope, 'cancel');
}
}
});
};
return new Promise((resolve) => {
wx.authorize({
scope: 'scope.camera',
success: () => {
wx.authorize({
scope: 'scope.record',
success: () => resolve(true),
fail: () => { guideToSetting('record'); resolve(false); }
});
},
fail: () => { guideToSetting('camera'); resolve(false); }
});
});
}
// #endif
// #ifndef MP-WEIXIN
function requestAVPermissions() { return Promise.resolve(true); }
// #endif
async function makeVideoCall() {
// 发起通话前先检查权限,若被拒引导去设置
const granted = await requestAVPermissions({ silent: false, scene: 'makeCall' });
if (!granted) return;
try {
hideDoctorCardByCall();
if (!uni.CallManager) {