385 lines
8.2 KiB
Vue
385 lines
8.2 KiB
Vue
|
|
<script setup lang="ts">
|
||
|
|
import { ref, computed } from 'vue'
|
||
|
|
import { onLoad } from '@dcloudio/uni-app'
|
||
|
|
import { Order, useOrderStore } from '@/pinia/stores/order'
|
||
|
|
import { useWxStore } from '@/pinia/stores/wx'
|
||
|
|
import { useAb98UserStore } from '@/pinia/stores/ab98-user'
|
||
|
|
import { openCabinetApi } from '@/api/shop'
|
||
|
|
|
||
|
|
definePage({
|
||
|
|
style: {
|
||
|
|
navigationBarTitleText: '订单详情',
|
||
|
|
},
|
||
|
|
enablePullDownRefresh: true,
|
||
|
|
})
|
||
|
|
|
||
|
|
const orderStore = useOrderStore()
|
||
|
|
const wxStore = useWxStore()
|
||
|
|
const ab98UserStore = useAb98UserStore()
|
||
|
|
|
||
|
|
const { corpidLogin, userid: qyUserid, name: qyName } = wxStore
|
||
|
|
const { tel, userid: ab98Userid, name } = ab98UserStore
|
||
|
|
|
||
|
|
const orderId = ref<number>(0)
|
||
|
|
const isButtonDisabled = ref<Record<number, boolean>>({})
|
||
|
|
|
||
|
|
const statusMap: Record<number, string> = {
|
||
|
|
1: '待付款',
|
||
|
|
2: '已付款',
|
||
|
|
3: '已发货',
|
||
|
|
4: '已完成',
|
||
|
|
5: '已取消'
|
||
|
|
}
|
||
|
|
|
||
|
|
const getStatusText = (status: number) => {
|
||
|
|
return statusMap[status] || '未知状态'
|
||
|
|
}
|
||
|
|
|
||
|
|
const order = computed(() => {
|
||
|
|
return orderStore.orders.find(o => o.orderId === orderId.value)
|
||
|
|
})
|
||
|
|
|
||
|
|
const orderGoodsStatusMap: Record<number, string> = {
|
||
|
|
5: '审核中',
|
||
|
|
2: '已退货',
|
||
|
|
6: '退货未通过'
|
||
|
|
}
|
||
|
|
|
||
|
|
const getOrderGoodsStatusText = (status: number) => {
|
||
|
|
return orderGoodsStatusMap[status] || ''
|
||
|
|
}
|
||
|
|
|
||
|
|
const handleRefund = (item: any) => {
|
||
|
|
uni.navigateTo({
|
||
|
|
url: `/pages/approval/submit?orderGoodsId=${item.orderGoods.orderGoodsId}&orderId=${orderId.value}`
|
||
|
|
})
|
||
|
|
}
|
||
|
|
|
||
|
|
// 打开柜子
|
||
|
|
async function handleOpenCabinet(item: any) {
|
||
|
|
const orderGoodsId = item.orderGoods.orderGoodsId
|
||
|
|
isButtonDisabled.value[orderGoodsId] = true
|
||
|
|
try {
|
||
|
|
const isInternal = corpidLogin ? 2 : ab98Userid ? 1 : 0
|
||
|
|
const result = await openCabinetApi(orderId.value, orderGoodsId, {
|
||
|
|
userid: isInternal === 2 ? qyUserid : ab98Userid,
|
||
|
|
isInternal: isInternal,
|
||
|
|
name: isInternal === 2 ? qyName : name,
|
||
|
|
mobile: tel,
|
||
|
|
operationType: 1
|
||
|
|
})
|
||
|
|
if (result.code !== 0) {
|
||
|
|
uni.showToast({
|
||
|
|
title: result.msg || '开启失败,请稍后重试',
|
||
|
|
icon: 'none'
|
||
|
|
})
|
||
|
|
return
|
||
|
|
}
|
||
|
|
uni.showToast({
|
||
|
|
title: '柜口已成功开启',
|
||
|
|
icon: 'success'
|
||
|
|
})
|
||
|
|
} catch (error) {
|
||
|
|
uni.showToast({
|
||
|
|
title: '开启失败,请稍后重试',
|
||
|
|
icon: 'none'
|
||
|
|
})
|
||
|
|
} finally {
|
||
|
|
setTimeout((currentId: number) => {
|
||
|
|
delete isButtonDisabled.value[currentId]
|
||
|
|
}, 10000, orderGoodsId)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// 下拉刷新
|
||
|
|
const onPullDownRefresh = () => {
|
||
|
|
orderStore.getOrders(wxStore.corpid, wxStore.openid, wxStore.qyUserId, 0).then(() => {
|
||
|
|
uni.stopPullDownRefresh()
|
||
|
|
})
|
||
|
|
}
|
||
|
|
|
||
|
|
// 返回上一页
|
||
|
|
const goBack = () => {
|
||
|
|
uni.navigateBack()
|
||
|
|
}
|
||
|
|
|
||
|
|
onLoad((options: any) => {
|
||
|
|
orderId.value = Number(options.id)
|
||
|
|
if (!order.value) {
|
||
|
|
// 订单不存在处理
|
||
|
|
}
|
||
|
|
})
|
||
|
|
</script>
|
||
|
|
|
||
|
|
<template>
|
||
|
|
<view class="order-detail" v-if="order">
|
||
|
|
<view class="order-info">
|
||
|
|
<view class="info-item">
|
||
|
|
<text class="label">订单号:</text>
|
||
|
|
<text class="value">{{ order.orderId }}</text>
|
||
|
|
</view>
|
||
|
|
<view class="info-item">
|
||
|
|
<text class="label">状态:</text>
|
||
|
|
<text class="value status">{{ getStatusText(order.status) }}</text>
|
||
|
|
</view>
|
||
|
|
<view class="info-item">
|
||
|
|
<text class="label">总价:</text>
|
||
|
|
<text class="value price">¥{{ order.totalAmount }}</text>
|
||
|
|
</view>
|
||
|
|
<view class="info-item" v-if="order.payTime">
|
||
|
|
<text class="label">支付时间:</text>
|
||
|
|
<text class="value">{{ order.payTime }}</text>
|
||
|
|
</view>
|
||
|
|
</view>
|
||
|
|
|
||
|
|
<view class="goods-list">
|
||
|
|
<view
|
||
|
|
v-for="(item, index) in order.goodsList"
|
||
|
|
:key="index"
|
||
|
|
class="goods-item"
|
||
|
|
>
|
||
|
|
<image
|
||
|
|
:src="item.goodsInfo.coverImg"
|
||
|
|
mode="aspectFill"
|
||
|
|
class="product-image"
|
||
|
|
/>
|
||
|
|
<view class="product-info">
|
||
|
|
<view class="product-name-price">
|
||
|
|
<text class="product-name text-ellipsis">
|
||
|
|
{{ item.goodsInfo.goodsName }}
|
||
|
|
</text>
|
||
|
|
<text class="product-price">¥{{ item.orderGoods.price.toFixed(2) }}</text>
|
||
|
|
</view>
|
||
|
|
<view class="action-row">
|
||
|
|
<text class="quantity">数量: {{ item.orderGoods.quantity }}</text>
|
||
|
|
<text class="subtotal">小计: ¥{{ (item.orderGoods.price * item.orderGoods.quantity).toFixed(2) }}</text>
|
||
|
|
<view class="button-group">
|
||
|
|
<button
|
||
|
|
v-if="[1, 5].includes(item.orderGoods.status) && [2, 3].includes(order.payStatus)"
|
||
|
|
class="btn btn-primary"
|
||
|
|
size="mini"
|
||
|
|
@tap="handleOpenCabinet(item)"
|
||
|
|
:disabled="isButtonDisabled[item.orderGoods.orderGoodsId]"
|
||
|
|
>
|
||
|
|
{{ isButtonDisabled[item.orderGoods.orderGoodsId] ? '处理中...' : '打开柜子' }}
|
||
|
|
</button>
|
||
|
|
<button
|
||
|
|
v-if="item.orderGoods.status === 1 && [2, 3].includes(order.payStatus)"
|
||
|
|
class="btn btn-outline"
|
||
|
|
size="mini"
|
||
|
|
@tap="handleRefund(item)"
|
||
|
|
>
|
||
|
|
退还商品
|
||
|
|
</button>
|
||
|
|
</view>
|
||
|
|
</view>
|
||
|
|
<text
|
||
|
|
v-if="[2, 5, 6].includes(item.orderGoods.status)"
|
||
|
|
class="status-text"
|
||
|
|
:class="`status-${item.orderGoods.status}`"
|
||
|
|
>
|
||
|
|
{{ getOrderGoodsStatusText(item.orderGoods.status) }}
|
||
|
|
</text>
|
||
|
|
</view>
|
||
|
|
</view>
|
||
|
|
</view>
|
||
|
|
</view>
|
||
|
|
|
||
|
|
<view v-else class="not-found">
|
||
|
|
<view class="empty-icon">🔍</view>
|
||
|
|
<view class="empty-text">订单不存在或已失效</view>
|
||
|
|
<button class="btn btn-primary" @tap="goBack">返回</button>
|
||
|
|
</view>
|
||
|
|
</template>
|
||
|
|
|
||
|
|
<style scoped>
|
||
|
|
.order-detail {
|
||
|
|
padding: 20rpx;
|
||
|
|
}
|
||
|
|
|
||
|
|
.order-info {
|
||
|
|
padding: 30rpx;
|
||
|
|
margin-bottom: 20rpx;
|
||
|
|
background: #fff;
|
||
|
|
border-radius: 16rpx;
|
||
|
|
}
|
||
|
|
|
||
|
|
.info-item {
|
||
|
|
display: flex;
|
||
|
|
justify-content: space-between;
|
||
|
|
padding: 16rpx 0;
|
||
|
|
border-bottom: 1rpx solid #f5f5f5;
|
||
|
|
}
|
||
|
|
|
||
|
|
.info-item:last-child {
|
||
|
|
border-bottom: none;
|
||
|
|
}
|
||
|
|
|
||
|
|
.label {
|
||
|
|
font-size: 28rpx;
|
||
|
|
color: #666;
|
||
|
|
}
|
||
|
|
|
||
|
|
.value {
|
||
|
|
font-size: 28rpx;
|
||
|
|
color: #333;
|
||
|
|
}
|
||
|
|
|
||
|
|
.value.status {
|
||
|
|
color: #1989fa;
|
||
|
|
font-weight: 500;
|
||
|
|
}
|
||
|
|
|
||
|
|
.value.price {
|
||
|
|
color: #e95d5d;
|
||
|
|
font-weight: 500;
|
||
|
|
}
|
||
|
|
|
||
|
|
.goods-list {
|
||
|
|
padding: 20rpx;
|
||
|
|
background: #fff;
|
||
|
|
border-radius: 16rpx;
|
||
|
|
}
|
||
|
|
|
||
|
|
.goods-item {
|
||
|
|
display: flex;
|
||
|
|
padding: 24rpx 0;
|
||
|
|
border-bottom: 1rpx solid #f5f5f5;
|
||
|
|
align-items: flex-start;
|
||
|
|
}
|
||
|
|
|
||
|
|
.goods-item:last-child {
|
||
|
|
border-bottom: none;
|
||
|
|
}
|
||
|
|
|
||
|
|
.product-image {
|
||
|
|
width: 160rpx;
|
||
|
|
height: 160rpx;
|
||
|
|
border-radius: 12rpx;
|
||
|
|
margin-right: 24rpx;
|
||
|
|
flex-shrink: 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
.product-info {
|
||
|
|
flex: 1;
|
||
|
|
display: flex;
|
||
|
|
flex-direction: column;
|
||
|
|
}
|
||
|
|
|
||
|
|
.product-name-price {
|
||
|
|
display: flex;
|
||
|
|
justify-content: space-between;
|
||
|
|
align-items: center;
|
||
|
|
margin-bottom: 12rpx;
|
||
|
|
}
|
||
|
|
|
||
|
|
.product-name {
|
||
|
|
flex: 1;
|
||
|
|
margin-right: 20rpx;
|
||
|
|
font-size: 28rpx;
|
||
|
|
color: #333;
|
||
|
|
line-height: 1.4;
|
||
|
|
}
|
||
|
|
|
||
|
|
.text-ellipsis {
|
||
|
|
overflow: hidden;
|
||
|
|
text-overflow: ellipsis;
|
||
|
|
white-space: nowrap;
|
||
|
|
}
|
||
|
|
|
||
|
|
.product-price {
|
||
|
|
color: #e95d5d;
|
||
|
|
font-weight: 500;
|
||
|
|
font-size: 28rpx;
|
||
|
|
flex-shrink: 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
.action-row {
|
||
|
|
display: flex;
|
||
|
|
flex-direction: column;
|
||
|
|
align-items: flex-end;
|
||
|
|
gap: 12rpx;
|
||
|
|
margin-top: auto;
|
||
|
|
}
|
||
|
|
|
||
|
|
.quantity, .subtotal {
|
||
|
|
font-size: 24rpx;
|
||
|
|
color: #666;
|
||
|
|
}
|
||
|
|
|
||
|
|
.subtotal {
|
||
|
|
color: #333;
|
||
|
|
font-weight: 500;
|
||
|
|
}
|
||
|
|
|
||
|
|
.button-group {
|
||
|
|
display: flex;
|
||
|
|
gap: 16rpx;
|
||
|
|
width: 100%;
|
||
|
|
justify-content: flex-end;
|
||
|
|
}
|
||
|
|
|
||
|
|
.btn {
|
||
|
|
padding: 0 24rpx;
|
||
|
|
height: 56rpx;
|
||
|
|
line-height: 56rpx;
|
||
|
|
border-radius: 28rpx;
|
||
|
|
font-size: 24rpx;
|
||
|
|
}
|
||
|
|
|
||
|
|
.btn-primary {
|
||
|
|
background-color: #e95d5d;
|
||
|
|
color: #fff;
|
||
|
|
border: none;
|
||
|
|
}
|
||
|
|
|
||
|
|
.btn-outline {
|
||
|
|
background-color: #fff;
|
||
|
|
color: #e95d5d;
|
||
|
|
border: 1rpx solid #e95d5d;
|
||
|
|
}
|
||
|
|
|
||
|
|
.status-text {
|
||
|
|
display: inline-block;
|
||
|
|
margin-top: 12rpx;
|
||
|
|
padding: 8rpx 16rpx;
|
||
|
|
border-radius: 20rpx;
|
||
|
|
font-size: 22rpx;
|
||
|
|
}
|
||
|
|
|
||
|
|
.status-text.status-2 {
|
||
|
|
background-color: #e6f7ff;
|
||
|
|
color: #1890ff;
|
||
|
|
}
|
||
|
|
|
||
|
|
.status-text.status-5 {
|
||
|
|
background-color: #fff7e6;
|
||
|
|
color: #fa8c16;
|
||
|
|
}
|
||
|
|
|
||
|
|
.status-text.status-6 {
|
||
|
|
background-color: #fff1f0;
|
||
|
|
color: #f5222d;
|
||
|
|
}
|
||
|
|
|
||
|
|
.not-found {
|
||
|
|
display: flex;
|
||
|
|
flex-direction: column;
|
||
|
|
align-items: center;
|
||
|
|
justify-content: center;
|
||
|
|
padding: 160rpx 40rpx;
|
||
|
|
text-align: center;
|
||
|
|
}
|
||
|
|
|
||
|
|
.empty-icon {
|
||
|
|
font-size: 80rpx;
|
||
|
|
margin-bottom: 20rpx;
|
||
|
|
}
|
||
|
|
|
||
|
|
.empty-text {
|
||
|
|
font-size: 28rpx;
|
||
|
|
color: #999;
|
||
|
|
margin-bottom: 40rpx;
|
||
|
|
}
|
||
|
|
</style>
|