863 lines
21 KiB
Vue
863 lines
21 KiB
Vue
|
|
<template>
|
|||
|
|
<view class="order-detail-page">
|
|||
|
|
<!-- 橙色头部 -->
|
|||
|
|
<view class="header-section">
|
|||
|
|
<view class="header-content">
|
|||
|
|
<text class="header-icon" @click="goBack">‹</text>
|
|||
|
|
<text class="header-title">订单详情</text>
|
|||
|
|
<view class="header-placeholder"></view>
|
|||
|
|
</view>
|
|||
|
|
</view>
|
|||
|
|
|
|||
|
|
<scroll-view class="content" scroll-y>
|
|||
|
|
<!-- 状态和进度卡片 -->
|
|||
|
|
<view class="card-section status-card">
|
|||
|
|
<!-- 状态头部 -->
|
|||
|
|
<view class="status-header">
|
|||
|
|
<text class="status-text">{{ orderInfo.status_text }}</text>
|
|||
|
|
<text class="order-no-text">订单号: {{ orderInfo.order_no }}</text>
|
|||
|
|
</view>
|
|||
|
|
|
|||
|
|
<!-- 进度条 -->
|
|||
|
|
<view class="progress-bar">
|
|||
|
|
<view
|
|||
|
|
v-for="(step, index) in progressSteps"
|
|||
|
|
:key="index"
|
|||
|
|
class="progress-step"
|
|||
|
|
:class="{ 'active': index <= currentProgressIndex, 'current': index === currentProgressIndex }"
|
|||
|
|
>
|
|||
|
|
<view class="step-icon-wrap">
|
|||
|
|
<view class="step-icon">
|
|||
|
|
<text class="icon-text">{{ getStepIcon(index) }}</text>
|
|||
|
|
</view>
|
|||
|
|
<view v-if="index < progressSteps.length - 1" class="step-line"></view>
|
|||
|
|
</view>
|
|||
|
|
<text class="step-text">{{ step.name }}</text>
|
|||
|
|
</view>
|
|||
|
|
</view>
|
|||
|
|
</view>
|
|||
|
|
|
|||
|
|
<!-- 收货信息 -->
|
|||
|
|
<view class="card-section address-card">
|
|||
|
|
<view class="address-icon">
|
|||
|
|
<text class="icon-location">📍</text>
|
|||
|
|
</view>
|
|||
|
|
<view class="address-content">
|
|||
|
|
<view class="address-row">
|
|||
|
|
<text class="receiver-name">{{ orderInfo.receiver_name }}</text>
|
|||
|
|
<text class="receiver-phone">{{ orderInfo.receiver_phone }}</text>
|
|||
|
|
</view>
|
|||
|
|
<text class="address-text">{{ orderInfo.receiver_address }}</text>
|
|||
|
|
</view>
|
|||
|
|
</view>
|
|||
|
|
|
|||
|
|
<!-- 商品信息 -->
|
|||
|
|
<view class="card-section goods-card">
|
|||
|
|
<view class="card-header">
|
|||
|
|
<text class="card-title">商品信息</text>
|
|||
|
|
</view>
|
|||
|
|
|
|||
|
|
<!-- 商品列表 -->
|
|||
|
|
<view class="goods-list">
|
|||
|
|
<view
|
|||
|
|
v-for="(goods, index) in orderInfo.orderInfoList"
|
|||
|
|
:key="index"
|
|||
|
|
class="goods-item"
|
|||
|
|
>
|
|||
|
|
<text class="goods-name">{{ goods.storeName || goods.productName }}</text>
|
|||
|
|
<view class="goods-price-row">
|
|||
|
|
<text class="goods-price">{{ formatPoints(goods.integral || goods.vipPrice || goods.price) }}积分</text>
|
|||
|
|
<text class="goods-qty">x{{ goods.cartNum }}</text>
|
|||
|
|
</view>
|
|||
|
|
</view>
|
|||
|
|
|
|||
|
|
<!-- 无商品时显示默认 -->
|
|||
|
|
<view v-if="!orderInfo.orderInfoList || orderInfo.orderInfoList.length === 0" class="goods-item">
|
|||
|
|
<text class="goods-name">{{ orderInfo.goods_name }}</text>
|
|||
|
|
<view class="goods-price-row">
|
|||
|
|
<text class="goods-price">{{ formatPoints(orderInfo.points) }}积分</text>
|
|||
|
|
<text class="goods-qty">x{{ orderInfo.quantity }}</text>
|
|||
|
|
</view>
|
|||
|
|
</view>
|
|||
|
|
</view>
|
|||
|
|
|
|||
|
|
<!-- 汇总信息 -->
|
|||
|
|
<view class="goods-summary">
|
|||
|
|
<view class="summary-row">
|
|||
|
|
<text class="summary-label">商品数量</text>
|
|||
|
|
<text class="summary-value">{{ orderInfo.quantity }}件</text>
|
|||
|
|
</view>
|
|||
|
|
<view class="summary-row">
|
|||
|
|
<text class="summary-label">总计</text>
|
|||
|
|
<text class="summary-total">{{ formatPoints(orderInfo.points) }}积分</text>
|
|||
|
|
</view>
|
|||
|
|
</view>
|
|||
|
|
</view>
|
|||
|
|
|
|||
|
|
<!-- 订单信息 -->
|
|||
|
|
<view class="card-section order-info-card">
|
|||
|
|
<view class="card-header">
|
|||
|
|
<text class="card-title">订单信息</text>
|
|||
|
|
</view>
|
|||
|
|
<view class="info-content">
|
|||
|
|
<view class="info-row">
|
|||
|
|
<text class="info-label">订单编号</text>
|
|||
|
|
<text class="info-value" @click="copyText(orderInfo.order_no)">{{ orderInfo.order_no }}</text>
|
|||
|
|
</view>
|
|||
|
|
<view class="info-row">
|
|||
|
|
<text class="info-label">下单时间</text>
|
|||
|
|
<text class="info-value">{{ orderInfo.created_at }}</text>
|
|||
|
|
</view>
|
|||
|
|
<view class="info-row">
|
|||
|
|
<text class="info-label">订单状态</text>
|
|||
|
|
<text class="info-value status-value">{{ orderInfo.status_text }}</text>
|
|||
|
|
</view>
|
|||
|
|
</view>
|
|||
|
|
</view>
|
|||
|
|
</scroll-view>
|
|||
|
|
|
|||
|
|
<!-- 底部操作栏 -->
|
|||
|
|
<view v-if="showActions" class="bottom-actions">
|
|||
|
|
<!-- 待兑换(未付款): 取消订单、立即支付 -->
|
|||
|
|
<template v-if="!orderInfo.paid">
|
|||
|
|
<button class="action-btn cancel-btn" @click="cancelOrder">取消订单</button>
|
|||
|
|
<button class="action-btn primary-btn" @click="goPay">立即兑换</button>
|
|||
|
|
</template>
|
|||
|
|
<!-- 待收货: 确认收货 -->
|
|||
|
|
<template v-else-if="orderInfo.paid && orderInfo.status === 1">
|
|||
|
|
<button class="action-btn primary-btn" @click="confirmReceipt">确认收货</button>
|
|||
|
|
</template>
|
|||
|
|
</view>
|
|||
|
|
</view>
|
|||
|
|
</template>
|
|||
|
|
|
|||
|
|
<script>
|
|||
|
|
import { getOrderDetail, orderCancel, orderTake } from '@/api/order.js';
|
|||
|
|
import { mapGetters } from 'vuex';
|
|||
|
|
import { toLogin } from '@/libs/login.js';
|
|||
|
|
|
|||
|
|
export default {
|
|||
|
|
data() {
|
|||
|
|
return {
|
|||
|
|
orderId: '',
|
|||
|
|
orderInfo: {
|
|||
|
|
id: '',
|
|||
|
|
order_no: '',
|
|||
|
|
goods_id: '',
|
|||
|
|
goods_name: '',
|
|||
|
|
goods_image: '',
|
|||
|
|
quantity: 1,
|
|||
|
|
points: 0,
|
|||
|
|
status: 1,
|
|||
|
|
paid: true,
|
|||
|
|
status_text: '',
|
|||
|
|
express_company: '',
|
|||
|
|
express_no: '',
|
|||
|
|
receiver_name: '',
|
|||
|
|
receiver_phone: '',
|
|||
|
|
receiver_address: '',
|
|||
|
|
created_at: '',
|
|||
|
|
pay_at: '',
|
|||
|
|
ship_at: '',
|
|||
|
|
finish_at: '',
|
|||
|
|
orderInfoList: []
|
|||
|
|
},
|
|||
|
|
progressSteps: [
|
|||
|
|
{ name: '待兑换', status: 0 },
|
|||
|
|
{ name: '待发货', status: 1 },
|
|||
|
|
{ name: '待收货', status: 2 },
|
|||
|
|
{ name: '已完成', status: 3 }
|
|||
|
|
],
|
|||
|
|
loading: false
|
|||
|
|
}
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
computed: {
|
|||
|
|
...mapGetters(['isLogin']),
|
|||
|
|
|
|||
|
|
showActions() {
|
|||
|
|
// 待兑换(未付款)显示取消按钮,待收货显示确认收货按钮
|
|||
|
|
return (!this.orderInfo.paid) || (this.orderInfo.paid && this.orderInfo.status === 1)
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
// 计算总积分
|
|||
|
|
totalPoints() {
|
|||
|
|
return this.orderInfo.points || 0;
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
// 当前进度索引
|
|||
|
|
currentProgressIndex() {
|
|||
|
|
if (!this.orderInfo.paid) return 0; // 待兑换
|
|||
|
|
// status: 0-待发货 1-待收货 2-待评价 3-已完成
|
|||
|
|
if (this.orderInfo.status === 0) return 1; // 待发货
|
|||
|
|
if (this.orderInfo.status === 1) return 2; // 待收货
|
|||
|
|
if (this.orderInfo.status >= 2) return 3; // 已完成
|
|||
|
|
return 0;
|
|||
|
|
}
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
onLoad(options) {
|
|||
|
|
if (options.id) {
|
|||
|
|
this.orderId = options.id
|
|||
|
|
this.loadOrderDetail()
|
|||
|
|
}
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
methods: {
|
|||
|
|
// 返回上一页
|
|||
|
|
goBack() {
|
|||
|
|
uni.navigateBack()
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
// 格式化积分数字(添加千分位逗号)
|
|||
|
|
formatPoints(points) {
|
|||
|
|
if (!points && points !== 0) return '0'
|
|||
|
|
return points.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',')
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
// 获取步骤图标
|
|||
|
|
getStepIcon(index) {
|
|||
|
|
const icons = ['⏱', '📦', '🚚', '✓'];
|
|||
|
|
return icons[index] || '○';
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
// 加载订单详情
|
|||
|
|
async loadOrderDetail() {
|
|||
|
|
if (this.loading) return
|
|||
|
|
|
|||
|
|
// 检查登录状态
|
|||
|
|
if (!this.isLogin) {
|
|||
|
|
toLogin();
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
this.loading = true
|
|||
|
|
uni.showLoading({ title: '加载中...' })
|
|||
|
|
|
|||
|
|
try {
|
|||
|
|
const res = await getOrderDetail(this.orderId);
|
|||
|
|
|
|||
|
|
if (res.data) {
|
|||
|
|
const order = res.data;
|
|||
|
|
const orderInfoList = order.orderInfoList || [];
|
|||
|
|
|
|||
|
|
// 获取第一个商品信息
|
|||
|
|
let goodsName = '商品名称';
|
|||
|
|
let goodsImage = '/static/images/default-goods.png';
|
|||
|
|
let totalNum = order.totalNum || 1;
|
|||
|
|
|
|||
|
|
// 计算总积分:优先使用payIntegral/useIntegral,否则从商品列表计算
|
|||
|
|
let totalPoints = 0;
|
|||
|
|
|
|||
|
|
// 优先使用订单级别的积分字段
|
|||
|
|
if (order.payIntegral !== undefined && order.payIntegral !== null) {
|
|||
|
|
totalPoints = parseFloat(order.payIntegral) || 0;
|
|||
|
|
} else if (order.useIntegral !== undefined && order.useIntegral !== null) {
|
|||
|
|
totalPoints = parseFloat(order.useIntegral) || 0;
|
|||
|
|
} else if (order.integral !== undefined && order.integral !== null) {
|
|||
|
|
totalPoints = parseFloat(order.integral) || 0;
|
|||
|
|
} else {
|
|||
|
|
// 从商品列表计算总积分
|
|||
|
|
totalPoints = orderInfoList.reduce((sum, item) => {
|
|||
|
|
// 优先使用integral字段,否则使用vipPrice或price
|
|||
|
|
const itemPoints = parseFloat(item.integral) || parseFloat(item.vipPrice) || parseFloat(item.price) || 0;
|
|||
|
|
const quantity = parseInt(item.cartNum) || 1;
|
|||
|
|
return sum + (itemPoints * quantity);
|
|||
|
|
}, 0);
|
|||
|
|
|
|||
|
|
// 如果计算结果为0,尝试使用payPrice或totalPrice
|
|||
|
|
if (totalPoints === 0) {
|
|||
|
|
totalPoints = parseFloat(order.payPrice) || parseFloat(order.totalPrice) || 0;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
console.log('订单详情积分计算:', {
|
|||
|
|
orderId: order.orderId,
|
|||
|
|
payIntegral: order.payIntegral,
|
|||
|
|
useIntegral: order.useIntegral,
|
|||
|
|
integral: order.integral,
|
|||
|
|
payPrice: order.payPrice,
|
|||
|
|
totalPrice: order.totalPrice,
|
|||
|
|
calculatedPoints: totalPoints,
|
|||
|
|
orderInfoList: orderInfoList.map(item => ({
|
|||
|
|
name: item.storeName,
|
|||
|
|
integral: item.integral,
|
|||
|
|
vipPrice: item.vipPrice,
|
|||
|
|
price: item.price,
|
|||
|
|
cartNum: item.cartNum
|
|||
|
|
}))
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
if (orderInfoList.length > 0) {
|
|||
|
|
const firstGoods = orderInfoList[0];
|
|||
|
|
goodsName = firstGoods.storeName || firstGoods.productName || goodsName;
|
|||
|
|
goodsImage = firstGoods.image || goodsImage;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 格式化订单数据
|
|||
|
|
this.orderInfo = {
|
|||
|
|
id: order.id,
|
|||
|
|
order_no: order.orderId || order.orderNo || '',
|
|||
|
|
goods_id: orderInfoList.length > 0 ? orderInfoList[0].productId : '',
|
|||
|
|
goods_name: goodsName,
|
|||
|
|
goods_image: goodsImage,
|
|||
|
|
quantity: totalNum,
|
|||
|
|
points: totalPoints,
|
|||
|
|
status: order.status,
|
|||
|
|
paid: order.paid,
|
|||
|
|
status_text: order.orderStatus || this.getStatusText(order.status, order.paid),
|
|||
|
|
express_company: order.deliveryName || '',
|
|||
|
|
express_no: order.deliveryId || '',
|
|||
|
|
receiver_name: order.realName || '',
|
|||
|
|
receiver_phone: order.userPhone || '',
|
|||
|
|
receiver_address: order.userAddress || '',
|
|||
|
|
created_at: order.createTime || '',
|
|||
|
|
pay_at: order.payTime || '',
|
|||
|
|
ship_at: order.deliveryTime || '',
|
|||
|
|
finish_at: order.finishTime || '',
|
|||
|
|
orderInfoList: orderInfoList
|
|||
|
|
};
|
|||
|
|
} else {
|
|||
|
|
throw new Error(res.msg || '加载失败');
|
|||
|
|
}
|
|||
|
|
} catch (error) {
|
|||
|
|
console.error('加载订单详情失败:', error)
|
|||
|
|
uni.showToast({
|
|||
|
|
title: error.msg || error.message || '加载失败',
|
|||
|
|
icon: 'none'
|
|||
|
|
})
|
|||
|
|
|
|||
|
|
setTimeout(() => {
|
|||
|
|
uni.navigateBack()
|
|||
|
|
}, 1500)
|
|||
|
|
} finally {
|
|||
|
|
this.loading = false
|
|||
|
|
uni.hideLoading()
|
|||
|
|
}
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
// 获取状态文本
|
|||
|
|
getStatusText(status, paid) {
|
|||
|
|
if (!paid) return '待兑换';
|
|||
|
|
|
|||
|
|
const statusMap = {
|
|||
|
|
0: '待发货',
|
|||
|
|
1: '待收货',
|
|||
|
|
2: '待评价',
|
|||
|
|
3: '已完成'
|
|||
|
|
};
|
|||
|
|
return statusMap[status] || '未知状态';
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
// 取消订单
|
|||
|
|
cancelOrder() {
|
|||
|
|
uni.showModal({
|
|||
|
|
title: '提示',
|
|||
|
|
content: '确定要取消这个订单吗?积分将退回到您的账户',
|
|||
|
|
confirmColor: '#F54900',
|
|||
|
|
success: async (res) => {
|
|||
|
|
if (res.confirm) {
|
|||
|
|
uni.showLoading({ title: '取消中...' })
|
|||
|
|
|
|||
|
|
try {
|
|||
|
|
await orderCancel(this.orderInfo.id);
|
|||
|
|
|
|||
|
|
uni.hideLoading()
|
|||
|
|
uni.showToast({
|
|||
|
|
title: '订单已取消',
|
|||
|
|
icon: 'success'
|
|||
|
|
})
|
|||
|
|
|
|||
|
|
setTimeout(() => {
|
|||
|
|
uni.navigateBack()
|
|||
|
|
}, 1500)
|
|||
|
|
} catch (error) {
|
|||
|
|
uni.hideLoading()
|
|||
|
|
uni.showToast({
|
|||
|
|
title: error.msg || '取消失败,请重试',
|
|||
|
|
icon: 'none'
|
|||
|
|
})
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
})
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
// 确认收货
|
|||
|
|
confirmReceipt() {
|
|||
|
|
uni.showModal({
|
|||
|
|
title: '确认收货',
|
|||
|
|
content: '确认已收到商品?',
|
|||
|
|
confirmColor: '#F54900',
|
|||
|
|
success: async (res) => {
|
|||
|
|
if (res.confirm) {
|
|||
|
|
uni.showLoading({ title: '确认中...' })
|
|||
|
|
|
|||
|
|
try {
|
|||
|
|
const result = await orderTake(this.orderInfo.id);
|
|||
|
|
console.log('确认收货接口返回:', result)
|
|||
|
|
|
|||
|
|
uni.hideLoading()
|
|||
|
|
|
|||
|
|
// 接口返回 code: 200 表示成功
|
|||
|
|
if (result.code === 200 || result.code === 0) {
|
|||
|
|
uni.showToast({
|
|||
|
|
title: '确认收货成功',
|
|||
|
|
icon: 'success'
|
|||
|
|
})
|
|||
|
|
|
|||
|
|
// 重新加载订单详情
|
|||
|
|
setTimeout(() => {
|
|||
|
|
this.loadOrderDetail()
|
|||
|
|
}, 1500)
|
|||
|
|
} else {
|
|||
|
|
uni.showToast({
|
|||
|
|
title: result.msg || '操作失败,请重试',
|
|||
|
|
icon: 'none'
|
|||
|
|
})
|
|||
|
|
}
|
|||
|
|
} catch (error) {
|
|||
|
|
uni.hideLoading()
|
|||
|
|
console.error('确认收货失败:', error)
|
|||
|
|
uni.showToast({
|
|||
|
|
title: error.msg || error.message || '操作失败,请重试',
|
|||
|
|
icon: 'none'
|
|||
|
|
})
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
})
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
// 复制文本
|
|||
|
|
copyText(text) {
|
|||
|
|
uni.setClipboardData({
|
|||
|
|
data: text,
|
|||
|
|
success: () => {
|
|||
|
|
uni.showToast({
|
|||
|
|
title: '已复制',
|
|||
|
|
icon: 'success'
|
|||
|
|
})
|
|||
|
|
}
|
|||
|
|
})
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
// 获取状态图标
|
|||
|
|
getStatusIcon(status) {
|
|||
|
|
const icons = {
|
|||
|
|
1: '⏳', // 待发货
|
|||
|
|
2: '🚚', // 待收货
|
|||
|
|
3: '✅', // 已完成
|
|||
|
|
4: '❌' // 已取消
|
|||
|
|
}
|
|||
|
|
return icons[status] || '📦'
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
// 获取状态提示
|
|||
|
|
getStatusTip(status) {
|
|||
|
|
if (!this.orderInfo.paid) {
|
|||
|
|
return '请尽快完成支付,积分商品数量有限';
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
const tips = {
|
|||
|
|
0: '商家正在准备发货,请耐心等待',
|
|||
|
|
1: '商品已发货,请注意查收',
|
|||
|
|
2: '请对本次交易进行评价',
|
|||
|
|
3: '交易已完成,感谢您的支持'
|
|||
|
|
}
|
|||
|
|
return tips[status] || ''
|
|||
|
|
},
|
|||
|
|
|
|||
|
|
// 去支付
|
|||
|
|
goPay() {
|
|||
|
|
uni.navigateTo({
|
|||
|
|
url: `/pages/order/order_payment/index?orderNo=${this.orderInfo.order_no}&payPrice=${this.orderInfo.points}`
|
|||
|
|
})
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
</script>
|
|||
|
|
|
|||
|
|
<style lang="scss" scoped>
|
|||
|
|
.order-detail-page {
|
|||
|
|
min-height: 100vh;
|
|||
|
|
height: 100vh;
|
|||
|
|
background-color: #F5F5F5;
|
|||
|
|
display: flex;
|
|||
|
|
flex-direction: column;
|
|||
|
|
overflow: hidden;
|
|||
|
|
position: relative;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 橙色头部
|
|||
|
|
.header-section {
|
|||
|
|
background-color: #F54900;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.header-content {
|
|||
|
|
height: 88rpx;
|
|||
|
|
display: flex;
|
|||
|
|
align-items: center;
|
|||
|
|
justify-content: space-between;
|
|||
|
|
padding: 0 32rpx;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.header-icon {
|
|||
|
|
font-size: 48rpx;
|
|||
|
|
color: #FFFFFF;
|
|||
|
|
font-weight: 300;
|
|||
|
|
width: 60rpx;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.header-title {
|
|||
|
|
flex: 1;
|
|||
|
|
font-size: 34rpx;
|
|||
|
|
color: #FFFFFF;
|
|||
|
|
font-weight: 500;
|
|||
|
|
text-align: center;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.header-placeholder {
|
|||
|
|
width: 60rpx;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.content {
|
|||
|
|
flex: 1;
|
|||
|
|
padding: 24rpx 32rpx;
|
|||
|
|
padding-bottom: 140rpx;
|
|||
|
|
box-sizing: border-box;
|
|||
|
|
height: calc(100vh - 88rpx - 120rpx);
|
|||
|
|
overflow-y: auto;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 卡片通用样式
|
|||
|
|
.card-section {
|
|||
|
|
background-color: #FFFFFF;
|
|||
|
|
border-radius: 24rpx;
|
|||
|
|
margin-bottom: 24rpx;
|
|||
|
|
overflow: hidden;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 状态卡片
|
|||
|
|
.status-card {
|
|||
|
|
padding: 32rpx;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.status-header {
|
|||
|
|
display: flex;
|
|||
|
|
justify-content: space-between;
|
|||
|
|
align-items: center;
|
|||
|
|
margin-bottom: 40rpx;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.status-text {
|
|||
|
|
font-size: 36rpx;
|
|||
|
|
color: #F54900;
|
|||
|
|
font-weight: 500;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.order-no-text {
|
|||
|
|
font-size: 26rpx;
|
|||
|
|
color: #666666;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 进度条
|
|||
|
|
.progress-bar {
|
|||
|
|
display: flex;
|
|||
|
|
align-items: flex-start;
|
|||
|
|
justify-content: space-between;
|
|||
|
|
position: relative;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.progress-step {
|
|||
|
|
flex: 1;
|
|||
|
|
display: flex;
|
|||
|
|
flex-direction: column;
|
|||
|
|
align-items: center;
|
|||
|
|
position: relative;
|
|||
|
|
|
|||
|
|
&.active {
|
|||
|
|
.step-icon {
|
|||
|
|
background-color: #F54900;
|
|||
|
|
border-color: #F54900;
|
|||
|
|
|
|||
|
|
.icon-text {
|
|||
|
|
color: #FFFFFF;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.step-text {
|
|||
|
|
color: #F54900;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
&.current {
|
|||
|
|
.step-icon {
|
|||
|
|
background-color: #F54900;
|
|||
|
|
border-color: #F54900;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.step-icon-wrap {
|
|||
|
|
position: relative;
|
|||
|
|
display: flex;
|
|||
|
|
align-items: center;
|
|||
|
|
width: 100%;
|
|||
|
|
justify-content: center;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.step-icon {
|
|||
|
|
width: 72rpx;
|
|||
|
|
height: 72rpx;
|
|||
|
|
border-radius: 50%;
|
|||
|
|
background-color: #FFFFFF;
|
|||
|
|
border: 4rpx solid #E5E7EB;
|
|||
|
|
display: flex;
|
|||
|
|
align-items: center;
|
|||
|
|
justify-content: center;
|
|||
|
|
z-index: 2;
|
|||
|
|
position: relative;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.icon-text {
|
|||
|
|
font-size: 28rpx;
|
|||
|
|
color: #E5E7EB;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.step-line {
|
|||
|
|
position: absolute;
|
|||
|
|
top: 50%;
|
|||
|
|
left: calc(50% + 36rpx);
|
|||
|
|
width: calc(100% - 72rpx);
|
|||
|
|
height: 4rpx;
|
|||
|
|
background-color: #E5E7EB;
|
|||
|
|
z-index: 1;
|
|||
|
|
transform: translateY(-50%);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.progress-step.active .step-line {
|
|||
|
|
background-color: #F54900;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.progress-step:last-child .step-line {
|
|||
|
|
display: none;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.step-text {
|
|||
|
|
margin-top: 16rpx;
|
|||
|
|
font-size: 24rpx;
|
|||
|
|
color: #999999;
|
|||
|
|
white-space: nowrap;
|
|||
|
|
text-align: center;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 收货信息卡片
|
|||
|
|
.address-card {
|
|||
|
|
display: flex;
|
|||
|
|
flex-direction: row;
|
|||
|
|
align-items: flex-start;
|
|||
|
|
gap: 20rpx;
|
|||
|
|
padding: 32rpx;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.address-icon {
|
|||
|
|
flex-shrink: 0;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.icon-location {
|
|||
|
|
font-size: 36rpx;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.address-content {
|
|||
|
|
flex: 1;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.address-row {
|
|||
|
|
display: flex;
|
|||
|
|
align-items: center;
|
|||
|
|
gap: 16rpx;
|
|||
|
|
margin-bottom: 12rpx;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.receiver-name {
|
|||
|
|
font-size: 30rpx;
|
|||
|
|
color: #333333;
|
|||
|
|
font-weight: 500;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.receiver-phone {
|
|||
|
|
font-size: 30rpx;
|
|||
|
|
color: #333333;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.address-text {
|
|||
|
|
font-size: 28rpx;
|
|||
|
|
color: #666666;
|
|||
|
|
line-height: 1.5;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 商品信息卡片
|
|||
|
|
.goods-card {
|
|||
|
|
display: flex;
|
|||
|
|
flex-direction: column;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.card-header {
|
|||
|
|
padding: 32rpx;
|
|||
|
|
border-bottom: 1rpx solid #F5F5F5;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.card-title {
|
|||
|
|
font-size: 28rpx;
|
|||
|
|
color: #999999;
|
|||
|
|
font-weight: normal;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.goods-list {
|
|||
|
|
padding: 0 32rpx;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.goods-item {
|
|||
|
|
padding: 32rpx 0;
|
|||
|
|
border-bottom: 1rpx solid #F5F5F5;
|
|||
|
|
|
|||
|
|
&:last-child {
|
|||
|
|
border-bottom: none;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.goods-name {
|
|||
|
|
font-size: 30rpx;
|
|||
|
|
color: #333333;
|
|||
|
|
line-height: 1.5;
|
|||
|
|
margin-bottom: 16rpx;
|
|||
|
|
display: block;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.goods-price-row {
|
|||
|
|
display: flex;
|
|||
|
|
justify-content: space-between;
|
|||
|
|
align-items: center;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.goods-price {
|
|||
|
|
font-size: 30rpx;
|
|||
|
|
color: #F54900;
|
|||
|
|
font-weight: 500;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.goods-qty {
|
|||
|
|
font-size: 28rpx;
|
|||
|
|
color: #999999;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 商品汇总
|
|||
|
|
.goods-summary {
|
|||
|
|
padding: 24rpx 32rpx;
|
|||
|
|
border-top: 1rpx solid #F5F5F5;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.summary-row {
|
|||
|
|
display: flex;
|
|||
|
|
justify-content: space-between;
|
|||
|
|
align-items: center;
|
|||
|
|
margin-bottom: 16rpx;
|
|||
|
|
|
|||
|
|
&:last-child {
|
|||
|
|
margin-bottom: 0;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.summary-label {
|
|||
|
|
font-size: 28rpx;
|
|||
|
|
color: #333333;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.summary-value {
|
|||
|
|
font-size: 28rpx;
|
|||
|
|
color: #333333;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.summary-total {
|
|||
|
|
font-size: 32rpx;
|
|||
|
|
color: #F54900;
|
|||
|
|
font-weight: 500;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 订单信息卡片
|
|||
|
|
.order-info-card {
|
|||
|
|
display: flex;
|
|||
|
|
flex-direction: column;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.info-content {
|
|||
|
|
padding: 24rpx 32rpx;
|
|||
|
|
display: flex;
|
|||
|
|
flex-direction: column;
|
|||
|
|
gap: 20rpx;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.info-row {
|
|||
|
|
display: flex;
|
|||
|
|
justify-content: space-between;
|
|||
|
|
align-items: center;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.status-value {
|
|||
|
|
color: #F54900 !important;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.info-label {
|
|||
|
|
font-size: 28rpx;
|
|||
|
|
color: #999999;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.info-value {
|
|||
|
|
font-size: 28rpx;
|
|||
|
|
color: #333333;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/* 底部操作栏 - 固定在页面底部 */
|
|||
|
|
.bottom-actions {
|
|||
|
|
position: fixed;
|
|||
|
|
bottom: 0;
|
|||
|
|
left: 0;
|
|||
|
|
right: 0;
|
|||
|
|
z-index: 999;
|
|||
|
|
background-color: #FFFFFF;
|
|||
|
|
padding: 20rpx 30rpx;
|
|||
|
|
padding-bottom: calc(20rpx + constant(safe-area-inset-bottom));
|
|||
|
|
padding-bottom: calc(20rpx + env(safe-area-inset-bottom));
|
|||
|
|
border-top: 1rpx solid #EEEEEE;
|
|||
|
|
display: flex;
|
|||
|
|
justify-content: flex-end;
|
|||
|
|
gap: 20rpx;
|
|||
|
|
box-shadow: 0 -4rpx 20rpx rgba(0, 0, 0, 0.05);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.action-btn {
|
|||
|
|
padding: 0 50rpx;
|
|||
|
|
height: 80rpx;
|
|||
|
|
line-height: 80rpx;
|
|||
|
|
border-radius: 40rpx;
|
|||
|
|
font-size: 30rpx;
|
|||
|
|
border: none;
|
|||
|
|
|
|||
|
|
&::after {
|
|||
|
|
border: none;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.cancel-btn {
|
|||
|
|
background-color: #F5F5F5;
|
|||
|
|
color: #666666;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.primary-btn {
|
|||
|
|
background-color: #F54900;
|
|||
|
|
color: #FFFFFF;
|
|||
|
|
}
|
|||
|
|
</style>
|
|||
|
|
|