修正了 pages 名为拼音的问题
This commit is contained in:
@@ -1,400 +1,400 @@
|
||||
// utils/chat-core.js — 全局 IM 连接、监听、角标(稳定版)
|
||||
import GoEasy from '../static/lib/goeasy-2.13.24.esm.min';
|
||||
import { resolveAvatarUrl } from './avatar.js';
|
||||
import { getLocalImUserId, getLocalImIdentity } from './im-user.js';
|
||||
|
||||
let _convListener = null;
|
||||
let _privateListener = null;
|
||||
let _groupListener = null;
|
||||
let _notificationHandler = null;
|
||||
let _heartbeatTimer = null;
|
||||
let _listenersBoundForUser = null;
|
||||
let _lastGroupSubscribeAt = 0;
|
||||
const _notifiedMessageIds = new Map();
|
||||
const NOTIFY_MAX_AGE_MS = 15000;
|
||||
|
||||
function shouldShowNotification(message) {
|
||||
if (!message) return false;
|
||||
const id = message.messageId || `${message.senderId}_${message.timestamp}`;
|
||||
if (_notifiedMessageIds.has(id)) return false;
|
||||
if (message.timestamp && Date.now() - message.timestamp > NOTIFY_MAX_AGE_MS) return false;
|
||||
_notifiedMessageIds.set(id, Date.now());
|
||||
if (_notifiedMessageIds.size > 400) {
|
||||
const cutoff = Date.now() - 60000;
|
||||
_notifiedMessageIds.forEach((t, k) => {
|
||||
if (t < cutoff) _notifiedMessageIds.delete(k);
|
||||
});
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function bindGlobalListenersIfNeeded(app, userId) {
|
||||
if (_listenersBoundForUser === userId && _convListener) return;
|
||||
registerGlobalListeners(app);
|
||||
registerNotification(app);
|
||||
_listenersBoundForUser = userId;
|
||||
}
|
||||
|
||||
function initGlobalMessageSystem(app) {
|
||||
app.ensureConnection = () => ensureConnection(app);
|
||||
app.connectForCurrentRole = () => ensureConnection(app);
|
||||
app.loadConversations = () => loadConversations(app);
|
||||
app.disconnectGoEasy = () => disconnectGoEasy(app);
|
||||
app.switchRoleAndReconnect = (newRole) => switchRoleAndReconnect(app, newRole);
|
||||
app.updateUnreadCount = (count) => updateTabBarBadge(app, count || 0);
|
||||
app.reregisterNotification = () => registerNotification(app);
|
||||
app.startImWhenReady = () => startImWhenReady(app);
|
||||
|
||||
if (!app.globalData.messageManager) {
|
||||
app.globalData.messageManager = {};
|
||||
}
|
||||
try {
|
||||
const muted = wx.getStorageSync('notificationMuted');
|
||||
if (muted !== undefined) app.globalData.messageManager.notificationMuted = muted;
|
||||
} catch (e) {}
|
||||
|
||||
initAppStateListener(app);
|
||||
initNetworkListener(app);
|
||||
startHeartbeat(app);
|
||||
startImWhenReady(app);
|
||||
}
|
||||
|
||||
/** GoEasy 未就绪时轮询,登录后尽早建立监听 */
|
||||
function startImWhenReady(app, maxAttempts = 40) {
|
||||
let attempts = 0;
|
||||
const tick = () => {
|
||||
if (!wx.getStorageSync('uid')) return;
|
||||
attempts += 1;
|
||||
if (!wx.goEasy) {
|
||||
if (attempts < maxAttempts) setTimeout(tick, 250);
|
||||
return;
|
||||
}
|
||||
ensureConnection(app);
|
||||
};
|
||||
tick();
|
||||
}
|
||||
|
||||
function getCurrentUserId() {
|
||||
return (wx.goEasy && wx.goEasy.im && wx.goEasy.im.userId) || null;
|
||||
}
|
||||
|
||||
function getConnectionStatus() {
|
||||
if (!wx.goEasy || !wx.goEasy.getConnectionStatus) return 'disconnected';
|
||||
return wx.goEasy.getConnectionStatus();
|
||||
}
|
||||
|
||||
function isConnected() {
|
||||
const s = getConnectionStatus();
|
||||
return s === 'connected' || s === 'reconnected';
|
||||
}
|
||||
|
||||
/** 统一会话数据结构,避免不同回调格式导致列表空白 */
|
||||
function normalizeConversationsPayload(result) {
|
||||
if (!result) return { conversations: [], unreadTotal: 0 };
|
||||
const content = result.content || result;
|
||||
const conversations = content.conversations || result.conversations || [];
|
||||
const unreadTotal = content.unreadTotal ?? result.unreadTotal ?? 0;
|
||||
return { conversations, unreadTotal };
|
||||
}
|
||||
|
||||
function emitConversationsUpdated(app, result) {
|
||||
const payload = normalizeConversationsPayload(result);
|
||||
updateTabBarBadge(app, payload.unreadTotal);
|
||||
app.emitEvent('conversationsUpdated', {
|
||||
content: payload,
|
||||
unreadTotal: payload.unreadTotal,
|
||||
raw: result,
|
||||
});
|
||||
}
|
||||
|
||||
async function ensureConnection(app) {
|
||||
const uid = wx.getStorageSync('uid');
|
||||
if (!uid || !wx.goEasy) return;
|
||||
|
||||
const targetUserId = getLocalImUserId(app);
|
||||
const identityType = getLocalImIdentity(app);
|
||||
if (!targetUserId) return;
|
||||
|
||||
if (isConnected()) {
|
||||
const currentUserId = getCurrentUserId();
|
||||
if (currentUserId === targetUserId) {
|
||||
bindGlobalListenersIfNeeded(app, targetUserId);
|
||||
loadConversations(app);
|
||||
const now = Date.now();
|
||||
if (now - _lastGroupSubscribeAt > 60000) {
|
||||
_lastGroupSubscribeAt = now;
|
||||
await subscribeAllGroups(app);
|
||||
}
|
||||
return;
|
||||
}
|
||||
try {
|
||||
wx.goEasy.disconnect();
|
||||
} catch (e) {}
|
||||
}
|
||||
|
||||
connectGoEasy(app, targetUserId, identityType);
|
||||
}
|
||||
|
||||
function connectGoEasy(app, userId, identityType) {
|
||||
const defAvatar = resolveAvatarUrl('', app);
|
||||
const tx = wx.getStorageSync('touxiang') || '';
|
||||
const uid = wx.getStorageSync('uid') || '';
|
||||
const nick = wx.getStorageSync('nicheng') || app.globalData.nicheng || app.globalData.dashouNicheng || '';
|
||||
const name = nick || ('用户' + (uid || '').substring(0, 6));
|
||||
const avatar = resolveAvatarUrl(tx, app) || defAvatar;
|
||||
|
||||
wx.goEasy.connect({
|
||||
id: userId,
|
||||
data: {
|
||||
name,
|
||||
avatar,
|
||||
identityType: identityType === 'normal' ? 'boss' : identityType,
|
||||
},
|
||||
onSuccess: async () => {
|
||||
try {
|
||||
wx.setStorageSync('savedGoEasyConnection', JSON.stringify({
|
||||
userId,
|
||||
identityType,
|
||||
lastConnectTime: Date.now(),
|
||||
status: 'connected',
|
||||
}));
|
||||
} catch (e) {}
|
||||
bindGlobalListenersIfNeeded(app, userId);
|
||||
_lastGroupSubscribeAt = Date.now();
|
||||
await subscribeAllGroups(app);
|
||||
loadConversations(app);
|
||||
},
|
||||
onFailed: (error) => {
|
||||
console.error('GoEasy连接失败', error);
|
||||
if (error.code === 408) {
|
||||
bindGlobalListenersIfNeeded(app, userId);
|
||||
loadConversations(app);
|
||||
} else {
|
||||
wx.showToast({ title: '连接失败,请重试', icon: 'none' });
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
function subscribeAllGroups(app) {
|
||||
return new Promise((resolve) => {
|
||||
if (!wx.goEasy || !wx.goEasy.im) return resolve();
|
||||
wx.goEasy.im.latestConversations({
|
||||
onSuccess: (result) => {
|
||||
const payload = normalizeConversationsPayload(result);
|
||||
const groupIds = payload.conversations
|
||||
.filter((c) => c.type === 'group' && c.groupId)
|
||||
.map((c) => c.groupId);
|
||||
if (groupIds.length && wx.goEasy.im.subscribeGroup) {
|
||||
wx.goEasy.im.subscribeGroup({
|
||||
groupIds,
|
||||
onSuccess: () => resolve(),
|
||||
onFailed: () => resolve(),
|
||||
});
|
||||
} else {
|
||||
resolve();
|
||||
}
|
||||
},
|
||||
onFailed: () => resolve(),
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function registerGlobalListeners(app) {
|
||||
if (!wx.goEasy || !wx.goEasy.im) return;
|
||||
|
||||
if (_convListener) {
|
||||
wx.goEasy.im.off(wx.GoEasy.IM_EVENT.CONVERSATIONS_UPDATED, _convListener);
|
||||
}
|
||||
if (_privateListener) {
|
||||
wx.goEasy.im.off(wx.GoEasy.IM_EVENT.PRIVATE_MESSAGE_RECEIVED, _privateListener);
|
||||
}
|
||||
if (_groupListener) {
|
||||
wx.goEasy.im.off(wx.GoEasy.IM_EVENT.GROUP_MESSAGE_RECEIVED, _groupListener);
|
||||
}
|
||||
|
||||
_convListener = (result) => {
|
||||
emitConversationsUpdated(app, result);
|
||||
};
|
||||
wx.goEasy.im.on(wx.GoEasy.IM_EVENT.CONVERSATIONS_UPDATED, _convListener);
|
||||
|
||||
_privateListener = () => {
|
||||
loadConversations(app);
|
||||
};
|
||||
wx.goEasy.im.on(wx.GoEasy.IM_EVENT.PRIVATE_MESSAGE_RECEIVED, _privateListener);
|
||||
|
||||
_groupListener = () => {
|
||||
loadConversations(app);
|
||||
};
|
||||
wx.goEasy.im.on(wx.GoEasy.IM_EVENT.GROUP_MESSAGE_RECEIVED, _groupListener);
|
||||
}
|
||||
|
||||
function loadConversations(app) {
|
||||
if (!wx.goEasy || !wx.goEasy.im) return;
|
||||
if (!getCurrentUserId()) return;
|
||||
|
||||
wx.goEasy.im.latestConversations({
|
||||
onSuccess: (result) => {
|
||||
emitConversationsUpdated(app, result);
|
||||
subscribeAllGroups(app);
|
||||
},
|
||||
onFailed: (err) => {
|
||||
console.error('加载会话失败', err);
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
function updateTabBarBadge(app, unreadCount) {
|
||||
const badgeText = unreadCount > 0 ? (unreadCount > 99 ? '99+' : String(unreadCount)) : '';
|
||||
if (!app.globalData.messageManager) app.globalData.messageManager = {};
|
||||
app.globalData.messageManager.unreadTotal = unreadCount;
|
||||
app.globalData.messageManager.tabBarBadgeText = badgeText;
|
||||
app.emitEvent('tabBarBadgeChanged', { badgeText, showRedDot: unreadCount > 0 });
|
||||
|
||||
try {
|
||||
const pages = getCurrentPages();
|
||||
if (pages.length) {
|
||||
const page = pages[pages.length - 1];
|
||||
const tabBar = page.selectComponent('#custom-tab-bar');
|
||||
if (tabBar && tabBar.setData) tabBar.setData({ badgeText });
|
||||
if (page.getTabBar) {
|
||||
const tb = page.getTabBar();
|
||||
if (tb && tb.setData) tb.setData({ badgeText });
|
||||
}
|
||||
}
|
||||
} catch (e) {}
|
||||
wx.setStorageSync('messageUnreadTotal', unreadCount);
|
||||
}
|
||||
|
||||
function registerNotification(app) {
|
||||
if (!wx.goEasy || !wx.goEasy.im) return;
|
||||
|
||||
if (_notificationHandler) {
|
||||
wx.goEasy.im.off(wx.GoEasy.IM_EVENT.PRIVATE_MESSAGE_RECEIVED, _notificationHandler);
|
||||
wx.goEasy.im.off(wx.GoEasy.IM_EVENT.GROUP_MESSAGE_RECEIVED, _notificationHandler);
|
||||
}
|
||||
|
||||
_notificationHandler = (message) => {
|
||||
if (app.globalData.messageManager && app.globalData.messageManager.notificationMuted) return;
|
||||
if (!shouldShowNotification(message)) return;
|
||||
const pages = getCurrentPages();
|
||||
if (pages.length) {
|
||||
const curPage = pages[pages.length - 1];
|
||||
const route = curPage.route || '';
|
||||
if (route === 'pages/liaotian/liaotian' || route === 'pages/qunliaotian/qunliaotian') return;
|
||||
}
|
||||
const senderName = message.senderData?.name || (message.senderId || '用户');
|
||||
let content = '';
|
||||
if (message.type === 'text') content = message.payload?.text || '[文本]';
|
||||
else if (message.type === 'image') content = '[图片]';
|
||||
else if (message.type === 'audio') content = '[语音]';
|
||||
else content = '[新消息]';
|
||||
const avatar = resolveAvatarUrl(message.senderData?.avatar, app);
|
||||
|
||||
if (app.globalData.globalNotification && app.globalData.globalNotification.show) {
|
||||
app.globalData.globalNotification.show({
|
||||
senderName,
|
||||
content,
|
||||
avatar,
|
||||
message,
|
||||
notificationType: message.groupId ? 'group' : 'private',
|
||||
groupId: message.groupId,
|
||||
orderId: message.orderId,
|
||||
});
|
||||
} else {
|
||||
wx.showToast({ title: `${senderName}: ${content}`, icon: 'none', duration: 2000 });
|
||||
}
|
||||
};
|
||||
wx.goEasy.im.on(wx.GoEasy.IM_EVENT.PRIVATE_MESSAGE_RECEIVED, _notificationHandler);
|
||||
wx.goEasy.im.on(wx.GoEasy.IM_EVENT.GROUP_MESSAGE_RECEIVED, _notificationHandler);
|
||||
}
|
||||
|
||||
function detachGlobalListeners() {
|
||||
if (!wx.goEasy || !wx.goEasy.im) return;
|
||||
if (_convListener) {
|
||||
wx.goEasy.im.off(wx.GoEasy.IM_EVENT.CONVERSATIONS_UPDATED, _convListener);
|
||||
_convListener = null;
|
||||
}
|
||||
if (_privateListener) {
|
||||
wx.goEasy.im.off(wx.GoEasy.IM_EVENT.PRIVATE_MESSAGE_RECEIVED, _privateListener);
|
||||
_privateListener = null;
|
||||
}
|
||||
if (_groupListener) {
|
||||
wx.goEasy.im.off(wx.GoEasy.IM_EVENT.GROUP_MESSAGE_RECEIVED, _groupListener);
|
||||
_groupListener = null;
|
||||
}
|
||||
if (_notificationHandler) {
|
||||
wx.goEasy.im.off(wx.GoEasy.IM_EVENT.PRIVATE_MESSAGE_RECEIVED, _notificationHandler);
|
||||
wx.goEasy.im.off(wx.GoEasy.IM_EVENT.GROUP_MESSAGE_RECEIVED, _notificationHandler);
|
||||
_notificationHandler = null;
|
||||
}
|
||||
_listenersBoundForUser = null;
|
||||
}
|
||||
|
||||
function disconnectGoEasy(app) {
|
||||
stopHeartbeat(app);
|
||||
detachGlobalListeners();
|
||||
if (wx.goEasy && wx.goEasy.disconnect) {
|
||||
wx.goEasy.disconnect({ onSuccess: () => {}, onFailed: () => {} });
|
||||
}
|
||||
wx.removeStorageSync('savedGoEasyConnection');
|
||||
}
|
||||
|
||||
async function switchRoleAndReconnect(app, newRole) {
|
||||
disconnectGoEasy(app);
|
||||
app.globalData.currentRole = newRole;
|
||||
wx.setStorageSync('currentRole', newRole);
|
||||
if (app.globalData.primaryRole !== newRole && ['normal', 'dashou', 'shangjia'].includes(newRole)) {
|
||||
app.globalData.primaryRole = newRole;
|
||||
wx.setStorageSync('primaryRole', newRole);
|
||||
}
|
||||
startHeartbeat(app);
|
||||
await ensureConnection(app);
|
||||
return true;
|
||||
}
|
||||
|
||||
function startHeartbeat(app) {
|
||||
stopHeartbeat(app);
|
||||
_heartbeatTimer = setInterval(() => {
|
||||
if (!wx.getStorageSync('uid')) return;
|
||||
if (isConnected()) {
|
||||
loadConversations(app);
|
||||
} else {
|
||||
ensureConnection(app);
|
||||
}
|
||||
}, 45000);
|
||||
}
|
||||
|
||||
function stopHeartbeat(app) {
|
||||
if (_heartbeatTimer) {
|
||||
clearInterval(_heartbeatTimer);
|
||||
_heartbeatTimer = null;
|
||||
}
|
||||
}
|
||||
|
||||
function initAppStateListener(app) {
|
||||
wx.onAppShow(() => {
|
||||
setTimeout(() => {
|
||||
if (!wx.getStorageSync('uid')) return;
|
||||
if (!isConnected()) {
|
||||
ensureConnection(app);
|
||||
} else {
|
||||
loadConversations(app);
|
||||
setTimeout(() => {
|
||||
const unread = (app.globalData.messageManager && app.globalData.messageManager.unreadTotal) || 0;
|
||||
updateTabBarBadge(app, unread);
|
||||
}, 300);
|
||||
}
|
||||
}, 200);
|
||||
});
|
||||
}
|
||||
|
||||
function initNetworkListener(app) {
|
||||
wx.onNetworkStatusChange((res) => {
|
||||
if (res.isConnected) {
|
||||
setTimeout(() => ensureConnection(app), 1000);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = { initGlobalMessageSystem };
|
||||
// utils/chat-core.js — 全局 IM 连接、监听、角标(稳定版)
|
||||
import GoEasy from '../static/lib/goeasy-2.13.24.esm.min';
|
||||
import { resolveAvatarUrl } from './avatar.js';
|
||||
import { getLocalImUserId, getLocalImIdentity } from './im-user.js';
|
||||
|
||||
let _convListener = null;
|
||||
let _privateListener = null;
|
||||
let _groupListener = null;
|
||||
let _notificationHandler = null;
|
||||
let _heartbeatTimer = null;
|
||||
let _listenersBoundForUser = null;
|
||||
let _lastGroupSubscribeAt = 0;
|
||||
const _notifiedMessageIds = new Map();
|
||||
const NOTIFY_MAX_AGE_MS = 15000;
|
||||
|
||||
function shouldShowNotification(message) {
|
||||
if (!message) return false;
|
||||
const id = message.messageId || `${message.senderId}_${message.timestamp}`;
|
||||
if (_notifiedMessageIds.has(id)) return false;
|
||||
if (message.timestamp && Date.now() - message.timestamp > NOTIFY_MAX_AGE_MS) return false;
|
||||
_notifiedMessageIds.set(id, Date.now());
|
||||
if (_notifiedMessageIds.size > 400) {
|
||||
const cutoff = Date.now() - 60000;
|
||||
_notifiedMessageIds.forEach((t, k) => {
|
||||
if (t < cutoff) _notifiedMessageIds.delete(k);
|
||||
});
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function bindGlobalListenersIfNeeded(app, userId) {
|
||||
if (_listenersBoundForUser === userId && _convListener) return;
|
||||
registerGlobalListeners(app);
|
||||
registerNotification(app);
|
||||
_listenersBoundForUser = userId;
|
||||
}
|
||||
|
||||
function initGlobalMessageSystem(app) {
|
||||
app.ensureConnection = () => ensureConnection(app);
|
||||
app.connectForCurrentRole = () => ensureConnection(app);
|
||||
app.loadConversations = () => loadConversations(app);
|
||||
app.disconnectGoEasy = () => disconnectGoEasy(app);
|
||||
app.switchRoleAndReconnect = (newRole) => switchRoleAndReconnect(app, newRole);
|
||||
app.updateUnreadCount = (count) => updateTabBarBadge(app, count || 0);
|
||||
app.reregisterNotification = () => registerNotification(app);
|
||||
app.startImWhenReady = () => startImWhenReady(app);
|
||||
|
||||
if (!app.globalData.messageManager) {
|
||||
app.globalData.messageManager = {};
|
||||
}
|
||||
try {
|
||||
const muted = wx.getStorageSync('notificationMuted');
|
||||
if (muted !== undefined) app.globalData.messageManager.notificationMuted = muted;
|
||||
} catch (e) {}
|
||||
|
||||
initAppStateListener(app);
|
||||
initNetworkListener(app);
|
||||
startHeartbeat(app);
|
||||
startImWhenReady(app);
|
||||
}
|
||||
|
||||
/** GoEasy 未就绪时轮询,登录后尽早建立监听 */
|
||||
function startImWhenReady(app, maxAttempts = 40) {
|
||||
let attempts = 0;
|
||||
const tick = () => {
|
||||
if (!wx.getStorageSync('uid')) return;
|
||||
attempts += 1;
|
||||
if (!wx.goEasy) {
|
||||
if (attempts < maxAttempts) setTimeout(tick, 250);
|
||||
return;
|
||||
}
|
||||
ensureConnection(app);
|
||||
};
|
||||
tick();
|
||||
}
|
||||
|
||||
function getCurrentUserId() {
|
||||
return (wx.goEasy && wx.goEasy.im && wx.goEasy.im.userId) || null;
|
||||
}
|
||||
|
||||
function getConnectionStatus() {
|
||||
if (!wx.goEasy || !wx.goEasy.getConnectionStatus) return 'disconnected';
|
||||
return wx.goEasy.getConnectionStatus();
|
||||
}
|
||||
|
||||
function isConnected() {
|
||||
const s = getConnectionStatus();
|
||||
return s === 'connected' || s === 'reconnected';
|
||||
}
|
||||
|
||||
/** 统一会话数据结构,避免不同回调格式导致列表空白 */
|
||||
function normalizeConversationsPayload(result) {
|
||||
if (!result) return { conversations: [], unreadTotal: 0 };
|
||||
const content = result.content || result;
|
||||
const conversations = content.conversations || result.conversations || [];
|
||||
const unreadTotal = content.unreadTotal ?? result.unreadTotal ?? 0;
|
||||
return { conversations, unreadTotal };
|
||||
}
|
||||
|
||||
function emitConversationsUpdated(app, result) {
|
||||
const payload = normalizeConversationsPayload(result);
|
||||
updateTabBarBadge(app, payload.unreadTotal);
|
||||
app.emitEvent('conversationsUpdated', {
|
||||
content: payload,
|
||||
unreadTotal: payload.unreadTotal,
|
||||
raw: result,
|
||||
});
|
||||
}
|
||||
|
||||
async function ensureConnection(app) {
|
||||
const uid = wx.getStorageSync('uid');
|
||||
if (!uid || !wx.goEasy) return;
|
||||
|
||||
const targetUserId = getLocalImUserId(app);
|
||||
const identityType = getLocalImIdentity(app);
|
||||
if (!targetUserId) return;
|
||||
|
||||
if (isConnected()) {
|
||||
const currentUserId = getCurrentUserId();
|
||||
if (currentUserId === targetUserId) {
|
||||
bindGlobalListenersIfNeeded(app, targetUserId);
|
||||
loadConversations(app);
|
||||
const now = Date.now();
|
||||
if (now - _lastGroupSubscribeAt > 60000) {
|
||||
_lastGroupSubscribeAt = now;
|
||||
await subscribeAllGroups(app);
|
||||
}
|
||||
return;
|
||||
}
|
||||
try {
|
||||
wx.goEasy.disconnect();
|
||||
} catch (e) {}
|
||||
}
|
||||
|
||||
connectGoEasy(app, targetUserId, identityType);
|
||||
}
|
||||
|
||||
function connectGoEasy(app, userId, identityType) {
|
||||
const defAvatar = resolveAvatarUrl('', app);
|
||||
const tx = wx.getStorageSync('touxiang') || '';
|
||||
const uid = wx.getStorageSync('uid') || '';
|
||||
const nick = wx.getStorageSync('nicheng') || app.globalData.nicheng || app.globalData.dashouNicheng || '';
|
||||
const name = nick || ('用户' + (uid || '').substring(0, 6));
|
||||
const avatar = resolveAvatarUrl(tx, app) || defAvatar;
|
||||
|
||||
wx.goEasy.connect({
|
||||
id: userId,
|
||||
data: {
|
||||
name,
|
||||
avatar,
|
||||
identityType: identityType === 'normal' ? 'boss' : identityType,
|
||||
},
|
||||
onSuccess: async () => {
|
||||
try {
|
||||
wx.setStorageSync('savedGoEasyConnection', JSON.stringify({
|
||||
userId,
|
||||
identityType,
|
||||
lastConnectTime: Date.now(),
|
||||
status: 'connected',
|
||||
}));
|
||||
} catch (e) {}
|
||||
bindGlobalListenersIfNeeded(app, userId);
|
||||
_lastGroupSubscribeAt = Date.now();
|
||||
await subscribeAllGroups(app);
|
||||
loadConversations(app);
|
||||
},
|
||||
onFailed: (error) => {
|
||||
console.error('GoEasy连接失败', error);
|
||||
if (error.code === 408) {
|
||||
bindGlobalListenersIfNeeded(app, userId);
|
||||
loadConversations(app);
|
||||
} else {
|
||||
wx.showToast({ title: '连接失败,请重试', icon: 'none' });
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
function subscribeAllGroups(app) {
|
||||
return new Promise((resolve) => {
|
||||
if (!wx.goEasy || !wx.goEasy.im) return resolve();
|
||||
wx.goEasy.im.latestConversations({
|
||||
onSuccess: (result) => {
|
||||
const payload = normalizeConversationsPayload(result);
|
||||
const groupIds = payload.conversations
|
||||
.filter((c) => c.type === 'group' && c.groupId)
|
||||
.map((c) => c.groupId);
|
||||
if (groupIds.length && wx.goEasy.im.subscribeGroup) {
|
||||
wx.goEasy.im.subscribeGroup({
|
||||
groupIds,
|
||||
onSuccess: () => resolve(),
|
||||
onFailed: () => resolve(),
|
||||
});
|
||||
} else {
|
||||
resolve();
|
||||
}
|
||||
},
|
||||
onFailed: () => resolve(),
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function registerGlobalListeners(app) {
|
||||
if (!wx.goEasy || !wx.goEasy.im) return;
|
||||
|
||||
if (_convListener) {
|
||||
wx.goEasy.im.off(wx.GoEasy.IM_EVENT.CONVERSATIONS_UPDATED, _convListener);
|
||||
}
|
||||
if (_privateListener) {
|
||||
wx.goEasy.im.off(wx.GoEasy.IM_EVENT.PRIVATE_MESSAGE_RECEIVED, _privateListener);
|
||||
}
|
||||
if (_groupListener) {
|
||||
wx.goEasy.im.off(wx.GoEasy.IM_EVENT.GROUP_MESSAGE_RECEIVED, _groupListener);
|
||||
}
|
||||
|
||||
_convListener = (result) => {
|
||||
emitConversationsUpdated(app, result);
|
||||
};
|
||||
wx.goEasy.im.on(wx.GoEasy.IM_EVENT.CONVERSATIONS_UPDATED, _convListener);
|
||||
|
||||
_privateListener = () => {
|
||||
loadConversations(app);
|
||||
};
|
||||
wx.goEasy.im.on(wx.GoEasy.IM_EVENT.PRIVATE_MESSAGE_RECEIVED, _privateListener);
|
||||
|
||||
_groupListener = () => {
|
||||
loadConversations(app);
|
||||
};
|
||||
wx.goEasy.im.on(wx.GoEasy.IM_EVENT.GROUP_MESSAGE_RECEIVED, _groupListener);
|
||||
}
|
||||
|
||||
function loadConversations(app) {
|
||||
if (!wx.goEasy || !wx.goEasy.im) return;
|
||||
if (!getCurrentUserId()) return;
|
||||
|
||||
wx.goEasy.im.latestConversations({
|
||||
onSuccess: (result) => {
|
||||
emitConversationsUpdated(app, result);
|
||||
subscribeAllGroups(app);
|
||||
},
|
||||
onFailed: (err) => {
|
||||
console.error('加载会话失败', err);
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
function updateTabBarBadge(app, unreadCount) {
|
||||
const badgeText = unreadCount > 0 ? (unreadCount > 99 ? '99+' : String(unreadCount)) : '';
|
||||
if (!app.globalData.messageManager) app.globalData.messageManager = {};
|
||||
app.globalData.messageManager.unreadTotal = unreadCount;
|
||||
app.globalData.messageManager.tabBarBadgeText = badgeText;
|
||||
app.emitEvent('tabBarBadgeChanged', { badgeText, showRedDot: unreadCount > 0 });
|
||||
|
||||
try {
|
||||
const pages = getCurrentPages();
|
||||
if (pages.length) {
|
||||
const page = pages[pages.length - 1];
|
||||
const tabBar = page.selectComponent('#custom-tab-bar');
|
||||
if (tabBar && tabBar.setData) tabBar.setData({ badgeText });
|
||||
if (page.getTabBar) {
|
||||
const tb = page.getTabBar();
|
||||
if (tb && tb.setData) tb.setData({ badgeText });
|
||||
}
|
||||
}
|
||||
} catch (e) {}
|
||||
wx.setStorageSync('messageUnreadTotal', unreadCount);
|
||||
}
|
||||
|
||||
function registerNotification(app) {
|
||||
if (!wx.goEasy || !wx.goEasy.im) return;
|
||||
|
||||
if (_notificationHandler) {
|
||||
wx.goEasy.im.off(wx.GoEasy.IM_EVENT.PRIVATE_MESSAGE_RECEIVED, _notificationHandler);
|
||||
wx.goEasy.im.off(wx.GoEasy.IM_EVENT.GROUP_MESSAGE_RECEIVED, _notificationHandler);
|
||||
}
|
||||
|
||||
_notificationHandler = (message) => {
|
||||
if (app.globalData.messageManager && app.globalData.messageManager.notificationMuted) return;
|
||||
if (!shouldShowNotification(message)) return;
|
||||
const pages = getCurrentPages();
|
||||
if (pages.length) {
|
||||
const curPage = pages[pages.length - 1];
|
||||
const route = curPage.route || '';
|
||||
if (route === 'pages/chat/chat' || route === 'pages/group-chat/group-chat') return;
|
||||
}
|
||||
const senderName = message.senderData?.name || (message.senderId || '用户');
|
||||
let content = '';
|
||||
if (message.type === 'text') content = message.payload?.text || '[文本]';
|
||||
else if (message.type === 'image') content = '[图片]';
|
||||
else if (message.type === 'audio') content = '[语音]';
|
||||
else content = '[新消息]';
|
||||
const avatar = resolveAvatarUrl(message.senderData?.avatar, app);
|
||||
|
||||
if (app.globalData.globalNotification && app.globalData.globalNotification.show) {
|
||||
app.globalData.globalNotification.show({
|
||||
senderName,
|
||||
content,
|
||||
avatar,
|
||||
message,
|
||||
notificationType: message.groupId ? 'group' : 'private',
|
||||
groupId: message.groupId,
|
||||
orderId: message.orderId,
|
||||
});
|
||||
} else {
|
||||
wx.showToast({ title: `${senderName}: ${content}`, icon: 'none', duration: 2000 });
|
||||
}
|
||||
};
|
||||
wx.goEasy.im.on(wx.GoEasy.IM_EVENT.PRIVATE_MESSAGE_RECEIVED, _notificationHandler);
|
||||
wx.goEasy.im.on(wx.GoEasy.IM_EVENT.GROUP_MESSAGE_RECEIVED, _notificationHandler);
|
||||
}
|
||||
|
||||
function detachGlobalListeners() {
|
||||
if (!wx.goEasy || !wx.goEasy.im) return;
|
||||
if (_convListener) {
|
||||
wx.goEasy.im.off(wx.GoEasy.IM_EVENT.CONVERSATIONS_UPDATED, _convListener);
|
||||
_convListener = null;
|
||||
}
|
||||
if (_privateListener) {
|
||||
wx.goEasy.im.off(wx.GoEasy.IM_EVENT.PRIVATE_MESSAGE_RECEIVED, _privateListener);
|
||||
_privateListener = null;
|
||||
}
|
||||
if (_groupListener) {
|
||||
wx.goEasy.im.off(wx.GoEasy.IM_EVENT.GROUP_MESSAGE_RECEIVED, _groupListener);
|
||||
_groupListener = null;
|
||||
}
|
||||
if (_notificationHandler) {
|
||||
wx.goEasy.im.off(wx.GoEasy.IM_EVENT.PRIVATE_MESSAGE_RECEIVED, _notificationHandler);
|
||||
wx.goEasy.im.off(wx.GoEasy.IM_EVENT.GROUP_MESSAGE_RECEIVED, _notificationHandler);
|
||||
_notificationHandler = null;
|
||||
}
|
||||
_listenersBoundForUser = null;
|
||||
}
|
||||
|
||||
function disconnectGoEasy(app) {
|
||||
stopHeartbeat(app);
|
||||
detachGlobalListeners();
|
||||
if (wx.goEasy && wx.goEasy.disconnect) {
|
||||
wx.goEasy.disconnect({ onSuccess: () => {}, onFailed: () => {} });
|
||||
}
|
||||
wx.removeStorageSync('savedGoEasyConnection');
|
||||
}
|
||||
|
||||
async function switchRoleAndReconnect(app, newRole) {
|
||||
disconnectGoEasy(app);
|
||||
app.globalData.currentRole = newRole;
|
||||
wx.setStorageSync('currentRole', newRole);
|
||||
if (app.globalData.primaryRole !== newRole && ['normal', 'dashou', 'shangjia'].includes(newRole)) {
|
||||
app.globalData.primaryRole = newRole;
|
||||
wx.setStorageSync('primaryRole', newRole);
|
||||
}
|
||||
startHeartbeat(app);
|
||||
await ensureConnection(app);
|
||||
return true;
|
||||
}
|
||||
|
||||
function startHeartbeat(app) {
|
||||
stopHeartbeat(app);
|
||||
_heartbeatTimer = setInterval(() => {
|
||||
if (!wx.getStorageSync('uid')) return;
|
||||
if (isConnected()) {
|
||||
loadConversations(app);
|
||||
} else {
|
||||
ensureConnection(app);
|
||||
}
|
||||
}, 45000);
|
||||
}
|
||||
|
||||
function stopHeartbeat(app) {
|
||||
if (_heartbeatTimer) {
|
||||
clearInterval(_heartbeatTimer);
|
||||
_heartbeatTimer = null;
|
||||
}
|
||||
}
|
||||
|
||||
function initAppStateListener(app) {
|
||||
wx.onAppShow(() => {
|
||||
setTimeout(() => {
|
||||
if (!wx.getStorageSync('uid')) return;
|
||||
if (!isConnected()) {
|
||||
ensureConnection(app);
|
||||
} else {
|
||||
loadConversations(app);
|
||||
setTimeout(() => {
|
||||
const unread = (app.globalData.messageManager && app.globalData.messageManager.unreadTotal) || 0;
|
||||
updateTabBarBadge(app, unread);
|
||||
}, 300);
|
||||
}
|
||||
}, 200);
|
||||
});
|
||||
}
|
||||
|
||||
function initNetworkListener(app) {
|
||||
wx.onNetworkStatusChange((res) => {
|
||||
if (res.isConnected) {
|
||||
setTimeout(() => ensureConnection(app), 1000);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = { initGlobalMessageSystem };
|
||||
|
||||
156
utils/im-user.js
156
utils/im-user.js
@@ -1,78 +1,78 @@
|
||||
/** IM 用户 ID:三端连接 + 管事/组长/考核官统一走打手 Ds 前缀 */
|
||||
import { getPrimaryRole } from './primary-role.js';
|
||||
import { resolveAvatarUrl } from './avatar.js';
|
||||
import { ensureRoleOnCenterPage } from './role-tab-bar.js';
|
||||
|
||||
/** 联系对象前缀:管事/组长/考核官已废弃独立前缀,统一 Ds */
|
||||
const PEER_PREFIX = {
|
||||
boss: 'Boss',
|
||||
normal: 'Boss',
|
||||
dashou: 'Ds',
|
||||
shangjia: 'Sj',
|
||||
guanshi: 'Ds',
|
||||
zuzhang: 'Ds',
|
||||
kaoheguan: 'Ds',
|
||||
};
|
||||
|
||||
export function getImPrefixForRole(role) {
|
||||
return PEER_PREFIX[role] || 'Ds';
|
||||
}
|
||||
|
||||
/** 当前端连接 GoEasy 用的 userId */
|
||||
export function getLocalImUserId(app) {
|
||||
app = app || getApp();
|
||||
const uid = wx.getStorageSync('uid') || '';
|
||||
if (!uid) return '';
|
||||
const primary = getPrimaryRole(app);
|
||||
if (primary === 'dashou') return 'Ds' + uid;
|
||||
if (primary === 'shangjia') return 'Sj' + uid;
|
||||
return 'Boss' + uid;
|
||||
}
|
||||
|
||||
export function getLocalImIdentity(app) {
|
||||
app = app || getApp();
|
||||
return getPrimaryRole(app) || 'normal';
|
||||
}
|
||||
|
||||
export function buildPeerImUserId(uid, role = 'dashou') {
|
||||
if (!uid) return '';
|
||||
return getImPrefixForRole(role) + uid;
|
||||
}
|
||||
|
||||
/** 联系邀请人/管事/组长:统一 Ds 前缀 */
|
||||
export function buildGuanshiPeerId(uid) {
|
||||
return buildDashouPeerId(uid);
|
||||
}
|
||||
|
||||
export function buildDashouPeerId(uid) {
|
||||
return buildPeerImUserId(uid, 'dashou');
|
||||
}
|
||||
|
||||
export function buildInviterPeerId(uid) {
|
||||
return buildDashouPeerId(uid);
|
||||
}
|
||||
|
||||
export function ensureDashouImReady(page) {
|
||||
const app = getApp();
|
||||
ensureRoleOnCenterPage(page, 'dashou');
|
||||
if (app.ensureConnection) app.ensureConnection();
|
||||
}
|
||||
|
||||
export function openPrivateChat(page, { toUserId, toName, toAvatar, delay = 350 }) {
|
||||
ensureDashouImReady(page);
|
||||
const avatar = resolveAvatarUrl(toAvatar);
|
||||
const param = {
|
||||
toUserId,
|
||||
toName: toName || '用户',
|
||||
toAvatar: avatar,
|
||||
};
|
||||
return new Promise((resolve) => {
|
||||
setTimeout(() => {
|
||||
wx.navigateTo({
|
||||
url: '/pages/liaotian/liaotian?data=' + encodeURIComponent(JSON.stringify(param)),
|
||||
fail: () => wx.showToast({ title: '打开聊天失败', icon: 'none' }),
|
||||
complete: resolve,
|
||||
});
|
||||
}, delay);
|
||||
});
|
||||
}
|
||||
/** IM 用户 ID:三端连接 + 管事/组长/考核官统一走打手 Ds 前缀 */
|
||||
import { getPrimaryRole } from './primary-role.js';
|
||||
import { resolveAvatarUrl } from './avatar.js';
|
||||
import { ensureRoleOnCenterPage } from './role-tab-bar.js';
|
||||
|
||||
/** 联系对象前缀:管事/组长/考核官已废弃独立前缀,统一 Ds */
|
||||
const PEER_PREFIX = {
|
||||
boss: 'Boss',
|
||||
normal: 'Boss',
|
||||
dashou: 'Ds',
|
||||
shangjia: 'Sj',
|
||||
guanshi: 'Ds',
|
||||
zuzhang: 'Ds',
|
||||
kaoheguan: 'Ds',
|
||||
};
|
||||
|
||||
export function getImPrefixForRole(role) {
|
||||
return PEER_PREFIX[role] || 'Ds';
|
||||
}
|
||||
|
||||
/** 当前端连接 GoEasy 用的 userId */
|
||||
export function getLocalImUserId(app) {
|
||||
app = app || getApp();
|
||||
const uid = wx.getStorageSync('uid') || '';
|
||||
if (!uid) return '';
|
||||
const primary = getPrimaryRole(app);
|
||||
if (primary === 'dashou') return 'Ds' + uid;
|
||||
if (primary === 'shangjia') return 'Sj' + uid;
|
||||
return 'Boss' + uid;
|
||||
}
|
||||
|
||||
export function getLocalImIdentity(app) {
|
||||
app = app || getApp();
|
||||
return getPrimaryRole(app) || 'normal';
|
||||
}
|
||||
|
||||
export function buildPeerImUserId(uid, role = 'dashou') {
|
||||
if (!uid) return '';
|
||||
return getImPrefixForRole(role) + uid;
|
||||
}
|
||||
|
||||
/** 联系邀请人/管事/组长:统一 Ds 前缀 */
|
||||
export function buildGuanshiPeerId(uid) {
|
||||
return buildDashouPeerId(uid);
|
||||
}
|
||||
|
||||
export function buildDashouPeerId(uid) {
|
||||
return buildPeerImUserId(uid, 'dashou');
|
||||
}
|
||||
|
||||
export function buildInviterPeerId(uid) {
|
||||
return buildDashouPeerId(uid);
|
||||
}
|
||||
|
||||
export function ensureDashouImReady(page) {
|
||||
const app = getApp();
|
||||
ensureRoleOnCenterPage(page, 'dashou');
|
||||
if (app.ensureConnection) app.ensureConnection();
|
||||
}
|
||||
|
||||
export function openPrivateChat(page, { toUserId, toName, toAvatar, delay = 350 }) {
|
||||
ensureDashouImReady(page);
|
||||
const avatar = resolveAvatarUrl(toAvatar);
|
||||
const param = {
|
||||
toUserId,
|
||||
toName: toName || '用户',
|
||||
toAvatar: avatar,
|
||||
};
|
||||
return new Promise((resolve) => {
|
||||
setTimeout(() => {
|
||||
wx.navigateTo({
|
||||
url: '/pages/chat/chat?data=' + encodeURIComponent(JSON.stringify(param)),
|
||||
fail: () => wx.showToast({ title: '打开聊天失败', icon: 'none' }),
|
||||
complete: resolve,
|
||||
});
|
||||
}, delay);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,105 +1,105 @@
|
||||
/** 三端固定:normal | dashou | shangjia,认证后不可回退 */
|
||||
|
||||
const VALID = ['normal', 'dashou', 'shangjia'];
|
||||
const LEGACY_CENTER_ROLES = ['guanshi', 'zuzhang', 'kaoheguan'];
|
||||
|
||||
/** 旧版管事/组长/考核官主端标识 → 统一回落打手 Tab */
|
||||
export function migrateLegacyCenterRole(app) {
|
||||
app = app || getApp();
|
||||
const cur = wx.getStorageSync('currentRole') || app.globalData.currentRole || '';
|
||||
const pri = wx.getStorageSync('primaryRole') || '';
|
||||
const isLegacy = LEGACY_CENTER_ROLES.includes(cur) || LEGACY_CENTER_ROLES.includes(pri);
|
||||
if (!isLegacy) return false;
|
||||
|
||||
const hasDashouSide =
|
||||
isRoleStatusActive(wx.getStorageSync('dashoustatus'))
|
||||
|| isRoleStatusActive(wx.getStorageSync('guanshistatus'))
|
||||
|| isRoleStatusActive(wx.getStorageSync('zuzhangstatus'))
|
||||
|| isRoleStatusActive(wx.getStorageSync('kaoheguanstatus'));
|
||||
|
||||
if (hasDashouSide) {
|
||||
lockPrimaryRole('dashou', app);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
export function isRoleStatusActive(status) {
|
||||
return Number(status) === 1;
|
||||
}
|
||||
|
||||
/** 读取主端(兼容旧 currentRole / 管事组长落地页) */
|
||||
export function getPrimaryRole(app) {
|
||||
app = app || getApp();
|
||||
const stored = wx.getStorageSync('primaryRole');
|
||||
if (VALID.includes(stored)) {
|
||||
return stored;
|
||||
}
|
||||
const legacy = wx.getStorageSync('currentRole') || app.globalData.currentRole || 'normal';
|
||||
if (legacy === 'dashou' || legacy === 'shangjia') {
|
||||
return legacy;
|
||||
}
|
||||
if (legacy === 'guanshi' || legacy === 'zuzhang' || legacy === 'kaoheguan') {
|
||||
if (isRoleStatusActive(wx.getStorageSync('dashoustatus'))) {
|
||||
return 'dashou';
|
||||
}
|
||||
if (isRoleStatusActive(wx.getStorageSync('shangjiastatus'))) {
|
||||
return 'shangjia';
|
||||
}
|
||||
}
|
||||
if (isRoleStatusActive(wx.getStorageSync('dashoustatus'))) {
|
||||
return 'dashou';
|
||||
}
|
||||
if (isRoleStatusActive(wx.getStorageSync('shangjiastatus'))) {
|
||||
return 'shangjia';
|
||||
}
|
||||
return 'normal';
|
||||
}
|
||||
|
||||
/** 锁定主端并同步 TabBar 角色 */
|
||||
export function lockPrimaryRole(role, app) {
|
||||
if (!VALID.includes(role)) return;
|
||||
app = app || getApp();
|
||||
wx.setStorageSync('primaryRole', role);
|
||||
wx.setStorageSync('currentRole', role);
|
||||
app.globalData.primaryRole = role;
|
||||
app.globalData.currentRole = role;
|
||||
if (app.emitEvent) {
|
||||
app.emitEvent('currentRoleChanged', { role });
|
||||
}
|
||||
}
|
||||
|
||||
/** TabBar / IM 使用的有效角色(仅三端) */
|
||||
export function getTabRole(app) {
|
||||
return getPrimaryRole(app);
|
||||
}
|
||||
|
||||
export function clearPrimaryRole(app) {
|
||||
app = app || getApp();
|
||||
wx.removeStorageSync('primaryRole');
|
||||
lockPrimaryRole('normal', app);
|
||||
}
|
||||
|
||||
export const PRIMARY_DEFAULT_PAGES = {
|
||||
normal: '/pages/wode/wode',
|
||||
dashou: '/pages/jiedan/jiedan',
|
||||
shangjia: '/pages/sjdingdan/sjdingdan',
|
||||
};
|
||||
|
||||
/** 锁定主端并跳转到该端默认首页,同时建立 IM 长连接 */
|
||||
export function enterLockedRole(role, app) {
|
||||
if (!VALID.includes(role) || role === 'normal') return false;
|
||||
app = app || getApp();
|
||||
lockPrimaryRole(role, app);
|
||||
wx.reLaunch({ url: PRIMARY_DEFAULT_PAGES[role] });
|
||||
setTimeout(() => {
|
||||
if (app.switchRoleAndReconnect) {
|
||||
app.switchRoleAndReconnect(role).catch(() => {
|
||||
if (app.connectForCurrentRole) app.connectForCurrentRole();
|
||||
});
|
||||
} else if (app.connectForCurrentRole) {
|
||||
app.connectForCurrentRole();
|
||||
}
|
||||
}, 600);
|
||||
return true;
|
||||
}
|
||||
/** 三端固定:normal | dashou | shangjia,认证后不可回退 */
|
||||
|
||||
const VALID = ['normal', 'dashou', 'shangjia'];
|
||||
const LEGACY_CENTER_ROLES = ['guanshi', 'zuzhang', 'kaoheguan'];
|
||||
|
||||
/** 旧版管事/组长/考核官主端标识 → 统一回落打手 Tab */
|
||||
export function migrateLegacyCenterRole(app) {
|
||||
app = app || getApp();
|
||||
const cur = wx.getStorageSync('currentRole') || app.globalData.currentRole || '';
|
||||
const pri = wx.getStorageSync('primaryRole') || '';
|
||||
const isLegacy = LEGACY_CENTER_ROLES.includes(cur) || LEGACY_CENTER_ROLES.includes(pri);
|
||||
if (!isLegacy) return false;
|
||||
|
||||
const hasDashouSide =
|
||||
isRoleStatusActive(wx.getStorageSync('dashoustatus'))
|
||||
|| isRoleStatusActive(wx.getStorageSync('guanshistatus'))
|
||||
|| isRoleStatusActive(wx.getStorageSync('zuzhangstatus'))
|
||||
|| isRoleStatusActive(wx.getStorageSync('kaoheguanstatus'));
|
||||
|
||||
if (hasDashouSide) {
|
||||
lockPrimaryRole('dashou', app);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
export function isRoleStatusActive(status) {
|
||||
return Number(status) === 1;
|
||||
}
|
||||
|
||||
/** 读取主端(兼容旧 currentRole / 管事组长落地页) */
|
||||
export function getPrimaryRole(app) {
|
||||
app = app || getApp();
|
||||
const stored = wx.getStorageSync('primaryRole');
|
||||
if (VALID.includes(stored)) {
|
||||
return stored;
|
||||
}
|
||||
const legacy = wx.getStorageSync('currentRole') || app.globalData.currentRole || 'normal';
|
||||
if (legacy === 'dashou' || legacy === 'shangjia') {
|
||||
return legacy;
|
||||
}
|
||||
if (legacy === 'guanshi' || legacy === 'zuzhang' || legacy === 'kaoheguan') {
|
||||
if (isRoleStatusActive(wx.getStorageSync('dashoustatus'))) {
|
||||
return 'dashou';
|
||||
}
|
||||
if (isRoleStatusActive(wx.getStorageSync('shangjiastatus'))) {
|
||||
return 'shangjia';
|
||||
}
|
||||
}
|
||||
if (isRoleStatusActive(wx.getStorageSync('dashoustatus'))) {
|
||||
return 'dashou';
|
||||
}
|
||||
if (isRoleStatusActive(wx.getStorageSync('shangjiastatus'))) {
|
||||
return 'shangjia';
|
||||
}
|
||||
return 'normal';
|
||||
}
|
||||
|
||||
/** 锁定主端并同步 TabBar 角色 */
|
||||
export function lockPrimaryRole(role, app) {
|
||||
if (!VALID.includes(role)) return;
|
||||
app = app || getApp();
|
||||
wx.setStorageSync('primaryRole', role);
|
||||
wx.setStorageSync('currentRole', role);
|
||||
app.globalData.primaryRole = role;
|
||||
app.globalData.currentRole = role;
|
||||
if (app.emitEvent) {
|
||||
app.emitEvent('currentRoleChanged', { role });
|
||||
}
|
||||
}
|
||||
|
||||
/** TabBar / IM 使用的有效角色(仅三端) */
|
||||
export function getTabRole(app) {
|
||||
return getPrimaryRole(app);
|
||||
}
|
||||
|
||||
export function clearPrimaryRole(app) {
|
||||
app = app || getApp();
|
||||
wx.removeStorageSync('primaryRole');
|
||||
lockPrimaryRole('normal', app);
|
||||
}
|
||||
|
||||
export const PRIMARY_DEFAULT_PAGES = {
|
||||
normal: '/pages/mine/mine',
|
||||
dashou: '/pages/accept-order/accept-order',
|
||||
shangjia: '/pages/merchant-orders/merchant-orders',
|
||||
};
|
||||
|
||||
/** 锁定主端并跳转到该端默认首页,同时建立 IM 长连接 */
|
||||
export function enterLockedRole(role, app) {
|
||||
if (!VALID.includes(role) || role === 'normal') return false;
|
||||
app = app || getApp();
|
||||
lockPrimaryRole(role, app);
|
||||
wx.reLaunch({ url: PRIMARY_DEFAULT_PAGES[role] });
|
||||
setTimeout(() => {
|
||||
if (app.switchRoleAndReconnect) {
|
||||
app.switchRoleAndReconnect(role).catch(() => {
|
||||
if (app.connectForCurrentRole) app.connectForCurrentRole();
|
||||
});
|
||||
} else if (app.connectForCurrentRole) {
|
||||
app.connectForCurrentRole();
|
||||
}
|
||||
}, 600);
|
||||
return true;
|
||||
}
|
||||
|
||||
146
utils/request.js
146
utils/request.js
@@ -1,74 +1,74 @@
|
||||
// utils/request.js
|
||||
const app = getApp();
|
||||
|
||||
function request(options) {
|
||||
const token = wx.getStorageSync('token');
|
||||
|
||||
// 🔥 没有 token 时不发送请求,直接返回一个“空响应”对象,不影响后续代码
|
||||
if (!token) {
|
||||
// 返回一个模拟的响应,状态码为 401,但不会触发任何弹窗或跳转
|
||||
return Promise.resolve({
|
||||
statusCode: 401,
|
||||
data: { code: 401, msg: '未登录' },
|
||||
errMsg: 'request:ok'
|
||||
});
|
||||
}
|
||||
|
||||
const header = {
|
||||
'Content-Type': 'application/json',
|
||||
...options.header,
|
||||
};
|
||||
if (token) {
|
||||
header['Authorization'] = 'Bearer ' + token;
|
||||
}
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
wx.request({
|
||||
url: app.globalData.apiBaseUrl + options.url,
|
||||
method: options.method,
|
||||
data: options.data || {},
|
||||
header,
|
||||
success: async (res) => {
|
||||
if (res.statusCode === 401 || res.statusCode === 403) {
|
||||
// 注意:这里的弹窗逻辑只会在有 token 且 token 失效时触发
|
||||
// 无 token 的情况已经在上面直接返回,不会走到这里
|
||||
if (app.globalData.loginPromise) {
|
||||
try {
|
||||
await app.globalData.loginPromise;
|
||||
const retryRes = await request(options);
|
||||
resolve(retryRes);
|
||||
} catch (err) {
|
||||
wx.showModal({
|
||||
content: '操作失败,请先登录',
|
||||
success: (modalRes) => {
|
||||
if (modalRes.confirm) {
|
||||
wx.removeStorageSync('token');
|
||||
wx.switchTab({ url: '/pages/wode/wode' });
|
||||
}
|
||||
},
|
||||
});
|
||||
resolve(res);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
wx.showModal({
|
||||
content: '操作失败,请先登录',
|
||||
success: (modalRes) => {
|
||||
if (modalRes.confirm) {
|
||||
wx.removeStorageSync('token');
|
||||
wx.reLaunch({ url: '/pages/wode/wode' });
|
||||
}
|
||||
},
|
||||
});
|
||||
resolve(res);
|
||||
return;
|
||||
}
|
||||
resolve(res);
|
||||
},
|
||||
fail: reject,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// utils/request.js
|
||||
const app = getApp();
|
||||
|
||||
function request(options) {
|
||||
const token = wx.getStorageSync('token');
|
||||
|
||||
// 🔥 没有 token 时不发送请求,直接返回一个“空响应”对象,不影响后续代码
|
||||
if (!token) {
|
||||
// 返回一个模拟的响应,状态码为 401,但不会触发任何弹窗或跳转
|
||||
return Promise.resolve({
|
||||
statusCode: 401,
|
||||
data: { code: 401, msg: '未登录' },
|
||||
errMsg: 'request:ok'
|
||||
});
|
||||
}
|
||||
|
||||
const header = {
|
||||
'Content-Type': 'application/json',
|
||||
...options.header,
|
||||
};
|
||||
if (token) {
|
||||
header['Authorization'] = 'Bearer ' + token;
|
||||
}
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
wx.request({
|
||||
url: app.globalData.apiBaseUrl + options.url,
|
||||
method: options.method,
|
||||
data: options.data || {},
|
||||
header,
|
||||
success: async (res) => {
|
||||
if (res.statusCode === 401 || res.statusCode === 403) {
|
||||
// 注意:这里的弹窗逻辑只会在有 token 且 token 失效时触发
|
||||
// 无 token 的情况已经在上面直接返回,不会走到这里
|
||||
if (app.globalData.loginPromise) {
|
||||
try {
|
||||
await app.globalData.loginPromise;
|
||||
const retryRes = await request(options);
|
||||
resolve(retryRes);
|
||||
} catch (err) {
|
||||
wx.showModal({
|
||||
content: '操作失败,请先登录',
|
||||
success: (modalRes) => {
|
||||
if (modalRes.confirm) {
|
||||
wx.removeStorageSync('token');
|
||||
wx.switchTab({ url: '/pages/mine/mine' });
|
||||
}
|
||||
},
|
||||
});
|
||||
resolve(res);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
wx.showModal({
|
||||
content: '操作失败,请先登录',
|
||||
success: (modalRes) => {
|
||||
if (modalRes.confirm) {
|
||||
wx.removeStorageSync('token');
|
||||
wx.reLaunch({ url: '/pages/mine/mine' });
|
||||
}
|
||||
},
|
||||
});
|
||||
resolve(res);
|
||||
return;
|
||||
}
|
||||
resolve(res);
|
||||
},
|
||||
fail: reject,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
export default request;
|
||||
@@ -1,255 +1,255 @@
|
||||
import { clearPrimaryRole } from './primary-role';
|
||||
import { getLocalImUserId } from './im-user.js';
|
||||
export function isWechatLoginSuccess(body) {
|
||||
if (!body) return false;
|
||||
const code = Number(body.code);
|
||||
return code === 0 || code === 200;
|
||||
}
|
||||
|
||||
const SESSION_STATUS_KEYS = ['dashoustatus', 'guanshistatus', 'shangjiastatus', 'zuzhangstatus', 'kaoheguanstatus'];
|
||||
|
||||
/** 读取 token(Storage 优先,globalData 兜底并回写 Storage) */
|
||||
export function getSessionToken(app) {
|
||||
app = app || getApp();
|
||||
let token = wx.getStorageSync('token') || app.globalData.token || '';
|
||||
if (token && !wx.getStorageSync('token')) {
|
||||
wx.setStorageSync('token', token);
|
||||
}
|
||||
return token;
|
||||
}
|
||||
|
||||
export function isUserLoggedIn(app) {
|
||||
return !!getSessionToken(app);
|
||||
}
|
||||
|
||||
/** 从 Storage / globalData 汇总展示用用户信息(兼容其他端注册后 nick 未落盘) */
|
||||
export function getUserProfileForDisplay(app) {
|
||||
app = app || getApp();
|
||||
const token = getSessionToken(app);
|
||||
const uid = wx.getStorageSync('uid') || app.globalData.uid || '';
|
||||
let nick = wx.getStorageSync('nicheng') || app.globalData.nicheng || '';
|
||||
if (!nick && app.globalData.dashouNicheng) {
|
||||
nick = app.globalData.dashouNicheng;
|
||||
}
|
||||
const tx = wx.getStorageSync('touxiang') || '';
|
||||
const def = app.globalData.morentouxiang || '';
|
||||
const oss = app.globalData.ossImageUrl || '';
|
||||
let avatarUrl = '';
|
||||
if (tx) {
|
||||
avatarUrl = tx.startsWith('http') ? tx : oss + tx;
|
||||
} else if (def) {
|
||||
avatarUrl = def.startsWith('http') ? def : oss + def;
|
||||
}
|
||||
return {
|
||||
nick,
|
||||
uid,
|
||||
avatarUrl,
|
||||
isLoggedIn: !!token,
|
||||
};
|
||||
}
|
||||
|
||||
/** 其他端登录/注册成功后,把 globalData 里已有字段补写回 Storage */
|
||||
export function backfillUserProfileCache(app) {
|
||||
app = app || getApp();
|
||||
if (!isUserLoggedIn()) return;
|
||||
const profile = getUserProfileForDisplay(app);
|
||||
if (profile.nick && !wx.getStorageSync('nicheng')) {
|
||||
wx.setStorageSync('nicheng', profile.nick);
|
||||
app.globalData.nicheng = profile.nick;
|
||||
}
|
||||
if (profile.uid && !wx.getStorageSync('uid')) {
|
||||
wx.setStorageSync('uid', profile.uid);
|
||||
}
|
||||
}
|
||||
|
||||
export function applyWechatLoginData(data, page) {
|
||||
if (!data || typeof data !== 'object') return;
|
||||
const app = getApp();
|
||||
syncProfileFields(data);
|
||||
if (data.token) {
|
||||
wx.setStorageSync('token', data.token);
|
||||
}
|
||||
syncRoleStatuses(data);
|
||||
syncGroupFields(data);
|
||||
if (data.zuzhangstatus !== undefined) {
|
||||
wx.setStorageSync('zuzhangstatus', data.zuzhangstatus);
|
||||
app.globalData.zuzhangstatus = data.zuzhangstatus;
|
||||
}
|
||||
if (data.kaoheguanstatus !== undefined) {
|
||||
wx.setStorageSync('kaoheguanstatus', data.kaoheguanstatus);
|
||||
app.globalData.kaoheguanstatus = data.kaoheguanstatus;
|
||||
}
|
||||
if (data.dingdantiaoshu) {
|
||||
app.globalData.dingdanTiaoshu = {
|
||||
daifuwu: data.dingdantiaoshu.daifuwu || 0,
|
||||
fuwuzhong: data.dingdantiaoshu.fuwuzhong || 0,
|
||||
yiwancheng: data.dingdantiaoshu.yiwancheng || 0,
|
||||
yituikuan: data.dingdantiaoshu.yituikuan || 0,
|
||||
};
|
||||
}
|
||||
if (data.isJinpai !== undefined) {
|
||||
wx.setStorageSync('isJinpai', Number(data.isJinpai));
|
||||
}
|
||||
|
||||
const targetPage = page || _getCurrentPage();
|
||||
refreshTabBar(targetPage);
|
||||
}
|
||||
|
||||
function _getCurrentPage() {
|
||||
const pages = getCurrentPages();
|
||||
return pages.length ? pages[pages.length - 1] : null;
|
||||
}
|
||||
|
||||
export function isRoleStatusActive(status) {
|
||||
return Number(status) === 1;
|
||||
}
|
||||
|
||||
export function isCenterPageActive(page, dataFlag, statusKey) {
|
||||
return page.data[dataFlag] || isRoleStatusActive(wx.getStorageSync(statusKey));
|
||||
}
|
||||
|
||||
export function syncRoleStatuses(data) {
|
||||
if (!data || typeof data !== 'object') return;
|
||||
const app = getApp();
|
||||
const roleFields = ['dashoustatus', 'guanshistatus', 'shangjiastatus', 'zuzhangstatus', 'kaoheguanstatus'];
|
||||
roleFields.forEach((field) => {
|
||||
if (Object.prototype.hasOwnProperty.call(data, field)) {
|
||||
const val = Number(data[field]);
|
||||
const normalized = Number.isNaN(val) ? 0 : val;
|
||||
wx.setStorageSync(field, normalized);
|
||||
app.globalData[field] = normalized;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
export function syncProfileFields(data) {
|
||||
if (!data || typeof data !== 'object') return;
|
||||
const app = getApp();
|
||||
['nicheng', 'uid', 'touxiang', 'token'].forEach((field) => {
|
||||
if (data[field] !== undefined && data[field] !== null) {
|
||||
wx.setStorageSync(field, data[field]);
|
||||
app.globalData[field] = data[field];
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/** 清除缓存:清空登录与身份,回到点单端「我的」 */
|
||||
export function clearCacheAndEnterNormal(page) {
|
||||
resetGuestSession(page, { skipPageReset: true });
|
||||
wx.reLaunch({ url: '/pages/wode/wode' });
|
||||
}
|
||||
|
||||
/** 清除缓存并重置为点单端(不跳转,供当前已在点单端时使用) */
|
||||
export function resetGuestSession(page, options = {}) {
|
||||
const app = getApp();
|
||||
const configKey = app.CONFIG_CACHE_KEY || 'app_dynamic_config';
|
||||
let configCache = null;
|
||||
try {
|
||||
configCache = wx.getStorageSync(configKey);
|
||||
} catch (e) {}
|
||||
|
||||
wx.clearStorageSync();
|
||||
|
||||
if (configCache && typeof configCache === 'object') {
|
||||
wx.setStorageSync(configKey, configCache);
|
||||
}
|
||||
|
||||
clearPrimaryRole(app);
|
||||
app.globalData.token = '';
|
||||
app.globalData.nicheng = '';
|
||||
app.globalData.uid = '';
|
||||
app.globalData.loginPromise = null;
|
||||
app.globalData.currentUser = null;
|
||||
app.globalData.dashouNicheng = '';
|
||||
app.globalData.dingdanTiaoshu = { daifuwu: 0, fuwuzhong: 0, yiwancheng: 0, yituikuan: 0 };
|
||||
app.globalData.dashouqun = '';
|
||||
app.globalData.dashouqunid = '';
|
||||
app.globalData.guanshiqun = '';
|
||||
app.globalData.guanshiqunid = '';
|
||||
SESSION_STATUS_KEYS.forEach((key) => {
|
||||
app.globalData[key] = 0;
|
||||
});
|
||||
app.globalData.shangpinleixing = [];
|
||||
app.globalData.shangpinzhuanqu = [];
|
||||
app.globalData.shangpinliebiao = [];
|
||||
|
||||
app.emitEvent('currentRoleChanged', { role: 'normal' });
|
||||
refreshTabBar(page);
|
||||
|
||||
if (!options.skipPageReset && page && page.setData) {
|
||||
page.setData({
|
||||
avatarUrl: '',
|
||||
userNicheng: '',
|
||||
userUid: '',
|
||||
showLoginBtn: true,
|
||||
orderCounts: { daifuwu: 0, fuwuzhong: 0, yiwancheng: 0, yituikuan: 0 },
|
||||
dashouCertified: false,
|
||||
shangjiaCertified: false,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export function syncGroupFields(data) {
|
||||
if (!data || typeof data !== 'object') return;
|
||||
const app = getApp();
|
||||
['dashouqun', 'dashouqunid', 'guanshiqun', 'guanshiqunid'].forEach((field) => {
|
||||
if (data[field] !== undefined) {
|
||||
wx.setStorageSync(field, data[field]);
|
||||
app.globalData[field] = data[field];
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
export function refreshTabBar(page) {
|
||||
const tryRefresh = () => {
|
||||
const tabBar = page.getTabBar && page.getTabBar();
|
||||
if (tabBar && tabBar.refresh) tabBar.refresh();
|
||||
};
|
||||
tryRefresh();
|
||||
[50, 150, 300, 500, 800].forEach((delay) => setTimeout(tryRefresh, delay));
|
||||
}
|
||||
|
||||
export function setRoleAndRefreshTabBar(page, role) {
|
||||
const app = getApp();
|
||||
if (app.setCurrentRole) {
|
||||
app.setCurrentRole(role);
|
||||
} else {
|
||||
app.globalData.currentRole = role;
|
||||
wx.setStorageSync('currentRole', role);
|
||||
app.emitEvent('currentRoleChanged', { role });
|
||||
}
|
||||
refreshTabBar(page);
|
||||
}
|
||||
|
||||
export function reconnectForRole(role) {
|
||||
const app = getApp();
|
||||
if (!wx.getStorageSync('uid')) return;
|
||||
|
||||
const targetUserId = getLocalImUserId(app);
|
||||
if (!targetUserId) return;
|
||||
|
||||
const status = wx.goEasy?.getConnectionStatus?.() || 'disconnected';
|
||||
const currentUserId = wx.goEasy?.im?.userId || '';
|
||||
const connected = status === 'connected' || status === 'reconnected';
|
||||
|
||||
if (connected && currentUserId === targetUserId) {
|
||||
if (app.loadConversations) app.loadConversations();
|
||||
if (app.ensureConnection) app.ensureConnection();
|
||||
return;
|
||||
}
|
||||
|
||||
if (app.switchRoleAndReconnect) {
|
||||
app.switchRoleAndReconnect(role).catch(() => {
|
||||
if (app.ensureConnection) app.ensureConnection();
|
||||
});
|
||||
} else if (app.connectForCurrentRole) {
|
||||
app.connectForCurrentRole();
|
||||
} else if (app.ensureConnection) {
|
||||
app.ensureConnection();
|
||||
}
|
||||
}
|
||||
|
||||
export function ensureRoleOnCenterPage(page, role) {
|
||||
setRoleAndRefreshTabBar(page, role);
|
||||
reconnectForRole(role);
|
||||
}
|
||||
import { clearPrimaryRole } from './primary-role';
|
||||
import { getLocalImUserId } from './im-user.js';
|
||||
export function isWechatLoginSuccess(body) {
|
||||
if (!body) return false;
|
||||
const code = Number(body.code);
|
||||
return code === 0 || code === 200;
|
||||
}
|
||||
|
||||
const SESSION_STATUS_KEYS = ['dashoustatus', 'guanshistatus', 'shangjiastatus', 'zuzhangstatus', 'kaoheguanstatus'];
|
||||
|
||||
/** 读取 token(Storage 优先,globalData 兜底并回写 Storage) */
|
||||
export function getSessionToken(app) {
|
||||
app = app || getApp();
|
||||
let token = wx.getStorageSync('token') || app.globalData.token || '';
|
||||
if (token && !wx.getStorageSync('token')) {
|
||||
wx.setStorageSync('token', token);
|
||||
}
|
||||
return token;
|
||||
}
|
||||
|
||||
export function isUserLoggedIn(app) {
|
||||
return !!getSessionToken(app);
|
||||
}
|
||||
|
||||
/** 从 Storage / globalData 汇总展示用用户信息(兼容其他端注册后 nick 未落盘) */
|
||||
export function getUserProfileForDisplay(app) {
|
||||
app = app || getApp();
|
||||
const token = getSessionToken(app);
|
||||
const uid = wx.getStorageSync('uid') || app.globalData.uid || '';
|
||||
let nick = wx.getStorageSync('nicheng') || app.globalData.nicheng || '';
|
||||
if (!nick && app.globalData.dashouNicheng) {
|
||||
nick = app.globalData.dashouNicheng;
|
||||
}
|
||||
const tx = wx.getStorageSync('touxiang') || '';
|
||||
const def = app.globalData.morentouxiang || '';
|
||||
const oss = app.globalData.ossImageUrl || '';
|
||||
let avatarUrl = '';
|
||||
if (tx) {
|
||||
avatarUrl = tx.startsWith('http') ? tx : oss + tx;
|
||||
} else if (def) {
|
||||
avatarUrl = def.startsWith('http') ? def : oss + def;
|
||||
}
|
||||
return {
|
||||
nick,
|
||||
uid,
|
||||
avatarUrl,
|
||||
isLoggedIn: !!token,
|
||||
};
|
||||
}
|
||||
|
||||
/** 其他端登录/注册成功后,把 globalData 里已有字段补写回 Storage */
|
||||
export function backfillUserProfileCache(app) {
|
||||
app = app || getApp();
|
||||
if (!isUserLoggedIn()) return;
|
||||
const profile = getUserProfileForDisplay(app);
|
||||
if (profile.nick && !wx.getStorageSync('nicheng')) {
|
||||
wx.setStorageSync('nicheng', profile.nick);
|
||||
app.globalData.nicheng = profile.nick;
|
||||
}
|
||||
if (profile.uid && !wx.getStorageSync('uid')) {
|
||||
wx.setStorageSync('uid', profile.uid);
|
||||
}
|
||||
}
|
||||
|
||||
export function applyWechatLoginData(data, page) {
|
||||
if (!data || typeof data !== 'object') return;
|
||||
const app = getApp();
|
||||
syncProfileFields(data);
|
||||
if (data.token) {
|
||||
wx.setStorageSync('token', data.token);
|
||||
}
|
||||
syncRoleStatuses(data);
|
||||
syncGroupFields(data);
|
||||
if (data.zuzhangstatus !== undefined) {
|
||||
wx.setStorageSync('zuzhangstatus', data.zuzhangstatus);
|
||||
app.globalData.zuzhangstatus = data.zuzhangstatus;
|
||||
}
|
||||
if (data.kaoheguanstatus !== undefined) {
|
||||
wx.setStorageSync('kaoheguanstatus', data.kaoheguanstatus);
|
||||
app.globalData.kaoheguanstatus = data.kaoheguanstatus;
|
||||
}
|
||||
if (data.dingdantiaoshu) {
|
||||
app.globalData.dingdanTiaoshu = {
|
||||
daifuwu: data.dingdantiaoshu.daifuwu || 0,
|
||||
fuwuzhong: data.dingdantiaoshu.fuwuzhong || 0,
|
||||
yiwancheng: data.dingdantiaoshu.yiwancheng || 0,
|
||||
yituikuan: data.dingdantiaoshu.yituikuan || 0,
|
||||
};
|
||||
}
|
||||
if (data.isJinpai !== undefined) {
|
||||
wx.setStorageSync('isJinpai', Number(data.isJinpai));
|
||||
}
|
||||
|
||||
const targetPage = page || _getCurrentPage();
|
||||
refreshTabBar(targetPage);
|
||||
}
|
||||
|
||||
function _getCurrentPage() {
|
||||
const pages = getCurrentPages();
|
||||
return pages.length ? pages[pages.length - 1] : null;
|
||||
}
|
||||
|
||||
export function isRoleStatusActive(status) {
|
||||
return Number(status) === 1;
|
||||
}
|
||||
|
||||
export function isCenterPageActive(page, dataFlag, statusKey) {
|
||||
return page.data[dataFlag] || isRoleStatusActive(wx.getStorageSync(statusKey));
|
||||
}
|
||||
|
||||
export function syncRoleStatuses(data) {
|
||||
if (!data || typeof data !== 'object') return;
|
||||
const app = getApp();
|
||||
const roleFields = ['dashoustatus', 'guanshistatus', 'shangjiastatus', 'zuzhangstatus', 'kaoheguanstatus'];
|
||||
roleFields.forEach((field) => {
|
||||
if (Object.prototype.hasOwnProperty.call(data, field)) {
|
||||
const val = Number(data[field]);
|
||||
const normalized = Number.isNaN(val) ? 0 : val;
|
||||
wx.setStorageSync(field, normalized);
|
||||
app.globalData[field] = normalized;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
export function syncProfileFields(data) {
|
||||
if (!data || typeof data !== 'object') return;
|
||||
const app = getApp();
|
||||
['nicheng', 'uid', 'touxiang', 'token'].forEach((field) => {
|
||||
if (data[field] !== undefined && data[field] !== null) {
|
||||
wx.setStorageSync(field, data[field]);
|
||||
app.globalData[field] = data[field];
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/** 清除缓存:清空登录与身份,回到点单端「我的」 */
|
||||
export function clearCacheAndEnterNormal(page) {
|
||||
resetGuestSession(page, { skipPageReset: true });
|
||||
wx.reLaunch({ url: '/pages/mine/mine' });
|
||||
}
|
||||
|
||||
/** 清除缓存并重置为点单端(不跳转,供当前已在点单端时使用) */
|
||||
export function resetGuestSession(page, options = {}) {
|
||||
const app = getApp();
|
||||
const configKey = app.CONFIG_CACHE_KEY || 'app_dynamic_config';
|
||||
let configCache = null;
|
||||
try {
|
||||
configCache = wx.getStorageSync(configKey);
|
||||
} catch (e) {}
|
||||
|
||||
wx.clearStorageSync();
|
||||
|
||||
if (configCache && typeof configCache === 'object') {
|
||||
wx.setStorageSync(configKey, configCache);
|
||||
}
|
||||
|
||||
clearPrimaryRole(app);
|
||||
app.globalData.token = '';
|
||||
app.globalData.nicheng = '';
|
||||
app.globalData.uid = '';
|
||||
app.globalData.loginPromise = null;
|
||||
app.globalData.currentUser = null;
|
||||
app.globalData.dashouNicheng = '';
|
||||
app.globalData.dingdanTiaoshu = { daifuwu: 0, fuwuzhong: 0, yiwancheng: 0, yituikuan: 0 };
|
||||
app.globalData.dashouqun = '';
|
||||
app.globalData.dashouqunid = '';
|
||||
app.globalData.guanshiqun = '';
|
||||
app.globalData.guanshiqunid = '';
|
||||
SESSION_STATUS_KEYS.forEach((key) => {
|
||||
app.globalData[key] = 0;
|
||||
});
|
||||
app.globalData.shangpinleixing = [];
|
||||
app.globalData.shangpinzhuanqu = [];
|
||||
app.globalData.shangpinliebiao = [];
|
||||
|
||||
app.emitEvent('currentRoleChanged', { role: 'normal' });
|
||||
refreshTabBar(page);
|
||||
|
||||
if (!options.skipPageReset && page && page.setData) {
|
||||
page.setData({
|
||||
avatarUrl: '',
|
||||
userNicheng: '',
|
||||
userUid: '',
|
||||
showLoginBtn: true,
|
||||
orderCounts: { daifuwu: 0, fuwuzhong: 0, yiwancheng: 0, yituikuan: 0 },
|
||||
dashouCertified: false,
|
||||
shangjiaCertified: false,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export function syncGroupFields(data) {
|
||||
if (!data || typeof data !== 'object') return;
|
||||
const app = getApp();
|
||||
['dashouqun', 'dashouqunid', 'guanshiqun', 'guanshiqunid'].forEach((field) => {
|
||||
if (data[field] !== undefined) {
|
||||
wx.setStorageSync(field, data[field]);
|
||||
app.globalData[field] = data[field];
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
export function refreshTabBar(page) {
|
||||
const tryRefresh = () => {
|
||||
const tabBar = page.getTabBar && page.getTabBar();
|
||||
if (tabBar && tabBar.refresh) tabBar.refresh();
|
||||
};
|
||||
tryRefresh();
|
||||
[50, 150, 300, 500, 800].forEach((delay) => setTimeout(tryRefresh, delay));
|
||||
}
|
||||
|
||||
export function setRoleAndRefreshTabBar(page, role) {
|
||||
const app = getApp();
|
||||
if (app.setCurrentRole) {
|
||||
app.setCurrentRole(role);
|
||||
} else {
|
||||
app.globalData.currentRole = role;
|
||||
wx.setStorageSync('currentRole', role);
|
||||
app.emitEvent('currentRoleChanged', { role });
|
||||
}
|
||||
refreshTabBar(page);
|
||||
}
|
||||
|
||||
export function reconnectForRole(role) {
|
||||
const app = getApp();
|
||||
if (!wx.getStorageSync('uid')) return;
|
||||
|
||||
const targetUserId = getLocalImUserId(app);
|
||||
if (!targetUserId) return;
|
||||
|
||||
const status = wx.goEasy?.getConnectionStatus?.() || 'disconnected';
|
||||
const currentUserId = wx.goEasy?.im?.userId || '';
|
||||
const connected = status === 'connected' || status === 'reconnected';
|
||||
|
||||
if (connected && currentUserId === targetUserId) {
|
||||
if (app.loadConversations) app.loadConversations();
|
||||
if (app.ensureConnection) app.ensureConnection();
|
||||
return;
|
||||
}
|
||||
|
||||
if (app.switchRoleAndReconnect) {
|
||||
app.switchRoleAndReconnect(role).catch(() => {
|
||||
if (app.ensureConnection) app.ensureConnection();
|
||||
});
|
||||
} else if (app.connectForCurrentRole) {
|
||||
app.connectForCurrentRole();
|
||||
} else if (app.ensureConnection) {
|
||||
app.ensureConnection();
|
||||
}
|
||||
}
|
||||
|
||||
export function ensureRoleOnCenterPage(page, role) {
|
||||
setRoleAndRefreshTabBar(page, role);
|
||||
reconnectForRole(role);
|
||||
}
|
||||
|
||||
@@ -1,215 +1,215 @@
|
||||
/**
|
||||
* 连接管理模块 - 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/liaotian/liaotian?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/qunliaotian/qunliaotian?data=' + encodeURIComponent(JSON.stringify(param));
|
||||
wx.navigateTo({ url: path });
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 连接管理模块 - 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();
|
||||
Reference in New Issue
Block a user