Initial commit
This commit is contained in:
807
miniprogram/pages/order/order-list/index.js
Normal file
807
miniprogram/pages/order/order-list/index.js
Normal file
@@ -0,0 +1,807 @@
|
||||
import { OrderStatus } from '../config';
|
||||
import { fetchOrders, fetchOrdersCount } from '../../../services/order/orderList';
|
||||
import { cosThumb } from '../../../utils/util';
|
||||
import config from '../../../config/index';
|
||||
|
||||
Page({
|
||||
page: {
|
||||
size: 5,
|
||||
num: 1,
|
||||
},
|
||||
|
||||
data: {
|
||||
tabs: [
|
||||
{ key: -1, text: '全部' },
|
||||
{ key: 1, text: '未付款', info: '' },
|
||||
{ key: 2, text: '已付款', info: '' },
|
||||
{ key: 3, text: '待发货', info: '' },
|
||||
{ key: 4, text: '已发货', info: '' },
|
||||
{ key: 5, text: '待收货', info: '' },
|
||||
{ key: 6, text: '已完成', info: '' },
|
||||
{ key: 9, text: '已退款', info: '' },
|
||||
],
|
||||
curTab: -1,
|
||||
orderList: [],
|
||||
listLoading: 0,
|
||||
pullDownRefreshing: false,
|
||||
emptyImg: 'https://tdesign.gtimg.com/miniprogram/template/retail/order/empty-order-list.png',
|
||||
backRefresh: false,
|
||||
status: -1,
|
||||
// 合并订单相关数据
|
||||
mergeMode: false,
|
||||
selectedOrders: [],
|
||||
// 空状态配置
|
||||
emptyStateConfig: {
|
||||
title: '暂无订单',
|
||||
description: '快去挑选心仪的商品吧~',
|
||||
buttonText: '去购物',
|
||||
showButton: true,
|
||||
icon: 'shop'
|
||||
},
|
||||
},
|
||||
|
||||
onLoad(query) {
|
||||
console.log('[订单列表] 页面加载开始', { query, timestamp: new Date().toISOString() });
|
||||
|
||||
let status = parseInt(query.status);
|
||||
status = this.data.tabs.map((t) => t.key).includes(status) ? status : -1;
|
||||
|
||||
console.log('[订单列表] 解析状态参数', {
|
||||
originalStatus: query.status,
|
||||
parsedStatus: status,
|
||||
availableStatuses: this.data.tabs.map((t) => t.key)
|
||||
});
|
||||
|
||||
// 初始化空状态配置
|
||||
this.updateEmptyStateConfig(status);
|
||||
|
||||
this.init(status);
|
||||
this.pullDownRefresh = this.selectComponent('#wr-pull-down-refresh');
|
||||
|
||||
console.log('[订单列表] 页面加载完成', { status });
|
||||
},
|
||||
|
||||
onShow() {
|
||||
console.log('[订单列表] 页面显示', {
|
||||
backRefresh: this.data.backRefresh,
|
||||
timestamp: new Date().toISOString()
|
||||
});
|
||||
|
||||
if (!this.data.backRefresh) return;
|
||||
this.onRefresh();
|
||||
this.setData({ backRefresh: false });
|
||||
},
|
||||
|
||||
onReachBottom() {
|
||||
console.log('[订单列表] 触底加载更多', {
|
||||
listLoading: this.data.listLoading,
|
||||
curTab: this.data.curTab,
|
||||
currentPage: this.page.num
|
||||
});
|
||||
|
||||
if (this.data.listLoading === 0) {
|
||||
this.getOrderList(this.data.curTab);
|
||||
}
|
||||
},
|
||||
|
||||
onPageScroll(e) {
|
||||
this.pullDownRefresh && this.pullDownRefresh.onPageScroll(e);
|
||||
},
|
||||
|
||||
onPullDownRefresh_(e) {
|
||||
console.log('[订单列表] 下拉刷新开始', {
|
||||
curTab: this.data.curTab,
|
||||
timestamp: new Date().toISOString()
|
||||
});
|
||||
|
||||
// 安全检查 e.detail 是否存在
|
||||
const callback = e && e.detail && e.detail.callback;
|
||||
this.setData({ pullDownRefreshing: true });
|
||||
this.refreshList(this.data.curTab)
|
||||
.then(() => {
|
||||
console.log('[订单列表] 下拉刷新成功');
|
||||
this.setData({ pullDownRefreshing: false });
|
||||
// 确保 callback 存在且是函数
|
||||
if (callback && typeof callback === 'function') {
|
||||
callback();
|
||||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error('[订单列表] 下拉刷新失败', err);
|
||||
this.setData({ pullDownRefreshing: false });
|
||||
// 即使出错也要调用 callback 来结束刷新状态
|
||||
if (callback && typeof callback === 'function') {
|
||||
callback();
|
||||
}
|
||||
Promise.reject(err);
|
||||
});
|
||||
},
|
||||
|
||||
init(status) {
|
||||
console.log('[订单列表] 初始化开始', {
|
||||
inputStatus: status,
|
||||
currentTab: this.data.curTab
|
||||
});
|
||||
|
||||
status = status !== undefined ? status : this.data.curTab;
|
||||
this.setData({
|
||||
status,
|
||||
curTab: status, // 设置当前tab,确保UI切换到对应的标签页
|
||||
});
|
||||
|
||||
console.log('[订单列表] 初始化完成,开始刷新列表', { finalStatus: status });
|
||||
this.refreshList(status);
|
||||
},
|
||||
|
||||
getOrderList(statusCode = -1, reset = false) {
|
||||
console.log('[订单列表] 开始获取订单数据', {
|
||||
statusCode,
|
||||
reset,
|
||||
currentPage: this.page.num,
|
||||
pageSize: this.page.size,
|
||||
timestamp: new Date().toISOString()
|
||||
});
|
||||
|
||||
this.setData({ listLoading: 1 });
|
||||
|
||||
// 使用修复后的API调用方式
|
||||
const status = statusCode === -1 ? '' : statusCode.toString();
|
||||
console.log('🔍 [订单列表] API调用参数', {
|
||||
originalStatusCode: statusCode,
|
||||
convertedStatus: status,
|
||||
pageNum: this.page.num,
|
||||
pageSize: this.page.size
|
||||
});
|
||||
|
||||
return fetchOrders(status, this.page.num, this.page.size)
|
||||
.then((res) => {
|
||||
console.log('📋 [订单列表] API响应成功 - 完整数据结构', {
|
||||
responseData: res,
|
||||
listLength: res?.orders?.length || 0
|
||||
});
|
||||
|
||||
// 打印完整的原始订单数据
|
||||
console.log('🔍 [订单列表] 原始订单数据详情', {
|
||||
totalOrders: res?.orders?.length || 0,
|
||||
rawOrdersData: res?.orders,
|
||||
responseStructure: {
|
||||
hasOrders: !!res?.orders,
|
||||
hasData: !!res?.data,
|
||||
hasList: !!res?.list,
|
||||
responseKeys: res ? Object.keys(res) : []
|
||||
}
|
||||
});
|
||||
|
||||
// 逐个打印每个订单的详细信息
|
||||
if (res?.orders && Array.isArray(res.orders)) {
|
||||
res.orders.forEach((order, index) => {
|
||||
console.log(`📦 [订单${index + 1}] 原始订单数据:`, {
|
||||
orderIndex: index,
|
||||
orderId: order.orderId || order.id,
|
||||
orderNo: order.orderNo || order.order_no,
|
||||
orderStatus: order.orderStatus || order.status,
|
||||
paymentAmount: order.paymentAmount || order.pay_amount,
|
||||
orderItemVOs: order.orderItemVOs,
|
||||
items: order.items,
|
||||
order_items: order.order_items,
|
||||
rawOrderData: order,
|
||||
orderKeys: Object.keys(order)
|
||||
});
|
||||
|
||||
// 打印订单商品详情
|
||||
const orderItems = order.orderItemVOs || order.order_items || order.items || [];
|
||||
if (orderItems.length > 0) {
|
||||
console.log(`🛍️ [订单${index + 1}] 商品列表详情:`, {
|
||||
itemCount: orderItems.length,
|
||||
items: orderItems.map((item, itemIndex) => ({
|
||||
itemIndex,
|
||||
id: item.id,
|
||||
goodsName: item.goodsName,
|
||||
product_name: item.product_name,
|
||||
productName: item.productName,
|
||||
title: item.title,
|
||||
price: item.price,
|
||||
actualPrice: item.actualPrice,
|
||||
unit_price: item.unit_price,
|
||||
quantity: item.quantity,
|
||||
buyQuantity: item.buyQuantity,
|
||||
num: item.num,
|
||||
specifications: item.specifications,
|
||||
specs: item.specs,
|
||||
specification: item.specification,
|
||||
product_image: item.product_image,
|
||||
goodsPictureUrl: item.goodsPictureUrl,
|
||||
productImage: item.productImage,
|
||||
thumb: item.thumb,
|
||||
rawItemData: item,
|
||||
itemKeys: Object.keys(item)
|
||||
}))
|
||||
});
|
||||
} else {
|
||||
console.log(`⚠️ [订单${index + 1}] 无商品数据或商品列表为空`);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
this.page.num++;
|
||||
let orderList = [];
|
||||
|
||||
// 适配新的API响应格式
|
||||
if (res && res.orders) {
|
||||
orderList = (res.orders || []).map((order) => {
|
||||
// 处理商品列表数据
|
||||
const goodsList = (order.orderItemVOs || order.order_items || order.items || []).map((item) => {
|
||||
// 尝试从多个可能的来源获取图片
|
||||
const finalThumb = item.product_image ||
|
||||
item.goodsPictureUrl ||
|
||||
item.productImage ||
|
||||
item.thumb ||
|
||||
item.image ||
|
||||
item.goodsPictureURL ||
|
||||
item.picture ||
|
||||
item.pic ||
|
||||
item.img ||
|
||||
(item.product && item.product.main_image) ||
|
||||
(item.product && item.product.images && item.product.images[0]) ||
|
||||
(item.sku && item.sku.image);
|
||||
|
||||
|
||||
|
||||
// 调试spec_info数据
|
||||
console.log(`🔍 [商品规格] 商品${item.goodsName || item.product_name}的规格信息:`, {
|
||||
spec_info: item.spec_info,
|
||||
specInfo: item.specInfo,
|
||||
specText: item.specText,
|
||||
specifications: item.specifications,
|
||||
specs: item.specs,
|
||||
specification: item.specification
|
||||
});
|
||||
|
||||
const goodsItem = {
|
||||
id: item.id || item.product_id,
|
||||
title: item.goodsName || item.product_name || item.productName || item.title,
|
||||
thumb: finalThumb,
|
||||
price: ((item.price || item.actualPrice || item.unit_price || 0) / 100).toFixed(2),
|
||||
originPrice: ((item.original_price || item.originPrice || 0) / 100).toFixed(2),
|
||||
num: item.quantity || item.buyQuantity || item.num || 1,
|
||||
// 优先使用服务层处理好的specText,然后是其他规格信息
|
||||
specs: item.specText ||
|
||||
(Array.isArray(item.specifications)
|
||||
? item.specifications.map(spec => `${spec.specTitle}:${spec.specValue}`).join(' ')
|
||||
: (item.specs || item.specification || '')),
|
||||
// 保留原始的spec_info数据供调试使用
|
||||
spec_info: item.spec_info,
|
||||
specInfo: item.specInfo,
|
||||
skuId: item.skuId || item.sku_id,
|
||||
productId: item.spuId || item.productId || item.product_id,
|
||||
hideKey: {
|
||||
thumb: false,
|
||||
title: false,
|
||||
desc: false,
|
||||
price: false,
|
||||
num: false,
|
||||
originPrice: false,
|
||||
specs: false
|
||||
}
|
||||
};
|
||||
|
||||
console.log(`✅ [商品规格] 最终商品数据:`, {
|
||||
title: goodsItem.title,
|
||||
specs: goodsItem.specs,
|
||||
spec_info: goodsItem.spec_info,
|
||||
specInfo: goodsItem.specInfo
|
||||
});
|
||||
|
||||
|
||||
|
||||
return goodsItem;
|
||||
});
|
||||
|
||||
const orderItem = {
|
||||
id: order.orderId || order.id,
|
||||
orderNo: order.orderNo || order.order_no,
|
||||
parentOrderNo: order.parentOrderNo,
|
||||
storeId: order.storeId || order.store_id,
|
||||
storeName: order.storeName || '默认店铺',
|
||||
status: order.orderStatus || order.status,
|
||||
statusDesc: order.statusName || this.getOrderStatusName(order.orderStatus || order.status),
|
||||
amount: order.paymentAmount || order.pay_amount || order.payAmount,
|
||||
totalAmount: order.totalAmount || order.total_amount,
|
||||
logisticsNo: order.logisticsNo || order.express_no,
|
||||
createTime: order.createdAt || order.created_at,
|
||||
goodsList: goodsList,
|
||||
buttons: order.buttons || this.getOrderButtons(order.orderStatus || order.status),
|
||||
groupInfoVo: order.groupInfoVo,
|
||||
freightFee: order.freightFee || order.shipping_fee || 0,
|
||||
receiverName: order.receiverName || order.receiver_name,
|
||||
receiverAddress: order.receiverAddress || order.receiver_address,
|
||||
// 合并相关属性
|
||||
canMerge: (order.orderStatus || order.status) === 0, // 只有待支付订单可以合并
|
||||
selected: false,
|
||||
};
|
||||
|
||||
return orderItem;
|
||||
});
|
||||
}
|
||||
|
||||
return new Promise((resolve) => {
|
||||
if (reset) {
|
||||
this.setData({ orderList: [] }, () => resolve());
|
||||
} else resolve();
|
||||
}).then(() => {
|
||||
const newList = reset ? orderList : this.data.orderList.concat(orderList);
|
||||
|
||||
console.log('✅ [订单列表] 数据处理完成', {
|
||||
reset,
|
||||
newOrderCount: orderList.length,
|
||||
totalOrderCount: newList.length,
|
||||
listLoading: orderList.length > 0 ? 0 : 2
|
||||
});
|
||||
|
||||
// 打印处理后的订单数据详情
|
||||
console.log('🎯 [订单列表] 处理后的订单数据详情', {
|
||||
processedOrderCount: orderList.length,
|
||||
processedOrders: orderList.map((order, index) => ({
|
||||
index,
|
||||
id: order.id,
|
||||
orderNo: order.orderNo,
|
||||
status: order.status,
|
||||
statusDesc: order.statusDesc,
|
||||
amount: order.amount,
|
||||
totalAmount: order.totalAmount,
|
||||
goodsCount: order.goodsList?.length || 0,
|
||||
goodsList: order.goodsList?.map((goods, goodsIndex) => ({
|
||||
goodsIndex,
|
||||
id: goods.id,
|
||||
title: goods.title,
|
||||
price: goods.price,
|
||||
num: goods.num,
|
||||
specs: goods.specs,
|
||||
thumb: goods.thumb,
|
||||
skuId: goods.skuId,
|
||||
productId: goods.productId
|
||||
})),
|
||||
receiverName: order.receiverName,
|
||||
receiverAddress: order.receiverAddress,
|
||||
createTime: order.createTime,
|
||||
canMerge: order.canMerge,
|
||||
buttons: order.buttons
|
||||
}))
|
||||
});
|
||||
|
||||
// 打印最终的订单列表状态
|
||||
console.log('📊 [订单列表] 最终状态汇总', {
|
||||
totalOrdersInList: newList.length,
|
||||
ordersByStatus: newList.reduce((acc, order) => {
|
||||
const status = order.status;
|
||||
acc[status] = (acc[status] || 0) + 1;
|
||||
return acc;
|
||||
}, {}),
|
||||
ordersWithGoods: newList.filter(order => order.goodsList && order.goodsList.length > 0).length,
|
||||
ordersWithoutGoods: newList.filter(order => !order.goodsList || order.goodsList.length === 0).length
|
||||
});
|
||||
|
||||
// 设置正确的加载状态
|
||||
let loadingStatus = 0; // 默认为正常状态
|
||||
if (reset && newList.length === 0) {
|
||||
// 首次加载且无数据,显示空状态
|
||||
loadingStatus = 2;
|
||||
console.log('🔍 [订单列表] 首次加载无数据,设置空状态', {
|
||||
reset,
|
||||
orderListLength: orderList.length,
|
||||
newListLength: newList.length,
|
||||
loadingStatus
|
||||
});
|
||||
} else if (!reset && newList.length === this.data.orderList.length) {
|
||||
// 加载更多但无新数据,显示"没有更多了"
|
||||
loadingStatus = 2;
|
||||
console.log('🔍 [订单列表] 加载更多无新数据', {
|
||||
reset,
|
||||
orderListLength: orderList.length,
|
||||
newListLength: newList.length,
|
||||
currentOrderListLength: this.data.orderList.length,
|
||||
loadingStatus
|
||||
});
|
||||
} else {
|
||||
console.log('🔍 [订单列表] 正常数据状态', {
|
||||
reset,
|
||||
orderListLength: orderList.length,
|
||||
newListLength: newList.length,
|
||||
loadingStatus
|
||||
});
|
||||
}
|
||||
|
||||
this.setData({
|
||||
orderList: newList,
|
||||
listLoading: loadingStatus,
|
||||
});
|
||||
|
||||
console.log('[订单列表] UI更新完成', {
|
||||
finalOrderListLength: newList.length,
|
||||
listLoading: loadingStatus,
|
||||
listIsEmpty: !newList.length,
|
||||
shouldShowEmpty: !newList.length && (loadingStatus === 0 || loadingStatus === 2)
|
||||
});
|
||||
});
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error('[订单列表] 获取订单列表失败', {
|
||||
error: err,
|
||||
statusCode,
|
||||
timestamp: new Date().toISOString()
|
||||
});
|
||||
this.setData({ listLoading: 3 });
|
||||
return Promise.reject(err);
|
||||
});
|
||||
},
|
||||
|
||||
// 获取订单状态名称
|
||||
getOrderStatusName(status) {
|
||||
const statusMap = {
|
||||
1: '未付款',
|
||||
2: '待发货', // 统一为待发货
|
||||
3: '待发货', // 统一为待发货
|
||||
4: '已发货',
|
||||
5: '待收货',
|
||||
6: '已完成',
|
||||
7: '已取消',
|
||||
8: '退货中',
|
||||
9: '已退款'
|
||||
};
|
||||
return statusMap[status] || '未知状态';
|
||||
},
|
||||
|
||||
// 获取订单操作按钮
|
||||
getOrderButtons(status) {
|
||||
switch (status) {
|
||||
case 0:
|
||||
return [{ name: '去支付', type: 2 }, { name: '取消订单', type: 1 }];
|
||||
case 1:
|
||||
return [{ name: '查看详情', type: 'detail' }];
|
||||
case 2:
|
||||
return [{ name: '确认收货', type: 4 }, { name: '查看物流', type: 'logistics' }];
|
||||
case 3:
|
||||
return [{ name: '查看详情', type: 'detail' }, { name: '再次购买', type: 9 }];
|
||||
case 4:
|
||||
return [{ name: '查看详情', type: 'detail' }, { name: '再次购买', type: 9 }];
|
||||
case 9:
|
||||
return [{ name: '查看退款', type: 10 }, { name: '再次购买', type: 9 }];
|
||||
default:
|
||||
return [{ name: '查看详情', type: 'detail' }];
|
||||
}
|
||||
},
|
||||
|
||||
onReTryLoad() {
|
||||
this.getOrderList(this.data.curTab);
|
||||
},
|
||||
|
||||
onTabChange(e) {
|
||||
const { value } = e.detail;
|
||||
console.log('[订单列表] 标签切换', {
|
||||
fromTab: this.data.curTab,
|
||||
toTab: value,
|
||||
timestamp: new Date().toISOString()
|
||||
});
|
||||
|
||||
this.setData({
|
||||
status: value,
|
||||
});
|
||||
this.updateEmptyStateConfig(value);
|
||||
this.refreshList(value);
|
||||
},
|
||||
|
||||
// 根据订单状态更新空状态配置
|
||||
updateEmptyStateConfig(status) {
|
||||
let config = {
|
||||
title: '暂无订单',
|
||||
description: '快去挑选心仪的商品吧~',
|
||||
buttonText: '去购物',
|
||||
showButton: true,
|
||||
icon: 'shop'
|
||||
};
|
||||
|
||||
switch (status) {
|
||||
case -1: // 全部
|
||||
config = {
|
||||
title: '暂无订单',
|
||||
description: '快去挑选心仪的商品吧~',
|
||||
buttonText: '去购物',
|
||||
showButton: true,
|
||||
icon: 'shop'
|
||||
};
|
||||
break;
|
||||
case 1: // 未付款
|
||||
config = {
|
||||
title: '暂无待付款订单',
|
||||
description: '您当前没有需要付款的订单',
|
||||
buttonText: '去购物',
|
||||
showButton: true,
|
||||
icon: 'wallet'
|
||||
};
|
||||
break;
|
||||
case 2: // 已付款
|
||||
config = {
|
||||
title: '暂无已付款订单',
|
||||
description: '您当前没有已付款的订单',
|
||||
buttonText: '去购物',
|
||||
showButton: true,
|
||||
icon: 'check-circle'
|
||||
};
|
||||
break;
|
||||
case 3: // 待发货
|
||||
config = {
|
||||
title: '暂无待发货订单',
|
||||
description: '您当前没有等待发货的订单',
|
||||
buttonText: '去购物',
|
||||
showButton: true,
|
||||
icon: 'package'
|
||||
};
|
||||
break;
|
||||
case 4: // 已发货
|
||||
config = {
|
||||
title: '暂无已发货订单',
|
||||
description: '您当前没有已发货的订单',
|
||||
buttonText: '去购物',
|
||||
showButton: true,
|
||||
icon: 'delivery'
|
||||
};
|
||||
break;
|
||||
case 5: // 待收货
|
||||
config = {
|
||||
title: '暂无待收货订单',
|
||||
description: '您当前没有等待收货的订单',
|
||||
buttonText: '去购物',
|
||||
showButton: true,
|
||||
icon: 'location'
|
||||
};
|
||||
break;
|
||||
case 6: // 已完成
|
||||
config = {
|
||||
title: '暂无已完成订单',
|
||||
description: '您还没有完成的订单',
|
||||
buttonText: '去购物',
|
||||
showButton: true,
|
||||
icon: 'check-circle-filled'
|
||||
};
|
||||
break;
|
||||
case 9: // 已退款
|
||||
config = {
|
||||
title: '暂无退款订单',
|
||||
description: '您当前没有退款记录',
|
||||
buttonText: '去购物',
|
||||
showButton: true,
|
||||
icon: 'money-circle'
|
||||
};
|
||||
break;
|
||||
}
|
||||
|
||||
this.setData({
|
||||
emptyStateConfig: config
|
||||
});
|
||||
},
|
||||
|
||||
// 处理空状态按钮点击
|
||||
onEmptyButtonTap() {
|
||||
// 跳转到首页
|
||||
wx.switchTab({
|
||||
url: '/pages/home/home'
|
||||
});
|
||||
},
|
||||
|
||||
getOrdersCount() {
|
||||
return fetchOrdersCount().then((res) => {
|
||||
const tabsCount = res.data || [];
|
||||
const { tabs } = this.data;
|
||||
tabs.forEach((tab) => {
|
||||
const tabCount = tabsCount.find((c) => c.tabType === tab.key);
|
||||
if (tabCount) {
|
||||
tab.info = tabCount.orderNum;
|
||||
}
|
||||
});
|
||||
this.setData({ tabs });
|
||||
});
|
||||
},
|
||||
|
||||
refreshList(status = -1) {
|
||||
console.log('[订单列表] 刷新列表开始', {
|
||||
status,
|
||||
timestamp: new Date().toISOString()
|
||||
});
|
||||
|
||||
this.page = {
|
||||
size: this.page.size,
|
||||
num: 1,
|
||||
};
|
||||
this.setData({
|
||||
curTab: status,
|
||||
orderList: [],
|
||||
listLoading: 1 // 设置为加载中状态
|
||||
});
|
||||
|
||||
return Promise.all([this.getOrderList(status, true), this.getOrdersCount()]);
|
||||
},
|
||||
|
||||
onRefresh() {
|
||||
console.log('[订单列表] 手动刷新', {
|
||||
curTab: this.data.curTab
|
||||
});
|
||||
this.refreshList(this.data.curTab);
|
||||
},
|
||||
|
||||
onOrderCardTap(e) {
|
||||
const { order } = e.currentTarget.dataset;
|
||||
|
||||
console.log('[订单列表] 订单卡片点击', {
|
||||
orderNo: order?.orderNo,
|
||||
mergeMode: this.data.mergeMode,
|
||||
timestamp: new Date().toISOString()
|
||||
});
|
||||
|
||||
// 合并模式下不跳转详情页
|
||||
if (this.data.mergeMode) {
|
||||
console.log('[订单列表] 合并模式下,不跳转详情页');
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('[订单列表] 跳转到订单详情页', {
|
||||
orderNo: order.orderNo
|
||||
});
|
||||
|
||||
wx.navigateTo({
|
||||
url: `/pages/order/order-detail/index?orderNo=${order.orderNo}`,
|
||||
});
|
||||
},
|
||||
|
||||
// 进入合并模式
|
||||
enterMergeMode() {
|
||||
this.setData({
|
||||
mergeMode: true,
|
||||
selectedOrders: []
|
||||
});
|
||||
},
|
||||
|
||||
// 退出合并模式
|
||||
exitMergeMode() {
|
||||
// 清除所有选择状态
|
||||
const orderList = this.data.orderList.map(order => ({
|
||||
...order,
|
||||
selected: false
|
||||
}));
|
||||
|
||||
this.setData({
|
||||
mergeMode: false,
|
||||
selectedOrders: [],
|
||||
orderList
|
||||
});
|
||||
},
|
||||
|
||||
// 订单选择/取消选择
|
||||
onOrderSelect(e) {
|
||||
const { orderIndex } = e.currentTarget.dataset;
|
||||
const { value } = e.detail;
|
||||
const orderList = [...this.data.orderList];
|
||||
const order = orderList[orderIndex];
|
||||
|
||||
order.selected = value;
|
||||
|
||||
// 更新选中的订单列表
|
||||
let selectedOrders = [...this.data.selectedOrders];
|
||||
if (value) {
|
||||
selectedOrders.push(order.id);
|
||||
} else {
|
||||
selectedOrders = selectedOrders.filter(id => id !== order.id);
|
||||
}
|
||||
|
||||
this.setData({
|
||||
orderList,
|
||||
selectedOrders
|
||||
});
|
||||
},
|
||||
|
||||
// 确认合并订单
|
||||
confirmMergeOrders() {
|
||||
const { selectedOrders } = this.data;
|
||||
|
||||
if (selectedOrders.length < 2) {
|
||||
wx.showToast({
|
||||
title: '请至少选择2个订单',
|
||||
icon: 'none'
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// 验证选中的订单是否可以合并
|
||||
const selectedOrderList = this.data.orderList.filter(order =>
|
||||
selectedOrders.includes(order.id)
|
||||
);
|
||||
|
||||
// 检查是否都是同一个收货地址
|
||||
const firstAddress = selectedOrderList[0].receiverAddress;
|
||||
const hasDifferentAddress = selectedOrderList.some(order =>
|
||||
order.receiverAddress !== firstAddress
|
||||
);
|
||||
|
||||
if (hasDifferentAddress) {
|
||||
wx.showToast({
|
||||
title: '只能合并相同收货地址的订单',
|
||||
icon: 'none'
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
wx.showModal({
|
||||
title: '确认合并订单',
|
||||
content: `确定要合并这${selectedOrders.length}个订单吗?合并后将生成一个新订单。`,
|
||||
success: (res) => {
|
||||
if (res.confirm) {
|
||||
this.mergeOrders(selectedOrders);
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
// 执行订单合并
|
||||
mergeOrders(orderIds) {
|
||||
wx.showLoading({
|
||||
title: '合并中...'
|
||||
});
|
||||
|
||||
// 调用合并订单API
|
||||
wx.request({
|
||||
url: `${config.apiBase}/orders/merge`,
|
||||
method: 'POST',
|
||||
header: {
|
||||
'Content-Type': 'application/json',
|
||||
'Authorization': `Bearer ${wx.getStorageSync('token')}`
|
||||
},
|
||||
data: {
|
||||
orderIds: orderIds
|
||||
},
|
||||
success: (res) => {
|
||||
wx.hideLoading();
|
||||
|
||||
if (res.statusCode === 200 && res.data.code === 0) {
|
||||
wx.showToast({
|
||||
title: '合并成功',
|
||||
icon: 'success'
|
||||
});
|
||||
|
||||
// 退出合并模式并刷新列表
|
||||
this.exitMergeMode();
|
||||
this.refreshList(this.data.curTab);
|
||||
} else {
|
||||
wx.showToast({
|
||||
title: res.data.message || '合并失败',
|
||||
icon: 'none'
|
||||
});
|
||||
}
|
||||
},
|
||||
fail: (err) => {
|
||||
wx.hideLoading();
|
||||
console.error('合并订单失败:', err);
|
||||
wx.showToast({
|
||||
title: '网络错误,请重试',
|
||||
icon: 'none'
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
// 分享功能
|
||||
onShareAppMessage() {
|
||||
const { curTab } = this.data;
|
||||
const tabText = this.data.tabs.find(t => t.key === curTab)?.text || '全部';
|
||||
|
||||
return {
|
||||
title: `我的订单 - ${tabText}订单`,
|
||||
path: `/pages/order/order-list/index?status=${curTab}`
|
||||
};
|
||||
},
|
||||
|
||||
// 分享到朋友圈
|
||||
onShareTimeline() {
|
||||
return {
|
||||
title: '我的订单 - 查看我的购物记录'
|
||||
};
|
||||
}
|
||||
});
|
||||
16
miniprogram/pages/order/order-list/index.json
Normal file
16
miniprogram/pages/order/order-list/index.json
Normal file
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"navigationBarTitleText": "我的订单",
|
||||
"usingComponents": {
|
||||
"t-tabs": "tdesign-miniprogram/tabs/tabs",
|
||||
"t-tab-panel": "tdesign-miniprogram/tab-panel/tab-panel",
|
||||
"t-empty": "tdesign-miniprogram/empty/empty",
|
||||
"t-toast": "tdesign-miniprogram/toast/toast",
|
||||
"t-dialog": "tdesign-miniprogram/dialog/dialog",
|
||||
"t-pull-down-refresh": "tdesign-miniprogram/pull-down-refresh/pull-down-refresh",
|
||||
"load-more": "/components/load-more/index",
|
||||
"order-button-bar": "../components/order-button-bar/index",
|
||||
"price": "/components/price/index",
|
||||
"order-card": "../components/order-card/index",
|
||||
"specs-goods-card": "../components/specs-goods-card/index"
|
||||
}
|
||||
}
|
||||
154
miniprogram/pages/order/order-list/index.wxml
Normal file
154
miniprogram/pages/order/order-list/index.wxml
Normal file
@@ -0,0 +1,154 @@
|
||||
<view class="page-container">
|
||||
<view class="tab-bar">
|
||||
<view class="tab-bar__placeholder" />
|
||||
<t-tabs
|
||||
t-class="tab-bar__inner"
|
||||
t-class-active="tab-bar__active"
|
||||
t-class-track="t-tabs-track"
|
||||
bind:change="onTabChange"
|
||||
value="{{status}}"
|
||||
style="position: fixed; top: 0; left: 0; z-index: 100"
|
||||
>
|
||||
<t-tab-panel
|
||||
wx:for="{{tabs}}"
|
||||
wx:for-index="index"
|
||||
wx:for-item="item"
|
||||
wx:key="index"
|
||||
label="{{item.text}}"
|
||||
value="{{item.key}}"
|
||||
/>
|
||||
</t-tabs>
|
||||
</view>
|
||||
|
||||
<!-- 合并订单工具栏 -->
|
||||
<view class="merge-toolbar" wx:if="{{status === 0}}">
|
||||
<view class="merge-actions">
|
||||
<t-button
|
||||
wx:if="{{!mergeMode}}"
|
||||
size="small"
|
||||
variant="outline"
|
||||
bind:tap="enterMergeMode"
|
||||
>
|
||||
合并订单
|
||||
</t-button>
|
||||
<view wx:else class="merge-mode-actions">
|
||||
<text class="selected-count">已选择 {{selectedOrders.length}} 个订单</text>
|
||||
<t-button
|
||||
size="small"
|
||||
variant="outline"
|
||||
bind:tap="exitMergeMode"
|
||||
>
|
||||
取消
|
||||
</t-button>
|
||||
<t-button
|
||||
size="small"
|
||||
theme="primary"
|
||||
bind:tap="confirmMergeOrders"
|
||||
disabled="{{selectedOrders.length < 2}}"
|
||||
>
|
||||
确认合并
|
||||
</t-button>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<t-pull-down-refresh
|
||||
id="pull-down-refresh"
|
||||
normal-bar-height="{{200}}"
|
||||
max-bar-height="{{272}}"
|
||||
refreshTimeout="{{3000}}"
|
||||
background="#f5f5f5"
|
||||
use-loading-slot
|
||||
loading-size="60rpx"
|
||||
bindrefresh="onPullDownRefresh_"
|
||||
t-class-indicator="t-class-indicator"
|
||||
>
|
||||
<order-card
|
||||
wx:for="{{orderList}}"
|
||||
wx:key="id"
|
||||
wx:for-item="order"
|
||||
wx:for-index="oIndex"
|
||||
order="{{order}}"
|
||||
defaultShowNum="{{3}}"
|
||||
data-order="{{order}}"
|
||||
bindcardtap="onOrderCardTap"
|
||||
useLogoSlot
|
||||
class="{{mergeMode ? 'merge-mode-card' : ''}}"
|
||||
>
|
||||
<view slot="top-left" class="order-number">
|
||||
<!-- 合并模式下的选择框 -->
|
||||
<view wx:if="{{mergeMode && order.canMerge}}" class="order-checkbox">
|
||||
<t-checkbox
|
||||
value="{{order.selected}}"
|
||||
bind:change="onOrderSelect"
|
||||
data-order-id="{{order.id}}"
|
||||
data-order-index="{{oIndex}}"
|
||||
/>
|
||||
</view>
|
||||
<text decode>订单号 </text>
|
||||
{{order.orderNo}}
|
||||
<!-- 不可合并订单的提示 -->
|
||||
<text wx:if="{{mergeMode && !order.canMerge}}" class="cannot-merge-tip">(不可合并)</text>
|
||||
</view>
|
||||
<specs-goods-card
|
||||
wx:for="{{order.goodsList}}"
|
||||
wx:key="id"
|
||||
wx:for-item="goods"
|
||||
wx:for-index="gIndex"
|
||||
data="{{goods}}"
|
||||
no-top-line="{{gIndex === 0}}"
|
||||
/>
|
||||
<view slot="more">
|
||||
<view class="price-total">
|
||||
<text>总价</text>
|
||||
<price fill price="{{order.totalAmount + ''}}" />
|
||||
<text>,运费</text>
|
||||
<price fill price="{{order.freightFee + ''}}" />
|
||||
<text decode> </text>
|
||||
<text class="bold-price" decode="{{true}}">实付 </text>
|
||||
<price fill class="real-pay" price="{{order.amount + ''}}" decimalSmaller />
|
||||
</view>
|
||||
<!-- 订单按钮栏 -->
|
||||
<order-button-bar order="{{order}}" bindrefresh="onRefresh" data-order="{{order}}" />
|
||||
</view>
|
||||
</order-card>
|
||||
|
||||
|
||||
<!-- 列表加载中/已全部加载 -->
|
||||
<load-more
|
||||
wx:if="{{!pullDownRefreshing}}"
|
||||
list-is-empty="{{!orderList.length}}"
|
||||
status="{{listLoading}}"
|
||||
bindretry="onReTryLoad"
|
||||
>
|
||||
<!-- 空态 -->
|
||||
<view slot="empty" class="empty-wrapper">
|
||||
<view class="empty-state">
|
||||
<!-- 空状态图标 -->
|
||||
<view class="empty-icon">
|
||||
<t-icon name="{{emptyStateConfig.icon}}" size="120rpx" color="#E6E6E6" />
|
||||
</view>
|
||||
|
||||
<!-- 空状态标题 -->
|
||||
<view class="empty-title">{{emptyStateConfig.title}}</view>
|
||||
|
||||
<!-- 空状态描述 -->
|
||||
<view class="empty-description">{{emptyStateConfig.description}}</view>
|
||||
|
||||
<!-- 操作按钮 -->
|
||||
<view class="empty-actions" wx:if="{{emptyStateConfig.showButton}}">
|
||||
<t-button
|
||||
theme="primary"
|
||||
size="medium"
|
||||
bind:tap="onEmptyButtonTap"
|
||||
t-class="empty-button"
|
||||
>
|
||||
{{emptyStateConfig.buttonText}}
|
||||
</t-button>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</load-more>
|
||||
</t-pull-down-refresh>
|
||||
</view>
|
||||
<t-toast id="t-toast" />
|
||||
<t-dialog id="t-dialog" />
|
||||
222
miniprogram/pages/order/order-list/index.wxss
Normal file
222
miniprogram/pages/order/order-list/index.wxss
Normal file
@@ -0,0 +1,222 @@
|
||||
:host {
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
.page-container .tab-bar__placeholder,
|
||||
.page-container .tab-bar__inner {
|
||||
height: 88rpx;
|
||||
line-height: 88rpx;
|
||||
background: #fff;
|
||||
}
|
||||
.page-container .tab-bar__inner {
|
||||
font-size: 26rpx;
|
||||
color: #333333;
|
||||
position: fixed;
|
||||
width: 100vw;
|
||||
top: 0;
|
||||
left: 0;
|
||||
}
|
||||
.page-container .tab-bar__inner.order-nav .order-nav-item .bottom-line {
|
||||
bottom: 12rpx;
|
||||
}
|
||||
.tab-bar__inner .t-tabs-is-active {
|
||||
color: #fa4126 !important;
|
||||
}
|
||||
|
||||
.tab-bar__inner .t-tabs-track {
|
||||
background: #fa4126 !important;
|
||||
}
|
||||
|
||||
.page-container .tab-bar__active {
|
||||
font-size: 28rpx;
|
||||
}
|
||||
.page-container .specs-popup .bottom-btn {
|
||||
color: #fa4126;
|
||||
color: var(--color-primary, #fa4126);
|
||||
}
|
||||
.page-container .specs-popup .bottom-btn::after {
|
||||
border-color: #fa4126;
|
||||
border-color: var(--color-primary, #fa4126);
|
||||
}
|
||||
.dialog .dialog__button-confirm {
|
||||
color: #fa4126;
|
||||
color: var(--color-primary, #fa4126);
|
||||
}
|
||||
.list-loading {
|
||||
height: 100rpx;
|
||||
}
|
||||
.empty-wrapper {
|
||||
height: calc(100vh - 88rpx);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.empty-state {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 80rpx 40rpx;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.empty-icon {
|
||||
margin-bottom: 40rpx;
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
.empty-title {
|
||||
font-size: 32rpx;
|
||||
font-weight: 500;
|
||||
color: #333333;
|
||||
margin-bottom: 16rpx;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.empty-description {
|
||||
font-size: 28rpx;
|
||||
color: #999999;
|
||||
margin-bottom: 60rpx;
|
||||
line-height: 1.5;
|
||||
max-width: 400rpx;
|
||||
}
|
||||
|
||||
.empty-actions {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.empty-button {
|
||||
min-width: 200rpx !important;
|
||||
border-radius: 50rpx !important;
|
||||
font-size: 28rpx !important;
|
||||
}
|
||||
.btn-bar {
|
||||
margin-top: 20rpx;
|
||||
}
|
||||
.load-more {
|
||||
margin: 0 24rpx;
|
||||
}
|
||||
wr-order-goods-card:not(:first-child) .wr-goods-card {
|
||||
margin-top: 40rpx;
|
||||
}
|
||||
|
||||
.price-total {
|
||||
font-size: 24rpx;
|
||||
line-height: 32rpx;
|
||||
color: #999999;
|
||||
padding-top: 10rpx;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
.price-total .bold-price {
|
||||
color: #333333;
|
||||
font-size: 28rpx;
|
||||
line-height: 40rpx;
|
||||
color: #333333;
|
||||
}
|
||||
.price-total .real-pay {
|
||||
font-size: 36rpx;
|
||||
line-height: 48rpx;
|
||||
color: #fa4126;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.t-tabs.t-tabs--top .t-tabs-scroll {
|
||||
border: none !important;
|
||||
}
|
||||
.t-empty-text {
|
||||
font-size: 28rpx;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.page-container .order-number {
|
||||
color: #666666;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
.t-class-indicator {
|
||||
color: #b9b9b9 !important;
|
||||
}
|
||||
.tab-bar .tab-bar__active {
|
||||
color: #333333 !important;
|
||||
}
|
||||
|
||||
/* 合并订单相关样式 */
|
||||
.merge-toolbar {
|
||||
background: #fff;
|
||||
padding: 20rpx 24rpx;
|
||||
border-bottom: 1rpx solid #f0f0f0;
|
||||
position: sticky;
|
||||
top: 88rpx;
|
||||
z-index: 99;
|
||||
}
|
||||
|
||||
.merge-actions {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.merge-mode-actions {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 20rpx;
|
||||
width: 100%;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.selected-count {
|
||||
font-size: 28rpx;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.order-checkbox {
|
||||
display: inline-block;
|
||||
margin-right: 16rpx;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.order-number {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.cannot-merge-tip {
|
||||
font-size: 24rpx;
|
||||
color: #999;
|
||||
margin-left: 16rpx;
|
||||
}
|
||||
|
||||
.merge-mode-card {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.merge-mode-card::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
border: 2rpx solid transparent;
|
||||
border-radius: 16rpx;
|
||||
pointer-events: none;
|
||||
transition: border-color 0.3s ease;
|
||||
}
|
||||
|
||||
.merge-mode-card.selected::before {
|
||||
border-color: #fa4126;
|
||||
}
|
||||
|
||||
.tab-bar .t-tabs-track {
|
||||
background: #333333 !important;
|
||||
}
|
||||
|
||||
.t-button {
|
||||
--td-button-default-color: #000;
|
||||
--td-button-primary-text-color: #fa4126;
|
||||
}
|
||||
Reference in New Issue
Block a user