// pages/shangjiazhongxin/shangjiiazhongxin.js import { createPage, ensureRoleOnCenterPage, lockPrimaryRole, parseSceneOptions, request } from '../../utils/base-page.js'; import { ensureLogin } from '../../utils/login.js'; import { STAFF_API, isStaffMode, isMerchantPortalUser, refreshStaffContext, syncStaffUi, getStaffContext, restoreStaffContextAfterAuth, applyStaffStatsToPage, guardMerchantOwnerAction, clearStaffSession, } from '../../utils/staff-api.js'; import { fetchMerchantOrderStats, applyOrderStatsToPage } from '../../utils/merchant-order-stats.js'; import { clearCacheAndEnterNormal } from '../../utils/base-page.js'; import { ICON_KEYS, resolveMiniappIcon } from '../../utils/miniapp-icons.js'; import { getDefaultAvatarUrl } from '../../utils/avatar.js'; const app = getApp(); Page(createPage({ data: { // 图片资源 imgUrls: { pageBg: '', avatarCardBg: '', assetCardBg: '', statCardBg: '', funcItemBg: '', primaryFuncBg: '', highlightFuncBg: '', iconRelease: '', iconFast: '', iconOrders: '', iconService: '', iconPunish: '', iconRank: '', iconRecharge: '', iconWithdraw: '', iconRefresh: '', iconCopy: '', avatarFrame: '', iconClear: '', iconKefuList: '', }, // 商家状态 isShangjia: false, isStaffMode: false, staffRoleName: '', quotaAvailable: '0.00', canDispatch: true, canStaffManage: true, canAudit: true, showRechargeWithdraw: true, isAutoRegistering: false, staffBooting: false, // 用户基础信息 uid: '', avatarUrl: '', defaultAvatarUrl: '', nicheng: '', // 商家核心数据 sjyue: '0.00', fabu: 0, tuikuan: 0, jinriliushui: '0.00', jinyueliushui: '0.00', jinridingdan: 0, jinrituikuan: 0, chenghaoList: [], identityTagList: [], // 交互控制 inviteCode: '', pendingCount: 0, punishPending: 0, canViewFinance: true, orderStats: { pending_count: 0, pending_amount: '0.00', completed_count: 0, completed_amount: '0.00', refund_count: 0, refund_amount: '0.00', dispatch_count: 0, dispatch_amount: '0.00', }, penaltyStats: { fakuan_pending: 0, fakuan_pending_amount: '0.00', jifen_pending: 0, }, statusBar: 20, navBar: 44, }, async onLoad(options) { const sys = wx.getSystemInfoSync(); this.setData({ statusBar: sys.statusBarHeight || 20, navBar: (sys.statusBarHeight || 20) + 44, }); const parsed = parseSceneOptions(options); this.setupImageUrls(); this.setData({ defaultAvatarUrl: getDefaultAvatarUrl(app) }); if (wx.getStorageSync('token')) { await restoreStaffContextAfterAuth(); } this.checkRoleStatus(); syncStaffUi(this); const inviteCode = parsed.inviteCode; if (inviteCode) { this.setData({ inviteCode }); setTimeout(() => this.handleInviteCodeWithLoginCheck({ inviteCode, role: 'shangjia', statusKey: 'shangjiastatus', alreadyMsg: '您已是商家', onNeedLogin: (code) => { this.setData({ inviteCode: code }); ensureLogin({ silent: false, page: this }) .then(() => { if (!this.data.isShangjia) { wx.showLoading({ title: '商家注册中...', mask: true }); this.setData({ isAutoRegistering: true }); this.onRegister(); } }) .catch(() => {}); }, onAlreadyRegistered: () => { wx.showToast({ title: '您已是商家', icon: 'success' }); ensureRoleOnCenterPage(this, 'shangjia'); }, }), 500); } this.checkColdStartPopup('shangjiaduan'); this.loadMerchantDataIfNeeded(true); }, async onShow() { this.registerNotificationComponent(); if (!this._ossImagesReady && app.globalData.ossImageUrl) { this.setupImageUrls(); this._ossImagesReady = true; } this.syncRoleStatusFromStorage(); syncStaffUi(this); if (this._showRefreshTimer) clearTimeout(this._showRefreshTimer); this._showRefreshTimer = setTimeout(() => { if (this.data.isShangjia || isMerchantPortalUser()) { if (!isStaffMode()) { this.loadDashboardStats(); } } this.loadMerchantDataIfNeeded(); }, 200); }, syncRoleStatusFromStorage() { try { const uid = wx.getStorageSync('uid'); const portal = isMerchantPortalUser(); const staffFlag = Number(wx.getStorageSync('staffstatus')) === 1; if (portal || staffFlag) { this.setData({ isShangjia: true, uid: uid || '', staffBooting: false, isLoading: false }); } else if (!this.data.isShangjia) { this.setData({ isShangjia: false, staffBooting: false, isLoading: false }); } } catch (error) { this.setData({ isShangjia: false, staffBooting: false, isLoading: false }); } }, async loadMerchantDataIfNeeded(force = false) { if (!this.data.isShangjia && !isMerchantPortalUser()) return; if (!force && this._merchantDataLoaded) return; try { const token = wx.getStorageSync('token'); if (token && Number(wx.getStorageSync('shangjiastatus')) !== 1 && !isStaffMode()) { await restoreStaffContextAfterAuth(); } else if (isStaffMode()) { await refreshStaffContext(request); } this.syncRoleStatusFromStorage(); syncStaffUi(this); if (this.data.isShangjia || isMerchantPortalUser()) { ensureRoleOnCenterPage(this, 'shangjia'); if (isStaffMode()) { await this.loadStaffProfile(); } else { await this.getShangjiaInfo(); } this.loadPendingCount(); if (!isStaffMode()) { this.loadPunishPending(); } this.loadIdentityTags(); this._merchantDataLoaded = true; } } catch (err) { console.error('商家个人中心加载', err); this.setData({ isLoading: false, staffBooting: false }); } }, // 图片路径:样式不变,仅图标地址走存储桶 + 后台可配置 setupImageUrls() { const ossBase = app.globalData.ossImageUrl || ''; const imgDir = `${ossBase}beijing/shangjiaduan/`; const icon = (key, ossName) => resolveMiniappIcon(app, key, imgDir + ossName); this.setData({ imgUrls: this.initImageUrls({ pageBg: imgDir + 'page_bg.png', avatarCardBg: imgDir + 'avatar_card_bg.png', assetCardBg: imgDir + 'asset_card_bg.png', statCardBg: imgDir + 'stat_card_bg.png', funcItemBg: imgDir + 'func_item_bg.png', primaryFuncBg: imgDir + 'primary_func_bg.png', highlightFuncBg: imgDir + 'highlight_func_bg.png', iconRelease: icon(ICON_KEYS.MERCHANT_CUSTOM, 'icon_release.png'), iconFast: icon(ICON_KEYS.MERCHANT_REGULAR, 'icon_fast.png'), iconOrders: icon(ICON_KEYS.MERCHANT_LINK, 'icon_orders.png'), iconService: icon(ICON_KEYS.MERCHANT_KEFU_KEY, 'icon_service.png'), iconKefuList: icon(ICON_KEYS.MERCHANT_KEFU_LIST, 'icon_kefu_list.png'), iconPunish: icon(ICON_KEYS.MERCHANT_PUNISH, 'icon_punish.png'), iconRank: icon(ICON_KEYS.MERCHANT_RANK, 'icon_rank.png'), iconWithdraw: imgDir + 'icon_withdraw.png', iconRefresh: icon(ICON_KEYS.MERCHANT_REFRESH, 'icon_refresh.png'), iconCopy: imgDir + 'icon_copy.png', avatarFrame: imgDir + 'avatar_frame.png', iconClear: ossBase ? `${ossBase}beijing/tubiao/grzx_qingchu.jpg` : '', iconSwitch: '/images/_exit.png', }), }); }, // 商家状态检查(首次进入拉数据;onShow 不重复请求) checkRoleStatus() { try { const uid = wx.getStorageSync('uid'); const portal = isMerchantPortalUser(); const staffFlag = Number(wx.getStorageSync('staffstatus')) === 1; if (portal) { this.setData({ isShangjia: true, uid: uid || '', staffBooting: false, isLoading: false }); syncStaffUi(this); ensureRoleOnCenterPage(this, 'shangjia'); return; } if (staffFlag) { this.bootStaffPortal(uid); return; } this.setData({ isShangjia: false, staffBooting: false, isLoading: false }); syncStaffUi(this); } catch (error) { console.error('读取商家状态失败', error); this.setData({ isShangjia: false, staffBooting: false, isLoading: false }); syncStaffUi(this); } }, /** 已绑定客服、尚未拉到 context 时恢复身份(不展示商家邀请码) */ async bootStaffPortal(uid) { this.setData({ staffBooting: true, isLoading: true, uid: uid || '' }); syncStaffUi(this); await restoreStaffContextAfterAuth(); if (isMerchantPortalUser()) { this.setData({ isShangjia: true, staffBooting: false, isLoading: false }); syncStaffUi(this); if (isStaffMode()) { await this.loadStaffProfile(); } ensureRoleOnCenterPage(this, 'shangjia'); return; } this.setData({ staffBooting: false, isLoading: false, isShangjia: false }); syncStaffUi(this); wx.showToast({ title: '客服身份已失效,请联系商家老板', icon: 'none' }); }, onInviteCodeInput(e) { this.setData({ inviteCode: (e.detail.value || '').trim() }); }, goToStaffJoin() { wx.navigateTo({ url: '/pages/staff-join/staff-join' }); }, clearCache() { wx.showModal({ title: '清除缓存', content: '将清除所有登录与身份数据,并回到点单端,确定继续?', confirmText: '确定', cancelText: '取消', success: (r) => { if (!r.confirm) return; clearStaffSession(); clearCacheAndEnterNormal(this); }, }); }, async loadStaffProfile() { const ctx = await refreshStaffContext(request); const profile = wx.getStorageSync('nicheng') || (ctx && ctx.display_name) || '商家客服'; this.loadAvatar(); this.setData({ nicheng: (ctx && ctx.display_name) || profile, sjyue: (ctx && ctx.wallet && ctx.wallet.quota_available) || '0.00', chenghaoList: [], isLoading: false, }); syncStaffUi(this); applyStaffStatsToPage(this, ctx); }, // 获取商家信息(仅商家老板;子客服禁止调用) async getShangjiaInfo() { if (isStaffMode() || Number(wx.getStorageSync('staffstatus')) === 1) { return this.loadStaffProfile(); } await this.loadData({ url: '/yonghu/shangjiaxinxi', method: 'POST', successCode: 200, errorMsg: '获取商家信息失败', onSuccess: (data) => { // 更新全局缓存 app.globalData.shangjia = data; wx.setStorageSync('shangjiastatus', 1); const chenghaoList = data.chenghao_list || []; this.setData({ nicheng: data.nicheng || '', sjyue: data.sjyue || '0.00', fabu: data.fabu || data.fadanzong || 0, tuikuan: data.tuikuan || data.tuikuanzong || 0, jinriliushui: data.riliushui || '0.00', jinyueliushui: data.yueliushui || '0.00', jinridingdan: data.jinripaidan || 0, jinrituikuan: data.jinrituikuan || 0, chenghaoList: chenghaoList, isLoading: false, }); this.loadAvatar(); if (this.data.isAutoRegistering) { this.setData({ isAutoRegistering: false }); wx.showToast({ title: '商家注册成功', icon: 'success' }); } }, }); }, refreshShangjiaInfo() { if (isStaffMode()) { this.throttledRefresh(() => this.loadStaffProfile()); return; } this.throttledRefresh(() => { this.getShangjiaInfo(); this.loadPendingCount(); this.loadPunishPending(); this.loadIdentityTags(); }); }, async onPullDownRefresh() { try { if (isStaffMode()) { await this.loadStaffProfile(); } else { await Promise.all([ this.getShangjiaInfo(), this.loadDashboardStats(), this.loadIdentityTags(), ]); } } finally { wx.stopPullDownRefresh(); } }, async loadDashboardStats() { try { const data = await fetchMerchantOrderStats(request, {}); applyOrderStatsToPage(this, data); } catch (e) { console.warn('经营统计失败', e); } }, async loadPendingCount() { return this.loadDashboardStats(); }, async loadPunishPending() { return this.loadDashboardStats(); }, async loadIdentityTags() { try { const res = await request({ url: '/jituan/identity-tag/my-tags', method: 'POST' }); if (res && res.data && (res.data.code === 0 || res.data.code === 200)) { const d = res.data.data || {}; this.setData({ identityTagList: d.shangjia || [] }); } } catch (e) { /* 静默 */ } }, async onRegister() { // 龙先生:商家由后台开通,禁止前端邀请码自助注册 wx.showToast({ title: '请联系客服开通商家', icon: 'none' }); this.setData({ isAutoRegistering: false }); }, previewAvatar() { if (this.data.avatarUrl) { wx.previewImage({ urls: [this.data.avatarUrl] }); } }, editNicheng() { if (!guardMerchantOwnerAction('子客服无法修改商家昵称')) return; wx.showModal({ title: '修改昵称', editable: true, placeholderText: '请输入商家昵称', content: this.data.nicheng || '', success: async (res) => { if (!res.confirm) return; const nicheng = (res.content || '').trim(); if (!nicheng) { wx.showToast({ title: '昵称不能为空', icon: 'none' }); return; } try { const r = await request({ url: '/yonghu/shangjiagxnc', method: 'POST', data: { nicheng }, }); if (r.data && r.data.code === 200) { wx.setStorageSync('nicheng', nicheng); this.setData({ nicheng }); wx.showToast({ title: '昵称已更新', icon: 'success' }); } else { wx.showToast({ title: (r.data && r.data.msg) || '更新失败', icon: 'none' }); } } catch (e) { wx.showToast({ title: '网络错误', icon: 'none' }); } }, }); }, // 页面跳转 goToRegularPaiDan() { wx.navigateTo({ url: '/pages/merchant-regular-dispatch/merchant-regular-dispatch' }); }, goToPaiDan() { wx.navigateTo({ url: '/pages/merchant-dispatch/merchant-dispatch' }); }, goToLinkPaiDan() { wx.vibrateShort({ type: 'medium' }); wx.navigateTo({ url: '/pages/express-order/express-order' }); }, goToMyOrders() { wx.redirectTo({ url: '/pages/merchant-orders/merchant-orders' }); }, goToPendingOrders() { wx.redirectTo({ url: '/pages/merchant-orders/merchant-orders' }); }, goToHome() { wx.redirectTo({ url: '/pages/merchant-home/merchant-home' }); }, goToKefuKey() { wx.navigateTo({ url: '/pages/merchant-kefu-key/merchant-kefu-key' }); }, goToKefuList() { wx.navigateTo({ url: '/pages/merchant-kefu-list/merchant-kefu-list' }); }, goToAuditLog() { wx.navigateTo({ url: '/pages/merchant-staff-audit/merchant-staff-audit' }); }, goToStaffRank() { wx.navigateTo({ url: '/pages/merchant-staff-audit/merchant-staff-audit?tab=rank' }); }, goToRecharge() { if (!guardMerchantOwnerAction('子客服无法充值,请联系商家老板')) return; wx.navigateTo({ url: '/pages/merchant-recharge/merchant-recharge' }); }, goToWithdraw() { if (!guardMerchantOwnerAction('子客服无法提现,请联系商家老板')) return; wx.navigateTo({ url: '/pages/withdraw/withdraw' }); }, goToRanking() { wx.navigateTo({ url: '/pages/fighter-rank/fighter-rank?type=shangjia' }); }, goToMessages() { wx.navigateTo({ url: '/pages/merchant-penalty/merchant-penalty' }); }, goToDataStats() { wx.navigateTo({ url: '/pages/merchant-data-stats/merchant-data-stats' }); }, }, { roleConfig: { role: 'shangjia', statusKey: 'shangjiastatus', dataFlag: 'isShangjia', pageId: 'shangjiaduan', apiUrl: '/yonghu/shangjiaxinxi', }, }));