You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

818 lines
18 KiB

<template>
<view class="order-detail-container">
<!-- 订单状态 -->
<view class="status-section">
<view class="status-icon">
<image
:src="getStatusIcon(orderDetail.status)"
mode="aspectFit"
class="icon"
/>
</view>
<view class="status-info">
<text class="status-text">{{ getStatusText(orderDetail.status) }}</text>
<text class="status-desc">{{ getStatusDesc(orderDetail.status) }}</text>
</view>
</view>
<!-- 订单信息 -->
<view class="order-info-section">
<view class="section-title">订单信息</view>
<view class="info-item">
<text class="label">订单号</text>
<text class="value">{{ orderDetail.orderNo }}</text>
<text class="copy-btn" @click="copyOrderNo">复制</text>
</view>
<view class="info-item">
<text class="label">下单时间</text>
<text class="value">{{ formatTime(orderDetail.createTime) }}</text>
</view>
<view class="info-item" v-if="orderDetail.payTime">
<text class="label">付款时间</text>
<text class="value">{{ formatTime(orderDetail.payTime) }}</text>
</view>
<view class="info-item">
<text class="label">支付方式</text>
<text class="value">{{ orderDetail.payMethod || "微信支付" }}</text>
</view>
</view>
<!-- 权益商品包 -->
<view class="package-section">
<view class="section-title">权益商品包</view>
<view class="package-name">{{ orderDetail.packageName }}</view>
</view>
<!-- 商品列表 -->
<view class="goods-section">
<view class="section-title">商品清单</view>
<view
class="goods-item"
v-for="goods in orderDetail.goodsList"
:key="goods.id"
>
<image class="goods-image" :src="goods.image" mode="aspectFill" />
<view class="goods-info">
<text class="goods-name">{{ goods.name }}</text>
<text class="goods-type">{{ getGoodsTypeName(goods.type) }}</text>
<text class="goods-spec" v-if="goods.spec">{{ goods.spec }}</text>
</view>
<view class="goods-price">
<text class="price">¥{{ goods.price }}</text>
<text class="quantity">×{{ goods.quantity || 1 }}</text>
</view>
</view>
</view>
<!-- 权益码信息 -->
<view class="equity-section" v-if="orderDetail.status !== 0">
<view class="section-title">权益码信息</view>
<view class="equity-card" @click="showEquityCode">
<view class="equity-info">
<text class="equity-label">权益码</text>
<text class="equity-code">{{ orderDetail.equityCode }}</text>
</view>
<view class="equity-action">
<text class="view-qr">查看二维码</text>
</view>
</view>
</view>
<!-- 费用明细 -->
<view class="cost-section">
<view class="section-title">费用明细</view>
<view class="cost-item">
<text class="cost-label">商品总价</text>
<text class="cost-value">¥{{ orderDetail.goodsAmount }}</text>
</view>
<view class="cost-item" v-if="orderDetail.discountAmount > 0">
<text class="cost-label">优惠金额</text>
<text class="cost-value discount"
>-¥{{ orderDetail.discountAmount }}</text
>
</view>
<view class="cost-item total">
<text class="cost-label">实付金额</text>
<text class="cost-value">¥{{ orderDetail.totalAmount }}</text>
</view>
</view>
<!-- 收货信息 -->
<view class="address-section" v-if="hasPhysicalGoods">
<view class="section-title">收货信息</view>
<view class="address-info" v-if="orderDetail.address">
<view class="receiver-info">
<text class="receiver-name">{{ orderDetail.address.name }}</text>
<text class="receiver-phone">{{ orderDetail.address.phone }}</text>
</view>
<text class="receiver-address">{{
orderDetail.address.fullAddress
}}</text>
</view>
<view class="no-address" v-else>
<text>该订单无需收货地址</text>
</view>
</view>
<!-- 底部操作 -->
<view class="bottom-actions" v-if="showBottomActions">
<button
class="action-btn secondary"
v-if="orderDetail.status === 0"
@click="cancelOrder"
>
取消订单
</button>
<button
class="action-btn primary"
v-if="orderDetail.status === 0"
@click="payOrder"
>
立即支付
</button>
<button
class="action-btn primary"
v-if="orderDetail.status === 3"
@click="buyAgain"
>
再次购买
</button>
</view>
<!-- 权益码弹窗 -->
<view
class="equity-popup-mask"
v-if="showEquityPopup"
@click="closeEquityPopup"
>
<view class="equity-popup" @click.stop>
<view class="popup-header">
<text class="popup-title">权益码</text>
<text class="popup-close" @click="closeEquityPopup">×</text>
</view>
<view class="popup-content">
<!-- 二维码 -->
<view class="qrcode-container">
<image
class="qrcode-image"
:src="orderDetail.qrcode"
mode="aspectFit"
/>
</view>
<!-- 编号串码 -->
<view class="code-container">
<text class="code-label">权益码:</text>
<text class="code-value" @longpress="copyEquityCode">{{
orderDetail.equityCode
}}</text>
</view>
<text class="code-tip">长按编号可复制</text>
</view>
</view>
</view>
</view>
</template>
<script>
export default {
data() {
return {
orderId: "",
showEquityPopup: false,
orderDetail: {
id: "",
orderNo: "",
status: 0,
packageName: "",
goodsList: [],
totalAmount: "0.00",
goodsAmount: "0.00",
discountAmount: "0.00",
createTime: "",
payTime: "",
payMethod: "",
equityCode: "",
qrcode: "",
address: null,
},
};
},
computed: {
// 是否有实体商品需要收货
hasPhysicalGoods() {
return this.orderDetail.goodsList.some((goods) => goods.type === 2);
},
// 是否显示底部操作按钮
showBottomActions() {
return [0, 3].includes(this.orderDetail.status);
},
},
onLoad(options) {
if (options.id) {
this.orderId = options.id;
this.loadOrderDetail();
}
},
methods: {
// 加载订单详情
async loadOrderDetail() {
try {
uni.showLoading({ title: "加载中..." });
const res = await this.getOrderDetail(this.orderId);
this.orderDetail = res.data;
} catch (error) {
console.error("加载订单详情失败:", error);
uni.showToast({
title: "加载失败",
icon: "none",
});
} finally {
uni.hideLoading();
}
},
// 获取状态图标
getStatusIcon(status) {
const iconMap = {
0: "/static/icon/status-pending.png",
1: "/static/icon/status-waiting.png",
2: "/static/icon/status-shipping.png",
3: "/static/icon/status-completed.png",
4: "/static/icon/status-refund.png",
};
return iconMap[status] || "/static/icon/status-default.png";
},
// 获取状态文本
getStatusText(status) {
const statusMap = {
0: "待付款",
1: "待使用",
2: "待收货",
3: "已完成",
4: "售后/退款",
};
return statusMap[status] || "未知状态";
},
// 获取状态描述
getStatusDesc(status) {
const descMap = {
0: "请尽快完成支付",
1: "权益商品可随时使用",
2: "商品正在配送中",
3: "订单已完成,感谢您的购买",
4: "退款处理中",
};
return descMap[status] || "";
},
// 获取商品类型名称
getGoodsTypeName(type) {
const typeMap = {
1: "IP数字资产",
2: "IP资源商品",
3: "君道苏州门票",
};
return typeMap[type] || "未知类型";
},
// 复制订单号
copyOrderNo() {
uni.setClipboardData({
data: this.orderDetail.orderNo,
success: () => {
uni.showToast({
title: "订单号已复制",
icon: "success",
});
},
});
},
// 显示权益码
showEquityCode() {
this.showEquityPopup = true;
},
// 关闭权益码弹窗
closeEquityPopup() {
this.showEquityPopup = false;
},
// 复制权益码
copyEquityCode() {
uni.setClipboardData({
data: this.orderDetail.equityCode,
success: () => {
uni.showToast({
title: "权益码已复制",
icon: "success",
});
},
});
},
// 取消订单
async cancelOrder() {
const res = await uni.showModal({
title: "确认取消",
content: "确定要取消这个订单吗?",
});
if (res.confirm) {
try {
await this.cancelOrderApi(this.orderId);
uni.showToast({
title: "订单已取消",
icon: "success",
});
this.loadOrderDetail();
} catch (error) {
uni.showToast({
title: "取消失败",
icon: "none",
});
}
}
},
// 支付订单
payOrder() {
// 跳转到支付页面或调用支付接口
uni.navigateTo({
url: `/pages/payment/index?orderId=${this.orderId}`,
});
},
// 再次购买
buyAgain() {
// 跳转到商品页面
uni.navigateTo({
url: `/subPackages/equityGoods/detail?id=${this.orderDetail.packageId}`,
});
},
// 格式化时间
formatTime(time) {
if (!time) return "";
const date = new Date(time);
return `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(
2,
"0"
)}-${String(date.getDate()).padStart(2, "0")} ${String(
date.getHours()
).padStart(2, "0")}:${String(date.getMinutes()).padStart(2, "0")}`;
},
// API接口 - 获取订单详情
async getOrderDetail(orderId) {
// 模拟API数据
return new Promise((resolve) => {
setTimeout(() => {
const mockData = {
code: 200,
data: {
id: orderId,
orderNo: "EQ202401011234567",
status: 1,
packageName: "Epic Soul限定权益包",
packageId: "pkg001",
totalAmount: "249.00",
goodsAmount: "299.00",
discountAmount: "50.00",
createTime: "2024-01-01 12:00:00",
payTime: "2024-01-01 12:05:00",
payMethod: "微信支付",
equityCode: "EPIC2024010112345",
qrcode: "/static/image/qrcode-sample.png",
goodsList: [
{
id: 1,
name: "数字藏品-桃子系列",
type: 1,
price: "99.00",
quantity: 1,
image: "/static/image/goods1.jpg",
spec: "限量版",
},
{
id: 2,
name: "文创周边产品",
type: 2,
price: "150.00",
quantity: 1,
image: "/static/image/goods2.jpg",
spec: "桃花主题",
},
{
id: 3,
name: "君道苏州体验门票",
type: 3,
price: "50.00",
quantity: 1,
image: "/static/image/goods3.jpg",
spec: "成人票",
},
],
address: {
name: "张三",
phone: "138****8888",
fullAddress: "江苏省苏州市工业园区某某街道某某小区1号楼101室",
},
},
};
resolve(mockData);
}, 500);
});
},
// API接口 - 取消订单
async cancelOrderApi(orderId) {
return new Promise((resolve) => {
setTimeout(() => {
resolve({ code: 200, message: "取消成功" });
}, 500);
});
},
},
};
</script>
<style lang="scss" scoped>
.order-detail-container {
min-height: 100vh;
background-color: #f5f5f5;
padding-bottom: 140rpx;
}
// 状态区域
.status-section {
background-color: #fff;
padding: 40rpx 30rpx;
display: flex;
align-items: center;
margin-bottom: 20rpx;
}
.status-icon {
margin-right: 30rpx;
.icon {
width: 80rpx;
height: 80rpx;
}
}
.status-info {
flex: 1;
}
.status-text {
display: block;
font-size: 32rpx;
font-weight: bold;
color: #333;
margin-bottom: 10rpx;
}
.status-desc {
font-size: 26rpx;
color: #666;
}
// 通用区域样式
.section-title {
font-size: 30rpx;
font-weight: bold;
color: #333;
margin-bottom: 30rpx;
}
// 订单信息
.order-info-section,
.package-section,
.goods-section,
.equity-section,
.cost-section,
.address-section {
background-color: #fff;
padding: 30rpx;
margin-bottom: 20rpx;
}
.info-item {
display: flex;
align-items: center;
margin-bottom: 20rpx;
&:last-child {
margin-bottom: 0;
}
}
.label {
font-size: 28rpx;
color: #666;
width: 160rpx;
}
.value {
flex: 1;
font-size: 28rpx;
color: #333;
}
.copy-btn {
font-size: 24rpx;
color: #007aff;
padding: 8rpx 16rpx;
border: 1px solid #007aff;
border-radius: 20rpx;
}
// 权益商品包
.package-name {
font-size: 28rpx;
color: #333;
background-color: #f8f9fa;
padding: 20rpx;
border-radius: 12rpx;
}
// 商品列表
.goods-item {
display: flex;
align-items: center;
padding: 20rpx 0;
border-bottom: 1px solid #f0f0f0;
&:last-child {
border-bottom: none;
}
}
.goods-image {
width: 120rpx;
height: 120rpx;
border-radius: 12rpx;
margin-right: 20rpx;
}
.goods-info {
flex: 1;
margin-right: 20rpx;
}
.goods-name {
display: block;
font-size: 28rpx;
color: #333;
margin-bottom: 8rpx;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.goods-type {
display: block;
font-size: 24rpx;
color: #999;
margin-bottom: 8rpx;
}
.goods-spec {
font-size: 24rpx;
color: #666;
}
.goods-price {
text-align: right;
}
.price {
display: block;
font-size: 28rpx;
color: #ff4757;
font-weight: bold;
margin-bottom: 5rpx;
}
.quantity {
font-size: 24rpx;
color: #999;
}
// 权益码
.equity-card {
display: flex;
align-items: center;
padding: 30rpx;
background-color: #f8f9fa;
border-radius: 12rpx;
border: 2rpx dashed #007aff;
}
.equity-info {
flex: 1;
}
.equity-label {
display: block;
font-size: 26rpx;
color: #666;
margin-bottom: 10rpx;
}
.equity-code {
font-size: 32rpx;
color: #333;
font-weight: bold;
}
.equity-action {
.view-qr {
font-size: 26rpx;
color: #007aff;
}
}
// 费用明细
.cost-item {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20rpx;
&:last-child {
margin-bottom: 0;
}
&.total {
padding-top: 20rpx;
border-top: 1px solid #f0f0f0;
.cost-label,
.cost-value {
font-size: 32rpx;
font-weight: bold;
}
}
}
.cost-label {
font-size: 28rpx;
color: #666;
}
.cost-value {
font-size: 28rpx;
color: #333;
&.discount {
color: #ff4757;
}
}
// 收货信息
.receiver-info {
display: flex;
align-items: center;
margin-bottom: 15rpx;
}
.receiver-name {
font-size: 28rpx;
color: #333;
font-weight: bold;
margin-right: 20rpx;
}
.receiver-phone {
font-size: 28rpx;
color: #666;
}
.receiver-address {
font-size: 26rpx;
color: #666;
line-height: 1.5;
}
.no-address {
text-align: center;
padding: 30rpx;
color: #999;
}
// 底部操作
.bottom-actions {
position: fixed;
bottom: 0;
left: 0;
right: 0;
background-color: #fff;
padding: 20rpx 30rpx;
border-top: 1px solid #eee;
display: flex;
gap: 20rpx;
}
.action-btn {
flex: 1;
height: 80rpx;
border-radius: 40rpx;
font-size: 28rpx;
border: none;
&.secondary {
background-color: #f0f0f0;
color: #666;
}
&.primary {
background-color: #007aff;
color: #fff;
}
}
// 权益码弹窗
.equity-popup-mask {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: rgba(0, 0, 0, 0.5);
z-index: 9999;
display: flex;
align-items: center;
justify-content: center;
}
.equity-popup {
width: 600rpx;
background-color: #fff;
border-radius: 20rpx;
overflow: hidden;
}
.popup-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 30rpx;
border-bottom: 1px solid #f0f0f0;
}
.popup-title {
font-size: 32rpx;
font-weight: bold;
color: #333;
}
.popup-close {
font-size: 40rpx;
color: #999;
}
.popup-content {
padding: 40rpx 30rpx;
text-align: center;
}
.qrcode-container {
margin-bottom: 40rpx;
}
.qrcode-image {
width: 300rpx;
height: 300rpx;
border: 1px solid #eee;
border-radius: 12rpx;
}
.code-container {
margin-bottom: 20rpx;
}
.code-label {
font-size: 28rpx;
color: #666;
margin-right: 10rpx;
}
.code-value {
font-size: 28rpx;
color: #333;
font-weight: bold;
background-color: #f8f9fa;
padding: 8rpx 16rpx;
border-radius: 8rpx;
}
.code-tip {
font-size: 24rpx;
color: #999;
}
</style>