本地备份:商家打手端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
const app = getApp();
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 { reconnectForRole } from '../../utils/role-tab-bar.js';
import { ensurePhoneAuth } from '../../utils/phone-auth.js';
import { fetchGonggaoLunbo, isGonggaoCacheValid } from '../../utils/display-config.js';
Page({
data: {
@@ -29,7 +35,7 @@ Page({
// 4. 刷新控制字段
scrollViewRefreshing: false,
lastRefreshTime: 0,
refreshCooldown: 2000,
refreshCooldown: 0,
isLoadingMore: false,
// 5. 切换类型冷却
@@ -46,13 +52,59 @@ Page({
// 商品轮播展示(只读 globalData无额外接口
lunboList: [],
gonggao: '',
examRequired: false,
examPassed: false,
_examChecked: false,
},
async onLoad(options) {
this.syncShopBannerFromGlobal();
async onLoad() {
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.registerNotificationComponent();
await this.syncDashouProfileFromServer();
this._skipShowRefresh = true;
return;
}
this.loadGlobalStatus();
await this.loadShangpinLeixing();
PopupService.checkAndShow(this, 'jiedan');
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');
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 () {
@@ -62,63 +114,84 @@ Page({
}
},
onShow() {
this.syncShopBannerFromGlobal();
async onShow() {
if (!app.globalData._dashouPhoneChecked) {
const phoneOk = await ensurePhoneAuth({ redirect: true, role: 'dashou' });
if (!phoneOk) return;
app.globalData._dashouPhoneChecked = true;
}
this.registerNotificationComponent();
this.loadGlobalStatus();
await this.syncDashouProfileFromServer();
warmupPindaoConfig(app);
if (wx.getStorageSync('uid')) {
reconnectForRole('dashou');
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;
});
}
},
/** 同步点单端已加载的商品轮播图,仅展示用 */
syncShopBannerFromGlobal() {
const oss = app.globalData.ossImageUrl || '';
const lunboList = (app.globalData.shangpinlunbo || []).map((url) => {
/** 进入页面静默刷新(无 loading 遮罩、不清空列表) */
async silentRefreshOnShow() {
try {
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 '';
return url.startsWith('http') ? url : oss + url;
}).filter(Boolean);
this.setData({ lunboList });
},
async refreshDashouProfileSilent() {
try {
const res = await request({ url: '/yonghu/dashouxinxi', method: 'POST' });
if (!res || res.data.code != 200) return;
const data = res.data.data || {};
const patch = {
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;
async loadGonggaoAndLunbo(forceFetch = false) {
let lunboRaw = app.globalData.shangpinlunbo || [];
let gonggaoText = app.globalData.shangpingonggao || '';
if (forceFetch || !isGonggaoCacheValid(app)) {
try {
const data = await fetchGonggaoLunbo(app, 'accept_order');
if (data) {
lunboRaw = data.shangpinlunbo || app.globalData.shangpinlunbo || [];
gonggaoText = data.shangpingonggao || app.globalData.shangpingonggao || '';
}
} catch (e) {
lunboRaw = app.globalData.shangpinlunbo || [];
gonggaoText = app.globalData.shangpingonggao || '';
}
this.setData({
zhuanghaoStatus: patch.zhanghaoStatus,
dashouzhuangtai: patch.dashouzhuangtai,
huiyuanList: patch.clumber,
yajin: patch.yajin,
jifen: patch.jifen,
});
} catch (e) {}
}
const lunboList = this.processLunboUrls(lunboRaw);
const gonggao = gonggaoText;
this.setData({ lunboList, gonggao });
return { lunboList, gonggao };
},
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() {
wx.showLoading({ title: '加载商品类型...' });
async loadShangpinLeixing(autoLoadOrders = false, preserveSelection = false, showLoading = true) {
if (showLoading) wx.showLoading({ title: '加载商品类型...' });
const prevId = this.data.xuanzhongLeixingId;
try {
const res = await request({
url: '/dingdan/dsqdhqddlx',
@@ -163,14 +249,16 @@ Page({
else if (Array.isArray(data)) list = data;
}
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({
shangpinleixing: processedList,
xuanzhongLeixingId: processedList[0]?.id || null
xuanzhongLeixingId: selectedId,
});
if (this.data.xuanzhongLeixingId) {
this.loadDingdanList(true);
// 🆕 加载板块标签
this.loadBankuaiBiaoqian();
if (autoLoadOrders && selectedId) {
await this.loadDingdanList(true);
await this.loadBankuaiBiaoqian();
}
} else {
wx.showToast({ title: res.data?.msg || '加载商品类型失败', icon: 'none' });
@@ -178,7 +266,7 @@ Page({
} catch (error) {
wx.showToast({ title: '网络错误,加载失败', icon: 'none' });
} finally {
wx.hideLoading();
if (showLoading) wx.hideLoading();
}
},
@@ -245,8 +333,8 @@ Page({
xuanzhongBiaoqianId: 0 // 重置标签筛选
});
await this.loadDingdanList(true);
// 🆕 切换类型后加载新标签
await this.loadBankuaiBiaoqian();
this.persistPageCache();
} catch (error) {
console.error('切换类型失败:', error);
} finally {
@@ -266,19 +354,24 @@ Page({
hasMore: true
});
await this.loadDingdanList(true);
this.persistPageCache();
},
// 加载订单列表
async loadDingdanList(isRefresh = false) {
if (this.data.isLoading || !this.data.xuanzhongLeixingId) return;
async loadDingdanList(isRefresh = false, silent = false) {
if ((!silent && this.data.isLoading) || !this.data.xuanzhongLeixingId) return;
if (silent && this._listRequesting) return;
const loadPage = isRefresh ? 1 : this.data.page;
if (!isRefresh && !this.data.hasMore) return;
this.setData({
isLoading: true,
isLoadingMore: !isRefresh
});
if (!silent) {
this.setData({
isLoading: true,
isLoadingMore: !isRefresh,
});
}
this._listRequesting = true;
try {
const res = await request({
@@ -298,6 +391,7 @@ Page({
isLoadingMore: false,
scrollViewRefreshing: false
});
this._listRequesting = false;
if (res.data.code === 200 || res.data.code === 0) {
const newList = res.data.data.list || [];
@@ -313,6 +407,7 @@ Page({
page: loadPage,
hasMore: hasMore
});
this.persistPageCache();
if (isRefresh) {
this.setData({ lastRefreshTime: Date.now() });
@@ -327,20 +422,28 @@ Page({
isLoadingMore: false,
scrollViewRefreshing: false
});
wx.showToast({ title: '网络请求失败', icon: 'none' });
this._listRequesting = false;
if (!silent) {
wx.showToast({ title: '网络请求失败', icon: 'none' });
}
}
},
// 处理单条订单数据(包含标签、会员判断)
processDingdanItem(item) {
const ossUrl = app.globalData.ossImageUrl || '';
const leixing = this.data.shangpinleixing.find((l) => l.id == item.leixing_id);
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 {
const leixing = this.data.shangpinleixing.find(l => l.id === item.leixing_id);
fullTupianUrl = leixing ? leixing.full_tupian_url : '/images/default-order.png';
fullTupianUrl = '/images/default-order.png';
}
const isZhiding = item.zhuangtai === 7;
@@ -353,25 +456,32 @@ Page({
}
const zhidingNicheng = item.zhiding_nicheng || '';
// 🆕 判断用户是否有订单所需的会员仅当订单要求会员类型且存在huiyuan_id
// 订单要求指定会员时,核对用户是否持有该会员类型
let hasRequiredMember = true;
if (item.yaoqiuleixing == 1 && item.huiyuan_id) {
const userHasIt = this.data.huiyuanList.some(h => h.huiyuanid == item.huiyuan_id);
hasRequiredMember = userHasIt;
hasRequiredMember = userHasHuiyuan(this.data.huiyuanList, item.huiyuan_id);
}
let shangjiaAvatar = getDefaultAvatarUrl(app);
const sjAvatar = (item.sj_avatar || '').trim();
if (sjAvatar) {
shangjiaAvatar = sjAvatar.startsWith('http') ? sjAvatar : ossUrl + sjAvatar;
}
const tags = normalizeOrderTags(item)
return {
...item,
full_tupian_url: fullTupianUrl,
leixing_icon_url: fullTupianUrl,
shangjia_avatar_full: shangjiaAvatar,
isZhiding: isZhiding,
isPingtai: item.pingtai == 1,
isShangjia: item.pingtai == 2,
zhiding_avatar_full: zhidingAvatar,
zhiding_nicheng: zhidingNicheng,
// 🆕 三层标签(后端返回,直接保留)
xuqiu_biaoqian: item.xuqiu_biaoqian || [],
dashou_biaoqian: item.dashou_biaoqian || [],
shangjia_biaoqian: item.shangjia_biaoqian || [],
...tags,
shangjia_youzhi: !!item.shangjia_youzhi,
// 🆕 是否有查看价格的权限
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) {
const dingdanItem = e.currentTarget.dataset.item;
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: 打手身份
if (!this.data.dashoustatus || this.data.dashoustatus != 1) {
wx.showToast({ title: '请先开启接单员身份', icon: 'none' });
@@ -438,7 +587,7 @@ Page({
}
// 校验5: 会员要求
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) {
wx.showToast({
title: '未开通对应会员,无法抢单',
@@ -504,6 +653,7 @@ Page({
item => item.dingdan_id !== dingdanItem.dingdan_id
);
that.setData({ dingdanList: newList });
that.persistPageCache();
} else {
wx.showToast({
title: qiangdanRes.data.msg || '抢单失败',
@@ -535,42 +685,14 @@ Page({
},
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.hasMore && !this.data.isLoading && this.data.xuanzhongLeixingId) {
this.setData({ page: this.data.page + 1 });
this.loadDingdanList(false);
}
},
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;
}
async onPullDownRefresh() {
if (this.data.isLoading) {
this.setData({ scrollViewRefreshing: false });
return;
@@ -578,14 +700,25 @@ Page({
this.setData({
scrollViewRefreshing: true,
lastRefreshTime: now,
lastRefreshTime: Date.now(),
page: 1,
hasMore: true
hasMore: true,
});
if (this.data.xuanzhongLeixingId) {
this.loadDingdanList(true);
} else {
try {
const banner = await this.loadGonggaoAndLunbo(true);
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 });
}
}

View File

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

View File

@@ -1,4 +1,4 @@
<!-- pages/qiangdan/qiangdan.wxml -->
<!-- pages/qiangdan/qiangdan.wxml -->
<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与点单端同源 -->
<view class="xym-lunbo-container" wx:if="{{lunboList.length > 0}}">
@@ -74,7 +80,7 @@
</view>
<view class="xym-section-gap" wx:if="{{lunboList.length > 0}}"></view>
<!-- 商品类型选择 -->
@@ -190,16 +196,6 @@
<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">
<image class="o-logo" src="{{item.full_tupian_url}}" mode="aspectFill"/>
@@ -212,6 +208,20 @@
</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}}">
<text class="reward-yen sm">¥</text>
@@ -226,9 +236,9 @@
</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>
@@ -236,10 +246,10 @@
<text class="xuqiu-label">需求标签</text>
<scroll-view class="biaoqian-inline-scroll" scroll-x>
<chenghao-tag wx:for="{{item.xuqiu_biaoqian}}" wx:for-item="tag" wx:key="id" mingcheng="{{tag.mingcheng}}" texiaoJson="{{tag.texiao_json}}" />
<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}}" />
</view>
</scroll-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}}">
@@ -276,19 +361,23 @@
<view class="order-con">
<view wx:if="{{item.isZhiding}}" class="zhiding-strip 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>
<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="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>
@@ -318,24 +407,33 @@
</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 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>
<chenghao-tag wx:for="{{item.shangjia_biaoqian}}" wx:for-item="tag" wx:key="id" mingcheng="{{tag.mingcheng}}" texiaoJson="{{tag.texiao_json}}" />
<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.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">
<chenghao-tag wx:for="{{item.xuqiu_biaoqian}}" wx:for-item="tag" wx:key="id" mingcheng="{{tag.mingcheng}}" texiaoJson="{{tag.texiao_json}}" />
<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 File

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

File diff suppressed because it is too large Load Diff

View File

@@ -49,7 +49,14 @@ Page(createPage({
onLoad() {
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();
},
@@ -59,8 +66,15 @@ Page(createPage({
reconnectForRole('dashou');
if (app.startImWhenReady) app.startImWhenReady();
}
if (this.data.currentStatusKey && this.data.xuanzhongLeixingId) {
this.loadCurrentStatusOrders(true);
if (this._skipShowRefresh) {
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 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;
this.setData({
[`dsDingdanShuju.${key}.isLoading`]: true,
isLoading: true,
isLoadingMore: !isRefresh
});
if (!silent) {
this.setData({
[`dsDingdanShuju.${key}.isLoading`]: true,
isLoading: true,
isLoadingMore: !isRefresh,
});
}
this._listRequesting = true;
try {
const apiUrl = this.data.orderType === 'peihu'
@@ -208,14 +226,20 @@ Page(createPage({
}
} catch (err) {
console.error('加载订单失败', err);
wx.showToast({ title: err.message || '加载失败', icon: 'none' });
this.setData({
[`dsDingdanShuju.${key}.isLoading`]: false,
isLoading: false,
isLoadingMore: false,
scrollViewRefreshing: false
});
this.refreshCurrentListView();
if (!silent) {
wx.showToast({ title: err.message || '加载失败', icon: 'none' });
}
if (!silent) {
this.setData({
[`dsDingdanShuju.${key}.isLoading`]: false,
isLoading: false,
isLoadingMore: false,
scrollViewRefreshing: false
});
this.refreshCurrentListView();
}
} finally {
this._listRequesting = false;
}
},

View File

@@ -1,6 +1,7 @@
{
"usingComponents": {
"global-notification": "/components/global-notification/global-notification"
"global-notification": "/components/global-notification/global-notification",
"tab-bar": "/tab-bar/index"
},
"navigationBarTitleText": "我的接单",
"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 { 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 = [
{ key: 'dashou', label: '接单员' },
@@ -27,6 +32,7 @@ const ROLE_META = {
title: '接单员排行榜',
sortField: 'chengjiao_zonge',
sortLabel: '分红总额',
mainType: 'money',
metrics: [
{ field: 'jiedan_zongliang', label: '接单量', type: 'int' },
{ field: 'jiedan_zonge', label: '接单额', type: 'money' },
@@ -37,6 +43,7 @@ const ROLE_META = {
title: '管事排行榜',
sortField: 'shouru_zonge',
sortLabel: '收入总额',
mainType: 'money',
metrics: [
{ field: 'yaoqing_dashou_shu', label: '邀请', type: 'int' },
{ field: 'chongzhi_dashou_shu', label: '充值', type: 'int' },
@@ -46,6 +53,7 @@ const ROLE_META = {
title: '组长排行榜',
sortField: 'shouru_zonge',
sortLabel: '收入总额',
mainType: 'money',
metrics: [
{ field: 'yaoqing_guanshi_shu', label: '邀请', type: 'int' },
{ field: 'fenyong_jine', label: '分佣', type: 'money' },
@@ -55,6 +63,7 @@ const ROLE_META = {
title: '商家排行榜',
sortField: 'jiesuan_jine',
sortLabel: '成交总额',
mainType: 'money',
metrics: [
{ field: 'jiesuan_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) {
if (path === null || path === undefined) return true
if (typeof path !== 'string') return true
@@ -99,7 +157,7 @@ Page({
onLoad(options) {
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.applyRole(validRole, false)
this.fetchRankList()
@@ -162,7 +220,7 @@ Page({
},
applyRole(role, reload = true) {
const meta = ROLE_META[role]
const meta = ACTIVE_ROLE_META[role]
wx.setNavigationBarTitle({ title: meta.title })
this.setData({ currentRole: role, roleMeta: meta, sortLabel: meta.sortLabel })
if (reload) this.fetchRankList()
@@ -196,7 +254,7 @@ Page({
},
normalizeItem(raw, index, role) {
const meta = ROLE_META[role]
const meta = ACTIVE_ROLE_META[role]
const app = getApp()
const uid = raw.yonghuid || raw.uid || ''
const nicheng = raw.nicheng || raw.nick || '用户'
@@ -209,12 +267,19 @@ Page({
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 {
mingci: raw.mingci || index + 1,
uid,
nicheng,
avatar,
mainValue: this.formatMoney(raw[meta.sortField]),
mainType,
mainPrefix: mainType === 'money' ? '¥' : '',
mainValue,
mainLabel: meta.sortLabel,
metrics,
}
@@ -224,7 +289,7 @@ Page({
this.setData({ isLoading: true, isEmpty: false })
try {
const res = await request({
url: '/yonghu/phbhqsj',
url: RANK_API,
method: 'POST',
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-uid">ID {{topThree[1].uid}}</text>
<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>
</view>
<view class="p-metrics">
@@ -70,7 +70,7 @@
<text class="p-name p-name-first">{{topThree[0].nicheng}}</text>
<text class="p-uid">ID {{topThree[0].uid}}</text>
<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>
</view>
<view class="p-metrics">
@@ -88,7 +88,7 @@
<text class="p-name">{{topThree[2].nicheng}}</text>
<text class="p-uid">ID {{topThree[2].uid}}</text>
<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>
</view>
<view class="p-metrics">
@@ -120,7 +120,7 @@
</view>
</view>
<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>
</view>
</view>

File diff suppressed because it is too large Load Diff

View File

@@ -47,6 +47,12 @@
<view class="vip-badge" wx:if="{{item.isBought}}">
<text class="badge-text">已拥有</text>
</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">
<text class="title-text">{{item.mingzi}}</text>
@@ -56,7 +62,11 @@
<view class="vip-price">
<text class="price-symbol">¥</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 class="vip-features">
@@ -107,20 +117,27 @@
<!-- 🔥 将“机甲能源”改为“价格” -->
<text class="price-label">价格:</text>
<text class="price-value">¥{{currentHuiyuan.jiage}}</text>
<text class="price-days">/{{currentHuiyuan.formal_days || 30}}天</text>
</view>
<text class="buy-desc" wx:if="{{currentHuiyuan.isBought && currentHuiyuan.buyInfo}}">
已激活,<text class="expire-date">{{currentHuiyuan.buyInfo.daoqi}}</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 class="buy-action">
<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-glow"></view>
<text class="buy-btn-text">
{{currentHuiyuan.isBought ? '立即续费' : '立即激活'}}
{{currentHuiyuan.isBought ? '正式续费' : '购买正式版'}}
</text>
<view class="buy-btn-energy">
<view class="energy-dot"></view>
@@ -128,6 +145,16 @@
<view class="energy-dot"></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 File

@@ -1,4 +1,5 @@
/* pages/dashou-chongzhi/index.wxss - 完整保留原有样式,仅删除导航栏相关,调整间距和字体 */
/* pages/dashou-chongzhi/index.wxss - 逍遥梦主题覆盖 + 机甲基础样式 */
@import '../../styles/dashou-xym-recharge-theme.wxss';
/* ==================== 基础样式 ==================== */
.page-container {
@@ -676,6 +677,32 @@
box-shadow: 0 0 15rpx rgba(255, 107, 157, 0.4);
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 {
margin-bottom: 25rpx;
@@ -855,11 +882,35 @@
/* 购买区域 */
.buy-section {
display: flex;
align-items: center;
justify-content: space-between;
flex-direction: column;
align-items: stretch;
gap: 20rpx;
padding-top: 25rpx;
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 {
display: flex;
@@ -928,6 +979,11 @@
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 {
background: linear-gradient(135deg, #0f2c5c, #36cfc9);
}
@@ -1702,6 +1758,4 @@
display: flex !important;
align-items: 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 { resolveAvatarUrl } from '../../utils/avatar.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'
/** 会员/保证金横幅 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({
data: {
// 图片路径对象
@@ -41,6 +57,7 @@ Page(createPage({
zuzhangInviterCache: null,
chenghaoList: [],
guanshiChenghaoList: [],
identityTagList: [],
gszhstatus: '',
yaoqingzongshu: 0,
fenyongzonge: '0.00',
@@ -65,13 +82,25 @@ Page(createPage({
statusBar: 20,
navBar: 44,
pindaoVisible: false,
pindaoTitle: '频道',
pindaoChannelNo: '',
examEnabled: false,
examPassed: false,
pindaoImages: [],
scrollViewRefreshing: false,
showRechargeBanners: false,
showPindaoEntry: true,
},
_buildImgUrls(ossImageUrl) {
const app = getApp();
const dsBase = ossImageUrl + 'beijing/dashouduan/';
const iconBase = ossImageUrl + 'beijing/dashouduan/dashoutubiaobeijing/';
const gsBase = ossImageUrl + 'beijing/guanshiduan/';
const khBase = ossImageUrl + 'beijing/kaohe/';
const icon = (key, fallback) => resolveMiniappIcon(app, key, fallback);
return {
pageBg: dsBase + 'page-bg.jpg',
userCardBg: dsBase + 'user-card-bg.png',
@@ -83,7 +112,7 @@ Page(createPage({
listBg: dsBase + 'list-card-bg.png',
topBg: iconBase + 'top-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',
iconVip: dsBase + 'icon-vip.png',
iconArrowLight: dsBase + 'icon-arrow-light.png',
@@ -118,6 +147,7 @@ Page(createPage({
iconSwitch: '/images/_exit.png',
iconKefu: ossImageUrl + 'beijing/tubiao/grzx_kefu.jpg',
iconKuaishou: ossImageUrl + 'beijing/tubiao/grzx_guanzhualong.jpg',
iconPindao: icon(ICON_KEYS.MINE_PINDAO, ossImageUrl + PINDAO_ICON_FALLBACK),
iconKaoheDafen: khBase + 'daofen.png',
iconKaoheJilu: khBase + 'jilu.png',
iconKaoheZhongxin: khBase + 'zhongxin.png',
@@ -128,8 +158,8 @@ Page(createPage({
kefuBannerBg: dsBase + 'kefu-banner-bg.png',
totalAssetBg: dsBase + 'total-asset-bg.png',
authPanelBg: dsBase + 'auth-panel-bg.png',
bannerVip: 'https://bintao-1308403501.cos.ap-guangzhou.myqcloud.com/uploads/images/20260512123427531240452.png',
bannerDeposit: 'https://bintao-1308403501.cos.ap-guangzhou.myqcloud.com/uploads/images/202605121234283091d3980.png',
bannerVip: resolveConfiguredIcon(app, ICON_KEYS.FIGHTER_RECHARGE_MEMBER) || FIGHTER_BANNER_VIP_FALLBACK,
bannerDeposit: resolveConfiguredIcon(app, ICON_KEYS.FIGHTER_RECHARGE_DEPOSIT) || FIGHTER_BANNER_DEPOSIT_FALLBACK,
};
},
@@ -177,9 +207,28 @@ Page(createPage({
}
}
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());
lockPrimaryRole('dashou', getApp());
wx.setStorageSync('isJinpai', 0);
@@ -190,16 +239,17 @@ Page(createPage({
this.setData({ inviterCache, zuzhangInviterCache });
this.registerNotificationComponent();
warmupPindaoConfig(app);
this.checkRoleStatuses();
this.syncConfiguredAssets();
if (isCenterPageActive(this, 'isDashou', 'dashoustatus')) {
if (!this.data.isDashou) this.setData({ isDashou: true });
ensureRoleOnCenterPage(this, 'dashou');
setTimeout(() => this.refreshAllInfo(false), 300);
this.loadExamStatus();
} else if (isRoleStatusActive(wx.getStorageSync('guanshistatus')) ||
isRoleStatusActive(wx.getStorageSync('zuzhangstatus')) ||
isRoleStatusActive(wx.getStorageSync('kaoheguanstatus'))) {
ensureRoleOnCenterPage(this, 'dashou');
setTimeout(() => this.refreshAllInfo(false), 300);
}
const pages = getCurrentPages();
const currentPage = pages[pages.length - 1];
@@ -277,12 +327,17 @@ Page(createPage({
tag: d.shangjiaCertified ? '进入商家端' : '去认证',
done: d.shangjiaCertified,
});
list.push({
type: 'staff',
name: '商家客服',
icon: img.iconKefu || img.iconShangjia,
tag: isStaffMode() ? '进入工作台' : '去入驻',
done: isStaffMode(),
});
if (!d.isGuanshi) {
list.push({ type: 'guanshi', name: '管事', icon: img.iconGuanshiAuth, tag: '去认证' });
}
if (!d.isZuzhang) {
list.push({ type: 'zuzhang', name: '组长', icon: img.iconZuzhangAuth, tag: '去认证' });
}
// 组长由后台添加,前端不再展示「组长认证」入口
if (!d.isDashou) {
list.push({ type: 'dashou', name: '接单员', icon: img.iconDashouAuth, tag: '去认证' });
}
@@ -293,35 +348,37 @@ Page(createPage({
},
async refreshAllInfo(showToast = true) {
this.throttledRefresh(async () => {
this.setData({ isLoading: true });
try {
this.checkRoleStatuses();
const results = await Promise.allSettled([
this._fetchDashouInfoSilent(),
this.fetchChenghaoList(),
this._fetchGuanshiInfoSilent(),
this.fetchGuanshiChenghaoList(),
this._fetchZuzhangInfoSilent(),
this._fetchKaoheguanInfoSilent(),
]);
this.checkRoleStatuses();
const dashouOk = results[0].status === 'fulfilled';
if (showToast) {
wx.showToast({
title: dashouOk ? '刷新成功' : '刷新失败',
icon: dashouOk ? 'success' : 'none',
duration: 1500,
});
}
} catch (e) {
if (showToast) {
wx.showToast({ title: '刷新失败', icon: 'none' });
}
} finally {
this.setData({ isLoading: false });
if (this._profileRefreshing) return;
this._profileRefreshing = true;
this.setData({ isLoading: true });
try {
this.checkRoleStatuses();
const results = await Promise.allSettled([
this._fetchDashouInfoSilent(),
this.fetchChenghaoList(),
this._fetchGuanshiInfoSilent(),
this.fetchGuanshiChenghaoList(),
this._fetchZuzhangInfoSilent(),
this._fetchKaoheguanInfoSilent(),
this.loadIdentityTags(),
]);
this.checkRoleStatuses();
const dashouOk = results[0].status === 'fulfilled';
if (showToast) {
wx.showToast({
title: dashouOk ? '刷新成功' : '刷新失败',
icon: dashouOk ? 'success' : 'none',
duration: 1500,
});
}
}, 3000);
} catch (e) {
if (showToast) {
wx.showToast({ title: '刷新失败', icon: 'none' });
}
} finally {
this._profileRefreshing = false;
this.setData({ isLoading: false });
}
},
refreshDashouInfo() {
@@ -332,6 +389,34 @@ Page(createPage({
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() {
const res = await request({ url: '/yonghu/dashouxinxi', method: 'POST' });
if (res && res.data.code == 200) {
@@ -1015,6 +1100,14 @@ Page(createPage({
onTapAuthItem(e) {
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') {
this.onTapShangjiaAuth();
return;
@@ -1038,6 +1131,21 @@ Page(createPage({
wx.navigateTo({ url: '/pages/verify/verify?type=shangjia' });
},
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' }) },
goToMyPunishment() { wx.navigateTo({ url: '/pages/penalty/penalty/penalty' }) },
goToRecharge() { wx.navigateTo({ url: '/pages/fighter-recharge/fighter-recharge' }) },
@@ -1045,7 +1153,33 @@ Page(createPage({
const type = e?.currentTarget?.dataset?.type || 'dashou';
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' }) },
goToKaoheJilu() { wx.navigateTo({ url: '/pages/assess-log/assess-log' }) },
goToKaoheZhongxin() { wx.navigateTo({ url: '/pages/assess-center/assess-center' }) },

View File

@@ -2,7 +2,8 @@
"usingComponents": {
"global-notification": "/components/global-notification/global-notification",
"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",
"backgroundColor": "#fff8e1",

View File

@@ -26,14 +26,23 @@
<view class="user-page">
<view class="page-header">
<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 class="refresh-float" bindtap="onTapRefresh">
<image class="refresh-float-ico" src="{{imgUrls.iconRefresh}}" mode="aspectFit"/>
</view>
<scroll-view class="content" scroll-y enhanced show-scrollbar="{{false}}">
<scroll-view
class="content"
scroll-y
enhanced
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="flex">
@@ -55,11 +64,14 @@
</view>
</view>
</view>
<image class="setting-ico" src="{{imgUrls.iconEdit}}" mode="aspectFit" bindtap="goToModifyInfo"/>
<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"/>
</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}}">
<view class="badge-tag-wrap" wx:for="{{chenghaoList}}" wx:key="index">
<chenghao-tag mingcheng="{{item.mingcheng}}" texiaoJson="{{item.texiao_json}}"/>
@@ -70,6 +82,11 @@
<chenghao-tag mingcheng="{{item.mingcheng}}" texiaoJson="{{item.texiao_json}}"/>
</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>
<!-- 佣金/资产卡(逍遥梦 wallet-card -->
@@ -85,10 +102,14 @@
</view>
</view>
<!-- 会员充值 + 保证金(均跳转同一充值页 -->
<view class="banner-row flex">
<image class="banner-img" src="{{imgUrls.bannerVip}}" mode="widthFix" bindtap="goToRecharge"/>
<image class="banner-img" src="{{imgUrls.bannerDeposit}}" mode="widthFix" bindtap="goToRecharge"/>
<!-- 会员充值 + 保证金(无后台图时显示文字按钮 -->
<view class="banner-row flex" wx:if="{{showRechargeBanners}}">
<image wx:if="{{imgUrls.bannerVip}}" class="banner-img" src="{{imgUrls.bannerVip}}" 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>
<!-- 资产统计(逍遥梦 freeze-row -->
@@ -123,7 +144,7 @@
<!-- 接单服务(对应逍遥梦「我的订单」四宫格) -->
<view class="panel shadow">
<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">
<image class="nav-icon" src="{{imgUrls.iconGame}}" mode="aspectFit"/><text class="sm">抢单大厅</text>
</view>
@@ -136,6 +157,11 @@
<view class="nav-item flexmc" bindtap="goToKaohe">
<image class="nav-icon" src="{{imgUrls.iconMedal}}" mode="aspectFit"/><text class="sm">考核金牌</text>
</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>
@@ -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="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="goToKaoheWithdraw"><image class="func-icon" src="{{imgUrls.iconWithdraw}}" mode="aspectFit"/><text class="func-txt">考核提现</text></view>
</view>
</view>
@@ -217,6 +242,7 @@
<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="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="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>
@@ -236,3 +262,10 @@
<global-notification id="global-notification"/>
<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;
}
.nav-bar-actions {
position: relative;
justify-content: center;
}
.nav-refresh-ico {
position: absolute;
right: 24rpx;
width: 44rpx;
height: 44rpx;
padding: 8rpx;
}
.nav-title {
font-size: 34rpx;
font-weight: 700;
@@ -134,6 +147,20 @@ page {
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 {
width: 53rpx;
height: 53rpx;
@@ -233,6 +260,23 @@ page {
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 {
margin: 16rpx 30rpx 0;
padding: 20rpx 10rpx;
@@ -356,11 +400,35 @@ page {
.order-nav {
padding: 10rpx 0 20rpx;
display: flex;
flex-direction: row;
flex-wrap: wrap;
justify-content: flex-start;
align-items: flex-start;
}
.nav-item {
width: 25%;
width: 20%;
box-sizing: border-box;
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 {

View File

@@ -11,6 +11,15 @@ import { fetchMerchantOrderStats, applyOrderStatsToHome } from '../../utils/merc
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 一致的状态筛选 */
const ALL_ORDER_ZHUANGTAI = [1, 2, 3, 4, 5, 6, 7, 8];
const RECENT_ORDER_SIZE = 5;
@@ -30,12 +39,12 @@ Page(createPage({
gonggao: '',
swiperCurrent: 0,
imgUrls: {
noticeIco: '',
statCardBg: '',
kefuKeyBtn: '',
kefuListBtn: '',
iconRegular: '',
iconCustom: '',
noticeIco: XYM_HOME_FALLBACK.noticeIco,
statCardBg: XYM_HOME_FALLBACK.statCardBg,
kefuKeyBtn: XYM_HOME_FALLBACK.kefuKeyBtn,
kefuListBtn: XYM_HOME_FALLBACK.kefuListBtn,
iconRegular: XYM_HOME_FALLBACK.iconRegular,
iconCustom: XYM_HOME_FALLBACK.iconCustom,
},
stats: {
pendingCount: 0,
@@ -155,12 +164,12 @@ Page(createPage({
const icon = (key, fallback) => resolveMiniappIcon(app, key, fallback);
this.setData({
imgUrls: {
noticeIco: icon(ICON_KEYS.MERCHANT_HOME_NOTICE, `${homeDir}notice.png`),
statCardBg: icon(ICON_KEYS.MERCHANT_HOME_STAT_BG, `${ossBase}beijing/shangjiaduan/stat_card_bg.png`),
kefuKeyBtn: icon(ICON_KEYS.MERCHANT_HOME_KEFU_KEY, `${homeDir}kefu_key.png`),
kefuListBtn: icon(ICON_KEYS.MERCHANT_HOME_KEFU_LIST, `${homeDir}kefu_list.png`),
iconRegular: icon(ICON_KEYS.MERCHANT_HOME_REGULAR, `${homeDir}regular_dispatch.png`),
iconCustom: icon(ICON_KEYS.MERCHANT_HOME_CUSTOM, `${homeDir}custom_dispatch.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`) || XYM_HOME_FALLBACK.statCardBg,
kefuKeyBtn: icon(ICON_KEYS.MERCHANT_HOME_KEFU_KEY, XYM_HOME_FALLBACK.kefuKeyBtn),
kefuListBtn: icon(ICON_KEYS.MERCHANT_HOME_KEFU_LIST, XYM_HOME_FALLBACK.kefuListBtn),
iconRegular: icon(ICON_KEYS.MERCHANT_HOME_REGULAR, XYM_HOME_FALLBACK.iconRegular),
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-row">
<view class="sj-fadan-img-btn" style="background-image:url({{imgUrls.iconRegular}})" 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--left" bindtap="goRegularDispatch"/>
<view class="sj-fadan-img-btn sj-fadan-img-btn--right" bindtap="goCustomDispatch"/>
</view>
<view class="sj-fadan-row sj-fadan-row--link">
<view class="sj-fadan-big-btn sj-fadan-big-btn--link" bindtap="goLinkDispatch">
@@ -74,28 +74,6 @@
<text class="stat-num">{{stats.pendingAmount}}</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.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="stat-col stat-col--l">
<text class="stat-lbl">今日派单(数)</text>

View File

@@ -102,6 +102,10 @@ page {
height: 56rpx;
flex-shrink: 0;
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 {
@@ -136,6 +140,14 @@ page {
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 {
flex: 1;
height: 128rpx;
@@ -179,8 +191,10 @@ page {
left: 0;
right: 0;
bottom: 0;
background-image: url('https://bintao.xmxym88.com/xcx/bintao/3.png');
background-size: 100% auto;
background-repeat: no-repeat;
background-position: center top;
pointer-events: none;
z-index: 0;
}

View File

@@ -47,7 +47,11 @@
<view class="staff-filter-row" wx:if="{{staffList.length > 0}}">
<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>
<view wx:if="{{selectedStaffMemberId}}" class="staff-filter-clear" bindtap="clearStaffFilter">清除</view>
</view>
@@ -63,12 +67,6 @@
<view class="main-container">
<!-- 左侧状态栏(固定) -->
<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">
<view class="status-item {{currentStatusKey == item.key ? 'status-active' : ''}}" data-key="{{item.key}}" bindtap="switchStatus">
<text class="status-name">{{item.name}}</text>

View File

@@ -154,39 +154,77 @@ page {
border-radius: 24rpx;
}
/* ========== 客服筛选 ========== */
.staff-filter-row {
display: flex;
align-items: center;
gap: 16rpx;
padding: 12rpx 24rpx;
padding: 0 24rpx 16rpx;
background: #fff;
border-bottom: 1rpx solid #f0f0f0;
gap: 16rpx;
flex-shrink: 0;
}
.staff-filter-pill {
padding: 10rpx 24rpx;
background: #f0f7ff;
color: #1565C0;
border-radius: 24rpx;
font-size: 24rpx;
display: inline-flex;
align-items: center;
max-width: 100%;
padding: 12rpx 24rpx;
border-radius: 32rpx;
background: #f7f7f7;
border: 1rpx solid #eee;
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.04);
}
.staff-filter-clear {
font-size: 24rpx;
.staff-filter-pill--active {
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;
}
.sidebar-stats {
padding: 12rpx 8rpx 16rpx;
margin-bottom: 8rpx;
border-bottom: 1rpx solid #eee;
.staff-filter-pill--active .staff-filter-arrow {
color: #8a6d2b;
}
.sb-line {
display: block;
font-size: 20rpx;
color: #888;
line-height: 1.6;
word-break: break-all;
.staff-filter-clear {
flex-shrink: 0;
font-size: 24rpx;
color: #c9a227;
padding: 10rpx 16rpx;
border-radius: 24rpx;
background: #fff8e8;
border: 1rpx solid #f0d89a;
}
.sb-line.accent { color: #E65100; font-weight: 600; }
/* ========== 待结算提示条(保留原样式) ========== */
.sj-pending-tip {
margin: 20rpx 24rpx;

View File

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

View File

@@ -96,54 +96,19 @@
</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-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">
<text class="freeze-num">{{jinridingdan}}</text>
<text class="freeze-lbl">今日派单</text>
</view>
<view class="freeze-col flexmc">
<text class="freeze-num">{{jinrituikuan}}</text>
<text class="freeze-lbl">今日退款</text>
</view>
</view>
<view class="sj-panel sj-mx20 order-nav-box">
@@ -183,6 +148,10 @@
<image class="sj-func-icon" src="{{imgUrls.iconOrders}}" mode="aspectFit"/>
<text class="sj-func-txt">链接派单</text>
</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}}">
<image class="sj-func-icon" src="{{imgUrls.iconService}}" mode="aspectFit"/>
<text class="sj-func-txt">客服邀请码</text>

View File

@@ -181,40 +181,6 @@ page {
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 {
flex: 1;
padding: 40rpx 0 16rpx;