Files
xingque/app.js
2026-07-09 00:17:03 +08:00

489 lines
16 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// 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';
import { setClubId, getConfiguredClubId, buildClubHeaders, getClubId } from './utils/club-context';
import { CLUB_ID, WX_APP_ID } from './config/club-config';
import { applyMiniappAssetsFromConfig, warmupPindaoConfig } from './utils/miniapp-icons.js';
import { refreshDashouMembership } from './utils/dashou-profile.js';
const { getDefaultAvatarUrl, resolveAvatarFromStorage } = require('./utils/avatar.js');
// 三端固定首页
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: WX_APP_ID,
clubId: CLUB_ID,
shangjiastatus: 0,
dashoustatus: 0,
guanshistatus: 0,
dashouNicheng: '',
zhanghaoStatus: null,
dashouzhuangtai: null,
yongjin: null,
zonge: null,
yajin: null,
chenghao: '',
jinfen: null,
clumber: [],
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,
chatEnabled: false,
groupInfoMap: {},
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,
isInGroupChat: false,
currentChatId: '',
lastPageUpdate: 0
},
eventListeners: {},
debugMode: false,
currentUser: null,
currentRole: 'normal',
primaryRole: 'normal',
/** 客服浮钮full | minionLaunch 重置为 full */
kefuFloatMode: 'full',
/** 本次启动内隐藏客服浮钮(不持久化,杀进程后恢复) */
kefuFloatSessionHidden: false,
kefuFloatY: null,
/** 从「我的」跳抢单页时高亮指定单 */
_acceptOrderHighlight: '',
},
// 核心启动流程
async onLaunch() {
this.globalData.kefuFloatMode = 'full';
this.globalData.kefuFloatSessionHidden = false;
try { wx.removeStorageSync('kefuFloatPermanentHidden'); } catch (e) {}
setClubId(getConfiguredClubId(), this);
this.globalData.clubId = CLUB_ID;
// ① 隐藏返回首页按钮
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;
}
// ②c 打手端冷启动:同步会员/押金等到 globalData抢单页依赖 clumber
if (wx.getStorageSync('token') && savedRole === 'dashou') {
refreshDashouMembership(this).catch(() => {});
}
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', {});
}
// ⑤ 建立连接(文赫式:全局监听,不反复 disconnect
setTimeout(() => {
if (this.globalData.chatEnabled && this.ensureConnection) {
this.ensureConnection();
}
}, 300);
// ⑥ 获取远程配置
this.fetchConfigSafely()
.then(latestConfig => {
this.saveConfigToStorage(latestConfig);
this.applyDynamicConfig(latestConfig);
warmupPindaoConfig(this);
try {
const { fetchGonggaoLunbo } = require('./utils/display-config');
fetchGonggaoLunbo(this, 'accept_order').catch(() => {});
} catch (e) {}
this.initGoEasyWithConfig();
this.initCurrentUser();
if (this.globalData.chatEnabled && this.ensureConnection) {
this.ensureConnection();
}
console.log('远程配置更新完成');
})
.catch(err => {
console.warn('远程配置获取失败,继续使用本地缓存', err);
});
},
/** 从后台切回前台时再次向后端校验,并维持 IM 连接 */
async onShow() {
if (!wx.getStorageSync('token')) return;
await ensurePhoneAuth({ redirect: true });
if (this.globalData.chatEnabled && typeof this.startImWhenReady === 'function') {
this.startImWhenReady();
} else if (this.globalData.chatEnabled && typeof this.ensureConnection === 'function') {
this.globalData.goEasyConnection.autoReconnect = true;
if (typeof this.restoreTabBarBadge === 'function') {
this.restoreTabBarBadge();
}
this.ensureConnection();
if (typeof this.syncConnectionStatus === 'function') {
setTimeout(() => this.syncConnectionStatus(), 800);
}
if (typeof this.loadConversations === 'function') {
setTimeout(() => this.loadConversations(), 300);
}
}
},
// 连接管理方法
getSavedConnection() {
try {
const saved = wx.getStorageSync(
this.globalData.goEasyConnection.cacheKeys.savedConnection
);
return saved || null;
} catch (e) {
return null;
}
},
// 配置缓存读写
CONFIG_CACHE_KEY_PREFIX: 'app_dynamic_config_',
getConfigCacheKey() {
const cid = getClubId(this) || CLUB_ID;
return this.CONFIG_CACHE_KEY_PREFIX + cid;
},
readConfigFromStorage() {
try {
const data = wx.getStorageSync(this.getConfigCacheKey());
if (data && typeof data === 'object') {
return data;
}
} catch (e) {}
return null;
},
saveConfigToStorage(config) {
try {
if (config && typeof config === 'object') {
wx.setStorageSync(this.getConfigCacheKey(), config);
}
} catch (e) {}
},
// 获取远程配置
fetchConfigSafely() {
return new Promise((resolve) => {
wx.request({
url: this.globalData.apiBaseUrl + '/peizhi/qdpzhq',
method: 'POST',
header: buildClubHeaders({ '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: buildClubHeaders({ '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 || ''
};
}
try {
applyMiniappAssetsFromConfig(this, config);
} catch (e) {
console.warn('miniapp assets apply failed', e);
}
if (this.emitEvent) {
this.emitEvent('configApplied', {
ossImageUrl: this.globalData.ossImageUrl,
morentouxiang: this.globalData.morentouxiang,
});
}
},
// 仅在有效 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;
this.globalData.chatEnabled = true;
console.log('GoEasy 初始化成功');
if (this.ensureConnection && wx.getStorageSync('uid')) {
setTimeout(() => this.ensureConnection(), 100);
}
} catch (error) {
console.error('GoEasy 初始化失败:', error);
}
},
initCurrentUser() {
const uid = wx.getStorageSync('uid');
if (uid) {
const def = getDefaultAvatarUrl(this);
const avatar = resolveAvatarFromStorage(this) || def;
this.globalData.currentUser = {
id: uid,
name: wx.getStorageSync('nicheng') || ('用户' + uid.substring(0, 6)),
avatar: avatar || def,
};
}
},
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);
}
}
}
});