2025-03-31 09:42:26 +08:00
|
|
|
<script setup lang="ts">
|
|
|
|
import { onMounted } from 'vue'
|
2025-04-15 16:54:40 +08:00
|
|
|
import { OrderGoods, useOrderStore } from '@/pinia/stores/order'
|
2025-04-07 15:50:12 +08:00
|
|
|
import { useRoute, useRouter } from 'vue-router'
|
2025-04-15 16:54:40 +08:00
|
|
|
import { openCabinetApi } from '@/common/apis/shop'
|
|
|
|
import { showSuccessToast, showFailToast } from 'vant'
|
|
|
|
import { ref } from 'vue'
|
2025-03-31 09:42:26 +08:00
|
|
|
|
|
|
|
const orderStore = useOrderStore()
|
|
|
|
const route = useRoute()
|
2025-04-07 15:50:12 +08:00
|
|
|
const router = useRouter()
|
2025-03-31 09:42:26 +08:00
|
|
|
|
|
|
|
const statusMap: Record<number, string> = {
|
|
|
|
1: '待付款',
|
|
|
|
2: '已付款',
|
|
|
|
3: '已发货',
|
|
|
|
4: '已完成',
|
|
|
|
5: '已取消'
|
|
|
|
}
|
|
|
|
|
|
|
|
const getStatusText = (status: number) => {
|
|
|
|
return statusMap[status] || '未知状态'
|
|
|
|
}
|
|
|
|
|
|
|
|
const orderId = ref(parseInt(String(route.params.id)))
|
|
|
|
|
|
|
|
// 监听路由参数变化
|
|
|
|
watch(() => route.params.id, (newId) => {
|
|
|
|
orderId.value = parseInt(String(newId))
|
|
|
|
})
|
|
|
|
|
|
|
|
const order = computed(() => {
|
|
|
|
return orderStore.orders.find(o => o.orderId === orderId.value)
|
|
|
|
})
|
|
|
|
|
2025-04-08 09:22:21 +08:00
|
|
|
const orderGoodsStatusMap: Record<number, string> = {
|
|
|
|
5: '审核中',
|
|
|
|
2: '已退货',
|
|
|
|
6: '退货未通过'
|
|
|
|
}
|
|
|
|
|
|
|
|
const getOrderGoodsStatusText = (status: number) => {
|
|
|
|
return orderGoodsStatusMap[status] || ''
|
|
|
|
}
|
|
|
|
|
2025-04-07 15:50:12 +08:00
|
|
|
const handleRefund = (item: any) => {
|
|
|
|
router.push({
|
|
|
|
path: '/approval/submit',
|
|
|
|
query: {
|
2025-04-08 09:22:21 +08:00
|
|
|
orderGoodsId: item.orderGoods.orderGoodsId,
|
|
|
|
orderId: orderId.value,
|
2025-04-07 15:50:12 +08:00
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2025-03-31 09:42:26 +08:00
|
|
|
onMounted(() => {
|
|
|
|
if (!order.value) {
|
2025-04-07 15:50:12 +08:00
|
|
|
// 订单不存在处理
|
2025-03-31 09:42:26 +08:00
|
|
|
}
|
|
|
|
})
|
2025-04-15 16:54:40 +08:00
|
|
|
|
|
|
|
const isButtonDisabled = ref<Record<number, boolean>>({})
|
|
|
|
|
|
|
|
async function handleOpenCabinet(item: OrderGoods) {
|
|
|
|
const orderGoodsId = item.orderGoods.orderGoodsId
|
|
|
|
isButtonDisabled.value[orderGoodsId] = true
|
|
|
|
try {
|
|
|
|
const result = await openCabinetApi(orderId.value, orderGoodsId)
|
|
|
|
if (result.code !== 0) {
|
|
|
|
showFailToast(result.msg || '开启失败,请稍后重试')
|
|
|
|
return
|
|
|
|
}
|
|
|
|
showSuccessToast('柜口已成功开启')
|
|
|
|
} catch (error) {
|
|
|
|
showFailToast('开启失败,请稍后重试')
|
|
|
|
} finally {
|
|
|
|
setTimeout((currentId) => {
|
|
|
|
delete isButtonDisabled.value[currentId]
|
|
|
|
}, 5000, orderGoodsId)
|
|
|
|
}
|
|
|
|
}
|
2025-03-31 09:42:26 +08:00
|
|
|
</script>
|
|
|
|
|
|
|
|
<template>
|
|
|
|
<div class="order-detail" v-if="order">
|
|
|
|
<h2>订单详情</h2>
|
|
|
|
|
|
|
|
<div class="order-info">
|
|
|
|
<p>订单号: {{ order.orderId }}</p>
|
|
|
|
<p>状态: {{ getStatusText(order.status) }}</p>
|
|
|
|
<p>总价: ¥{{ order.totalAmount }}</p>
|
|
|
|
<p>支付时间: {{ order.payTime }}</p>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<van-cell-group class="goods-list">
|
|
|
|
<van-cell
|
|
|
|
v-for="(item, index) in order.goodsList"
|
|
|
|
:key="index"
|
|
|
|
class="goods-item"
|
|
|
|
>
|
|
|
|
<template #icon>
|
|
|
|
<van-image
|
|
|
|
:src="item.goodsInfo.coverImg"
|
|
|
|
width="80"
|
|
|
|
height="80"
|
|
|
|
class="product-image"
|
|
|
|
/>
|
|
|
|
</template>
|
|
|
|
<div class="product-info">
|
2025-04-07 15:50:12 +08:00
|
|
|
<div class="product-name-price">
|
|
|
|
<div class="product-name van-ellipsis">
|
|
|
|
{{ item.goodsInfo.goodsName }}
|
|
|
|
</div>
|
|
|
|
<div class="product-price">
|
|
|
|
¥{{ item.orderGoods.price.toFixed(2) }}
|
|
|
|
</div>
|
2025-03-31 09:42:26 +08:00
|
|
|
</div>
|
|
|
|
<div class="action-row">
|
|
|
|
<p>数量: {{ item.orderGoods.quantity }}</p>
|
|
|
|
<p>小计: ¥{{ (item.orderGoods.price * item.orderGoods.quantity).toFixed(2) }}</p>
|
2025-04-15 16:54:40 +08:00
|
|
|
<div class="button-group">
|
|
|
|
<van-button
|
|
|
|
v-if="[1,5].includes(item.orderGoods.status)"
|
|
|
|
type="primary"
|
|
|
|
size="small"
|
|
|
|
@click="handleOpenCabinet(item)"
|
|
|
|
:disabled="isButtonDisabled[item.orderGoods.orderGoodsId]"
|
|
|
|
>
|
|
|
|
打开柜子
|
|
|
|
</van-button>
|
|
|
|
<van-button
|
|
|
|
v-if="item.orderGoods.status === 1"
|
|
|
|
type="primary"
|
|
|
|
size="small"
|
|
|
|
@click="handleRefund(item)"
|
|
|
|
>
|
|
|
|
退还商品
|
|
|
|
</van-button>
|
|
|
|
</div>
|
|
|
|
</div>
|
2025-04-08 09:22:21 +08:00
|
|
|
<span
|
|
|
|
v-if="[2,5,6].includes(item.orderGoods.status)"
|
|
|
|
class="status-text"
|
|
|
|
:class="`status-${item.orderGoods.status}`"
|
|
|
|
>
|
|
|
|
{{ getOrderGoodsStatusText(item.orderGoods.status) }}
|
|
|
|
</span>
|
2025-03-31 09:42:26 +08:00
|
|
|
</div>
|
|
|
|
</van-cell>
|
|
|
|
</van-cell-group>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<div v-else class="not-found">
|
|
|
|
订单不存在或已失效
|
|
|
|
</div>
|
|
|
|
</template>
|
|
|
|
|
|
|
|
<style scoped>
|
|
|
|
.order-detail {
|
|
|
|
padding: 20px;
|
|
|
|
}
|
|
|
|
|
|
|
|
.order-info {
|
|
|
|
padding: 15px;
|
|
|
|
margin-bottom: 20px;
|
|
|
|
background: #f5f5f5;
|
|
|
|
border-radius: 8px;
|
|
|
|
}
|
|
|
|
|
|
|
|
.goods-list {
|
|
|
|
padding: 15px;
|
|
|
|
background: #fff;
|
|
|
|
border-radius: 8px;
|
|
|
|
}
|
|
|
|
|
|
|
|
.goods-item {
|
|
|
|
display: flex;
|
|
|
|
padding: 15px 0;
|
|
|
|
border-bottom: 1px solid #f5f5f5;
|
|
|
|
}
|
|
|
|
|
|
|
|
goods-item:last-child {
|
|
|
|
border-bottom: none;
|
|
|
|
}
|
|
|
|
|
|
|
|
goods-item img {
|
|
|
|
width: 100px;
|
|
|
|
height: 100px;
|
|
|
|
object-fit: cover;
|
|
|
|
margin-right: 15px;
|
|
|
|
}
|
|
|
|
|
|
|
|
goods-info {
|
|
|
|
flex: 1;
|
|
|
|
}
|
|
|
|
|
2025-04-07 15:50:12 +08:00
|
|
|
.product-name-price {
|
|
|
|
display: flex;
|
|
|
|
justify-content: space-between;
|
|
|
|
align-items: center;
|
|
|
|
margin-bottom: 8px;
|
|
|
|
}
|
|
|
|
|
|
|
|
.product-name {
|
|
|
|
flex: 1;
|
|
|
|
margin-right: 10px;
|
|
|
|
}
|
|
|
|
|
|
|
|
.product-price {
|
|
|
|
color: #ee0a24;
|
|
|
|
font-weight: 500;
|
|
|
|
}
|
2025-03-31 09:42:26 +08:00
|
|
|
.not-found {
|
|
|
|
padding: 40px;
|
|
|
|
text-align: center;
|
|
|
|
color: #999;
|
|
|
|
}
|
2025-04-07 15:50:12 +08:00
|
|
|
|
2025-04-15 16:54:40 +08:00
|
|
|
.button-group {
|
|
|
|
display: flex;
|
|
|
|
justify-content: flex-end;
|
|
|
|
gap: 8px;
|
|
|
|
width: 100%;
|
2025-04-07 15:50:12 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
.action-row {
|
|
|
|
display: flex;
|
2025-04-08 09:22:21 +08:00
|
|
|
flex-direction: column;
|
|
|
|
align-items: flex-end;
|
2025-04-15 16:54:40 +08:00
|
|
|
gap: 4px;
|
2025-04-07 15:50:12 +08:00
|
|
|
}
|
2025-03-31 09:42:26 +08:00
|
|
|
</style>
|