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

523 lines
17 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.
// 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() {
const { inviteCode } = this.data;
await this.registerWithInviteCode({
inviteCode,
apiUrl: '/yonghu/shangjiahuce',
role: 'shangjia',
statusKey: 'shangjiastatus',
successMsg: '商家注册成功',
onSuccess: (userData) => {
app.globalData.shangjia = userData;
const chenghaoList = userData.chenghao_list || [];
this.setData({
isShangjia: true,
nicheng: userData.nicheng || '',
sjyue: userData.sjyue || '0.00',
fabu: userData.fabu || 0,
tuikuan: userData.tuikuan || 0,
jinriliushui: userData.jinriliushui || '0.00',
jinyueliushui: userData.jinyueliushui || '0.00',
jinridingdan: userData.jinridingdan || 0,
chenghaoList: chenghaoList,
isAutoRegistering: false,
});
this.loadAvatar();
ensureRoleOnCenterPage(this, 'shangjia');
lockPrimaryRole('shangjia');
},
});
},
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',
},
}));