本地备份:商家打手端UI恢复稳定版,后续可回退

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
XingQue
2026-06-27 07:38:01 +08:00
parent fc0ee9a4d1
commit eaf05663ee
24 changed files with 2759 additions and 2098 deletions

View File

@@ -1,8 +1,14 @@
// pages/qiangdan/qiangdan.js // pages/qiangdan/qiangdan.js
const app = getApp(); const app = getApp();
import request from '../../utils/request.js'; import request from '../../utils/request.js';
import { normalizeOrderTags } from '../../utils/order-tags.js';
import { refreshDashouMembership, userHasHuiyuan } from '../../utils/dashou-profile.js';
import { getDefaultAvatarUrl } from '../../utils/avatar.js';
import { warmupPindaoConfig } from '../../utils/miniapp-icons.js';
import PopupService from '../../services/popupService.js'; import PopupService from '../../services/popupService.js';
import { reconnectForRole } from '../../utils/role-tab-bar.js'; import { reconnectForRole } from '../../utils/role-tab-bar.js';
import { ensurePhoneAuth } from '../../utils/phone-auth.js';
import { fetchGonggaoLunbo, isGonggaoCacheValid } from '../../utils/display-config.js';
Page({ Page({
data: { data: {
@@ -29,7 +35,7 @@ Page({
// 4. 刷新控制字段 // 4. 刷新控制字段
scrollViewRefreshing: false, scrollViewRefreshing: false,
lastRefreshTime: 0, lastRefreshTime: 0,
refreshCooldown: 2000, refreshCooldown: 0,
isLoadingMore: false, isLoadingMore: false,
// 5. 切换类型冷却 // 5. 切换类型冷却
@@ -46,13 +52,59 @@ Page({
// 商品轮播展示(只读 globalData无额外接口 // 商品轮播展示(只读 globalData无额外接口
lunboList: [], lunboList: [],
gonggao: '',
examRequired: false,
examPassed: false,
_examChecked: false,
}, },
async onLoad(options) { async onLoad() {
this.syncShopBannerFromGlobal(); if (app.globalData._acceptOrderSessionReady && app.globalData._acceptOrderPageCache) {
const cache = app.globalData._acceptOrderPageCache;
this.setData({ ...cache });
if ((!cache.lunboList || cache.lunboList.length === 0) && !cache.gonggao && isGonggaoCacheValid(app)) {
const lunboList = this.processLunboUrls(app.globalData.shangpinlunbo);
const gonggao = app.globalData.shangpingonggao || '';
this.setData({ lunboList, gonggao });
this.persistPageCache({ lunboList, gonggao });
}
this.loadGlobalStatus(); this.loadGlobalStatus();
await this.loadShangpinLeixing(); this.registerNotificationComponent();
await this.syncDashouProfileFromServer();
this._skipShowRefresh = true;
return;
}
this.loadGlobalStatus();
const banner = await this.loadGonggaoAndLunbo(false);
await this.syncDashouProfileFromServer();
await this.loadShangpinLeixing(true, false, false);
this.persistPageCache(banner);
app.globalData._acceptOrderSessionReady = true;
if (!app.globalData._acceptOrderPopupDone) {
PopupService.checkAndShow(this, 'jiedan'); PopupService.checkAndShow(this, 'jiedan');
app.globalData._acceptOrderPopupDone = true;
}
this._skipShowRefresh = true;
},
persistPageCache(extra = {}) {
const d = this.data;
app.globalData._acceptOrderPageCache = {
shangpinleixing: d.shangpinleixing,
xuanzhongLeixingId: d.xuanzhongLeixingId,
dingdanList: d.dingdanList,
page: d.page,
hasMore: d.hasMore,
bankuaiBiaoqian: d.bankuaiBiaoqian,
xuanzhongBiaoqianId: d.xuanzhongBiaoqianId,
lunboList: extra.lunboList ?? d.lunboList,
gonggao: extra.gonggao ?? d.gonggao,
lastRefreshTime: d.lastRefreshTime,
ossImageUrl: d.ossImageUrl,
};
}, },
onHide: function () { onHide: function () {
@@ -62,63 +114,84 @@ Page({
} }
}, },
onShow() { async onShow() {
this.syncShopBannerFromGlobal(); if (!app.globalData._dashouPhoneChecked) {
const phoneOk = await ensurePhoneAuth({ redirect: true, role: 'dashou' });
if (!phoneOk) return;
app.globalData._dashouPhoneChecked = true;
}
this.registerNotificationComponent(); this.registerNotificationComponent();
this.loadGlobalStatus(); await this.syncDashouProfileFromServer();
warmupPindaoConfig(app);
if (wx.getStorageSync('uid')) { if (wx.getStorageSync('uid')) {
reconnectForRole('dashou'); reconnectForRole('dashou');
if (app.startImWhenReady) app.startImWhenReady(); if (app.startImWhenReady) app.startImWhenReady();
this.refreshDashouProfileSilent();
} }
if (this.data.xuanzhongLeixingId) {
this.loadDingdanList(true); await this.checkExamStatus(false);
if (this._skipShowRefresh) {
this._skipShowRefresh = false;
return;
}
if (app.globalData._acceptOrderSessionReady && !this._silentRefreshRunning) {
this._silentRefreshRunning = true;
this.silentRefreshOnShow().finally(() => {
this._silentRefreshRunning = false;
});
} }
}, },
/** 同步点单端已加载的商品轮播图,仅展示用 */ /** 进入页面静默刷新(无 loading 遮罩、不清空列表) */
syncShopBannerFromGlobal() { async silentRefreshOnShow() {
const oss = app.globalData.ossImageUrl || ''; try {
const lunboList = (app.globalData.shangpinlunbo || []).map((url) => { const banner = await this.loadGonggaoAndLunbo(true);
await this.syncDashouProfileFromServer();
const leixingId = this.data.xuanzhongLeixingId;
if (leixingId) {
await this.loadDingdanList(true, true);
await this.loadBankuaiBiaoqian();
}
this.loadGlobalStatus();
this.persistPageCache(banner);
} catch (e) {
console.error('静默刷新失败:', e);
}
},
/** 公告 + 轮播(首次/下拉强制拉接口,其余读 globalData 或页面缓存) */
processLunboUrls(urlList) {
const oss = app.globalData.ossImageUrl || this.data.ossImageUrl || '';
return (urlList || []).map((url) => {
if (!url) return ''; if (!url) return '';
return url.startsWith('http') ? url : oss + url; return url.startsWith('http') ? url : oss + url;
}).filter(Boolean); }).filter(Boolean);
this.setData({ lunboList });
}, },
async refreshDashouProfileSilent() { async loadGonggaoAndLunbo(forceFetch = false) {
let lunboRaw = app.globalData.shangpinlunbo || [];
let gonggaoText = app.globalData.shangpingonggao || '';
if (forceFetch || !isGonggaoCacheValid(app)) {
try { try {
const res = await request({ url: '/yonghu/dashouxinxi', method: 'POST' }); const data = await fetchGonggaoLunbo(app, 'accept_order');
if (!res || res.data.code != 200) return; if (data) {
const data = res.data.data || {}; lunboRaw = data.shangpinlunbo || app.globalData.shangpinlunbo || [];
const patch = { gonggaoText = data.shangpingonggao || app.globalData.shangpingonggao || '';
dashouNicheng: data.dashounicheng || '',
zhanghaoStatus: data.zhanghaostatus || '',
dashouzhuangtai: data.dashouzhuangtai || '',
yajin: data.yajin || 0,
jifen: data.jifen || 0,
clumber: data.clumber || [],
};
Object.assign(app.globalData, {
dashouNicheng: patch.dashouNicheng,
zhanghaoStatus: patch.zhanghaoStatus,
dashouzhuangtai: patch.dashouzhuangtai,
yajin: patch.yajin,
jinfen: patch.jifen,
clumber: patch.clumber,
});
if (data.dashoustatus !== undefined) {
wx.setStorageSync('dashoustatus', data.dashoustatus);
app.globalData.dashoustatus = data.dashoustatus;
} }
this.setData({ } catch (e) {
zhuanghaoStatus: patch.zhanghaoStatus, lunboRaw = app.globalData.shangpinlunbo || [];
dashouzhuangtai: patch.dashouzhuangtai, gonggaoText = app.globalData.shangpingonggao || '';
huiyuanList: patch.clumber, }
yajin: patch.yajin, }
jifen: patch.jifen,
}); const lunboList = this.processLunboUrls(lunboRaw);
} catch (e) {} const gonggao = gonggaoText;
this.setData({ lunboList, gonggao });
return { lunboList, gonggao };
}, },
registerNotificationComponent() { registerNotificationComponent() {
@@ -144,9 +217,22 @@ Page({
}); });
}, },
/** 拉取最新打手信息(会员/押金/积分),并刷新订单卡片上的会员展示 */
async syncDashouProfileFromServer() {
if (!wx.getStorageSync('token')) return;
await refreshDashouMembership(app);
this.loadGlobalStatus();
if (this.data.dingdanList && this.data.dingdanList.length) {
this.setData({
dingdanList: this.data.dingdanList.map((item) => this.processDingdanItem(item)),
});
}
},
// 加载商品类型 // 加载商品类型
async loadShangpinLeixing() { async loadShangpinLeixing(autoLoadOrders = false, preserveSelection = false, showLoading = true) {
wx.showLoading({ title: '加载商品类型...' }); if (showLoading) wx.showLoading({ title: '加载商品类型...' });
const prevId = this.data.xuanzhongLeixingId;
try { try {
const res = await request({ const res = await request({
url: '/dingdan/dsqdhqddlx', url: '/dingdan/dsqdhqddlx',
@@ -163,14 +249,16 @@ Page({
else if (Array.isArray(data)) list = data; else if (Array.isArray(data)) list = data;
} }
const processedList = this.processTupianUrl(list); const processedList = this.processTupianUrl(list);
const firstId = processedList[0]?.id || null;
const keepPrev = preserveSelection && prevId && processedList.some((i) => i.id === prevId);
const selectedId = keepPrev ? prevId : firstId;
this.setData({ this.setData({
shangpinleixing: processedList, shangpinleixing: processedList,
xuanzhongLeixingId: processedList[0]?.id || null xuanzhongLeixingId: selectedId,
}); });
if (this.data.xuanzhongLeixingId) { if (autoLoadOrders && selectedId) {
this.loadDingdanList(true); await this.loadDingdanList(true);
// 🆕 加载板块标签 await this.loadBankuaiBiaoqian();
this.loadBankuaiBiaoqian();
} }
} else { } else {
wx.showToast({ title: res.data?.msg || '加载商品类型失败', icon: 'none' }); wx.showToast({ title: res.data?.msg || '加载商品类型失败', icon: 'none' });
@@ -178,7 +266,7 @@ Page({
} catch (error) { } catch (error) {
wx.showToast({ title: '网络错误,加载失败', icon: 'none' }); wx.showToast({ title: '网络错误,加载失败', icon: 'none' });
} finally { } finally {
wx.hideLoading(); if (showLoading) wx.hideLoading();
} }
}, },
@@ -245,8 +333,8 @@ Page({
xuanzhongBiaoqianId: 0 // 重置标签筛选 xuanzhongBiaoqianId: 0 // 重置标签筛选
}); });
await this.loadDingdanList(true); await this.loadDingdanList(true);
// 🆕 切换类型后加载新标签
await this.loadBankuaiBiaoqian(); await this.loadBankuaiBiaoqian();
this.persistPageCache();
} catch (error) { } catch (error) {
console.error('切换类型失败:', error); console.error('切换类型失败:', error);
} finally { } finally {
@@ -266,19 +354,24 @@ Page({
hasMore: true hasMore: true
}); });
await this.loadDingdanList(true); await this.loadDingdanList(true);
this.persistPageCache();
}, },
// 加载订单列表 // 加载订单列表
async loadDingdanList(isRefresh = false) { async loadDingdanList(isRefresh = false, silent = false) {
if (this.data.isLoading || !this.data.xuanzhongLeixingId) return; if ((!silent && this.data.isLoading) || !this.data.xuanzhongLeixingId) return;
if (silent && this._listRequesting) return;
const loadPage = isRefresh ? 1 : this.data.page; const loadPage = isRefresh ? 1 : this.data.page;
if (!isRefresh && !this.data.hasMore) return; if (!isRefresh && !this.data.hasMore) return;
if (!silent) {
this.setData({ this.setData({
isLoading: true, isLoading: true,
isLoadingMore: !isRefresh isLoadingMore: !isRefresh,
}); });
}
this._listRequesting = true;
try { try {
const res = await request({ const res = await request({
@@ -298,6 +391,7 @@ Page({
isLoadingMore: false, isLoadingMore: false,
scrollViewRefreshing: false scrollViewRefreshing: false
}); });
this._listRequesting = false;
if (res.data.code === 200 || res.data.code === 0) { if (res.data.code === 200 || res.data.code === 0) {
const newList = res.data.data.list || []; const newList = res.data.data.list || [];
@@ -313,6 +407,7 @@ Page({
page: loadPage, page: loadPage,
hasMore: hasMore hasMore: hasMore
}); });
this.persistPageCache();
if (isRefresh) { if (isRefresh) {
this.setData({ lastRefreshTime: Date.now() }); this.setData({ lastRefreshTime: Date.now() });
@@ -327,20 +422,28 @@ Page({
isLoadingMore: false, isLoadingMore: false,
scrollViewRefreshing: false scrollViewRefreshing: false
}); });
this._listRequesting = false;
if (!silent) {
wx.showToast({ title: '网络请求失败', icon: 'none' }); wx.showToast({ title: '网络请求失败', icon: 'none' });
} }
}
}, },
// 处理单条订单数据(包含标签、会员判断) // 处理单条订单数据(包含标签、会员判断)
processDingdanItem(item) { processDingdanItem(item) {
const ossUrl = app.globalData.ossImageUrl || ''; const ossUrl = app.globalData.ossImageUrl || '';
const leixing = this.data.shangpinleixing.find((l) => l.id == item.leixing_id);
let fullTupianUrl = ''; let fullTupianUrl = '';
if (item.tupian) { // 卡片左上角优先用订单类型图,没有再退回默认图(不用商品图/头像顶替类型)
fullTupianUrl = !item.tupian.startsWith('http') ? ossUrl + item.tupian : item.tupian; if (leixing && leixing.full_tupian_url) {
fullTupianUrl = leixing.full_tupian_url;
} else if (leixing && leixing.tupian_url) {
fullTupianUrl = leixing.tupian_url.startsWith('http')
? leixing.tupian_url
: ossUrl + leixing.tupian_url;
} else { } else {
const leixing = this.data.shangpinleixing.find(l => l.id === item.leixing_id); fullTupianUrl = '/images/default-order.png';
fullTupianUrl = leixing ? leixing.full_tupian_url : '/images/default-order.png';
} }
const isZhiding = item.zhuangtai === 7; const isZhiding = item.zhuangtai === 7;
@@ -353,25 +456,32 @@ Page({
} }
const zhidingNicheng = item.zhiding_nicheng || ''; const zhidingNicheng = item.zhiding_nicheng || '';
// 🆕 判断用户是否有订单所需的会员仅当订单要求会员类型且存在huiyuan_id // 订单要求指定会员时,核对用户是否持有该会员类型
let hasRequiredMember = true; let hasRequiredMember = true;
if (item.yaoqiuleixing == 1 && item.huiyuan_id) { if (item.yaoqiuleixing == 1 && item.huiyuan_id) {
const userHasIt = this.data.huiyuanList.some(h => h.huiyuanid == item.huiyuan_id); hasRequiredMember = userHasHuiyuan(this.data.huiyuanList, item.huiyuan_id);
hasRequiredMember = userHasIt;
} }
let shangjiaAvatar = getDefaultAvatarUrl(app);
const sjAvatar = (item.sj_avatar || '').trim();
if (sjAvatar) {
shangjiaAvatar = sjAvatar.startsWith('http') ? sjAvatar : ossUrl + sjAvatar;
}
const tags = normalizeOrderTags(item)
return { return {
...item, ...item,
full_tupian_url: fullTupianUrl, full_tupian_url: fullTupianUrl,
leixing_icon_url: fullTupianUrl,
shangjia_avatar_full: shangjiaAvatar,
isZhiding: isZhiding, isZhiding: isZhiding,
isPingtai: item.pingtai == 1, isPingtai: item.pingtai == 1,
isShangjia: item.pingtai == 2, isShangjia: item.pingtai == 2,
zhiding_avatar_full: zhidingAvatar, zhiding_avatar_full: zhidingAvatar,
zhiding_nicheng: zhidingNicheng, zhiding_nicheng: zhidingNicheng,
// 🆕 三层标签(后端返回,直接保留) ...tags,
xuqiu_biaoqian: item.xuqiu_biaoqian || [], shangjia_youzhi: !!item.shangjia_youzhi,
dashou_biaoqian: item.dashou_biaoqian || [],
shangjia_biaoqian: item.shangjia_biaoqian || [],
// 🆕 是否有查看价格的权限 // 🆕 是否有查看价格的权限
hasRequiredMember: hasRequiredMember, hasRequiredMember: hasRequiredMember,
}; };
@@ -409,11 +519,50 @@ Page({
}); });
}, },
/** 抢单前考试状态(仅更新状态,不自动跳转考试页) */
async checkExamStatus() {
try {
const res = await request({
url: '/jituan/dashou-exam/status',
method: 'POST',
header: { 'content-type': 'application/json' },
});
const body = res?.data;
if (body && (body.code === 200 || body.code === 0) && body.data) {
const d = body.data;
this.setData({
examRequired: !!d.exam_required,
examPassed: !!d.exam_passed,
});
}
} catch (e) {
console.error('考试状态检查失败', e);
}
return true;
},
// 抢单按钮(原封不动) // 抢单按钮(原封不动)
async onQiangdanTap(e) { async onQiangdanTap(e) {
const dingdanItem = e.currentTarget.dataset.item; const dingdanItem = e.currentTarget.dataset.item;
if (!dingdanItem) return; if (!dingdanItem) return;
await this.checkExamStatus();
if (this.data.examRequired && !this.data.examPassed) {
wx.showModal({
title: '须通过接单考试',
content: '抢单前需先通过接单考试,是否现在去考试?',
confirmText: '去考试',
cancelText: '暂不',
success: (r) => {
if (r.confirm) {
wx.navigateTo({ url: '/pages/dashou-exam/dashou-exam' });
}
},
});
return;
}
// 校验1: 打手身份 // 校验1: 打手身份
if (!this.data.dashoustatus || this.data.dashoustatus != 1) { if (!this.data.dashoustatus || this.data.dashoustatus != 1) {
wx.showToast({ title: '请先开启接单员身份', icon: 'none' }); wx.showToast({ title: '请先开启接单员身份', icon: 'none' });
@@ -438,7 +587,7 @@ Page({
} }
// 校验5: 会员要求 // 校验5: 会员要求
if (dingdanItem.yaoqiuleixing == 1) { if (dingdanItem.yaoqiuleixing == 1) {
const hasHuiyuan = this.data.huiyuanList.some(h => h.huiyuanid == dingdanItem.huiyuan_id); const hasHuiyuan = userHasHuiyuan(this.data.huiyuanList, dingdanItem.huiyuan_id);
if (!hasHuiyuan) { if (!hasHuiyuan) {
wx.showToast({ wx.showToast({
title: '未开通对应会员,无法抢单', title: '未开通对应会员,无法抢单',
@@ -504,6 +653,7 @@ Page({
item => item.dingdan_id !== dingdanItem.dingdan_id item => item.dingdan_id !== dingdanItem.dingdan_id
); );
that.setData({ dingdanList: newList }); that.setData({ dingdanList: newList });
that.persistPageCache();
} else { } else {
wx.showToast({ wx.showToast({
title: qiangdanRes.data.msg || '抢单失败', title: qiangdanRes.data.msg || '抢单失败',
@@ -535,42 +685,14 @@ Page({
}, },
onReachBottom() { onReachBottom() {
const now = Date.now();
const lastTime = this.data.lastRefreshTime;
const cooldown = this.data.refreshCooldown;
if (now - lastTime < cooldown) {
wx.showToast({
title: `操作太快,请${Math.ceil((cooldown - (now - lastTime)) / 1000)}秒后再试`,
icon: 'none',
duration: 1500
});
return;
}
if (this.data.isLoading || this.data.isLoadingMore) return; if (this.data.isLoading || this.data.isLoadingMore) return;
if (this.data.hasMore && !this.data.isLoading && this.data.xuanzhongLeixingId) { if (this.data.hasMore && !this.data.isLoading && this.data.xuanzhongLeixingId) {
this.setData({ page: this.data.page + 1 }); this.setData({ page: this.data.page + 1 });
this.loadDingdanList(false); this.loadDingdanList(false);
} }
}, },
onPullDownRefresh() { async onPullDownRefresh() {
const now = Date.now();
const lastTime = this.data.lastRefreshTime;
const cooldown = this.data.refreshCooldown;
if (now - lastTime < cooldown) {
this.setData({ scrollViewRefreshing: false });
wx.showToast({
title: `操作太快,请${Math.ceil((cooldown - (now - lastTime)) / 1000)}秒后再试`,
icon: 'none',
duration: 1500
});
return;
}
if (this.data.isLoading) { if (this.data.isLoading) {
this.setData({ scrollViewRefreshing: false }); this.setData({ scrollViewRefreshing: false });
return; return;
@@ -578,14 +700,25 @@ Page({
this.setData({ this.setData({
scrollViewRefreshing: true, scrollViewRefreshing: true,
lastRefreshTime: now, lastRefreshTime: Date.now(),
page: 1, page: 1,
hasMore: true hasMore: true,
}); });
if (this.data.xuanzhongLeixingId) { try {
this.loadDingdanList(true); const banner = await this.loadGonggaoAndLunbo(true);
} else { await this.syncDashouProfileFromServer();
await this.loadShangpinLeixing(false, true, false);
const leixingId = this.data.xuanzhongLeixingId;
if (leixingId) {
await this.loadBankuaiBiaoqian();
await this.loadDingdanList(true);
}
this.loadGlobalStatus();
this.persistPageCache(banner);
} catch (e) {
console.error('下拉刷新失败:', e);
} finally {
this.setData({ scrollViewRefreshing: false }); this.setData({ scrollViewRefreshing: false });
} }
} }

View File

@@ -1,6 +1,8 @@
{ {
"navigationBarTitleText": "抢单大厅", "navigationBarTitleText": "抢单大厅",
"navigationBarBackgroundColor": "#f7dc51", "navigationBarBackgroundColor": "#f7dc51",
"backgroundColor": "#f7dc51",
"backgroundColorTop": "#f7dc51",
"navigationBarTextStyle": "black", "navigationBarTextStyle": "black",
"enablePullDownRefresh": false, "enablePullDownRefresh": false,
"backgroundTextStyle": "dark", "backgroundTextStyle": "dark",

View File

@@ -1,4 +1,4 @@
<!-- pages/qiangdan/qiangdan.wxml --> <!-- pages/qiangdan/qiangdan.wxml -->
<view class="qiangdan-page"> <view class="qiangdan-page">
@@ -38,6 +38,12 @@
<!-- 公告置顶 -->
<view class="xym-gonggao-bar" wx:if="{{gonggao}}">
<image class="xym-gonggao-ico" src="/images/notice.png" mode="aspectFit"/>
<text class="xym-gonggao-txt">{{gonggao}}</text>
</view>
<!-- 商品轮播(只读 globalData与点单端同源 --> <!-- 商品轮播(只读 globalData与点单端同源 -->
<view class="xym-lunbo-container" wx:if="{{lunboList.length > 0}}"> <view class="xym-lunbo-container" wx:if="{{lunboList.length > 0}}">
@@ -74,7 +80,7 @@
</view> </view>
<view class="xym-section-gap" wx:if="{{lunboList.length > 0}}"></view>
<!-- 商品类型选择 --> <!-- 商品类型选择 -->
@@ -190,16 +196,6 @@
<view class="order-con"> <view class="order-con">
<view wx:if="{{item.isZhiding}}" class="zhiding-strip myflex light">
<text class="zhiding-label">指定</text>
<image wx:if="{{item.zhiding_avatar_full}}" class="zhiding-avatar" src="{{item.zhiding_avatar_full}}" mode="aspectFill"/>
<text class="zhiding-name">{{item.zhiding_nicheng || '指定接单员'}}</text>
</view>
<view class="order-row myflex"> <view class="order-row myflex">
<image class="o-logo" src="{{item.full_tupian_url}}" mode="aspectFill"/> <image class="o-logo" src="{{item.full_tupian_url}}" mode="aspectFill"/>
@@ -212,6 +208,20 @@
</view> </view>
<block wx:if="{{item.isZhiding}}">
<view class="zhiding-strip light">
<view class="zhiding-strip-top myflex">
<text class="zhiding-label">指定</text>
<image wx:if="{{item.zhiding_avatar_full}}" class="zhiding-avatar" src="{{item.zhiding_avatar_full}}" mode="aspectFill"/>
<text class="zhiding-name">{{item.zhiding_nicheng || '指定接单员'}}</text>
</view>
<view wx:if="{{item.dashou_biaoqian.length > 0 || item.zhiding_identity_biaoqian.length > 0}}" class="zhiding-strip-tags">
<chenghao-tag wx:for="{{item.dashou_biaoqian}}" wx:for-item="tag" wx:key="id" mingcheng="{{tag.mingcheng}}" texiaoJson="{{tag.texiao_json}}" />
<chenghao-tag wx:for="{{item.zhiding_identity_biaoqian}}" wx:for-item="tag" wx:key="id" mingcheng="{{tag.mingcheng}}" texiaoJson="{{tag.texiao_json}}" />
</view>
</view>
</block>
<view class="reward-badge platform-reward" wx:if="{{item.hasRequiredMember}}"> <view class="reward-badge platform-reward" wx:if="{{item.hasRequiredMember}}">
<text class="reward-yen sm">¥</text> <text class="reward-yen sm">¥</text>
@@ -226,9 +236,9 @@
</view> </view>
<view wx:if="{{item.beizhu}}" class="remark-block gold" data-type="beizhu" data-content="{{item.beizhu}}" bindtap="onViewDetail"> <view class="remark-block gold" data-type="beizhu" data-content="{{item.beizhu}}" bindtap="onViewDetail">
<text class="remark-label">备注:</text>{{item.beizhu}} <text class="remark-label">备注:</text>{{item.beizhu || '暂无'}}
</view> </view>
@@ -236,10 +246,10 @@
<text class="xuqiu-label">需求标签</text> <text class="xuqiu-label">需求标签</text>
<scroll-view class="biaoqian-inline-scroll" scroll-x> <scroll-view class="biaoqian-inline-scroll" scroll-x enable-flex>
<view class="biaoqian-inline-inner">
<chenghao-tag wx:for="{{item.xuqiu_biaoqian}}" wx:for-item="tag" wx:key="id" mingcheng="{{tag.mingcheng}}" texiaoJson="{{tag.texiao_json}}" /> <chenghao-tag wx:for="{{item.xuqiu_biaoqian}}" wx:for-item="tag" wx:key="id" mingcheng="{{tag.mingcheng}}" texiaoJson="{{tag.texiao_json}}" />
</view>
</scroll-view> </scroll-view>
</view> </view>
@@ -260,6 +270,81 @@
<!-- 优质商家订单(金牌卡片) -->
<view wx:elif="{{item.isShangjia && item.shangjia_youzhi}}" class="xym-order-item gold-card" data-item="{{item}}">
<view class="gold-head flexb">
<view class="kehuduan-banner-wrap">
<image class="gold-banner" src="https://bintao.xmxym88.com/xcx/bintao/82.png" mode="widthFix"/>
</view>
</view>
<view class="gold-body-wrap">
<view class="order-con gold-inner">
<view class="order-row myflex">
<image class="o-logo" src="{{item.leixing_icon_url}}" mode="aspectFill"/>
<view class="o-col">
<view class="o-goods line2" data-type="jieshao" data-content="{{item.jieshao}}" bindtap="onViewDetail">{{item.jieshao || '暂无介绍'}}</view>
<view class="tag-row myflex">
<text class="tag-pill tag-youzhi">优质商家</text>
</view>
</view>
</view>
<block wx:if="{{item.isZhiding}}">
<view class="zhiding-strip">
<view class="zhiding-strip-top myflex">
<text class="zhiding-label">指定</text>
<image wx:if="{{item.zhiding_avatar_full}}" class="zhiding-avatar" src="{{item.zhiding_avatar_full}}" mode="aspectFill"/>
<text class="zhiding-name">{{item.zhiding_nicheng || '指定接单员'}}</text>
</view>
<view wx:if="{{item.dashou_biaoqian.length > 0 || item.zhiding_identity_biaoqian.length > 0}}" class="zhiding-strip-tags">
<chenghao-tag wx:for="{{item.dashou_biaoqian}}" wx:for-item="tag" wx:key="id" mingcheng="{{tag.mingcheng}}" texiaoJson="{{tag.texiao_json}}" />
<chenghao-tag wx:for="{{item.zhiding_identity_biaoqian}}" wx:for-item="tag" wx:key="id" mingcheng="{{tag.mingcheng}}" texiaoJson="{{tag.texiao_json}}" />
</view>
</view>
</block>
<view class="reward-badge normal-reward gold-reward" wx:if="{{item.hasRequiredMember}}">
<text class="reward-yen sm">¥</text>
<text class="reward-num dark">{{item.dashou_fencheng || 0}}</text>
</view>
<view class="reward-badge member-tip" wx:else>
<text class="reward-tip">未开通会员</text>
</view>
<view class="remark-block dark" data-type="beizhu" data-content="{{item.beizhu}}" bindtap="onViewDetail">
<text class="remark-label dark-t">商家备注:</text>{{item.beizhu || '暂无'}}
</view>
<view wx:if="{{item.shangjia_biaoqian.length > 0 || item.shangjia_identity_biaoqian.length > 0 || item.xuqiu_biaoqian.length > 0}}" class="xuqiu-tags-row">
<scroll-view wx:if="{{item.shangjia_biaoqian.length > 0}}" class="biaoqian-inline-scroll" scroll-x enable-flex>
<view class="biaoqian-inline-inner">
<chenghao-tag wx:for="{{item.shangjia_biaoqian}}" wx:for-item="tag" wx:key="id" mingcheng="{{tag.mingcheng}}" texiaoJson="{{tag.texiao_json}}" />
</view>
</scroll-view>
<scroll-view wx:if="{{item.shangjia_identity_biaoqian.length > 0}}" class="biaoqian-inline-scroll" scroll-x enable-flex style="margin-top:8rpx">
<view class="biaoqian-inline-inner">
<chenghao-tag wx:for="{{item.shangjia_identity_biaoqian}}" wx:for-item="tag" wx:key="id" mingcheng="{{tag.mingcheng}}" texiaoJson="{{tag.texiao_json}}" />
</view>
</scroll-view>
<scroll-view wx:if="{{item.xuqiu_biaoqian.length > 0}}" class="biaoqian-inline-scroll" scroll-x enable-flex style="margin-top:8rpx">
<view class="biaoqian-inline-inner">
<chenghao-tag wx:for="{{item.xuqiu_biaoqian}}" wx:for-item="tag" wx:key="id" mingcheng="{{tag.mingcheng}}" texiaoJson="{{tag.texiao_json}}" />
</view>
</scroll-view>
</view>
<view class="merchant-plain flexb">
<view class="merchant-user myflex">
<image class="m-avatar" src="{{item.shangjia_avatar_full}}" mode="aspectFill"/>
<view class="m-info">
<view class="m-name m-name-light line1">{{item.sjnicheng || '未知商家'}}</view>
<view class="m-sn m-sn-light">发布于 {{item.creat_time}}</view>
</view>
</view>
<view class="qiangdan flexa btn-bg btn-qiang" data-item="{{item}}" bindtap="onQiangdanTap">抢单</view>
</view>
<view class="o-foot flexb kehuduan-foot gold-foot-text-only">
<text class="o-amt-grey">商家派单</text>
</view>
</view>
</view>
</view>
<!-- 商家订单(逍遥梦卡片布局) --> <!-- 商家订单(逍遥梦卡片布局) -->
<view wx:elif="{{item.isShangjia}}" class="xym-order-item xym-shangjia-order" data-item="{{item}}"> <view wx:elif="{{item.isShangjia}}" class="xym-order-item xym-shangjia-order" data-item="{{item}}">
@@ -276,19 +361,23 @@
<view class="order-con"> <view class="order-con">
<view wx:if="{{item.isZhiding}}" class="zhiding-strip myflex"> <block wx:if="{{item.isZhiding}}">
<view class="zhiding-strip">
<view class="zhiding-strip-top myflex">
<text class="zhiding-label">指定</text> <text class="zhiding-label">指定</text>
<image wx:if="{{item.zhiding_avatar_full}}" class="zhiding-avatar" src="{{item.zhiding_avatar_full}}" mode="aspectFill"/> <image wx:if="{{item.zhiding_avatar_full}}" class="zhiding-avatar" src="{{item.zhiding_avatar_full}}" mode="aspectFill"/>
<text class="zhiding-name">{{item.zhiding_nicheng || '指定接单员'}}</text> <text class="zhiding-name">{{item.zhiding_nicheng || '指定接单员'}}</text>
</view> </view>
<view wx:if="{{item.dashou_biaoqian.length > 0 || item.zhiding_identity_biaoqian.length > 0}}" class="zhiding-strip-tags">
<chenghao-tag wx:for="{{item.dashou_biaoqian}}" wx:for-item="tag" wx:key="id" mingcheng="{{tag.mingcheng}}" texiaoJson="{{tag.texiao_json}}" />
<chenghao-tag wx:for="{{item.zhiding_identity_biaoqian}}" wx:for-item="tag" wx:key="id" mingcheng="{{tag.mingcheng}}" texiaoJson="{{tag.texiao_json}}" />
</view>
</view>
</block>
<view class="merchant-line myflex"> <view class="merchant-line myflex">
<image class="m-avatar-sm" src="{{item.full_tupian_url}}" mode="aspectFill"/> <image class="m-avatar-sm" src="{{item.shangjia_avatar_full}}" mode="aspectFill"/>
<text class="m-name-sm">{{item.sjnicheng || '未知商家'}}</text> <text class="m-name-sm">{{item.sjnicheng || '未知商家'}}</text>
@@ -318,24 +407,33 @@
</view> </view>
<view wx:if="{{item.beizhu}}" class="remark-block dark" data-type="beizhu" data-content="{{item.beizhu}}" bindtap="onViewDetail"> <view class="remark-block dark" data-type="beizhu" data-content="{{item.beizhu}}" bindtap="onViewDetail">
<text class="remark-label">商家备注:</text>{{item.beizhu}} <text class="remark-label">商家备注:</text>{{item.beizhu || '暂无'}}
</view> </view>
<view wx:if="{{item.shangjia_biaoqian.length > 0 || item.xuqiu_biaoqian.length > 0}}" class="xuqiu-tags-row"> <view wx:if="{{item.shangjia_biaoqian.length > 0 || item.shangjia_identity_biaoqian.length > 0 || item.xuqiu_biaoqian.length > 0}}" class="xuqiu-tags-row">
<scroll-view wx:if="{{item.shangjia_biaoqian.length > 0}}" class="biaoqian-inline-scroll" scroll-x> <scroll-view wx:if="{{item.shangjia_biaoqian.length > 0}}" class="biaoqian-inline-scroll" scroll-x enable-flex>
<view class="biaoqian-inline-inner">
<chenghao-tag wx:for="{{item.shangjia_biaoqian}}" wx:for-item="tag" wx:key="id" mingcheng="{{tag.mingcheng}}" texiaoJson="{{tag.texiao_json}}" /> <chenghao-tag wx:for="{{item.shangjia_biaoqian}}" wx:for-item="tag" wx:key="id" mingcheng="{{tag.mingcheng}}" texiaoJson="{{tag.texiao_json}}" />
</view>
</scroll-view> </scroll-view>
<scroll-view wx:if="{{item.xuqiu_biaoqian.length > 0}}" class="biaoqian-inline-scroll" scroll-x style="margin-top:8rpx"> <scroll-view wx:if="{{item.shangjia_identity_biaoqian.length > 0}}" class="biaoqian-inline-scroll" scroll-x enable-flex style="margin-top:8rpx">
<view class="biaoqian-inline-inner">
<chenghao-tag wx:for="{{item.shangjia_identity_biaoqian}}" wx:for-item="tag" wx:key="id" mingcheng="{{tag.mingcheng}}" texiaoJson="{{tag.texiao_json}}" />
</view>
</scroll-view>
<scroll-view wx:if="{{item.xuqiu_biaoqian.length > 0}}" class="biaoqian-inline-scroll" scroll-x enable-flex style="margin-top:8rpx">
<view class="biaoqian-inline-inner">
<chenghao-tag wx:for="{{item.xuqiu_biaoqian}}" wx:for-item="tag" wx:key="id" mingcheng="{{tag.mingcheng}}" texiaoJson="{{tag.texiao_json}}" /> <chenghao-tag wx:for="{{item.xuqiu_biaoqian}}" wx:for-item="tag" wx:key="id" mingcheng="{{tag.mingcheng}}" texiaoJson="{{tag.texiao_json}}" />
</view>
</scroll-view> </scroll-view>
</view> </view>

View File

@@ -1,5 +1,11 @@
/* pages/qiangdan/qiangdan.wxss - 高级机甲风格重构版(对称优化) */ /* pages/qiangdan/qiangdan.wxss - 逍遥梦抢单页 */
@import '../../styles/dashou-xym-theme.wxss'; @import '../../styles/dashou-xym-theme.wxss';
@import '../../styles/dashou-xym-order-card.wxss';
page {
background-color: #f7dc51;
}
.qiangdan-page { .qiangdan-page {
height: 100vh; height: 100vh;
display: flex; display: flex;
@@ -126,6 +132,7 @@
flex: 1; flex: 1;
height: 0; height: 0;
-webkit-overflow-scrolling: touch; -webkit-overflow-scrolling: touch;
background: transparent;
} }
.scroll-bottom-spacer { .scroll-bottom-spacer {
@@ -763,5 +770,3 @@
margin-left: auto; margin-left: auto;
max-width: 50%; max-width: 50%;
} }
@import '../../styles/dashou-xym-order-card.wxss';

View File

@@ -1,7 +1,7 @@
// pages/fighter-order-detail/fighter-order-detail.js - 【最终版:提交前公告弹窗 + 修改图片至少保留一张】 // pages/fighter-order-detail/fighter-order-detail.js - 【最终版:提交前公告弹窗 + 修改图片至少保留一张】
const app = getApp() const app = getApp()
import request from '../../utils/request.js' import request from '../../utils/request.js'
const COS = require('../../utils/cos-wx-sdk-v5.js') const COS = require('../../utils/cos-wx-sdk-v5.min.js')
Page({ Page({
data: { data: {

View File

@@ -49,7 +49,14 @@ Page(createPage({
onLoad() { onLoad() {
wx.setNavigationBarTitle({ title: '我的接单' }); wx.setNavigationBarTitle({ title: '我的接单' });
this.loadShangpinLeixing(); this.loadShangpinLeixing().then(() => {
if (this.data.xuanzhongLeixingId) {
return this.loadCurrentStatusOrders(true);
}
}).finally(() => {
this._ordersSessionReady = true;
this._skipShowRefresh = true;
});
this.registerNotificationComponent(); this.registerNotificationComponent();
}, },
@@ -59,8 +66,15 @@ Page(createPage({
reconnectForRole('dashou'); reconnectForRole('dashou');
if (app.startImWhenReady) app.startImWhenReady(); if (app.startImWhenReady) app.startImWhenReady();
} }
if (this.data.currentStatusKey && this.data.xuanzhongLeixingId) { if (this._skipShowRefresh) {
this.loadCurrentStatusOrders(true); this._skipShowRefresh = false;
return;
}
if (this._ordersSessionReady && this.data.xuanzhongLeixingId && !this._silentRefreshRunning) {
this._silentRefreshRunning = true;
this.loadCurrentStatusOrders(true, true).finally(() => {
this._silentRefreshRunning = false;
});
} }
}, },
@@ -141,17 +155,21 @@ Page(createPage({
}, },
// 加载订单(核心) // 加载订单(核心)
async loadCurrentStatusOrders(isRefresh = false) { async loadCurrentStatusOrders(isRefresh = false, silent = false) {
const key = this.data.currentStatusKey; const key = this.data.currentStatusKey;
const tabData = this.data.dsDingdanShuju[key]; const tabData = this.data.dsDingdanShuju[key];
if (tabData.isLoading) return; if (tabData.isLoading && !silent) return;
if (silent && this._listRequesting) return;
const page = isRefresh ? 1 : tabData.page; const page = isRefresh ? 1 : tabData.page;
if (!silent) {
this.setData({ this.setData({
[`dsDingdanShuju.${key}.isLoading`]: true, [`dsDingdanShuju.${key}.isLoading`]: true,
isLoading: true, isLoading: true,
isLoadingMore: !isRefresh isLoadingMore: !isRefresh,
}); });
}
this._listRequesting = true;
try { try {
const apiUrl = this.data.orderType === 'peihu' const apiUrl = this.data.orderType === 'peihu'
@@ -208,7 +226,10 @@ Page(createPage({
} }
} catch (err) { } catch (err) {
console.error('加载订单失败', err); console.error('加载订单失败', err);
if (!silent) {
wx.showToast({ title: err.message || '加载失败', icon: 'none' }); wx.showToast({ title: err.message || '加载失败', icon: 'none' });
}
if (!silent) {
this.setData({ this.setData({
[`dsDingdanShuju.${key}.isLoading`]: false, [`dsDingdanShuju.${key}.isLoading`]: false,
isLoading: false, isLoading: false,
@@ -217,6 +238,9 @@ Page(createPage({
}); });
this.refreshCurrentListView(); this.refreshCurrentListView();
} }
} finally {
this._listRequesting = false;
}
}, },
refreshCurrentListView() { refreshCurrentListView() {

View File

@@ -1,6 +1,7 @@
{ {
"usingComponents": { "usingComponents": {
"global-notification": "/components/global-notification/global-notification" "global-notification": "/components/global-notification/global-notification",
"tab-bar": "/tab-bar/index"
}, },
"navigationBarTitleText": "我的接单", "navigationBarTitleText": "我的接单",
"enablePullDownRefresh": false, "enablePullDownRefresh": false,

View File

@@ -1,9 +1,14 @@
/** /**
* 排行榜 POST /yonghu/phbhqsj * 排行榜
* 参数: shenfen(dashou|guanshi|zuzhang|shangjia), riqi(今日|本周|本月|总榜|昨日|上周|上月) * 默认 POST /yonghu/phbhqsj
* 星之界(xzj) POST /yonghu/xzjphbhqsj邀请人数排序等专用规则
*/ */
import request from '../../utils/request.js' import request from '../../utils/request.js'
import { resolveAvatarUrl, getDefaultAvatarUrl } from '../../utils/avatar.js' import { resolveAvatarUrl, getDefaultAvatarUrl } from '../../utils/avatar.js'
import { CLUB_ID } from '../../config/club-config.js'
const IS_XZJ = CLUB_ID === 'xzj'
const RANK_API = IS_XZJ ? '/yonghu/xzjphbhqsj' : '/yonghu/phbhqsj'
const ROLE_LIST = [ const ROLE_LIST = [
{ key: 'dashou', label: '接单员' }, { key: 'dashou', label: '接单员' },
@@ -27,6 +32,7 @@ const ROLE_META = {
title: '接单员排行榜', title: '接单员排行榜',
sortField: 'chengjiao_zonge', sortField: 'chengjiao_zonge',
sortLabel: '分红总额', sortLabel: '分红总额',
mainType: 'money',
metrics: [ metrics: [
{ field: 'jiedan_zongliang', label: '接单量', type: 'int' }, { field: 'jiedan_zongliang', label: '接单量', type: 'int' },
{ field: 'jiedan_zonge', label: '接单额', type: 'money' }, { field: 'jiedan_zonge', label: '接单额', type: 'money' },
@@ -37,6 +43,7 @@ const ROLE_META = {
title: '管事排行榜', title: '管事排行榜',
sortField: 'shouru_zonge', sortField: 'shouru_zonge',
sortLabel: '收入总额', sortLabel: '收入总额',
mainType: 'money',
metrics: [ metrics: [
{ field: 'yaoqing_dashou_shu', label: '邀请', type: 'int' }, { field: 'yaoqing_dashou_shu', label: '邀请', type: 'int' },
{ field: 'chongzhi_dashou_shu', label: '充值', type: 'int' }, { field: 'chongzhi_dashou_shu', label: '充值', type: 'int' },
@@ -46,6 +53,7 @@ const ROLE_META = {
title: '组长排行榜', title: '组长排行榜',
sortField: 'shouru_zonge', sortField: 'shouru_zonge',
sortLabel: '收入总额', sortLabel: '收入总额',
mainType: 'money',
metrics: [ metrics: [
{ field: 'yaoqing_guanshi_shu', label: '邀请', type: 'int' }, { field: 'yaoqing_guanshi_shu', label: '邀请', type: 'int' },
{ field: 'fenyong_jine', label: '分佣', type: 'money' }, { field: 'fenyong_jine', label: '分佣', type: 'money' },
@@ -55,6 +63,7 @@ const ROLE_META = {
title: '商家排行榜', title: '商家排行榜',
sortField: 'jiesuan_jine', sortField: 'jiesuan_jine',
sortLabel: '成交总额', sortLabel: '成交总额',
mainType: 'money',
metrics: [ metrics: [
{ field: 'jiesuan_dingdan_shu', label: '成交量', type: 'int' }, { field: 'jiesuan_dingdan_shu', label: '成交量', type: 'int' },
{ field: 'paifa_dingdan_shu', label: '派单量', type: 'int' }, { field: 'paifa_dingdan_shu', label: '派单量', type: 'int' },
@@ -63,6 +72,55 @@ const ROLE_META = {
}, },
} }
/** 星之界专用展示与排序字段 */
const XZJ_ROLE_META = {
dashou: {
title: '接单员排行榜',
sortField: 'chengjiao_zonge',
sortLabel: '成交金额',
mainType: 'money',
metrics: [
{ field: 'jiedan_zongliang', label: '接单量', type: 'int' },
{ field: 'jiedan_zonge', label: '接单额', type: 'money' },
{ field: 'chengjiao_zongliang', label: '成交量', type: 'int' },
],
},
guanshi: {
title: '管事排行榜',
sortField: 'yaoqing_dashou_shu',
sortLabel: '邀请人数',
mainType: 'int',
metrics: [
{ field: 'wuxiao_yaoqing_dashou_shu', label: '无效邀请', type: 'int' },
{ field: 'chongzhi_dashou_shu', label: '有效人数', type: 'int' },
{ field: 'shouru_zonge', label: '收入金额', type: 'money' },
],
},
zuzhang: {
title: '组长排行榜',
sortField: 'yaoqing_guanshi_shu',
sortLabel: '邀请人数',
mainType: 'int',
metrics: [
{ field: 'wuxiao_yaoqing_guanshi_shu', label: '无效邀请', type: 'int' },
{ field: 'youxiao_guanshi_shu', label: '有效人数', type: 'int' },
{ field: 'shouru_zonge', label: '收入金额', type: 'money' },
],
},
shangjia: {
title: '商家排行榜',
sortField: 'paifa_jine',
sortLabel: '派单流水',
mainType: 'money',
metrics: [
{ field: 'paifa_dingdan_shu', label: '派单量', type: 'int' },
{ field: 'paifa_jine', label: '派单流水', type: 'money' },
],
},
}
const ACTIVE_ROLE_META = IS_XZJ ? XZJ_ROLE_META : ROLE_META
function isInvalidAvatarPath(path) { function isInvalidAvatarPath(path) {
if (path === null || path === undefined) return true if (path === null || path === undefined) return true
if (typeof path !== 'string') return true if (typeof path !== 'string') return true
@@ -99,7 +157,7 @@ Page({
onLoad(options) { onLoad(options) {
const type = options.type || options.rankType || 'dashou' const type = options.type || options.rankType || 'dashou'
const validRole = ROLE_META[type] ? type : 'dashou' const validRole = ACTIVE_ROLE_META[type] ? type : 'dashou'
this.initPage() this.initPage()
this.applyRole(validRole, false) this.applyRole(validRole, false)
this.fetchRankList() this.fetchRankList()
@@ -162,7 +220,7 @@ Page({
}, },
applyRole(role, reload = true) { applyRole(role, reload = true) {
const meta = ROLE_META[role] const meta = ACTIVE_ROLE_META[role]
wx.setNavigationBarTitle({ title: meta.title }) wx.setNavigationBarTitle({ title: meta.title })
this.setData({ currentRole: role, roleMeta: meta, sortLabel: meta.sortLabel }) this.setData({ currentRole: role, roleMeta: meta, sortLabel: meta.sortLabel })
if (reload) this.fetchRankList() if (reload) this.fetchRankList()
@@ -196,7 +254,7 @@ Page({
}, },
normalizeItem(raw, index, role) { normalizeItem(raw, index, role) {
const meta = ROLE_META[role] const meta = ACTIVE_ROLE_META[role]
const app = getApp() const app = getApp()
const uid = raw.yonghuid || raw.uid || '' const uid = raw.yonghuid || raw.uid || ''
const nicheng = raw.nicheng || raw.nick || '用户' const nicheng = raw.nicheng || raw.nick || '用户'
@@ -209,12 +267,19 @@ Page({
value: m.type === 'money' ? this.formatMoney(v) : this.formatInt(v), value: m.type === 'money' ? this.formatMoney(v) : this.formatInt(v),
} }
}) })
const sortRaw = raw[meta.sortField]
const mainType = meta.mainType || 'money'
const mainValue = mainType === 'money'
? this.formatMoney(sortRaw)
: this.formatInt(sortRaw)
return { return {
mingci: raw.mingci || index + 1, mingci: raw.mingci || index + 1,
uid, uid,
nicheng, nicheng,
avatar, avatar,
mainValue: this.formatMoney(raw[meta.sortField]), mainType,
mainPrefix: mainType === 'money' ? '¥' : '',
mainValue,
mainLabel: meta.sortLabel, mainLabel: meta.sortLabel,
metrics, metrics,
} }
@@ -224,7 +289,7 @@ Page({
this.setData({ isLoading: true, isEmpty: false }) this.setData({ isLoading: true, isEmpty: false })
try { try {
const res = await request({ const res = await request({
url: '/yonghu/phbhqsj', url: RANK_API,
method: 'POST', method: 'POST',
data: { shenfen: this.data.currentRole, riqi: this.data.currentDate }, data: { shenfen: this.data.currentRole, riqi: this.data.currentDate },
}) })

View File

@@ -52,7 +52,7 @@
<text class="p-name">{{topThree[1].nicheng}}</text> <text class="p-name">{{topThree[1].nicheng}}</text>
<text class="p-uid">ID {{topThree[1].uid}}</text> <text class="p-uid">ID {{topThree[1].uid}}</text>
<view class="p-amount"> <view class="p-amount">
<text class="p-money">¥{{topThree[1].mainValue}}</text> <text class="p-money">{{topThree[1].mainPrefix}}{{topThree[1].mainValue}}</text>
<text class="p-label">{{topThree[1].mainLabel}}</text> <text class="p-label">{{topThree[1].mainLabel}}</text>
</view> </view>
<view class="p-metrics"> <view class="p-metrics">
@@ -70,7 +70,7 @@
<text class="p-name p-name-first">{{topThree[0].nicheng}}</text> <text class="p-name p-name-first">{{topThree[0].nicheng}}</text>
<text class="p-uid">ID {{topThree[0].uid}}</text> <text class="p-uid">ID {{topThree[0].uid}}</text>
<view class="p-amount"> <view class="p-amount">
<text class="p-money p-money-first">¥{{topThree[0].mainValue}}</text> <text class="p-money p-money-first">{{topThree[0].mainPrefix}}{{topThree[0].mainValue}}</text>
<text class="p-label">{{topThree[0].mainLabel}}</text> <text class="p-label">{{topThree[0].mainLabel}}</text>
</view> </view>
<view class="p-metrics"> <view class="p-metrics">
@@ -88,7 +88,7 @@
<text class="p-name">{{topThree[2].nicheng}}</text> <text class="p-name">{{topThree[2].nicheng}}</text>
<text class="p-uid">ID {{topThree[2].uid}}</text> <text class="p-uid">ID {{topThree[2].uid}}</text>
<view class="p-amount"> <view class="p-amount">
<text class="p-money">¥{{topThree[2].mainValue}}</text> <text class="p-money">{{topThree[2].mainPrefix}}{{topThree[2].mainValue}}</text>
<text class="p-label">{{topThree[2].mainLabel}}</text> <text class="p-label">{{topThree[2].mainLabel}}</text>
</view> </view>
<view class="p-metrics"> <view class="p-metrics">
@@ -120,7 +120,7 @@
</view> </view>
</view> </view>
<view class="lc-score"> <view class="lc-score">
<text class="lc-money">¥{{item.mainValue}}</text> <text class="lc-money">{{item.mainPrefix}}{{item.mainValue}}</text>
<text class="lc-label">{{item.mainLabel}}</text> <text class="lc-label">{{item.mainLabel}}</text>
</view> </view>
</view> </view>

View File

@@ -1,7 +1,7 @@
// pages/dashou-chongzhi/index.js // pages/dashou-chongzhi/index.js
import request from '../../utils/request'; import request from '../../utils/request';
// 引入弹窗服务(路径根据实际调整)
import PopupService from '../../services/popupService.js'; import PopupService from '../../services/popupService.js';
import { ensurePhoneAuth } from '../../utils/phone-auth.js';
Page({ Page({
data: { data: {
@@ -31,13 +31,7 @@ Page({
huiyuanListHeight: 120, huiyuanListHeight: 120,
// ========== 会员详情规则 ========== // ========== 会员详情规则 ==========
detailRules: [ detailRules: [],
'会员有效期为30天从购买当天开始计算',
'会员期间享受优先接单特权',
'可享受专属客服服务',
'会员到期前3天会有提醒',
'支持随时续费,续费天数叠加'
],
// ========== 新增:跳转参数处理 ========== // ========== 新增:跳转参数处理 ==========
// 用于接收从其他页面跳转过来的参数,决定是否自动滚动 // 用于接收从其他页面跳转过来的参数,决定是否自动滚动
@@ -47,6 +41,7 @@ Page({
showPayMethodModal: false, // 支付方式选择弹窗 showPayMethodModal: false, // 支付方式选择弹窗
currentBuyType: null, // 当前购买类型1会员 2押金 3积分 currentBuyType: null, // 当前购买类型1会员 2押金 3积分
currentHuiyuanId: null, // 当前选中的会员ID用于会员购买 currentHuiyuanId: null, // 当前选中的会员ID用于会员购买
currentBuyIsTrial: false, // 正式/体验:仅体验禁余额抵扣
currentYajinAmount: null, // 当前押金金额(用于押金购买) currentYajinAmount: null, // 当前押金金额(用于押金购买)
// ========== 新增:余额抵扣身份选择 ========== // ========== 新增:余额抵扣身份选择 ==========
@@ -83,7 +78,10 @@ onHide() {
} }
}, },
onShow() { async onShow() {
const phoneOk = await ensurePhoneAuth({ redirect: true, role: 'dashou' });
if (!phoneOk) return;
// 每次显示页面都刷新数据 // 每次显示页面都刷新数据
this.registerNotificationComponent(); this.registerNotificationComponent();
this.loadFromGlobalData(); this.loadFromGlobalData();
@@ -132,8 +130,11 @@ onHide() {
// ✅ 重要:保持字段对应关系 // ✅ 重要:保持字段对应关系
// 全局变量中是 clumber页面中是 clubmber // 全局变量中是 clumber页面中是 clubmber
// 全局变量中是 jinfen页面中是 jifen // 全局变量中是 jinfen页面中是 jifen
const rawClubmber = globalData.clumber || [];
const clubmber = rawClubmber.filter((c) => c && c.huiyuanid);
this.setData({ this.setData({
clubmber: globalData.clumber || [], clubmber: clubmber,
yajin: globalData.yajin || 0, yajin: globalData.yajin || 0,
jifen: globalData.jinfen || 0 // ✅ 注意:这里从 jinfen 读取 jifen: globalData.jinfen || 0 // ✅ 注意:这里从 jinfen 读取
}); });
@@ -181,9 +182,11 @@ onHide() {
// 处理数据,标记已购买的会员 // 处理数据,标记已购买的会员
const processedList = this.processHuiyuanList(huiyuanList); const processedList = this.processHuiyuanList(huiyuanList);
const currentHuiyuan = processedList[0] || {};
this.setData({ this.setData({
huiyuanList: processedList, huiyuanList: processedList,
currentHuiyuan: processedList[0] || {} currentHuiyuan,
detailRules: this.buildDetailRules(currentHuiyuan)
}); });
} else { } else {
wx.showToast({ wx.showToast({
@@ -220,10 +223,12 @@ onHide() {
onSwiperChange(e) { onSwiperChange(e) {
const current = e.detail.current; const current = e.detail.current;
const huiyuanList = this.data.huiyuanList || []; const huiyuanList = this.data.huiyuanList || [];
const currentHuiyuan = huiyuanList[current] || {};
this.setData({ this.setData({
currentHuiyuanIndex: current, currentHuiyuanIndex: current,
currentHuiyuan: huiyuanList[current] || {} currentHuiyuan,
detailRules: this.buildDetailRules(currentHuiyuan)
}); });
}, },
@@ -232,12 +237,31 @@ onHide() {
const index = e.currentTarget.dataset.index; const index = e.currentTarget.dataset.index;
const huiyuanList = this.data.huiyuanList || []; const huiyuanList = this.data.huiyuanList || [];
const currentHuiyuan = huiyuanList[index] || {};
this.setData({ this.setData({
currentHuiyuanIndex: index, currentHuiyuanIndex: index,
currentHuiyuan: huiyuanList[index] || {} currentHuiyuan,
detailRules: this.buildDetailRules(currentHuiyuan)
}); });
}, },
buildDetailRules(huiyuan = {}) {
const formalDays = huiyuan.formal_days || 30;
const rules = [
`正式会员有效期为${formalDays}天,从购买当天开始计算`,
'会员期间享受优先接单特权',
'支持随时续费,未过期续费天数叠加,已过期从今天重新计算'
];
if (huiyuan.can_buy_trial) {
rules.push(`体验会员终身仅可购买1次${huiyuan.trial_days || 0}天),体验期仅限制佣金提现`);
}
if (huiyuan.trial_enabled && !huiyuan.can_buy_trial) {
rules.push('您已使用过该会员的体验资格');
}
rules.push('体验会员仅支持微信支付;正式会员可使用佣金、分红或押金抵扣');
return rules;
},
// ========== 格式化到期时间 ========== // ========== 格式化到期时间 ==========
formatDaoqiTime(daoqi) { formatDaoqiTime(daoqi) {
if (!daoqi) return ''; if (!daoqi) return '';
@@ -424,6 +448,7 @@ onHide() {
// ========== 会员购买相关 ========== // ========== 会员购买相关 ==========
async handleHuiyuanBuy(e) { async handleHuiyuanBuy(e) {
const huiyuanId = e.currentTarget.dataset.id; const huiyuanId = e.currentTarget.dataset.id;
const isTrial = e.currentTarget.dataset.trial === true || e.currentTarget.dataset.trial === 'true';
if (!huiyuanId) { if (!huiyuanId) {
wx.showToast({ wx.showToast({
@@ -440,7 +465,8 @@ onHide() {
url: '/shangpin/huiyuangm', url: '/shangpin/huiyuangm',
method: 'POST', method: 'POST',
data: { data: {
huiyuanid: huiyuanId huiyuanid: huiyuanId,
is_trial: isTrial
} }
}); });
@@ -800,9 +826,17 @@ onHide() {
// ========== 新增功能(余额抵扣等) ========== // ========== 新增功能(余额抵扣等) ==========
onBuyHuiyuanClick(e) { onBuyHuiyuanClick(e) {
const huiyuanId = e.currentTarget.dataset.id; const huiyuanId = e.currentTarget.dataset.id;
const isTrial = e.currentTarget.dataset.trial === true || e.currentTarget.dataset.trial === 'true';
if (isTrial) {
this.handleHuiyuanBuy(e);
return;
}
this.setData({ this.setData({
currentBuyType: 1, currentBuyType: 1,
currentHuiyuanId: huiyuanId, currentHuiyuanId: huiyuanId,
currentBuyIsTrial: false,
showPayMethodModal: true showPayMethodModal: true
}); });
}, },
@@ -846,7 +880,9 @@ onHide() {
if (method === 'wx') { if (method === 'wx') {
if (currentBuyType === 1) { if (currentBuyType === 1) {
this.handleHuiyuanBuy({ currentTarget: { dataset: { id: currentHuiyuanId } } }); this.handleHuiyuanBuy({
currentTarget: { dataset: { id: currentHuiyuanId, trial: 'false' } }
});
} else if (currentBuyType === 2) { } else if (currentBuyType === 2) {
this.setData({ yajinAmount: currentYajinAmount }, () => { this.setData({ yajinAmount: currentYajinAmount }, () => {
this.handleYajinPay(); this.handleYajinPay();
@@ -862,7 +898,12 @@ onHide() {
// 🔥 修改点3请求余额抵扣选项前校验积分状态 // 🔥 修改点3请求余额抵扣选项前校验积分状态
async fetchBalanceOptions() { async fetchBalanceOptions() {
const { currentBuyType, currentHuiyuanId, currentYajinAmount, jifen } = this.data; const { currentBuyType, currentHuiyuanId, currentYajinAmount, currentBuyIsTrial, jifen } = this.data;
if (currentBuyType === 1 && currentBuyIsTrial) {
wx.showToast({ title: '体验会员仅支持微信支付', icon: 'none' });
return;
}
// 如果是积分购买,且积分已满,拒绝发起余额抵扣 // 如果是积分购买,且积分已满,拒绝发起余额抵扣
if (currentBuyType === 3 && jifen >= 10) { if (currentBuyType === 3 && jifen >= 10) {
@@ -882,6 +923,7 @@ onHide() {
data: { data: {
leixing: currentBuyType, leixing: currentBuyType,
huiyuan_id: currentBuyType === 1 ? currentHuiyuanId : undefined, huiyuan_id: currentBuyType === 1 ? currentHuiyuanId : undefined,
is_trial: currentBuyType === 1 ? false : undefined,
yajin_jine: currentBuyType === 2 ? parseInt(currentYajinAmount) : undefined, yajin_jine: currentBuyType === 2 ? parseInt(currentYajinAmount) : undefined,
} }
}); });
@@ -924,7 +966,7 @@ onHide() {
}, },
async confirmBalancePay() { async confirmBalancePay() {
const { selectedBalanceId, currentBuyType, currentHuiyuanId, currentYajinAmount } = this.data; const { selectedBalanceId, currentBuyType, currentHuiyuanId, currentYajinAmount, currentBuyIsTrial } = this.data;
if (!selectedBalanceId) return; if (!selectedBalanceId) return;
this.hideConfirmModal(); this.hideConfirmModal();
@@ -938,6 +980,7 @@ onHide() {
leixing: currentBuyType, leixing: currentBuyType,
shenfen_id: selectedBalanceId, shenfen_id: selectedBalanceId,
huiyuan_id: currentBuyType === 1 ? currentHuiyuanId : undefined, huiyuan_id: currentBuyType === 1 ? currentHuiyuanId : undefined,
is_trial: currentBuyType === 1 ? currentBuyIsTrial : undefined,
yajin_jine: currentBuyType === 2 ? parseInt(currentYajinAmount) : undefined, yajin_jine: currentBuyType === 2 ? parseInt(currentYajinAmount) : undefined,
} }
}); });

View File

@@ -47,6 +47,12 @@
<view class="vip-badge" wx:if="{{item.isBought}}"> <view class="vip-badge" wx:if="{{item.isBought}}">
<text class="badge-text">已拥有</text> <text class="badge-text">已拥有</text>
</view> </view>
<view class="vip-badge trial-badge" wx:if="{{item.can_buy_trial}}">
<text class="badge-text">可购体验</text>
</view>
<view class="vip-badge trial-off-badge" wx:elif="{{item.trial_enabled}}">
<text class="badge-text">体验已用/不可购</text>
</view>
<view class="vip-title"> <view class="vip-title">
<text class="title-text">{{item.mingzi}}</text> <text class="title-text">{{item.mingzi}}</text>
@@ -56,7 +62,11 @@
<view class="vip-price"> <view class="vip-price">
<text class="price-symbol">¥</text> <text class="price-symbol">¥</text>
<text class="price-number">{{item.jiage}}</text> <text class="price-number">{{item.jiage}}</text>
<text class="price-unit">/30天</text> <text class="price-unit">/{{item.formal_days || 30}}天</text>
</view>
<view class="vip-trial-price" wx:if="{{item.trial_enabled || item.can_buy_trial}}">
<text class="trial-price-label">体验</text>
<text class="trial-price-value">¥{{item.trial_price}}/{{item.trial_days}}天</text>
</view> </view>
<view class="vip-features"> <view class="vip-features">
@@ -107,20 +117,27 @@
<!-- 🔥 将“机甲能源”改为“价格” --> <!-- 🔥 将“机甲能源”改为“价格” -->
<text class="price-label">价格:</text> <text class="price-label">价格:</text>
<text class="price-value">¥{{currentHuiyuan.jiage}}</text> <text class="price-value">¥{{currentHuiyuan.jiage}}</text>
<text class="price-days">/{{currentHuiyuan.formal_days || 30}}天</text>
</view> </view>
<text class="buy-desc" wx:if="{{currentHuiyuan.isBought && currentHuiyuan.buyInfo}}"> <text class="buy-desc" wx:if="{{currentHuiyuan.isBought && currentHuiyuan.buyInfo}}">
已激活,<text class="expire-date">{{currentHuiyuan.buyInfo.daoqi}}</text>后到期 已激活,<text class="expire-date">{{currentHuiyuan.buyInfo.daoqi}}</text>后到期
</text> </text>
<text class="buy-desc" wx:else>激活会员特权</text> <text class="buy-desc" wx:else>正式会员支持微信或余额抵扣</text>
<text class="buy-desc trial-hint" wx:if="{{currentHuiyuan.can_buy_trial}}">
体验版仅微信支付 ¥{{currentHuiyuan.trial_price}}/{{currentHuiyuan.trial_days}}天终身1次
</text>
<text class="buy-desc trial-warn" wx:elif="{{!currentHuiyuan.trial_enabled}}">
本俱乐部尚未为该会员开启体验版,请联系管理员在后台配置
</text>
</view> </view>
<view class="buy-action"> <view class="buy-action">
<view class="tech-buy-btn {{currentHuiyuan.isBought ? 'renew' : ''}}" <view class="tech-buy-btn {{currentHuiyuan.isBought ? 'renew' : ''}}"
bindtap="onBuyHuiyuanClick" data-id="{{currentHuiyuan.id}}"> bindtap="onBuyHuiyuanClick" data-id="{{currentHuiyuan.id}}" data-trial="false">
<view class="buy-btn-bg"></view> <view class="buy-btn-bg"></view>
<view class="buy-btn-glow"></view> <view class="buy-btn-glow"></view>
<text class="buy-btn-text"> <text class="buy-btn-text">
{{currentHuiyuan.isBought ? '立即续费' : '立即激活'}} {{currentHuiyuan.isBought ? '正式续费' : '购买正式版'}}
</text> </text>
<view class="buy-btn-energy"> <view class="buy-btn-energy">
<view class="energy-dot"></view> <view class="energy-dot"></view>
@@ -128,6 +145,16 @@
<view class="energy-dot"></view> <view class="energy-dot"></view>
</view> </view>
</view> </view>
<view
wx:if="{{currentHuiyuan.can_buy_trial}}"
class="tech-buy-btn trial-buy-btn"
bindtap="onBuyHuiyuanClick"
data-id="{{currentHuiyuan.id}}"
data-trial="true"
>
<view class="buy-btn-bg"></view>
<text class="buy-btn-text">购买体验版</text>
</view>
</view> </view>
</view> </view>
</view> </view>

View File

@@ -1,4 +1,5 @@
/* pages/dashou-chongzhi/index.wxss - 完整保留原有样式,仅删除导航栏相关,调整间距和字体 */ /* pages/dashou-chongzhi/index.wxss - 逍遥梦主题覆盖 + 机甲基础样式 */
@import '../../styles/dashou-xym-recharge-theme.wxss';
/* ==================== 基础样式 ==================== */ /* ==================== 基础样式 ==================== */
.page-container { .page-container {
@@ -677,6 +678,32 @@
z-index: 20; z-index: 20;
} }
.vip-badge.trial-badge {
top: 60rpx;
background: linear-gradient(135deg, #ffb347, #ff7043);
}
.vip-badge.trial-off-badge {
top: 60rpx;
background: rgba(120, 120, 120, 0.85);
box-shadow: none;
}
.vip-trial-price {
margin-top: 8rpx;
font-size: 22rpx;
color: #ffb347;
}
.trial-price-label {
margin-right: 8rpx;
color: #a0c8ff;
}
.trial-price-value {
font-weight: 600;
}
.vip-title { .vip-title {
margin-bottom: 25rpx; margin-bottom: 25rpx;
} }
@@ -855,12 +882,36 @@
/* 购买区域 */ /* 购买区域 */
.buy-section { .buy-section {
display: flex; display: flex;
align-items: center; flex-direction: column;
justify-content: space-between; align-items: stretch;
gap: 20rpx;
padding-top: 25rpx; padding-top: 25rpx;
border-top: 1px solid rgba(64, 156, 255, 0.2); border-top: 1px solid rgba(64, 156, 255, 0.2);
} }
.buy-action {
display: flex;
flex-direction: column;
gap: 16rpx;
align-items: flex-end;
}
.price-days {
font-size: 22rpx;
color: #a0c8ff;
}
.trial-hint {
margin-top: 6rpx;
color: #ffb347;
}
.trial-warn {
margin-top: 6rpx;
color: #ff8a8a;
font-size: 22rpx;
}
.buy-info { .buy-info {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
@@ -928,6 +979,11 @@
background: linear-gradient(135deg, #1e4b8f, #409cff); background: linear-gradient(135deg, #1e4b8f, #409cff);
} }
.tech-buy-btn.trial-buy-btn .buy-btn-bg {
background: linear-gradient(135deg, rgba(255, 179, 71, 0.35), rgba(255, 120, 80, 0.45));
border: 1px solid rgba(255, 179, 71, 0.6);
}
.tech-buy-btn.renew .buy-btn-bg { .tech-buy-btn.renew .buy-btn-bg {
background: linear-gradient(135deg, #0f2c5c, #36cfc9); background: linear-gradient(135deg, #0f2c5c, #36cfc9);
} }
@@ -1703,5 +1759,3 @@
align-items: center !important; align-items: center !important;
justify-content: center !important; justify-content: center !important;
} }
@import '../../styles/dashou-xym-recharge-theme.wxss';

View File

@@ -2,9 +2,25 @@
import { createPage, request, isRoleStatusActive, isCenterPageActive, syncRoleStatuses, syncProfileFields, syncGroupFields, ensureRoleOnCenterPage, clearCacheAndEnterNormal, lockPrimaryRole, migrateLegacyCenterRole, enterLockedRole, parseSceneOptions } from '../../utils/base-page.js' import { createPage, request, isRoleStatusActive, isCenterPageActive, syncRoleStatuses, syncProfileFields, syncGroupFields, ensureRoleOnCenterPage, clearCacheAndEnterNormal, lockPrimaryRole, migrateLegacyCenterRole, enterLockedRole, parseSceneOptions } from '../../utils/base-page.js'
import { resolveAvatarUrl } from '../../utils/avatar.js' import { resolveAvatarUrl } from '../../utils/avatar.js'
import { openPrivateChat, buildInviterPeerId } from '../../utils/im-user.js' import { openPrivateChat, buildInviterPeerId } from '../../utils/im-user.js'
import { isStaffMode, getStaffContext } from '../../utils/staff-api.js'
import { ensurePhoneAuth } from '../../utils/phone-auth.js'
import {
ICON_KEYS,
resolveMiniappIcon,
resolveConfiguredIcon,
refreshPindaoConfig,
getPindaoConfig,
resolvePindaoImages,
warmupPindaoConfig,
PINDAO_ICON_FALLBACK,
} from '../../utils/miniapp-icons.js'
const PLATFORM_INVITE_CODE = '0000008RffVgKHMj7kQC' const PLATFORM_INVITE_CODE = '0000008RffVgKHMj7kQC'
/** 会员/保证金横幅 COS 兜底(后台未上传时仍显示) */
const FIGHTER_BANNER_VIP_FALLBACK = 'https://bintao-1308403501.cos.ap-guangzhou.myqcloud.com/uploads/images/20260512123427531240452.png'
const FIGHTER_BANNER_DEPOSIT_FALLBACK = 'https://bintao-1308403501.cos.ap-guangzhou.myqcloud.com/uploads/images/202605121234283091d3980.png'
Page(createPage({ Page(createPage({
data: { data: {
// 图片路径对象 // 图片路径对象
@@ -41,6 +57,7 @@ Page(createPage({
zuzhangInviterCache: null, zuzhangInviterCache: null,
chenghaoList: [], chenghaoList: [],
guanshiChenghaoList: [], guanshiChenghaoList: [],
identityTagList: [],
gszhstatus: '', gszhstatus: '',
yaoqingzongshu: 0, yaoqingzongshu: 0,
fenyongzonge: '0.00', fenyongzonge: '0.00',
@@ -65,13 +82,25 @@ Page(createPage({
statusBar: 20, statusBar: 20,
navBar: 44, navBar: 44,
pindaoVisible: false,
pindaoTitle: '频道',
pindaoChannelNo: '',
examEnabled: false,
examPassed: false,
pindaoImages: [],
scrollViewRefreshing: false,
showRechargeBanners: false,
showPindaoEntry: true,
}, },
_buildImgUrls(ossImageUrl) { _buildImgUrls(ossImageUrl) {
const app = getApp();
const dsBase = ossImageUrl + 'beijing/dashouduan/'; const dsBase = ossImageUrl + 'beijing/dashouduan/';
const iconBase = ossImageUrl + 'beijing/dashouduan/dashoutubiaobeijing/'; const iconBase = ossImageUrl + 'beijing/dashouduan/dashoutubiaobeijing/';
const gsBase = ossImageUrl + 'beijing/guanshiduan/'; const gsBase = ossImageUrl + 'beijing/guanshiduan/';
const khBase = ossImageUrl + 'beijing/kaohe/'; const khBase = ossImageUrl + 'beijing/kaohe/';
const icon = (key, fallback) => resolveMiniappIcon(app, key, fallback);
return { return {
pageBg: dsBase + 'page-bg.jpg', pageBg: dsBase + 'page-bg.jpg',
userCardBg: dsBase + 'user-card-bg.png', userCardBg: dsBase + 'user-card-bg.png',
@@ -83,7 +112,7 @@ Page(createPage({
listBg: dsBase + 'list-card-bg.png', listBg: dsBase + 'list-card-bg.png',
topBg: iconBase + 'top-bg.jpg', topBg: iconBase + 'top-bg.jpg',
cardBg: iconBase + 'card-bg.jpg', cardBg: iconBase + 'card-bg.jpg',
iconRefresh: gsBase + 'icon-refresh.png', iconRefresh: icon(ICON_KEYS.ICON_REFRESH, gsBase + 'icon-refresh.png'),
iconCopy: gsBase + 'icon-copy.png', iconCopy: gsBase + 'icon-copy.png',
iconVip: dsBase + 'icon-vip.png', iconVip: dsBase + 'icon-vip.png',
iconArrowLight: dsBase + 'icon-arrow-light.png', iconArrowLight: dsBase + 'icon-arrow-light.png',
@@ -118,6 +147,7 @@ Page(createPage({
iconSwitch: '/images/_exit.png', iconSwitch: '/images/_exit.png',
iconKefu: ossImageUrl + 'beijing/tubiao/grzx_kefu.jpg', iconKefu: ossImageUrl + 'beijing/tubiao/grzx_kefu.jpg',
iconKuaishou: ossImageUrl + 'beijing/tubiao/grzx_guanzhualong.jpg', iconKuaishou: ossImageUrl + 'beijing/tubiao/grzx_guanzhualong.jpg',
iconPindao: icon(ICON_KEYS.MINE_PINDAO, ossImageUrl + PINDAO_ICON_FALLBACK),
iconKaoheDafen: khBase + 'daofen.png', iconKaoheDafen: khBase + 'daofen.png',
iconKaoheJilu: khBase + 'jilu.png', iconKaoheJilu: khBase + 'jilu.png',
iconKaoheZhongxin: khBase + 'zhongxin.png', iconKaoheZhongxin: khBase + 'zhongxin.png',
@@ -128,8 +158,8 @@ Page(createPage({
kefuBannerBg: dsBase + 'kefu-banner-bg.png', kefuBannerBg: dsBase + 'kefu-banner-bg.png',
totalAssetBg: dsBase + 'total-asset-bg.png', totalAssetBg: dsBase + 'total-asset-bg.png',
authPanelBg: dsBase + 'auth-panel-bg.png', authPanelBg: dsBase + 'auth-panel-bg.png',
bannerVip: 'https://bintao-1308403501.cos.ap-guangzhou.myqcloud.com/uploads/images/20260512123427531240452.png', bannerVip: resolveConfiguredIcon(app, ICON_KEYS.FIGHTER_RECHARGE_MEMBER) || FIGHTER_BANNER_VIP_FALLBACK,
bannerDeposit: 'https://bintao-1308403501.cos.ap-guangzhou.myqcloud.com/uploads/images/202605121234283091d3980.png', bannerDeposit: resolveConfiguredIcon(app, ICON_KEYS.FIGHTER_RECHARGE_DEPOSIT) || FIGHTER_BANNER_DEPOSIT_FALLBACK,
}; };
}, },
@@ -177,9 +207,28 @@ Page(createPage({
} }
} }
this.checkColdStartPopup('dashouduan'); this.checkColdStartPopup('dashouduan');
this.syncConfiguredAssets();
}, },
onShow() { syncConfiguredAssets() {
const app = getApp();
const bannerVip = resolveConfiguredIcon(app, ICON_KEYS.FIGHTER_RECHARGE_MEMBER) || FIGHTER_BANNER_VIP_FALLBACK;
const bannerDeposit = resolveConfiguredIcon(app, ICON_KEYS.FIGHTER_RECHARGE_DEPOSIT) || FIGHTER_BANNER_DEPOSIT_FALLBACK;
const imgUrls = { ...this.data.imgUrls, bannerVip, bannerDeposit };
this.setData({
imgUrls,
showRechargeBanners: !!(bannerVip || bannerDeposit),
showPindaoEntry: this.data.isDashou || this.data.isGuanshi || this.data.isZuzhang || this.data.isKaoheguan,
});
},
async onShow() {
if (!app.globalData._dashouPhoneChecked) {
const phoneOk = await ensurePhoneAuth({ redirect: true, role: 'dashou' });
if (!phoneOk) return;
app.globalData._dashouPhoneChecked = true;
}
migrateLegacyCenterRole(getApp()); migrateLegacyCenterRole(getApp());
lockPrimaryRole('dashou', getApp()); lockPrimaryRole('dashou', getApp());
wx.setStorageSync('isJinpai', 0); wx.setStorageSync('isJinpai', 0);
@@ -190,16 +239,17 @@ Page(createPage({
this.setData({ inviterCache, zuzhangInviterCache }); this.setData({ inviterCache, zuzhangInviterCache });
this.registerNotificationComponent(); this.registerNotificationComponent();
warmupPindaoConfig(app);
this.checkRoleStatuses(); this.checkRoleStatuses();
this.syncConfiguredAssets();
if (isCenterPageActive(this, 'isDashou', 'dashoustatus')) { if (isCenterPageActive(this, 'isDashou', 'dashoustatus')) {
if (!this.data.isDashou) this.setData({ isDashou: true }); if (!this.data.isDashou) this.setData({ isDashou: true });
ensureRoleOnCenterPage(this, 'dashou'); ensureRoleOnCenterPage(this, 'dashou');
setTimeout(() => this.refreshAllInfo(false), 300); this.loadExamStatus();
} else if (isRoleStatusActive(wx.getStorageSync('guanshistatus')) || } else if (isRoleStatusActive(wx.getStorageSync('guanshistatus')) ||
isRoleStatusActive(wx.getStorageSync('zuzhangstatus')) || isRoleStatusActive(wx.getStorageSync('zuzhangstatus')) ||
isRoleStatusActive(wx.getStorageSync('kaoheguanstatus'))) { isRoleStatusActive(wx.getStorageSync('kaoheguanstatus'))) {
ensureRoleOnCenterPage(this, 'dashou'); ensureRoleOnCenterPage(this, 'dashou');
setTimeout(() => this.refreshAllInfo(false), 300);
} }
const pages = getCurrentPages(); const pages = getCurrentPages();
const currentPage = pages[pages.length - 1]; const currentPage = pages[pages.length - 1];
@@ -277,12 +327,17 @@ Page(createPage({
tag: d.shangjiaCertified ? '进入商家端' : '去认证', tag: d.shangjiaCertified ? '进入商家端' : '去认证',
done: d.shangjiaCertified, done: d.shangjiaCertified,
}); });
list.push({
type: 'staff',
name: '商家客服',
icon: img.iconKefu || img.iconShangjia,
tag: isStaffMode() ? '进入工作台' : '去入驻',
done: isStaffMode(),
});
if (!d.isGuanshi) { if (!d.isGuanshi) {
list.push({ type: 'guanshi', name: '管事', icon: img.iconGuanshiAuth, tag: '去认证' }); list.push({ type: 'guanshi', name: '管事', icon: img.iconGuanshiAuth, tag: '去认证' });
} }
if (!d.isZuzhang) { // 组长由后台添加,前端不再展示「组长认证」入口
list.push({ type: 'zuzhang', name: '组长', icon: img.iconZuzhangAuth, tag: '去认证' });
}
if (!d.isDashou) { if (!d.isDashou) {
list.push({ type: 'dashou', name: '接单员', icon: img.iconDashouAuth, tag: '去认证' }); list.push({ type: 'dashou', name: '接单员', icon: img.iconDashouAuth, tag: '去认证' });
} }
@@ -293,7 +348,8 @@ Page(createPage({
}, },
async refreshAllInfo(showToast = true) { async refreshAllInfo(showToast = true) {
this.throttledRefresh(async () => { if (this._profileRefreshing) return;
this._profileRefreshing = true;
this.setData({ isLoading: true }); this.setData({ isLoading: true });
try { try {
this.checkRoleStatuses(); this.checkRoleStatuses();
@@ -304,6 +360,7 @@ Page(createPage({
this.fetchGuanshiChenghaoList(), this.fetchGuanshiChenghaoList(),
this._fetchZuzhangInfoSilent(), this._fetchZuzhangInfoSilent(),
this._fetchKaoheguanInfoSilent(), this._fetchKaoheguanInfoSilent(),
this.loadIdentityTags(),
]); ]);
this.checkRoleStatuses(); this.checkRoleStatuses();
const dashouOk = results[0].status === 'fulfilled'; const dashouOk = results[0].status === 'fulfilled';
@@ -319,9 +376,9 @@ Page(createPage({
wx.showToast({ title: '刷新失败', icon: 'none' }); wx.showToast({ title: '刷新失败', icon: 'none' });
} }
} finally { } finally {
this._profileRefreshing = false;
this.setData({ isLoading: false }); this.setData({ isLoading: false });
} }
}, 3000);
}, },
refreshDashouInfo() { refreshDashouInfo() {
@@ -332,6 +389,34 @@ Page(createPage({
this.refreshAllInfo(true); this.refreshAllInfo(true);
}, },
onPullDownRefresh() {
this.setData({ scrollViewRefreshing: true });
Promise.all([
this.refreshAllInfo(false),
this.loadExamStatus(),
]).finally(() => {
this.setData({ scrollViewRefreshing: false });
wx.stopPullDownRefresh();
});
},
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 || {};
const merged = [
...(d.dashou || []),
...(d.zuzhang || []),
...(d.guanshi || []),
];
this.setData({ identityTagList: merged });
}
} catch (e) {
/* 静默 */
}
},
async _fetchDashouInfoSilent() { async _fetchDashouInfoSilent() {
const res = await request({ url: '/yonghu/dashouxinxi', method: 'POST' }); const res = await request({ url: '/yonghu/dashouxinxi', method: 'POST' });
if (res && res.data.code == 200) { if (res && res.data.code == 200) {
@@ -1015,6 +1100,14 @@ Page(createPage({
onTapAuthItem(e) { onTapAuthItem(e) {
const type = e.currentTarget.dataset.type; const type = e.currentTarget.dataset.type;
if (type === 'staff') {
if (isStaffMode()) {
enterLockedRole('shangjia', getApp());
} else {
wx.navigateTo({ url: '/pages/staff-join/staff-join' });
}
return;
}
if (type === 'shangjia') { if (type === 'shangjia') {
this.onTapShangjiaAuth(); this.onTapShangjiaAuth();
return; return;
@@ -1038,6 +1131,21 @@ Page(createPage({
wx.navigateTo({ url: '/pages/verify/verify?type=shangjia' }); wx.navigateTo({ url: '/pages/verify/verify?type=shangjia' });
}, },
goToReceiveOrder() { wx.navigateTo({ url: '/pages/accept-order/accept-order' }) }, goToReceiveOrder() { wx.navigateTo({ url: '/pages/accept-order/accept-order' }) },
goToDashouExam() { wx.navigateTo({ url: '/pages/dashou-exam/dashou-exam' }) },
async loadExamStatus() {
try {
const res = await request({ url: '/jituan/dashou-exam/status', method: 'POST' });
const body = res?.data;
if (body && (body.code === 200 || body.code === 0) && body.data) {
const d = body.data;
this.setData({
examEnabled: !!d.exam_enabled,
examPassed: !!d.exam_passed,
});
}
} catch (e) { /* 静默 */ }
},
goToMyOrders() { wx.navigateTo({ url: '/pages/fighter-orders/fighter-orders' }) }, goToMyOrders() { wx.navigateTo({ url: '/pages/fighter-orders/fighter-orders' }) },
goToMyPunishment() { wx.navigateTo({ url: '/pages/penalty/penalty/penalty' }) }, goToMyPunishment() { wx.navigateTo({ url: '/pages/penalty/penalty/penalty' }) },
goToRecharge() { wx.navigateTo({ url: '/pages/fighter-recharge/fighter-recharge' }) }, goToRecharge() { wx.navigateTo({ url: '/pages/fighter-recharge/fighter-recharge' }) },
@@ -1045,7 +1153,33 @@ Page(createPage({
const type = e?.currentTarget?.dataset?.type || 'dashou'; const type = e?.currentTarget?.dataset?.type || 'dashou';
wx.navigateTo({ url: `/pages/fighter-rank/fighter-rank?type=${type}` }); wx.navigateTo({ url: `/pages/fighter-rank/fighter-rank?type=${type}` });
}, },
goToGuanzhuKs() { wx.navigateTo({ url: '/pages/manager-assign/manager-assign' }) }, goToGuanzhuKs() {
wx.navigateTo({ url: '/pages/manager-assign/manager-assign' });
},
openPindaoModal() {
const app = getApp();
const cfg = getPindaoConfig(app);
const images = resolvePindaoImages(app);
this.setData({
pindaoVisible: true,
pindaoTitle: cfg.title || '频道',
pindaoChannelNo: cfg.channel_no || '',
pindaoImages: images,
});
refreshPindaoConfig(app).then(({ cfg: latest, images: latestImages }) => {
if (!this.data.pindaoVisible) return;
this.setData({
pindaoTitle: latest.title || '频道',
pindaoChannelNo: latest.channel_no || '',
pindaoImages: latestImages,
});
}).catch(() => {});
},
closePindaoModal() {
this.setData({ pindaoVisible: false });
},
goToKaoheDafen() { wx.navigateTo({ url: '/pages/assess-score/assess-score' }) }, goToKaoheDafen() { wx.navigateTo({ url: '/pages/assess-score/assess-score' }) },
goToKaoheJilu() { wx.navigateTo({ url: '/pages/assess-log/assess-log' }) }, goToKaoheJilu() { wx.navigateTo({ url: '/pages/assess-log/assess-log' }) },
goToKaoheZhongxin() { wx.navigateTo({ url: '/pages/assess-center/assess-center' }) }, goToKaoheZhongxin() { wx.navigateTo({ url: '/pages/assess-center/assess-center' }) },

View File

@@ -2,7 +2,8 @@
"usingComponents": { "usingComponents": {
"global-notification": "/components/global-notification/global-notification", "global-notification": "/components/global-notification/global-notification",
"chenghao-tag": "/components/chenghao-tag/chenghao-tag", "chenghao-tag": "/components/chenghao-tag/chenghao-tag",
"tab-bar": "/tab-bar/index" "tab-bar": "/tab-bar/index",
"pindao-modal": "/components/pindao-modal/pindao-modal"
}, },
"navigationStyle": "custom", "navigationStyle": "custom",
"backgroundColor": "#fff8e1", "backgroundColor": "#fff8e1",

View File

@@ -26,14 +26,23 @@
<view class="user-page"> <view class="user-page">
<view class="page-header"> <view class="page-header">
<view class="status-bar" style="height:{{statusBar}}px"></view> <view class="status-bar" style="height:{{statusBar}}px"></view>
<view class="nav-bar" style="height:{{navBar - statusBar}}px"><text class="nav-title">我的</text></view> <view class="nav-bar" style="height:{{navBar - statusBar}}px">
<text class="nav-title">我的</text>
</view>
</view> </view>
<view class="refresh-float" bindtap="onTapRefresh"> <scroll-view
<image class="refresh-float-ico" src="{{imgUrls.iconRefresh}}" mode="aspectFit"/> class="content"
</view> scroll-y
enhanced
<scroll-view class="content" scroll-y enhanced show-scrollbar="{{false}}"> show-scrollbar="{{false}}"
refresher-enabled="{{true}}"
refresher-threshold="80"
refresher-default-style="black"
refresher-background="#fff8e1"
refresher-triggered="{{scrollViewRefreshing}}"
bindrefresherrefresh="onPullDownRefresh"
>
<!-- 用户信息 --> <!-- 用户信息 -->
<view class="user-info flexb"> <view class="user-info flexb">
<view class="flex"> <view class="flex">
@@ -55,11 +64,14 @@
</view> </view>
</view> </view>
</view> </view>
<view class="user-header-actions">
<image class="header-action-ico" src="{{imgUrls.iconRefresh}}" mode="aspectFit" bindtap="onTapRefresh"/>
<image class="setting-ico" src="{{imgUrls.iconEdit}}" mode="aspectFit" bindtap="goToModifyInfo"/> <image class="setting-ico" src="{{imgUrls.iconEdit}}" mode="aspectFit" bindtap="goToModifyInfo"/>
</view> </view>
</view>
<!-- 称号 --> <!-- 称号 -->
<view class="badge-zone" wx:if="{{chenghaoList.length > 0 || (isGuanshi && guanshiChenghaoList.length > 0)}}"> <view class="badge-zone" wx:if="{{chenghaoList.length > 0 || (isGuanshi && guanshiChenghaoList.length > 0) || identityTagList.length > 0}}">
<scroll-view scroll-x class="badge-scroll" wx:if="{{chenghaoList.length > 0}}"> <scroll-view scroll-x class="badge-scroll" wx:if="{{chenghaoList.length > 0}}">
<view class="badge-tag-wrap" wx:for="{{chenghaoList}}" wx:key="index"> <view class="badge-tag-wrap" wx:for="{{chenghaoList}}" wx:key="index">
<chenghao-tag mingcheng="{{item.mingcheng}}" texiaoJson="{{item.texiao_json}}"/> <chenghao-tag mingcheng="{{item.mingcheng}}" texiaoJson="{{item.texiao_json}}"/>
@@ -70,6 +82,11 @@
<chenghao-tag mingcheng="{{item.mingcheng}}" texiaoJson="{{item.texiao_json}}"/> <chenghao-tag mingcheng="{{item.mingcheng}}" texiaoJson="{{item.texiao_json}}"/>
</view> </view>
</scroll-view> </scroll-view>
<scroll-view scroll-x class="badge-scroll identity-tag-scroll" wx:if="{{identityTagList.length > 0}}">
<view class="badge-tag-wrap" wx:for="{{identityTagList}}" wx:key="id">
<chenghao-tag mingcheng="{{item.mingcheng}}" texiaoJson="{{item.texiao_json}}"/>
</view>
</scroll-view>
</view> </view>
<!-- 佣金/资产卡(逍遥梦 wallet-card --> <!-- 佣金/资产卡(逍遥梦 wallet-card -->
@@ -85,10 +102,14 @@
</view> </view>
</view> </view>
<!-- 会员充值 + 保证金(均跳转同一充值页 --> <!-- 会员充值 + 保证金(无后台图时显示文字按钮 -->
<view class="banner-row flex"> <view class="banner-row flex" wx:if="{{showRechargeBanners}}">
<image class="banner-img" src="{{imgUrls.bannerVip}}" mode="widthFix" bindtap="goToRecharge"/> <image wx:if="{{imgUrls.bannerVip}}" class="banner-img" src="{{imgUrls.bannerVip}}" mode="widthFix" bindtap="goToRecharge"/>
<image class="banner-img" src="{{imgUrls.bannerDeposit}}" mode="widthFix" bindtap="goToRecharge"/> <image wx:if="{{imgUrls.bannerDeposit}}" class="banner-img" src="{{imgUrls.bannerDeposit}}" mode="widthFix" bindtap="goToRecharge"/>
</view>
<view class="recharge-text-row flex" wx:else>
<view class="recharge-text-btn" catchtap="goToRecharge">充值会员</view>
<view class="recharge-text-btn" catchtap="goToRecharge">充值保证金</view>
</view> </view>
<!-- 资产统计(逍遥梦 freeze-row --> <!-- 资产统计(逍遥梦 freeze-row -->
@@ -123,7 +144,7 @@
<!-- 接单服务(对应逍遥梦「我的订单」四宫格) --> <!-- 接单服务(对应逍遥梦「我的订单」四宫格) -->
<view class="panel shadow"> <view class="panel shadow">
<view class="panel-title flexb"><text class="lg">接单服务</text></view> <view class="panel-title flexb"><text class="lg">接单服务</text></view>
<view class="order-nav flexa"> <view class="order-nav">
<view class="nav-item flexmc" bindtap="goToReceiveOrder"> <view class="nav-item flexmc" bindtap="goToReceiveOrder">
<image class="nav-icon" src="{{imgUrls.iconGame}}" mode="aspectFit"/><text class="sm">抢单大厅</text> <image class="nav-icon" src="{{imgUrls.iconGame}}" mode="aspectFit"/><text class="sm">抢单大厅</text>
</view> </view>
@@ -136,6 +157,11 @@
<view class="nav-item flexmc" bindtap="goToKaohe"> <view class="nav-item flexmc" bindtap="goToKaohe">
<image class="nav-icon" src="{{imgUrls.iconMedal}}" mode="aspectFit"/><text class="sm">考核金牌</text> <image class="nav-icon" src="{{imgUrls.iconMedal}}" mode="aspectFit"/><text class="sm">考核金牌</text>
</view> </view>
<view class="nav-item flexmc" bindtap="goToDashouExam">
<image class="nav-icon" src="{{imgUrls.iconBook}}" mode="aspectFit"/>
<text class="sm">接单考试</text>
<text wx:if="{{examEnabled}}" class="exam-tag {{examPassed ? 'exam-tag-pass' : 'exam-tag-pending'}}">{{examPassed ? '已通过' : '待考试'}}</text>
</view>
</view> </view>
</view> </view>
@@ -195,7 +221,6 @@
<view class="func-item flexmc" bindtap="goToKaoheDafen"><image class="func-icon" src="{{imgUrls.iconKaoheDafen}}" mode="aspectFit"/><text class="func-txt">考核打分</text></view> <view class="func-item flexmc" bindtap="goToKaoheDafen"><image class="func-icon" src="{{imgUrls.iconKaoheDafen}}" mode="aspectFit"/><text class="func-txt">考核打分</text></view>
<view class="func-item flexmc" bindtap="goToKaoheJilu"><image class="func-icon" src="{{imgUrls.iconKaoheJilu}}" mode="aspectFit"/><text class="func-txt">考核记录</text></view> <view class="func-item flexmc" bindtap="goToKaoheJilu"><image class="func-icon" src="{{imgUrls.iconKaoheJilu}}" mode="aspectFit"/><text class="func-txt">考核记录</text></view>
<view class="func-item flexmc" bindtap="goToKaoheZhongxin"><image class="func-icon" src="{{imgUrls.iconKaoheZhongxin}}" mode="aspectFit"/><text class="func-txt">考核中心</text></view> <view class="func-item flexmc" bindtap="goToKaoheZhongxin"><image class="func-icon" src="{{imgUrls.iconKaoheZhongxin}}" mode="aspectFit"/><text class="func-txt">考核中心</text></view>
<view class="func-item flexmc" bindtap="goToKaoheWithdraw"><image class="func-icon" src="{{imgUrls.iconWithdraw}}" mode="aspectFit"/><text class="func-txt">考核提现</text></view>
</view> </view>
</view> </view>
@@ -217,6 +242,7 @@
<view class="func-grid"> <view class="func-grid">
<view class="func-item flexmc" bindtap="goToKefu"><image class="func-icon" src="{{imgUrls.iconKefu}}" mode="aspectFit"/><text class="func-txt">在线客服</text></view> <view class="func-item flexmc" bindtap="goToKefu"><image class="func-icon" src="{{imgUrls.iconKefu}}" mode="aspectFit"/><text class="func-txt">在线客服</text></view>
<view class="func-item flexmc" bindtap="goToGuanzhuKs"><image class="func-icon" src="{{imgUrls.iconKuaishou}}" mode="aspectFit"/><text class="func-txt">关注快手</text></view> <view class="func-item flexmc" bindtap="goToGuanzhuKs"><image class="func-icon" src="{{imgUrls.iconKuaishou}}" mode="aspectFit"/><text class="func-txt">关注快手</text></view>
<view class="func-item flexmc" wx:if="{{showPindaoEntry}}" bindtap="openPindaoModal"><image class="func-icon" src="{{imgUrls.iconPindao}}" mode="aspectFit"/><text class="func-txt">频道</text></view>
<view class="func-item flexmc" bindtap="contactInviter"><image class="func-icon" src="{{imgUrls.iconInvite}}" mode="aspectFit"/><text class="func-txt">联系邀请人</text></view> <view class="func-item flexmc" bindtap="contactInviter"><image class="func-icon" src="{{imgUrls.iconInvite}}" mode="aspectFit"/><text class="func-txt">联系邀请人</text></view>
<view class="func-item flexmc" bindtap="goToRules"><image class="func-icon" src="{{imgUrls.iconBook}}" mode="aspectFit"/><text class="func-txt">用户规则</text></view> <view class="func-item flexmc" bindtap="goToRules"><image class="func-icon" src="{{imgUrls.iconBook}}" mode="aspectFit"/><text class="func-txt">用户规则</text></view>
<view class="func-item flexmc" bindtap="switchToNormal"><image class="func-icon" src="{{imgUrls.iconSwitch}}" mode="aspectFit"/><text class="func-txt">返回点单端</text></view> <view class="func-item flexmc" bindtap="switchToNormal"><image class="func-icon" src="{{imgUrls.iconSwitch}}" mode="aspectFit"/><text class="func-txt">返回点单端</text></view>
@@ -236,3 +262,10 @@
<global-notification id="global-notification"/> <global-notification id="global-notification"/>
<popup-notice id="popupNotice"/> <popup-notice id="popupNotice"/>
<pindao-modal
visible="{{pindaoVisible}}"
title="{{pindaoTitle}}"
channelNo="{{pindaoChannelNo}}"
images="{{pindaoImages}}"
bind:close="closePindaoModal"
/>

View File

@@ -40,6 +40,19 @@ page {
justify-content: center; justify-content: center;
} }
.nav-bar-actions {
position: relative;
justify-content: center;
}
.nav-refresh-ico {
position: absolute;
right: 24rpx;
width: 44rpx;
height: 44rpx;
padding: 8rpx;
}
.nav-title { .nav-title {
font-size: 34rpx; font-size: 34rpx;
font-weight: 700; font-weight: 700;
@@ -134,6 +147,20 @@ page {
opacity: 0.6; opacity: 0.6;
} }
.user-header-actions {
display: flex;
align-items: center;
gap: 16rpx;
flex-shrink: 0;
}
.header-action-ico {
width: 48rpx;
height: 48rpx;
padding: 6rpx;
flex-shrink: 0;
}
.setting-ico { .setting-ico {
width: 53rpx; width: 53rpx;
height: 53rpx; height: 53rpx;
@@ -233,6 +260,23 @@ page {
margin-right: 2%; margin-right: 2%;
} }
.recharge-text-row {
margin: 20rpx 24rpx 0;
gap: 16rpx;
}
.recharge-text-btn {
flex: 1;
text-align: center;
padding: 22rpx 12rpx;
border-radius: 16rpx;
font-size: 28rpx;
font-weight: 600;
color: #492f00;
background: linear-gradient(180deg, #fff8e1, #ffe8b8);
border: 1rpx solid rgba(201, 169, 98, 0.45);
}
.freeze-row { .freeze-row {
margin: 16rpx 30rpx 0; margin: 16rpx 30rpx 0;
padding: 20rpx 10rpx; padding: 20rpx 10rpx;
@@ -356,11 +400,35 @@ page {
.order-nav { .order-nav {
padding: 10rpx 0 20rpx; padding: 10rpx 0 20rpx;
display: flex;
flex-direction: row;
flex-wrap: wrap;
justify-content: flex-start;
align-items: flex-start;
} }
.nav-item { .nav-item {
width: 25%; width: 20%;
box-sizing: border-box;
padding: 10rpx 0; padding: 10rpx 0;
position: relative;
}
.exam-tag {
font-size: 20rpx;
margin-top: 4rpx;
padding: 2rpx 10rpx;
border-radius: 8rpx;
}
.exam-tag-pass {
color: #52c41a;
background: rgba(82, 196, 26, 0.12);
}
.exam-tag-pending {
color: #fa8c16;
background: rgba(250, 140, 16, 0.12);
} }
.nav-icon { .nav-icon {

View File

@@ -11,6 +11,15 @@ import { fetchMerchantOrderStats, applyOrderStatsToHome } from '../../utils/merc
const app = getApp(); const app = getApp();
const XYM_HOME_FALLBACK = {
noticeIco: 'https://bintao.xmxym88.com/xcx/bintao/38.png',
statCardBg: 'https://bintao.xmxym88.com/xcx/bintao/3.png',
kefuKeyBtn: 'https://bintao.xmxym88.com/xcx/bintao/13.png',
kefuListBtn: 'https://bintao.xmxym88.com/xcx/bintao/21.png',
iconRegular: 'https://bintao.xmxym88.com/xcx/bintao/74.png',
iconCustom: 'https://bintao.xmxym88.com/xcx/bintao/76.png',
};
/** 与订单页「全部」Tab 一致的状态筛选 */ /** 与订单页「全部」Tab 一致的状态筛选 */
const ALL_ORDER_ZHUANGTAI = [1, 2, 3, 4, 5, 6, 7, 8]; const ALL_ORDER_ZHUANGTAI = [1, 2, 3, 4, 5, 6, 7, 8];
const RECENT_ORDER_SIZE = 5; const RECENT_ORDER_SIZE = 5;
@@ -30,12 +39,12 @@ Page(createPage({
gonggao: '', gonggao: '',
swiperCurrent: 0, swiperCurrent: 0,
imgUrls: { imgUrls: {
noticeIco: '', noticeIco: XYM_HOME_FALLBACK.noticeIco,
statCardBg: '', statCardBg: XYM_HOME_FALLBACK.statCardBg,
kefuKeyBtn: '', kefuKeyBtn: XYM_HOME_FALLBACK.kefuKeyBtn,
kefuListBtn: '', kefuListBtn: XYM_HOME_FALLBACK.kefuListBtn,
iconRegular: '', iconRegular: XYM_HOME_FALLBACK.iconRegular,
iconCustom: '', iconCustom: XYM_HOME_FALLBACK.iconCustom,
}, },
stats: { stats: {
pendingCount: 0, pendingCount: 0,
@@ -155,12 +164,12 @@ Page(createPage({
const icon = (key, fallback) => resolveMiniappIcon(app, key, fallback); const icon = (key, fallback) => resolveMiniappIcon(app, key, fallback);
this.setData({ this.setData({
imgUrls: { imgUrls: {
noticeIco: icon(ICON_KEYS.MERCHANT_HOME_NOTICE, `${homeDir}notice.png`), noticeIco: icon(ICON_KEYS.MERCHANT_HOME_NOTICE, XYM_HOME_FALLBACK.noticeIco),
statCardBg: icon(ICON_KEYS.MERCHANT_HOME_STAT_BG, `${ossBase}beijing/shangjiaduan/stat_card_bg.png`), statCardBg: icon(ICON_KEYS.MERCHANT_HOME_STAT_BG, `${ossBase}beijing/shangjiaduan/stat_card_bg.png`) || XYM_HOME_FALLBACK.statCardBg,
kefuKeyBtn: icon(ICON_KEYS.MERCHANT_HOME_KEFU_KEY, `${homeDir}kefu_key.png`), kefuKeyBtn: icon(ICON_KEYS.MERCHANT_HOME_KEFU_KEY, XYM_HOME_FALLBACK.kefuKeyBtn),
kefuListBtn: icon(ICON_KEYS.MERCHANT_HOME_KEFU_LIST, `${homeDir}kefu_list.png`), kefuListBtn: icon(ICON_KEYS.MERCHANT_HOME_KEFU_LIST, XYM_HOME_FALLBACK.kefuListBtn),
iconRegular: icon(ICON_KEYS.MERCHANT_HOME_REGULAR, `${homeDir}regular_dispatch.png`), iconRegular: icon(ICON_KEYS.MERCHANT_HOME_REGULAR, XYM_HOME_FALLBACK.iconRegular),
iconCustom: icon(ICON_KEYS.MERCHANT_HOME_CUSTOM, `${homeDir}custom_dispatch.png`), iconCustom: icon(ICON_KEYS.MERCHANT_HOME_CUSTOM, XYM_HOME_FALLBACK.iconCustom),
}, },
}); });
}, },

View File

@@ -45,8 +45,8 @@
<view class="sj-fadan-block" wx:if="{{canDispatch}}"> <view class="sj-fadan-block" wx:if="{{canDispatch}}">
<view class="sj-fadan-row"> <view class="sj-fadan-row">
<view class="sj-fadan-img-btn" style="background-image:url({{imgUrls.iconRegular}})" bindtap="goRegularDispatch"/> <view class="sj-fadan-img-btn sj-fadan-img-btn--left" bindtap="goRegularDispatch"/>
<view class="sj-fadan-img-btn" style="background-image:url({{imgUrls.iconCustom}})" bindtap="goCustomDispatch"/> <view class="sj-fadan-img-btn sj-fadan-img-btn--right" bindtap="goCustomDispatch"/>
</view> </view>
<view class="sj-fadan-row sj-fadan-row--link"> <view class="sj-fadan-row sj-fadan-row--link">
<view class="sj-fadan-big-btn sj-fadan-big-btn--link" bindtap="goLinkDispatch"> <view class="sj-fadan-big-btn sj-fadan-big-btn--link" bindtap="goLinkDispatch">
@@ -74,28 +74,6 @@
<text class="stat-num">{{stats.pendingAmount}}</text> <text class="stat-num">{{stats.pendingAmount}}</text>
</view> </view>
</view> </view>
<view class="stats-row flexa stats-row--gap">
<view class="stat-col stat-col--l">
<text class="stat-lbl">成交总量</text>
<text class="stat-num">{{stats.completedCount}}</text>
</view>
<view class="stat-divider"></view>
<view class="stat-col stat-col--r">
<text class="stat-lbl">成交总额(元)</text>
<text class="stat-num">{{stats.completedAmount}}</text>
</view>
</view>
<view class="stats-row flexa stats-row--gap">
<view class="stat-col stat-col--l">
<text class="stat-lbl">退款总量</text>
<text class="stat-num">{{stats.refundCount}}</text>
</view>
<view class="stat-divider"></view>
<view class="stat-col stat-col--r">
<text class="stat-lbl">退款总额(元)</text>
<text class="stat-num">{{stats.refundAmount}}</text>
</view>
</view>
<view class="stats-row flexa stats-row--gap"> <view class="stats-row flexa stats-row--gap">
<view class="stat-col stat-col--l"> <view class="stat-col stat-col--l">
<text class="stat-lbl">今日派单(数)</text> <text class="stat-lbl">今日派单(数)</text>

View File

@@ -102,6 +102,10 @@ page {
height: 56rpx; height: 56rpx;
flex-shrink: 0; flex-shrink: 0;
margin-right: 12rpx; margin-right: 12rpx;
background-image: url('https://bintao.xmxym88.com/xcx/bintao/38.png');
background-size: contain;
background-repeat: no-repeat;
background-position: center;
} }
.sj-notice-txt { .sj-notice-txt {
@@ -136,6 +140,14 @@ page {
background-repeat: no-repeat; background-repeat: no-repeat;
} }
.sj-fadan-img-btn--left {
background-image: url('https://bintao.xmxym88.com/xcx/bintao/74.png');
}
.sj-fadan-img-btn--right {
background-image: url('https://bintao.xmxym88.com/xcx/bintao/76.png');
}
.sj-fadan-big-btn { .sj-fadan-big-btn {
flex: 1; flex: 1;
height: 128rpx; height: 128rpx;
@@ -179,8 +191,10 @@ page {
left: 0; left: 0;
right: 0; right: 0;
bottom: 0; bottom: 0;
background-image: url('https://bintao.xmxym88.com/xcx/bintao/3.png');
background-size: 100% auto; background-size: 100% auto;
background-repeat: no-repeat; background-repeat: no-repeat;
background-position: center top;
pointer-events: none; pointer-events: none;
z-index: 0; z-index: 0;
} }

View File

@@ -47,7 +47,11 @@
<view class="staff-filter-row" wx:if="{{staffList.length > 0}}"> <view class="staff-filter-row" wx:if="{{staffList.length > 0}}">
<picker mode="selector" range="{{staffList}}" range-key="nickname" bindchange="onStaffFilterChange"> <picker mode="selector" range="{{staffList}}" range-key="nickname" bindchange="onStaffFilterChange">
<view class="staff-filter-pill">{{selectedStaffLabel}}</view> <view class="staff-filter-pill {{selectedStaffMemberId ? 'staff-filter-pill--active' : ''}}">
<text class="staff-filter-tag">客服</text>
<text class="staff-filter-value">{{selectedStaffLabel}}</text>
<text class="staff-filter-arrow">▾</text>
</view>
</picker> </picker>
<view wx:if="{{selectedStaffMemberId}}" class="staff-filter-clear" bindtap="clearStaffFilter">清除</view> <view wx:if="{{selectedStaffMemberId}}" class="staff-filter-clear" bindtap="clearStaffFilter">清除</view>
</view> </view>
@@ -63,12 +67,6 @@
<view class="main-container"> <view class="main-container">
<!-- 左侧状态栏(固定) --> <!-- 左侧状态栏(固定) -->
<view class="left-status"> <view class="left-status">
<view class="sidebar-stats" wx:if="{{canViewFinance}}">
<text class="sb-line">派单 {{orderStats.dispatch_count}} / ¥{{orderStats.dispatch_amount}}</text>
<text class="sb-line">成交 {{orderStats.completed_count}} / ¥{{orderStats.completed_amount}}</text>
<text class="sb-line">退款 {{orderStats.refund_count}} / ¥{{orderStats.refund_amount}}</text>
<text class="sb-line accent">待结 {{orderStats.pending_count}} / ¥{{orderStats.pending_amount}}</text>
</view>
<block wx:for="{{statusList}}" wx:key="key"> <block wx:for="{{statusList}}" wx:key="key">
<view class="status-item {{currentStatusKey == item.key ? 'status-active' : ''}}" data-key="{{item.key}}" bindtap="switchStatus"> <view class="status-item {{currentStatusKey == item.key ? 'status-active' : ''}}" data-key="{{item.key}}" bindtap="switchStatus">
<text class="status-name">{{item.name}}</text> <text class="status-name">{{item.name}}</text>

View File

@@ -154,38 +154,76 @@ page {
border-radius: 24rpx; border-radius: 24rpx;
} }
/* ========== 客服筛选 ========== */
.staff-filter-row { .staff-filter-row {
display: flex; display: flex;
align-items: center; align-items: center;
gap: 16rpx; padding: 0 24rpx 16rpx;
padding: 12rpx 24rpx;
background: #fff; background: #fff;
border-bottom: 1rpx solid #f0f0f0; border-bottom: 1rpx solid #f0f0f0;
gap: 16rpx;
flex-shrink: 0;
} }
.staff-filter-pill { .staff-filter-pill {
padding: 10rpx 24rpx; display: inline-flex;
background: #f0f7ff; align-items: center;
color: #1565C0; max-width: 100%;
border-radius: 24rpx; padding: 12rpx 24rpx;
font-size: 24rpx; border-radius: 32rpx;
background: #f7f7f7;
border: 1rpx solid #eee;
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.04);
} }
.staff-filter-clear { .staff-filter-pill--active {
font-size: 24rpx; background: linear-gradient(180deg, #fff8e1, #ffe9b8);
border-color: #e8c547;
box-shadow: 0 4rpx 12rpx rgba(232, 197, 71, 0.25);
}
.staff-filter-tag {
flex-shrink: 0;
font-size: 22rpx;
font-weight: 700;
color: #8a6d2b;
padding: 4rpx 12rpx;
margin-right: 12rpx;
border-radius: 16rpx;
background: rgba(255, 255, 255, 0.65);
}
.staff-filter-pill--active .staff-filter-tag {
background: rgba(255, 255, 255, 0.85);
color: #492f00;
}
.staff-filter-value {
flex: 1;
min-width: 0;
font-size: 26rpx;
font-weight: 600;
color: #333;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.staff-filter-pill--active .staff-filter-value {
color: #492f00;
}
.staff-filter-arrow {
flex-shrink: 0;
margin-left: 8rpx;
font-size: 22rpx;
color: #999; color: #999;
} }
.sidebar-stats { .staff-filter-pill--active .staff-filter-arrow {
padding: 12rpx 8rpx 16rpx; color: #8a6d2b;
margin-bottom: 8rpx;
border-bottom: 1rpx solid #eee;
} }
.sb-line { .staff-filter-clear {
display: block; flex-shrink: 0;
font-size: 20rpx; font-size: 24rpx;
color: #888; color: #c9a227;
line-height: 1.6; padding: 10rpx 16rpx;
word-break: break-all; border-radius: 24rpx;
background: #fff8e8;
border: 1rpx solid #f0d89a;
} }
.sb-line.accent { color: #E65100; font-weight: 600; }
/* ========== 待结算提示条(保留原样式) ========== */ /* ========== 待结算提示条(保留原样式) ========== */
.sj-pending-tip { .sj-pending-tip {

View File

@@ -499,6 +499,7 @@ Page(createPage({
}, },
goToRanking() { wx.navigateTo({ url: '/pages/fighter-rank/fighter-rank?type=shangjia' }); }, goToRanking() { wx.navigateTo({ url: '/pages/fighter-rank/fighter-rank?type=shangjia' }); },
goToMessages() { wx.navigateTo({ url: '/pages/merchant-penalty/merchant-penalty' }); }, goToMessages() { wx.navigateTo({ url: '/pages/merchant-penalty/merchant-penalty' }); },
goToDataStats() { wx.navigateTo({ url: '/pages/merchant-data-stats/merchant-data-stats' }); },
}, { }, {
roleConfig: { roleConfig: {
role: 'shangjia', role: 'shangjia',

View File

@@ -96,54 +96,19 @@
</view> </view>
</view> </view>
<view class="sj-panel sj-mx20 data-board" wx:if="{{canViewFinance || !isStaffMode}}">
<view class="sj-section-hd">经营数据</view>
<view class="data-highlight flexb">
<view class="data-hl-item" bindtap="goToPendingOrders">
<text class="data-hl-num accent">{{orderStats.pending_count}}</text>
<text class="data-hl-lbl">待结算(单)</text>
<text class="data-hl-sub" wx:if="{{canViewFinance}}">¥{{orderStats.pending_amount}}</text>
</view>
<view class="data-hl-item">
<text class="data-hl-num">{{orderStats.completed_count}}</text>
<text class="data-hl-lbl">成交总量</text>
<text class="data-hl-sub" wx:if="{{canViewFinance}}">¥{{orderStats.completed_amount}}</text>
</view>
</view>
<view class="data-grid">
<view class="data-cell">
<text class="data-cell-num">{{orderStats.refund_count}}</text>
<text class="data-cell-lbl">退款总量</text>
<text class="data-cell-sub" wx:if="{{canViewFinance}}">¥{{orderStats.refund_amount}}</text>
</view>
<view class="data-cell">
<text class="data-cell-num">{{orderStats.dispatch_count}}</text>
<text class="data-cell-lbl">发单总量</text>
<text class="data-cell-sub" wx:if="{{canViewFinance}}">¥{{orderStats.dispatch_amount}}</text>
</view>
<view class="data-cell">
<text class="data-cell-num">{{jinriliushui}}</text>
<text class="data-cell-lbl">今日流水</text>
</view>
<view class="data-cell">
<text class="data-cell-num">{{jinyueliushui}}</text>
<text class="data-cell-lbl">今月流水</text>
</view>
</view>
<view class="penalty-mini" wx:if="{{!isStaffMode}}">
<text>处罚待处理:罚单 {{penaltyStats.fakuan_pending}}(¥{{penaltyStats.fakuan_pending_amount}})· 积分 {{penaltyStats.jifen_pending}}</text>
</view>
</view>
<view class="freeze-row flexa"> <view class="freeze-row flexa">
<view class="freeze-col flexmc">
<text class="freeze-num">{{jinriliushui}}</text>
<text class="freeze-lbl">今日流水</text>
</view>
<view class="freeze-col flexmc">
<text class="freeze-num">{{jinyueliushui}}</text>
<text class="freeze-lbl">今月流水</text>
</view>
<view class="freeze-col flexmc"> <view class="freeze-col flexmc">
<text class="freeze-num">{{jinridingdan}}</text> <text class="freeze-num">{{jinridingdan}}</text>
<text class="freeze-lbl">今日派单</text> <text class="freeze-lbl">今日派单</text>
</view> </view>
<view class="freeze-col flexmc">
<text class="freeze-num">{{jinrituikuan}}</text>
<text class="freeze-lbl">今日退款</text>
</view>
</view> </view>
<view class="sj-panel sj-mx20 order-nav-box"> <view class="sj-panel sj-mx20 order-nav-box">
@@ -183,6 +148,10 @@
<image class="sj-func-icon" src="{{imgUrls.iconOrders}}" mode="aspectFit"/> <image class="sj-func-icon" src="{{imgUrls.iconOrders}}" mode="aspectFit"/>
<text class="sj-func-txt">链接派单</text> <text class="sj-func-txt">链接派单</text>
</view> </view>
<view class="sj-func-item" bindtap="goToDataStats" wx:if="{{canViewFinance || !isStaffMode}}">
<image class="sj-func-icon" src="{{imgUrls.iconRank}}" mode="aspectFit"/>
<text class="sj-func-txt">经营数据</text>
</view>
<view class="sj-func-item" bindtap="goToKefuKey" wx:if="{{canStaffManage}}"> <view class="sj-func-item" bindtap="goToKefuKey" wx:if="{{canStaffManage}}">
<image class="sj-func-icon" src="{{imgUrls.iconService}}" mode="aspectFit"/> <image class="sj-func-icon" src="{{imgUrls.iconService}}" mode="aspectFit"/>
<text class="sj-func-txt">客服邀请码</text> <text class="sj-func-txt">客服邀请码</text>

View File

@@ -181,40 +181,6 @@ page {
margin-top: 16rpx; margin-top: 16rpx;
} }
.data-board { margin-top: 16rpx; padding-bottom: 8rpx; }
.data-highlight {
display: flex;
padding: 8rpx 0 16rpx;
border-bottom: 1rpx solid #f0f0f0;
margin-bottom: 12rpx;
}
.data-hl-item { flex: 1; text-align: center; }
.data-hl-num { font-size: 40rpx; font-weight: 700; color: #333; display: block; }
.data-hl-num.accent { color: #E65100; }
.data-hl-lbl { font-size: 24rpx; color: #888; display: block; margin-top: 4rpx; }
.data-hl-sub { font-size: 22rpx; color: #1565C0; display: block; margin-top: 4rpx; }
.data-grid {
display: flex;
flex-wrap: wrap;
}
.data-cell {
width: 50%;
box-sizing: border-box;
padding: 12rpx 8rpx;
text-align: center;
}
.data-cell-num { font-size: 30rpx; font-weight: 600; color: #333; display: block; }
.data-cell-lbl { font-size: 22rpx; color: #999; display: block; margin-top: 4rpx; }
.data-cell-sub { font-size: 20rpx; color: #1565C0; display: block; }
.penalty-mini {
margin-top: 8rpx;
padding-top: 12rpx;
border-top: 1rpx solid #f0f0f0;
font-size: 22rpx;
color: #888;
text-align: center;
}
.unreg-area { .unreg-area {
flex: 1; flex: 1;
padding: 40rpx 0 16rpx; padding: 40rpx 0 16rpx;