/** * 订单群聊跳转:先确定群 ID,IM 连接失败也尽量能进聊天页 */ import request from './request'; import { persistGroupMeta } from './im-user.js'; import { resolveLocalGroupId } from './group-chat.js'; const app = getApp(); function formatError(err) { if (!err) return '进入聊天失败'; if (typeof err === 'string') return err; if (err.message) return err.message; if (err.content) return String(err.content); if (err.msg) return String(err.msg); if (err.code) return `连接失败(${err.code})`; try { return JSON.stringify(err); } catch (e) { return '进入聊天失败'; } } function withTimeout(promise, ms, errMsg) { return new Promise((resolve, reject) => { const timer = setTimeout(() => reject(new Error(errMsg || '操作超时')), ms); promise .then((v) => { clearTimeout(timer); resolve(v); }) .catch((e) => { clearTimeout(timer); reject(e); }); }); } function getConnectedUserId() { const fromState = app.globalData?.goEasyConnection?.userId; const fromIm = wx.goEasy?.im?.userId; return fromState || fromIm || ''; } function isImConnected() { const status = wx.goEasy?.getConnectionStatus?.() || 'disconnected'; return status === 'connected' || status === 'reconnected'; } async function ensureIdentityConnection(identityType, userId) { app.globalData.currentRole = identityType; wx.setStorageSync('currentRole', identityType); const uid = userId.replace(/^(Ds|Sj|Boss|Gs|Zz|Kh)/, ''); const avatar = wx.getStorageSync('touxiang') || (app.globalData.ossImageUrl + app.globalData.morentouxiang); app.globalData.currentUser = { id: userId, name: app.globalData.currentUser?.name || `用户${uid}`, avatar: avatar, }; if (!app.globalData.chatEnabled || !wx.goEasy?.im) { throw new Error('聊天服务未就绪,请稍后重试'); } if (isImConnected() && getConnectedUserId() === userId) { return; } const connectedId = getConnectedUserId(); if (connectedId && connectedId !== userId && app.disconnectGoEasy) { await app.disconnectGoEasy(); } if (!app.connectWithIdentity) { throw new Error('聊天功能未初始化'); } await withTimeout( app.connectWithIdentity(identityType, userId, true), 12000, 'IM连接超时' ); if (!isImConnected()) { throw new Error('IM连接失败,请检查网络后重试'); } } async function prepareGroupChat(identityType, userId, orderId, partnerUid, fadanPingtai, groupName, isCross) { let chatData = null; try { const res = await withTimeout( request({ url: '/dingdan/ltdhzb', method: 'POST', data: { dingdan_id: orderId, identityType, push_order_card: false, }, }), 12000, '准备群聊超时' ); const body = res?.data || {}; if (body.code === 0 && body.data?.groupId) { chatData = body.data; } else if (body.msg) { console.warn('ltdhzb:', body.msg); } } catch (e) { console.warn('ltdhzb 请求失败,尝试本地 groupId', e); } if (!chatData?.groupId) { const myUid = userId.replace(/^(Ds|Sj|Boss)/, ''); let localGroupId = resolveLocalGroupId( identityType, myUid, partnerUid, fadanPingtai, orderId, isCross ); if (!localGroupId && orderId) { localGroupId = `group_${orderId}`; } if (!localGroupId) { throw new Error('无法确定群聊,请确认订单已接单且对方信息完整'); } chatData = { groupId: localGroupId, orderId, groupName: groupName || '订单群聊', isCross: isCross || fadanPingtai || 0, }; try { await request({ url: '/dingdan/ltdhzb', method: 'POST', data: { dingdan_id: orderId, identityType, push_order_card: false }, }); } catch (e) { /* ignore */ } } return chatData; } class ConnectionManager { async connectAndChat(params) { const { identityType, userId, targetUser } = params; if (!identityType || !userId || !targetUser || !targetUser.id) { throw new Error('参数不完整'); } await ensureIdentityConnection(identityType, userId); 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 }; wx.navigateTo({ url: '/pages/liaotian/liaotian?data=' + encodeURIComponent(JSON.stringify(param)) }); } async connectToGroupChat(params) { const { identityType, userId, orderId, groupName, groupAvatar, isCross, partnerUid, fadanPingtai, } = params; if (!identityType || !userId || !orderId) { throw new Error('参数不完整'); } app.globalData.currentRole = identityType; wx.setStorageSync('currentRole', identityType); wx.showLoading({ title: '建立联系中...', mask: true }); try { const chatData = await prepareGroupChat( identityType, userId, orderId, partnerUid, fadanPingtai || isCross, groupName, isCross ); const realGroupId = chatData.groupId; let avatar = chatData.counterpartAvatar || chatData.groupAvatar || groupAvatar || ''; if (avatar && !avatar.startsWith('http')) { avatar = app.globalData.ossImageUrl + avatar.replace(/^\//, ''); } if (!app.globalData.groupInfoMap) app.globalData.groupInfoMap = {}; const meta = { name: chatData.counterpartName || chatData.groupName || groupName, avatar, orderId: chatData.orderId || orderId, orderDesc: chatData.orderDesc || '', orderZhuangtai: chatData.orderZhuangtai, dashouGoEasyId: chatData.dashouGoEasyId, partnerGoEasyId: chatData.partnerGoEasyId, dashouYonghuid: chatData.dashouYonghuid, partnerYonghuid: chatData.partnerYonghuid, dashouName: chatData.dashouName, partnerName: chatData.partnerName, dashouAvatar: chatData.dashouAvatar, partnerAvatar: chatData.partnerAvatar, counterpartId: chatData.counterpartId, counterpartYonghuid: chatData.counterpartYonghuid, }; app.globalData.groupInfoMap[realGroupId] = meta; persistGroupMeta(app, realGroupId, meta); let imReady = false; try { await ensureIdentityConnection(identityType, userId); imReady = true; try { await withTimeout( new Promise((resolve, reject) => { wx.goEasy.im.subscribeGroup({ groupIds: [realGroupId], onSuccess: () => resolve(), onFailed: (error) => reject(error), }); }), 8000, '订阅群聊超时' ); } catch (subErr) { console.warn('订阅群聊失败,仍尝试进入页面', subErr); } } catch (imErr) { console.warn('IM连接失败,仍进入聊天页由页面重连', imErr); } const uid = userId.replace(/^(Ds|Sj|Boss)/, ''); const param = { groupId: realGroupId, orderId: chatData.orderId || orderId, groupName: chatData.counterpartName || chatData.groupName || groupName || '订单群聊', groupAvatar: avatar, isCross: chatData.isCross != null ? chatData.isCross : (isCross || 0), currentUserId: userId, currentUserName: app.globalData.currentUser?.name || `用户${uid}`, currentUserAvatar: app.globalData.currentUser?.avatar || (wx.getStorageSync('touxiang') || (app.globalData.ossImageUrl + app.globalData.morentouxiang)), orderZhuangtai: chatData.orderZhuangtai, orderJine: chatData.orderJine, orderDesc: chatData.orderDesc || '', imReady, }; wx.hideLoading(); wx.navigateTo({ url: '/pages/qunliaotian/qunliaotian?data=' + encodeURIComponent(JSON.stringify(param)), fail: (navErr) => { wx.showToast({ title: formatError(navErr), icon: 'none', duration: 2500 }); }, }); } catch (err) { wx.hideLoading(); console.error('跳转群聊失败:', err); wx.showToast({ title: formatError(err), icon: 'none', duration: 2500 }); throw err; } } } export default new ConnectionManager();