统一状态码,优化对应逻辑

This commit is contained in:
not-like-juvenile
2026-02-09 16:53:20 +08:00
parent 3ea0f008b5
commit f46ec4c461
19 changed files with 591 additions and 236 deletions

View File

@@ -28,14 +28,14 @@
<text class="label">收件人:</text>
<text class="value">{{ order.receiver_name }} {{ order.receiver_masked_phone }}</text>
</view>
<view v-if="order.tracking_no" class="info-row">
<view class="info-row">
<text class="label">运单号:</text>
<text class="value">{{ order.tracking_no }} ({{ order.carrier }})</text>
<text class="value">{{ order.tracking_no ? order.tracking_no + ' (' + order.carrier + ')' : '暂无运单号' }}</text>
</view>
</view>
<view class="order-footer">
<button v-if="order.status === 'PENDING'" class="btn-primary" @click="openShipModal(order)">去发货</button>
<button v-if="order.status === 'PENDING' || order.status === 'ORDER_PLACED'" class="btn-primary" @click="openShipModal(order)">去发货</button>
<button class="btn-secondary" @click="viewDetail(order)">详情</button>
</view>
</view>
@@ -49,7 +49,10 @@
<view v-if="showShipModal" class="modal-mask">
<view class="modal-content">
<view class="modal-header">
<text class="modal-title">订单发货</text>
<view class="title-box">
<text class="modal-title">订单发货</text>
<text v-if="selectedOrder != null" class="modal-order-no">单号: {{ selectedOrder!.order_no }}</text>
</view>
<text class="close-btn" @click="showShipModal = false">×</text>
</view>
<view class="modal-body">
@@ -61,7 +64,12 @@
</view>
<view class="form-item">
<text class="label">运单号</text>
<input v-model="trackingNo" placeholder="请输入或扫码录入" class="input" />
<view class="input-wrapper">
<input v-model="trackingNo" placeholder="请输入或扫码录入" class="input" />
<view class="scan-btn" @click="scanCode">
<text class="scan-icon">📷</text>
</view>
</view>
</view>
</view>
<view class="modal-footer">
@@ -75,7 +83,7 @@
<script uts>
import supa from '@/components/supadb/aksupainstance.uts'
import { mockService, MockOrder } from './mock-service.uts'
import { mockService, MockOrder, LogisticsConstants } from './mock-service.uts'
export default {
data() {
@@ -84,14 +92,8 @@
orders: [] as MockOrder[],
showShipModal: false,
selectedOrder: null as MockOrder | null,
carriers: [
{ label: '韵达快递', value: '韵达快递' },
{ label: '圆通速递', value: '圆通速递' },
{ label: '中通快递', value: '中通快递' },
{ label: '申通快递', value: '申通快递' },
{ label: '顺丰速运', value: '顺丰速运' }
],
currentCarrier: '韵达快递',
carriers: LogisticsConstants.CARRIERS,
currentCarrier: '顺丰速运',
trackingNo: ''
}
},
@@ -102,12 +104,18 @@
filteredOrders() : MockOrder[] {
const list = this.orders
if (this.currentFilter === 'all') return list
// 待发货:包含已下单和待发货状态
if (this.currentFilter === 'pending') {
return list.filter((o : MockOrder) : boolean => o.status === 'PENDING')
return list.filter((o : MockOrder) : boolean =>
o.status === 'PENDING' || o.status === 'ORDER_PLACED'
)
}
// 已发货:只要已经有了运单号或状态已转为发货后的
if (this.currentFilter === 'shipped') {
// 除了待发货,其余所有状态(运输中、派送中、已签收、异常)都属于“已发货”范畴
return list.filter((o : MockOrder) : boolean => o.status !== 'PENDING')
const shippedStates = ['SHIPPED', 'IN_TRANSIT', 'OUT_FOR_DELIVERY', 'READY_FOR_PICKUP', 'DELIVERED', 'EXCEPTION', 'RETURNED']
return list.filter((o : MockOrder) : boolean => shippedStates.includes(o.status))
}
return []
}
@@ -124,25 +132,17 @@
this.currentFilter = filter
},
getStatusText(status: string) : string {
const maps = {
'PENDING': '待发货',
'SHIPPED': '已发货',
'IN_TRANSIT': '运输中',
'DELIVERED': '已签收',
'OUT_FOR_DELIVERY': '派送中',
'EXCEPTION': '包裹异常'
}
return (maps[status] != null) ? maps[status] : status
return mockService.getStatusText(status)
},
openShipModal(order: MockOrder) {
this.selectedOrder = order
this.currentCarrier = '韵达快递'
this.currentCarrier = '顺丰速运'
this.trackingNo = ''
this.showShipModal = true
},
onCarrierChange(e: any) {
const index = e.detail.value as number
this.currentCarrier = this.carriers[index].value
this.currentCarrier = this.carriers[index]['value'] as string
},
async confirmShip() {
if (!this.trackingNo) {
@@ -152,14 +152,12 @@
uni.showLoading({ title: '提交中...' })
// 调用 Mock 入库接口,实现同步修改
setTimeout(() => {
uni.hideLoading()
const orderNo = this.selectedOrder?.order_no
if (orderNo != null) {
// 1. 同步修改 Mock Service 中的原始数据
mockService.bindShipment(orderNo, this.currentCarrier, this.trackingNo)
const orderNo = this.selectedOrder?.order_no
if (orderNo != null) {
// 1. 同步修改 数据库 中的数据
const success = await mockService.bindShipment(orderNo, this.currentCarrier, this.trackingNo)
if (success) {
// 2. 直接修改本地选中的订单对象状态,确保 Vue 响应式立即触发
if (this.selectedOrder != null) {
const target = this.selectedOrder!
@@ -168,17 +166,35 @@
target.tracking_no = this.trackingNo
}
// 3. 重新加载数据(通过新引用触发 computed
this.loadData()
// 3. 重新加载数据(从数据库刷新
await this.loadData()
uni.hideLoading()
this.showShipModal = false
uni.showToast({ title: '发货成功' })
} else {
uni.hideLoading()
uni.showToast({ title: '发货失败,请重试', icon: 'none' })
}
this.showShipModal = false
uni.showToast({ title: '发货成功' })
}, 1000)
}
},
viewDetail(order: MockOrder) {
uni.navigateTo({
url: `/pages/mall/delivery/test/merchant-order-detail?order_no=${order.order_no}`
})
},
scanCode() {
uni.scanCode({
success: (res) => {
this.trackingNo = res.result
},
fail: (_) => {
uni.showToast({
title: '该功能尚未完成',
icon: 'none'
})
}
})
}
}
}
@@ -307,12 +323,29 @@
}
.modal-header {
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: flex-start;
margin-bottom: 30rpx;
}
.title-box {
display: flex;
flex-direction: column;
}
.modal-title {
font-size: 32rpx;
font-size: 36rpx;
font-weight: bold;
color: #333;
}
.modal-order-no {
font-size: 24rpx;
color: #999;
margin-top: 8rpx;
}
.close-btn {
font-size: 40rpx;
color: #ccc;
padding: 10rpx;
}
.form-item {
margin-bottom: 30rpx;
@@ -323,11 +356,33 @@
border-radius: 8rpx;
margin-top: 10rpx;
}
.input-wrapper {
position: relative;
display: flex;
flex-direction: row;
align-items: center;
margin-top: 10rpx;
}
.input {
flex: 1;
border: 1rpx solid #ddd;
padding: 16rpx;
padding-right: 80rpx;
border-radius: 8rpx;
margin-top: 10rpx;
}
.scan-btn {
position: absolute;
right: 0;
top: 0;
bottom: 0;
width: 80rpx;
display: flex;
justify-content: center;
align-items: center;
z-index: 10;
}
.scan-icon {
font-size: 36rpx;
}
.modal-footer {
display: flex;