215 lines
7.7 KiB
JavaScript
215 lines
7.7 KiB
JavaScript
/**
|
||
* 连接管理模块 - xiaoxilj.js (根治发送失败:跳转前确保群组已订阅)
|
||
* 从详情页跳转订单群聊时,提前订阅群组,避免发送消息时订阅未完成而失败
|
||
*/
|
||
const app = getApp();
|
||
|
||
function waitForConnection(expectedUserId, timeout = 10000) {
|
||
return new Promise((resolve, reject) => {
|
||
const timer = setTimeout(() => {
|
||
app.off('connectionChanged', handler);
|
||
reject(new Error('连接超时'));
|
||
}, timeout);
|
||
|
||
const handler = (event) => {
|
||
if (event.status === 'connected') {
|
||
if (event.userId === expectedUserId) {
|
||
clearTimeout(timer);
|
||
app.off('connectionChanged', handler);
|
||
resolve();
|
||
} else {
|
||
console.error(`连接身份不匹配: 期望 ${expectedUserId}, 实际 ${event.userId}`);
|
||
wx.removeStorageSync('savedGoEasyConnection');
|
||
wx.removeStorageSync('goEasyUserId');
|
||
wx.removeStorageSync('currentGoEasyIdentity');
|
||
if (app.clearSavedConnection) app.clearSavedConnection();
|
||
clearTimeout(timer);
|
||
app.off('connectionChanged', handler);
|
||
reject(new Error(`连接身份不匹配: 期望 ${expectedUserId}, 实际 ${event.userId}`));
|
||
}
|
||
} else if (event.status === 'disconnected' && !event.manual) {
|
||
wx.removeStorageSync('savedGoEasyConnection');
|
||
wx.removeStorageSync('goEasyUserId');
|
||
wx.removeStorageSync('currentGoEasyIdentity');
|
||
if (app.clearSavedConnection) app.clearSavedConnection();
|
||
clearTimeout(timer);
|
||
app.off('connectionChanged', handler);
|
||
reject(new Error('连接失败'));
|
||
}
|
||
};
|
||
app.on('connectionChanged', handler);
|
||
});
|
||
}
|
||
|
||
class ConnectionManager {
|
||
// 原有的私聊方法保持不变
|
||
async connectAndChat(params) {
|
||
const { identityType, userId, targetUser } = params;
|
||
if (!identityType || !userId || !targetUser || !targetUser.id) {
|
||
throw new Error('参数不完整');
|
||
}
|
||
|
||
if (identityType === 'dashou' && !userId.startsWith('Ds')) {
|
||
throw new Error(`接单员身份的用户ID必须以Ds开头,实际为 ${userId}`);
|
||
}
|
||
if (identityType === 'shangjia' && !userId.startsWith('Sj')) {
|
||
throw new Error(`商家身份的用户ID必须以Sj开头,实际为 ${userId}`);
|
||
}
|
||
if (identityType === 'boss' && !userId.startsWith('Boss')) {
|
||
throw new Error(`老板身份的用户ID必须以Boss开头,实际为 ${userId}`);
|
||
}
|
||
|
||
wx.removeStorageSync('savedGoEasyConnection');
|
||
wx.removeStorageSync('goEasyUserId');
|
||
wx.removeStorageSync('currentGoEasyIdentity');
|
||
if (app.clearSavedConnection) app.clearSavedConnection();
|
||
|
||
if (wx.goEasy && wx.goEasy.getConnectionStatus() === 'connected') {
|
||
wx.goEasy.disconnect();
|
||
}
|
||
|
||
const waitPromise = waitForConnection(userId);
|
||
app.connectWithIdentity(identityType, userId, false);
|
||
|
||
try {
|
||
await waitPromise;
|
||
|
||
const currentUser = {
|
||
id: userId,
|
||
name: app.globalData.currentUser?.name || '用户',
|
||
avatar: app.globalData.currentUser?.avatar || (app.globalData.ossImageUrl + app.globalData.morentouxiang)
|
||
};
|
||
|
||
const to = {
|
||
id: targetUser.id,
|
||
name: targetUser.name || '用户',
|
||
avatar: targetUser.avatar || (app.globalData.ossImageUrl + app.globalData.morentouxiang)
|
||
};
|
||
|
||
const param = { to, currentUser };
|
||
const path = '/pages/chat/chat?data=' + encodeURIComponent(JSON.stringify(param));
|
||
wx.navigateTo({ url: path });
|
||
} catch (err) {
|
||
console.error('连接失败:', err);
|
||
wx.showToast({ title: err.message || '连接失败', icon: 'none' });
|
||
throw err;
|
||
}
|
||
}
|
||
|
||
async connectToGroupChat(params) {
|
||
const { identityType, userId, orderId, groupName, groupAvatar, isCross } = params;
|
||
if (!identityType || !userId || !orderId) {
|
||
throw new Error('参数不完整:identityType, userId, orderId 必填');
|
||
}
|
||
|
||
// 校验 userId 前缀
|
||
if (identityType === 'dashou' && !userId.startsWith('Ds')) {
|
||
throw new Error(`接单员身份的用户ID必须以Ds开头,实际为 ${userId}`);
|
||
}
|
||
if (identityType === 'shangjia' && !userId.startsWith('Sj')) {
|
||
throw new Error(`商家身份的用户ID必须以Sj开头,实际为 ${userId}`);
|
||
}
|
||
if (identityType === 'boss' && !userId.startsWith('Boss')) {
|
||
throw new Error(`老板身份的用户ID必须以Boss开头,实际为 ${userId}`);
|
||
}
|
||
|
||
|
||
// 1. 同步全局角色,确保群聊页初始化正确
|
||
app.globalData.currentRole = identityType;
|
||
wx.setStorageSync('currentRole', identityType);
|
||
|
||
const uid = userId.replace(/^(Ds|Sj|Boss|Gs|Zz)/, '');
|
||
const avatar = wx.getStorageSync('touxiang') ||
|
||
(app.globalData.ossImageUrl + app.globalData.morentouxiang);
|
||
app.globalData.currentUser = {
|
||
id: userId,
|
||
name: app.globalData.currentUser?.name || `用户${uid}`,
|
||
avatar: avatar
|
||
};
|
||
|
||
// 2. 确保 GoEasy 已使用目标身份连接
|
||
let needConnect = false;
|
||
if (!wx.goEasy || !wx.goEasy.getConnectionStatus || wx.goEasy.getConnectionStatus() !== 'connected') {
|
||
needConnect = true;
|
||
} else {
|
||
const currentUserId = wx.goEasy.im?.userId;
|
||
if (currentUserId !== userId) {
|
||
needConnect = true;
|
||
}
|
||
}
|
||
|
||
if (needConnect) {
|
||
wx.removeStorageSync('savedGoEasyConnection');
|
||
wx.removeStorageSync('goEasyUserId');
|
||
if (app.clearSavedConnection) app.clearSavedConnection();
|
||
if (wx.goEasy && wx.goEasy.getConnectionStatus() === 'connected') {
|
||
wx.goEasy.disconnect();
|
||
}
|
||
const waitPromise = waitForConnection(userId);
|
||
app.connectWithIdentity(identityType, userId, false);
|
||
try {
|
||
await waitPromise;
|
||
} catch (err) {
|
||
wx.showToast({ title: '连接失败', icon: 'none' });
|
||
throw err;
|
||
}
|
||
}
|
||
|
||
// 3. 从会话列表查找真实群组ID
|
||
let realGroupId = null;
|
||
try {
|
||
const result = await new Promise((resolve, reject) => {
|
||
wx.goEasy.im.latestConversations({
|
||
onSuccess: (res) => {
|
||
const conversations = res.content?.conversations || [];
|
||
const found = conversations.find(c => c.type === 'group' && c.data && c.data.orderId === orderId);
|
||
resolve(found ? found.groupId : null);
|
||
},
|
||
onFailed: reject
|
||
});
|
||
});
|
||
realGroupId = result;
|
||
} catch (err) {
|
||
console.error('获取会话列表失败:', err);
|
||
wx.showToast({ title: '获取群聊信息失败', icon: 'none' });
|
||
throw err;
|
||
}
|
||
|
||
if (!realGroupId) {
|
||
wx.showToast({ title: '暂未创建群聊', icon: 'none' });
|
||
return;
|
||
}
|
||
|
||
// 4. 🔥 关键:主动订阅群组并等待成功,确保发送消息时订阅已完成
|
||
try {
|
||
await new Promise((resolve, reject) => {
|
||
wx.goEasy.im.subscribeGroup({
|
||
groupIds: [realGroupId],
|
||
onSuccess: () => {
|
||
resolve();
|
||
},
|
||
onFailed: (error) => {
|
||
console.error('订阅群组失败:', error);
|
||
reject(error);
|
||
}
|
||
});
|
||
});
|
||
} catch (err) {
|
||
wx.showToast({ title: '订阅群组失败', icon: 'none' });
|
||
throw err;
|
||
}
|
||
|
||
// 5. 跳转群聊页(参数与消息列表完全一致)
|
||
const param = {
|
||
groupId: realGroupId,
|
||
orderId: orderId,
|
||
groupName: groupName || '订单群聊',
|
||
groupAvatar: groupAvatar || '',
|
||
isCross: isCross || 0
|
||
};
|
||
const path = '/pages/group-chat/group-chat?data=' + encodeURIComponent(JSON.stringify(param));
|
||
wx.navigateTo({ url: path });
|
||
}
|
||
}
|
||
|
||
export default new ConnectionManager(); |