// app.js import GoEasy from './static/lib/goeasy-2.13.24.esm.min'; const ChatCore = require('./utils/chat-core'); import { ensurePhoneAuth } from './utils/phone-auth'; import { getPrimaryRole, lockPrimaryRole, migrateLegacyCenterRole, PRIMARY_DEFAULT_PAGES } from './utils/primary-role'; // 三端固定首页 const roleDefaultPage = PRIMARY_DEFAULT_PAGES; App({ globalData: { hasShownPopupOnColdStart: false, apiBaseUrl: 'https://www.abas.asia/hqhd', ossImageUrl: '', morentouxiang: '', dashouguize: '', shangpinliebiao: [], shangpinzhuanqu: [], shangpinleixing: [], shangpinlunbo: [], shangpingonggao: '', lunbozhanwei: '/images/lunbozhanwei.jpg', dingdanTiaoshu: { daifuwu: 0, fuwuzhong: 0, yiwancheng: 0, yituikuan: 0 }, dashouqun: '', dashouqunid: '', guanshiqun: '', guanshiqunid: '', appId:'wx0e4be86faac4a8d1', shangjiastatus: 0, dashoustatus: 0, guanshistatus: 0, dashouNicheng: '', zhanghaoStatus: null, dashouzhuangtai: null, yongjin: null, zonge: null, yajin: null, chenghao: '', jinfen: null, clumber: [{ huiyuanid: '', huiyuanming: '', daoqi: '' }], chengjiaoliang: null, zaixianZhuangtai: null, guanshi: { nicheng: '', uid: '', touxiang: '', gszhstatus: '', yaoqingzongshu: 0, fenyongzonge: '0.00', fenyongtixian: '0.00' }, shangjia: { sjzhzhuangtai: '', sjyue: '', fadanzong: null, tuikuanzong: null, riliushui: '', yueliushui: '' }, liaotian_liebiao: [], xshenfen: 1, goEasyConfig: null, kefuConfig: { link: '', enterpriseId: '' }, cosConfig: { bucket: '', region: 'ap-shanghai', uploadPathPrefix: 'order/' }, goEasyConnection: { status: 'disconnected', userId: '', identityType: '', lastConnectTime: 0, autoReconnect: true, reconnectAttempts: 0, maxReconnectAttempts: 5, heartbeatInterval: null, cacheKeys: { savedConnection: 'savedGoEasyConnection', userId: 'goEasyUserId', identityType: 'currentGoEasyIdentity', connectTime: 'goEasyConnectTime' }, config: { heartbeatInterval: 20000, reconnectDelay: 3000, offlineTimeout: 30000, cacheValidityHours: 12 } }, messageManager: { unreadTotal: 0, unreadMap: {}, latestMessages: [], notificationQueue: [], notificationVisible: false, lastNotificationTime: 0, notificationCooldown: 3000, tabBarIndex: 2, showTabBarBadge: true, customTabBar: true, tabBarBadgeText: 0, soundEnabled: true, vibrationEnabled: true, doNotDisturb: false, doNotDisturbStart: '22:00', doNotDisturbEnd: '08:00', notificationStyle: { position: 'top', duration: 3000, backgroundColor: '#00f7ff', textColor: '#ffffff', borderRadius: '16rpx', boxShadow: '0 10rpx 30rpx rgba(0, 247, 255, 0.3)' }, currentNotification: null, cacheKeys: { messageSettings: 'messageSettings', unreadTotal: 'messageUnreadTotal', latestMessages: 'latestMessages', notificationMuted: 'notificationMuted' } }, pageState: { currentPage: '', isInChatPage: false, currentChatId: '', lastPageUpdate: 0 }, eventListeners: {}, debugMode: false, currentUser: null, currentRole: 'normal', primaryRole: 'normal' }, // 核心启动流程 async onLaunch() { // ① 隐藏返回首页按钮 wx.hideHomeButton(); wx.onAppRoute((res) => { wx.hideHomeButton(); const path = (res && res.path) || ''; if (path === 'pages/manager/manager' || path === 'pages/leader/leader') { migrateLegacyCenterRole(this); lockPrimaryRole('dashou', this); } }); // ② 已登录时先恢复子客服身份,再决定主端 Tab(避免客服被当成未入驻) if (wx.getStorageSync('token')) { try { const { restoreStaffContextAfterAuth } = require('./utils/staff-api.js'); await restoreStaffContextAfterAuth(); } catch (e) {} } migrateLegacyCenterRole(this); const savedRole = getPrimaryRole(this); lockPrimaryRole(savedRole, this); // ②b 冷启动:有 token 时先问后端是否需要手机号认证 if (wx.getStorageSync('token')) { const phoneOk = await ensurePhoneAuth({ redirect: true }); if (!phoneOk) return; } const targetPage = roleDefaultPage[savedRole] || '/pages/index/index'; if (savedRole !== 'normal') { setTimeout(() => { wx.reLaunch({ url: targetPage }); }, 0); } // ③ 应用本地缓存配置 const cachedConfig = this.readConfigFromStorage(); if (cachedConfig) { this.applyDynamicConfig(cachedConfig); } // ④ 初始化 this.initGoEasyWithConfig(); // 只有appkey有效时才真正初始化 ChatCore.initGlobalMessageSystem(this); this.initCurrentUser(); if (wx.getStorageSync('token') && this.emitEvent) { this.emitEvent('staffContextChanged', {}); } // ⑤ 建立连接 const saved = this.getSavedConnection(); console.log('【启动】缓存身份:', saved ? saved.identityType : '无', 'userId:', saved ? saved.userId : '无'); setTimeout(() => { if (this.startImWhenReady) this.startImWhenReady(); else if (this.ensureConnection) this.ensureConnection(); }, 300); // ⑥ 获取远程配置 this.fetchConfigSafely() .then(latestConfig => { this.saveConfigToStorage(latestConfig); this.applyDynamicConfig(latestConfig); this.initGoEasyWithConfig(); this.initCurrentUser(); if (this.startImWhenReady) this.startImWhenReady(); else if (this.connectForCurrentRole) this.connectForCurrentRole(); console.log('远程配置更新完成'); }) .catch(err => { console.warn('远程配置获取失败,继续使用本地缓存', err); }); }, /** 从后台切回前台时再次向后端校验 */ async onShow() { if (!wx.getStorageSync('token')) return; await ensurePhoneAuth({ redirect: true }); }, // 连接管理方法 getSavedConnection() { try { const saved = wx.getStorageSync( this.globalData.goEasyConnection.cacheKeys.savedConnection ); return saved || null; } catch (e) { return null; } }, // 配置缓存读写 CONFIG_CACHE_KEY: 'app_dynamic_config', readConfigFromStorage() { try { const data = wx.getStorageSync(this.CONFIG_CACHE_KEY); if (data && typeof data === 'object') { return data; } } catch (e) {} return null; }, saveConfigToStorage(config) { try { if (config && typeof config === 'object') { wx.setStorageSync(this.CONFIG_CACHE_KEY, config); } } catch (e) {} }, // 获取远程配置 fetchConfigSafely() { return new Promise((resolve) => { wx.request({ url: this.globalData.apiBaseUrl + '/peizhi/qdpzhq', method: 'POST', header: { 'content-type': 'application/json' }, success: (res) => { if (res.statusCode === 200 && res.data && res.data.code === 0 && res.data.data) { resolve(res.data.data); } else { console.warn('远程配置接口返回异常,使用已有配置'); resolve(this.readConfigFromStorage() || {}); } }, fail: (err) => { console.warn('远程配置网络请求失败,使用已有配置', err); resolve(this.readConfigFromStorage() || {}); } }); }); }, // 获取远程配置 fetchDynamicConfig() { return new Promise((resolve, reject) => { wx.request({ url: this.globalData.apiBaseUrl + '/peizhi/qdpzhq', method: 'POST', header: { 'content-type': 'application/json' }, success: (res) => { if (res.statusCode === 200 && res.data && res.data.code === 0) { resolve(res.data.data); } else { reject(new Error(res.data?.msg || '接口返回错误')); } }, fail: reject }); }); }, applyDynamicConfig(config) { if (!config || typeof config !== 'object') return; if (config.cos) { this.globalData.ossImageUrl = config.cos.ossImageUrl || ''; this.globalData.cosConfig = { bucket: config.cos.bucket || '', region: config.cos.region || 'ap-shanghai', uploadPathPrefix: config.cos.uploadPathPrefix || 'order/' }; } if (config.goEasy) { this.globalData.goEasyConfig = { host: config.goEasy.host || 'hangzhou.goeasy.io', appkey: config.goEasy.appkey || '' }; } if (config.otherConfig) { this.globalData.morentouxiang = config.otherConfig.morentouxiang || ''; this.globalData.dashouguize = config.otherConfig.dashouguize || ''; } if (config.kefu) { this.globalData.kefuConfig = { link: config.kefu.link || '', enterpriseId: config.kefu.enterpriseId || '' }; } }, // 仅在有效 appkey 时初始化 initGoEasyWithConfig() { const cfg = this.globalData.goEasyConfig; if (!cfg || !cfg.appkey) { console.warn('GoEasy appkey 未配置,聊天功能将在配置就绪后自动恢复'); return; } // 避免重复初始化 if (wx.goEasy && wx.GoEasy) { console.log('GoEasy 已初始化,跳过'); return; } try { wx.goEasy = GoEasy.getInstance({ host: cfg.host || 'hangzhou.goeasy.io', appkey: cfg.appkey, modules: ['im', 'pubsub'] }); wx.GoEasy = GoEasy; console.log('GoEasy 初始化成功'); if (this.startImWhenReady && wx.getStorageSync('uid')) { setTimeout(() => this.startImWhenReady(), 100); } } catch (error) { console.error('GoEasy 初始化失败:', error); } }, initCurrentUser() { const uid = wx.getStorageSync('uid'); if (uid) { this.globalData.currentUser = { id: uid, name: '用户' + uid.substring(0, 6), avatar: this.globalData.ossImageUrl + this.globalData.morentouxiang }; } }, emitEvent(eventName, data) { if (this.globalData.eventListeners[eventName]) { this.globalData.eventListeners[eventName].forEach(callback => { try { callback(data); } catch (error) { console.error(error); } }); } }, /** 切换角色并通知刷新 */ setCurrentRole(role) { if (!role) return; this.globalData.currentRole = role; wx.setStorageSync('currentRole', role); this.emitEvent('currentRoleChanged', { role }); }, on(eventName, callback) { if (!this.globalData.eventListeners[eventName]) { this.globalData.eventListeners[eventName] = []; } this.globalData.eventListeners[eventName].push(callback); }, off(eventName, callback) { if (this.globalData.eventListeners[eventName]) { const index = this.globalData.eventListeners[eventName].indexOf(callback); if (index > -1) { this.globalData.eventListeners[eventName].splice(index, 1); } } } });