523 lines
17 KiB
JavaScript
523 lines
17 KiB
JavaScript
// 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',
|
||
},
|
||
}));
|