301 lines
7.7 KiB
Vue
301 lines
7.7 KiB
Vue
<template>
|
|
<view class="detail-container">
|
|
<common-header title="发货详情" theme="shipping" @back="goBack" />
|
|
|
|
<view class="detail-content">
|
|
<view class="detail-card">
|
|
<view class="detail-header">
|
|
<text class="detail-title">{{ shippingData.orderNo || '订单号' }}</text>
|
|
<view class="status-badge" :class="{
|
|
'pending': shippingData.status === 0,
|
|
'shipped': shippingData.status === 1,
|
|
'delivered': shippingData.status === 2,
|
|
'cancelled': shippingData.status === 3
|
|
}">
|
|
{{ getStatusText(shippingData.status) }}
|
|
</view>
|
|
</view>
|
|
|
|
<view class="detail-body">
|
|
<view class="detail-section">
|
|
<text class="section-title">订单信息</text>
|
|
<view class="detail-item">
|
|
<text class="item-label">关联订单</text>
|
|
<text class="item-value">{{ shippingData.orderNo || '暂无' }}</text>
|
|
</view>
|
|
<view class="detail-item">
|
|
<text class="item-label">客户名称</text>
|
|
<text class="item-value">{{ shippingData.customerName || '暂无' }}</text>
|
|
</view>
|
|
<view class="detail-item">
|
|
<text class="item-label">收货地址</text>
|
|
<text class="item-value">{{ shippingData.address || '暂无' }}</text>
|
|
</view>
|
|
</view>
|
|
|
|
<view class="detail-section">
|
|
<text class="section-title">物流信息</text>
|
|
<view class="detail-item">
|
|
<text class="item-label">物流公司</text>
|
|
<text class="item-value">{{ getLogisticsText(shippingData.logistics) }}</text>
|
|
</view>
|
|
<view class="detail-item">
|
|
<text class="item-label">物流单号</text>
|
|
<text class="item-value">{{ shippingData.trackingNo || '暂无' }}</text>
|
|
</view>
|
|
<view class="detail-item">
|
|
<text class="item-label">发货时间</text>
|
|
<text class="item-value">{{ formatTime(shippingData.shipTime) }}</text>
|
|
</view>
|
|
</view>
|
|
|
|
<view class="detail-section">
|
|
<text class="section-title">其他信息</text>
|
|
<view class="detail-item">
|
|
<text class="item-label">发货备注</text>
|
|
<text class="item-value">{{ shippingData.remark || '暂无备注' }}</text>
|
|
</view>
|
|
<view class="detail-item">
|
|
<text class="item-label">创建时间</text>
|
|
<text class="item-value">{{ formatTime(shippingData.createTime) }}</text>
|
|
</view>
|
|
<view class="detail-item">
|
|
<text class="item-label">更新时间</text>
|
|
<text class="item-value">{{ formatTime(shippingData.updateTime) }}</text>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
|
|
<view class="detail-actions">
|
|
<uni-button type="default" size="small" @click="editShipping">编辑</uni-button>
|
|
<uni-button type="primary" size="small" @click="shipOrder" v-if="shippingData.status === 0">发货</uni-button>
|
|
<uni-button type="primary" size="small" @click="viewLogistics" v-if="shippingData.status > 0">物流查询</uni-button>
|
|
<uni-button type="warn" size="small" @click="cancelShipping" v-if="shippingData.status < 2">取消</uni-button>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</template>
|
|
|
|
<script>
|
|
import CommonHeader from '@/components/common-header/common-header.vue'
|
|
|
|
export default {
|
|
name: 'ShippingDetail',
|
|
components: {
|
|
CommonHeader
|
|
},
|
|
|
|
data() {
|
|
return {
|
|
shippingData: {},
|
|
loading: false
|
|
}
|
|
},
|
|
|
|
onLoad(option) {
|
|
const { id } = option
|
|
if (id) {
|
|
this.getShippingDetail(id)
|
|
}
|
|
},
|
|
|
|
methods: {
|
|
async getShippingDetail(id) {
|
|
this.loading = true
|
|
try {
|
|
// TODO: Replace with actual API call
|
|
const response = await this.$http.get(`/brewery/shipping/${id}`)
|
|
this.shippingData = response.data || {}
|
|
} catch (error) {
|
|
console.error('获取发货详情失败:', error)
|
|
this.$modal.showToast('获取发货详情失败')
|
|
} finally {
|
|
this.loading = false
|
|
}
|
|
},
|
|
|
|
getStatusText(status) {
|
|
const statusMap = {
|
|
0: '待发货',
|
|
1: '已发货',
|
|
2: '已送达',
|
|
3: '已取消'
|
|
}
|
|
return statusMap[status] || '未知'
|
|
},
|
|
|
|
getLogisticsText(logistics) {
|
|
const logisticsMap = {
|
|
sf: '顺丰快递',
|
|
ems: '中国邮政',
|
|
zt: '中通快递',
|
|
yd: '韵达快递',
|
|
sto: '申通快递',
|
|
other: '其他'
|
|
}
|
|
return logisticsMap[logistics] || '未知'
|
|
},
|
|
|
|
formatTime(time) {
|
|
if (!time) return ''
|
|
return time.substring(0, 16)
|
|
},
|
|
|
|
editShipping() {
|
|
uni.navigateTo({
|
|
url: `/subpages/shipping/edit?id=${this.shippingData.id}`
|
|
})
|
|
},
|
|
|
|
shipOrder() {
|
|
uni.showModal({
|
|
title: '确认发货',
|
|
content: '确定要发货此订单吗?',
|
|
success: (res) => {
|
|
if (res.confirm) {
|
|
this.updateShippingStatus(1)
|
|
}
|
|
}
|
|
})
|
|
},
|
|
|
|
viewLogistics() {
|
|
uni.navigateTo({
|
|
url: `/subpages/shipping/logistics?id=${this.shippingData.id}`
|
|
})
|
|
},
|
|
|
|
cancelShipping() {
|
|
uni.showModal({
|
|
title: '确认取消',
|
|
content: '确定要取消此发货记录吗?',
|
|
success: (res) => {
|
|
if (res.confirm) {
|
|
this.updateShippingStatus(3)
|
|
}
|
|
}
|
|
})
|
|
},
|
|
|
|
async updateShippingStatus(status) {
|
|
try {
|
|
// TODO: Replace with actual API call
|
|
await this.$http.put(`/brewery/shipping/${this.shippingData.id}/status`, { status })
|
|
this.$modal.showToast('操作成功')
|
|
this.shippingData.status = status
|
|
} catch (error) {
|
|
console.error('操作失败:', error)
|
|
this.$modal.showToast('操作失败')
|
|
}
|
|
},
|
|
|
|
goBack() {
|
|
uni.navigateBack()
|
|
}
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<style lang="scss" scoped>
|
|
.detail-container {
|
|
min-height: 100vh;
|
|
background: #f5f7fa;
|
|
}
|
|
|
|
.detail-content {
|
|
padding: 20rpx;
|
|
}
|
|
|
|
.detail-card {
|
|
background: #fff;
|
|
border-radius: 16rpx;
|
|
padding: 30rpx;
|
|
margin-bottom: 20rpx;
|
|
box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.08);
|
|
}
|
|
|
|
.detail-header {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: flex-start;
|
|
margin-bottom: 30rpx;
|
|
padding-bottom: 20rpx;
|
|
border-bottom: 1px solid #f0f0f0;
|
|
}
|
|
|
|
.detail-title {
|
|
font-size: 32rpx;
|
|
font-weight: bold;
|
|
color: #333;
|
|
flex: 1;
|
|
}
|
|
|
|
.status-badge {
|
|
padding: 8rpx 16rpx;
|
|
border-radius: 20rpx;
|
|
font-size: 24rpx;
|
|
|
|
&.pending {
|
|
background: #fff2e8;
|
|
color: #fa8c16;
|
|
}
|
|
|
|
&.shipped {
|
|
background: #e6f7ff;
|
|
color: #1890ff;
|
|
}
|
|
|
|
&.delivered {
|
|
background: #e8f5e8;
|
|
color: #52c41a;
|
|
}
|
|
|
|
&.cancelled {
|
|
background: #ffebee;
|
|
color: #f44336;
|
|
}
|
|
}
|
|
|
|
.detail-body {
|
|
.detail-section {
|
|
margin-bottom: 30rpx;
|
|
|
|
.section-title {
|
|
display: block;
|
|
font-size: 28rpx;
|
|
font-weight: bold;
|
|
color: #333;
|
|
margin-bottom: 20rpx;
|
|
padding-bottom: 12rpx;
|
|
border-bottom: 2rpx solid #f0f0f0;
|
|
}
|
|
|
|
.detail-item {
|
|
display: flex;
|
|
margin-bottom: 16rpx;
|
|
|
|
.item-label {
|
|
flex: 0 0 160rpx;
|
|
font-size: 26rpx;
|
|
color: #666;
|
|
}
|
|
|
|
.item-value {
|
|
flex: 1;
|
|
font-size: 26rpx;
|
|
color: #333;
|
|
line-height: 1.5;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
.detail-actions {
|
|
display: flex;
|
|
gap: 20rpx;
|
|
margin-top: 30rpx;
|
|
padding-top: 20rpx;
|
|
border-top: 1px solid #f0f0f0;
|
|
}
|
|
</style> |