Files
xingque/pages/accept-order/accept-order.js
2026-06-27 05:41:55 +08:00

725 lines
22 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// pages/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: {
// 1. 商品类型相关
shangpinleixing: [],
xuanzhongLeixingId: null,
// 2. 订单列表与分页相关
dingdanList: [],
page: 1,
pageSize: 5,
hasMore: true,
isLoading: false,
// 3. 全局状态字段
dashoustatus: null,
zhuanghaoStatus: null,
dashouzhuangtai: null,
uid: null,
huiyuanList: [],
yajin: 0,
jifen: 0,
// 4. 刷新控制字段
scrollViewRefreshing: false,
lastRefreshTime: 0,
refreshCooldown: 0,
isLoadingMore: false,
// 5. 切换类型冷却
lastSwitchTime: 0,
switchCooldown: 1500,
isSwitching: false,
// 6. OSS地址
ossImageUrl: app.globalData.ossImageUrl || '',
// 🆕 7. 标签筛选相关
bankuaiBiaoqian: [], // 当前商品类型所属板块的全部标签
xuanzhongBiaoqianId: 0, // 0=全部
// 商品轮播展示(只读 globalData无额外接口
lunboList: [],
gonggao: '',
examRequired: false,
examPassed: false,
_examChecked: false,
},
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();
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 () {
const popupComp = this.selectComponent('#popupNotice');
if (popupComp && popupComp.cleanup) {
popupComp.cleanup();
}
},
async onShow() {
if (!app.globalData._dashouPhoneChecked) {
const phoneOk = await ensurePhoneAuth({ redirect: true, role: 'dashou' });
if (!phoneOk) return;
app.globalData._dashouPhoneChecked = true;
}
this.registerNotificationComponent();
await this.syncDashouProfileFromServer();
warmupPindaoConfig(app);
if (wx.getStorageSync('uid')) {
reconnectForRole('dashou');
if (app.startImWhenReady) app.startImWhenReady();
}
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 遮罩、不清空列表) */
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);
},
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 || '';
}
}
const lunboList = this.processLunboUrls(lunboRaw);
const gonggao = gonggaoText;
this.setData({ lunboList, gonggao });
return { lunboList, gonggao };
},
registerNotificationComponent() {
const notificationComp = this.selectComponent('#global-notification');
if (notificationComp && notificationComp.showNotification) {
app.globalData.globalNotification = {
show: (data) => notificationComp.showNotification(data),
hide: () => notificationComp.hideNotification()
};
}
},
loadGlobalStatus() {
const globalData = app.globalData;
this.setData({
dashoustatus: wx.getStorageSync('dashoustatus'),
zhuanghaoStatus: globalData.zhanghaoStatus,
dashouzhuangtai: globalData.dashouzhuangtai,
uid: wx.getStorageSync('uid'),
huiyuanList: globalData.clumber || [],
yajin: globalData.yajin || 0,
jifen: globalData.jinfen || 0
});
},
/** 拉取最新打手信息(会员/押金/积分),并刷新订单卡片上的会员展示 */
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(autoLoadOrders = false, preserveSelection = false, showLoading = true) {
if (showLoading) wx.showLoading({ title: '加载商品类型...' });
const prevId = this.data.xuanzhongLeixingId;
try {
const res = await request({
url: '/dingdan/dsqdhqddlx',
method: 'POST',
header: { 'content-type': 'application/json' }
});
if (res.statusCode === 200 && res.data) {
const data = res.data;
let list = [];
if (data.code === 200 || data.code === 0) {
if (data.data && Array.isArray(data.data.list)) list = data.data.list;
else if (data.data && Array.isArray(data.data)) list = data.data;
else if (Array.isArray(data.list)) list = data.list;
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: selectedId,
});
if (autoLoadOrders && selectedId) {
await this.loadDingdanList(true);
await this.loadBankuaiBiaoqian();
}
} else {
wx.showToast({ title: res.data?.msg || '加载商品类型失败', icon: 'none' });
}
} catch (error) {
wx.showToast({ title: '网络错误,加载失败', icon: 'none' });
} finally {
if (showLoading) wx.hideLoading();
}
},
// 处理图片URL
processTupianUrl(list) {
const ossUrl = app.globalData.ossImageUrl || '';
return list.map(item => ({
...item,
full_tupian_url: item.tupian_url && !item.tupian_url.startsWith('http')
? ossUrl + item.tupian_url
: (item.tupian_url || '/images/default-type.png')
}));
},
// 🆕 加载板块标签
async loadBankuaiBiaoqian() {
const leixingId = this.data.xuanzhongLeixingId;
if (!leixingId) return;
try {
const res = await request({
url: '/dengji/bkqhbq',
method: 'POST',
data: { leixing_id: leixingId }
});
if (res && res.data.code === 0) {
this.setData({
bankuaiBiaoqian: res.data.data.biaoqian_list || [],
xuanzhongBiaoqianId: 0
});
}
} catch (e) {
// 标签加载失败不影响主流程
}
},
// 选择商品类型
async selectLeixing(e) {
const now = Date.now();
const lastSwitchTime = this.data.lastSwitchTime;
const switchCooldown = this.data.switchCooldown;
if (now - lastSwitchTime < switchCooldown) {
wx.showToast({
title: `操作太快,请${Math.ceil((switchCooldown - (now - lastSwitchTime)) / 1000)}秒后再试`,
icon: 'none',
duration: 1500
});
return;
}
if (this.data.isSwitching) return;
const leixingId = e.currentTarget.dataset.id;
if (leixingId === this.data.xuanzhongLeixingId) return;
this.setData({ isSwitching: true, lastSwitchTime: now });
wx.showLoading({ title: '切换中...' });
try {
this.setData({
xuanzhongLeixingId: leixingId,
dingdanList: [],
page: 1,
hasMore: true,
xuanzhongBiaoqianId: 0 // 重置标签筛选
});
await this.loadDingdanList(true);
await this.loadBankuaiBiaoqian();
this.persistPageCache();
} catch (error) {
console.error('切换类型失败:', error);
} finally {
this.setData({ isSwitching: false });
wx.hideLoading();
}
},
// 🆕 选择标签筛选
async selectBiaoqian(e) {
const id = e.currentTarget.dataset.id;
if (id === this.data.xuanzhongBiaoqianId) return;
this.setData({
xuanzhongBiaoqianId: id,
dingdanList: [],
page: 1,
hasMore: true
});
await this.loadDingdanList(true);
this.persistPageCache();
},
// 加载订单列表
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;
if (!silent) {
this.setData({
isLoading: true,
isLoadingMore: !isRefresh,
});
}
this._listRequesting = true;
try {
const res = await request({
url: '/dingdan/ddhq',
method: 'POST',
data: {
leixing_id: this.data.xuanzhongLeixingId,
page: loadPage,
page_size: this.data.pageSize,
// 🆕 传递标签筛选参数0时不传
biaoqian_id: this.data.xuanzhongBiaoqianId || undefined
}
});
this.setData({
isLoading: false,
isLoadingMore: false,
scrollViewRefreshing: false
});
this._listRequesting = false;
if (res.data.code === 200 || res.data.code === 0) {
const newList = res.data.data.list || [];
const hasMore = res.data.data.has_more || false;
// 🆕 处理每条订单,增加 hasRequiredMember 字段
const processedList = newList.map(item => this.processDingdanItem(item));
const updatedList = isRefresh ? processedList : [...this.data.dingdanList, ...processedList];
updatedList.sort((a, b) => (b.creat_time || '').localeCompare(a.creat_time || ''));
this.setData({
dingdanList: updatedList,
page: loadPage,
hasMore: hasMore
});
this.persistPageCache();
if (isRefresh) {
this.setData({ lastRefreshTime: Date.now() });
}
} else {
wx.showToast({ title: res.data.msg || '加载失败', icon: 'none' });
}
} catch (error) {
console.error('加载订单失败:', error);
this.setData({
isLoading: false,
isLoadingMore: false,
scrollViewRefreshing: false
});
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 (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 {
fullTupianUrl = '/images/default-order.png';
}
const isZhiding = item.zhuangtai === 7;
let zhidingAvatar = '';
if (item.zhiding_avatar) {
zhidingAvatar = !item.zhiding_avatar.startsWith('http')
? ossUrl + item.zhiding_avatar
: item.zhiding_avatar;
}
const zhidingNicheng = item.zhiding_nicheng || '';
// 订单要求指定会员时,核对用户是否持有该会员类型
let hasRequiredMember = true;
if (item.yaoqiuleixing == 1 && item.huiyuan_id) {
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,
...tags,
shangjia_youzhi: !!item.shangjia_youzhi,
// 🆕 是否有查看价格的权限
hasRequiredMember: hasRequiredMember,
};
},
// 跳转到充值页面(原封不动)
goToChongzhiPage(failureType, huiyuanId = null, requiredYajin = 0) {
let url = '/pages/fighter-recharge/fighter-recharge';
let params = {};
switch (failureType) {
case 'huiyuan':
params = { needScroll: '0', scrollTo: 'member' };
break;
case 'yajin':
params = { needScroll: '1', scrollTo: 'bottom', requiredYajin: requiredYajin };
break;
case 'jifen':
params = { needScroll: '1', scrollTo: 'bottom' };
break;
}
if (huiyuanId) params.huiyuanId = huiyuanId;
const queryString = Object.keys(params)
.map(key => `${key}=${encodeURIComponent(params[key])}`)
.join('&');
wx.navigateTo({
url: `${url}?${queryString}`,
fail: (err) => {
console.error('跳转失败:', err);
wx.showToast({ title: '跳转失败,请稍后重试', icon: 'none' });
}
});
},
/** 抢单前考试状态(仅更新状态,不自动跳转考试页) */
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' });
return;
}
// 校验2: 账号状态
if (this.data.zhuanghaoStatus != 1) {
wx.showToast({ title: '账号异常,无法接单', icon: 'none' });
return;
}
// 校验3: 接单员接单状态
if (this.data.dashouzhuangtai != 1) {
wx.showToast({ title: '您有订单正在接待中', icon: 'none' });
return;
}
// 校验4: 指定订单
if (dingdanItem.isZhiding) {
if (!this.data.uid || this.data.uid != dingdanItem.zhiding_uid) {
wx.showToast({ title: '此订单为指定单', icon: 'none' });
return;
}
}
// 校验5: 会员要求
if (dingdanItem.yaoqiuleixing == 1) {
const hasHuiyuan = userHasHuiyuan(this.data.huiyuanList, dingdanItem.huiyuan_id);
if (!hasHuiyuan) {
wx.showToast({
title: '未开通对应会员,无法抢单',
icon: 'none',
duration: 2000
});
setTimeout(() => {
this.goToChongzhiPage('huiyuan', dingdanItem.huiyuan_id);
}, 500);
return;
}
}
// 校验6: 押金要求
if (dingdanItem.yaoqiuleixing == 2) {
if (this.data.yajin < dingdanItem.yajin) {
wx.showToast({
title: `押金不足,需${dingdanItem.yajin}`,
icon: 'none',
duration: 2000
});
setTimeout(() => {
this.goToChongzhiPage('yajin', null, dingdanItem.yajin);
}, 500);
return;
}
}
// 校验7: 积分要求
if (this.data.jifen < 5) {
wx.showToast({
title: '积分不足至少需要5积分',
icon: 'none',
duration: 2000
});
setTimeout(() => {
this.goToChongzhiPage('jifen');
}, 500);
return;
}
// 确认框
const that = this;
wx.showModal({
title: '确认抢单',
content: `确定要抢此订单吗?${dingdanItem.isZhiding ? '(指定订单)' : ''}`,
success: async function (res) {
if (res.confirm) {
wx.showLoading({ title: '抢单中...', mask: true });
try {
const qiangdanRes = await request({
url: '/dingdan/qiangdan',
method: 'POST',
data: { dingdan_id: dingdanItem.dingdan_id }
});
wx.hideLoading();
if (qiangdanRes.data.code === 200 || qiangdanRes.data.code === 0) {
that.showQiangdanSuccessEffect();
if (app.globalData) {
app.globalData.dashouzhuangtai = 0;
that.setData({ dashouzhuangtai: 0 });
}
const newList = that.data.dingdanList.filter(
item => item.dingdan_id !== dingdanItem.dingdan_id
);
that.setData({ dingdanList: newList });
that.persistPageCache();
} else {
wx.showToast({
title: qiangdanRes.data.msg || '抢单失败',
icon: 'none'
});
}
} catch (error) {
wx.hideLoading();
console.error('抢单请求失败:', error);
wx.showToast({ title: '网络错误,抢单失败', icon: 'none' });
}
}
}
});
},
showQiangdanSuccessEffect() {
wx.showToast({ title: '抢单成功!', icon: 'success', duration: 2000 });
},
onViewDetail(e) {
const { type, content } = e.currentTarget.dataset;
wx.showModal({
title: type === 'jieshao' ? '订单介绍' : '订单备注',
content: content,
showCancel: false,
confirmText: '知道了'
});
},
onReachBottom() {
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);
}
},
async onPullDownRefresh() {
if (this.data.isLoading) {
this.setData({ scrollViewRefreshing: false });
return;
}
this.setData({
scrollViewRefreshing: true,
lastRefreshTime: Date.now(),
page: 1,
hasMore: true,
});
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 });
}
}
});