294 lines
7.0 KiB
Vue
294 lines
7.0 KiB
Vue
<template>
|
|
<view class="logistics-container">
|
|
<common-header title="物流查询" theme="shipping" @back="goBack" />
|
|
|
|
<view class="logistics-content">
|
|
<view class="logistics-info">
|
|
<view class="info-card">
|
|
<view class="card-header">
|
|
<text class="order-no">{{ shippingData.orderNo }}</text>
|
|
<text class="customer">{{ shippingData.customerName }}</text>
|
|
</view>
|
|
|
|
<view class="card-body">
|
|
<view class="info-item">
|
|
<uni-icons type="location" size="16" color="#666" />
|
|
<text class="info-text">{{ shippingData.address }}</text>
|
|
</view>
|
|
|
|
<view class="info-item">
|
|
<uni-icons type="car" size="16" color="#666" />
|
|
<text class="info-text">{{ getLogisticsText(shippingData.logistics) }}</text>
|
|
</view>
|
|
|
|
<view class="info-item">
|
|
<uni-icons type="list" size="16" color="#666" />
|
|
<text class="info-text">{{ shippingData.trackingNo }}</text>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
|
|
<view class="logistics-status">
|
|
<view class="status-header">
|
|
<text class="status-title">物流状态</text>
|
|
<uni-button type="default" size="small" @click="refreshLogistics">刷新</uni-button>
|
|
</view>
|
|
|
|
<view class="status-content">
|
|
<view v-if="!loading && logisticsList.length === 0" class="empty-state">
|
|
<uni-icons type="car" size="60" color="#ddd" />
|
|
<text class="empty-text">暂无物流信息</text>
|
|
</view>
|
|
|
|
<view v-else class="logistics-timeline">
|
|
<view
|
|
v-for="(item, index) in logisticsList"
|
|
:key="index"
|
|
class="timeline-item"
|
|
:class="{ 'active': index === 0 }">
|
|
|
|
<view class="timeline-dot"></view>
|
|
<view class="timeline-content">
|
|
<text class="timeline-text">{{ item.description }}</text>
|
|
<text class="timeline-time">{{ formatTime(item.time) }}</text>
|
|
<text class="timeline-location">{{ item.location }}</text>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</template>
|
|
|
|
<script>
|
|
import CommonHeader from '@/components/common-header/common-header.vue'
|
|
|
|
export default {
|
|
name: 'ShippingLogistics',
|
|
components: {
|
|
CommonHeader
|
|
},
|
|
|
|
data() {
|
|
return {
|
|
shippingData: {},
|
|
logisticsList: [],
|
|
loading: false
|
|
}
|
|
},
|
|
|
|
onLoad(option) {
|
|
const { id } = option
|
|
if (id) {
|
|
this.getShippingDetail(id)
|
|
this.getLogisticsInfo(id)
|
|
}
|
|
},
|
|
|
|
methods: {
|
|
async getShippingDetail(id) {
|
|
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('获取发货详情失败')
|
|
}
|
|
},
|
|
|
|
async getLogisticsInfo(id) {
|
|
this.loading = true
|
|
try {
|
|
// TODO: Replace with actual API call
|
|
const response = await this.$http.get(`/brewery/shipping/${id}/logistics`)
|
|
this.logisticsList = response.data || []
|
|
} catch (error) {
|
|
console.error('获取物流信息失败:', error)
|
|
this.$modal.showToast('获取物流信息失败')
|
|
} finally {
|
|
this.loading = false
|
|
}
|
|
},
|
|
|
|
refreshLogistics() {
|
|
if (this.shippingData.id) {
|
|
this.getLogisticsInfo(this.shippingData.id)
|
|
}
|
|
},
|
|
|
|
getLogisticsText(logistics) {
|
|
const logisticsMap = {
|
|
sf: '顺丰快递',
|
|
ems: '中国邮政',
|
|
zt: '中通快递',
|
|
yd: '韵达快递',
|
|
sto: '申通快递',
|
|
other: '其他'
|
|
}
|
|
return logisticsMap[logistics] || '未知'
|
|
},
|
|
|
|
formatTime(time) {
|
|
if (!time) return ''
|
|
return time.substring(0, 16)
|
|
},
|
|
|
|
goBack() {
|
|
uni.navigateBack()
|
|
}
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<style lang="scss" scoped>
|
|
.logistics-container {
|
|
min-height: 100vh;
|
|
background: #f5f7fa;
|
|
}
|
|
|
|
.logistics-content {
|
|
padding: 20rpx;
|
|
}
|
|
|
|
.logistics-info {
|
|
margin-bottom: 20rpx;
|
|
|
|
.info-card {
|
|
background: #fff;
|
|
border-radius: 16rpx;
|
|
padding: 30rpx;
|
|
box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.08);
|
|
|
|
.card-header {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
margin-bottom: 20rpx;
|
|
padding-bottom: 16rpx;
|
|
border-bottom: 1px solid #f0f0f0;
|
|
|
|
.order-no {
|
|
font-size: 30rpx;
|
|
font-weight: bold;
|
|
color: #333;
|
|
}
|
|
|
|
.customer {
|
|
font-size: 26rpx;
|
|
color: #666;
|
|
}
|
|
}
|
|
|
|
.card-body {
|
|
.info-item {
|
|
display: flex;
|
|
align-items: center;
|
|
margin-bottom: 12rpx;
|
|
|
|
.info-text {
|
|
font-size: 26rpx;
|
|
color: #333;
|
|
margin-left: 12rpx;
|
|
flex: 1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
.logistics-status {
|
|
background: #fff;
|
|
border-radius: 16rpx;
|
|
padding: 30rpx;
|
|
box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.08);
|
|
|
|
.status-header {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
margin-bottom: 20rpx;
|
|
padding-bottom: 16rpx;
|
|
border-bottom: 1px solid #f0f0f0;
|
|
|
|
.status-title {
|
|
font-size: 30rpx;
|
|
font-weight: bold;
|
|
color: #333;
|
|
}
|
|
}
|
|
|
|
.status-content {
|
|
.empty-state {
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
justify-content: center;
|
|
padding: 80rpx 0;
|
|
|
|
.empty-text {
|
|
font-size: 26rpx;
|
|
color: #999;
|
|
margin-top: 16rpx;
|
|
}
|
|
}
|
|
|
|
.logistics-timeline {
|
|
.timeline-item {
|
|
position: relative;
|
|
padding-left: 40rpx;
|
|
padding-bottom: 30rpx;
|
|
|
|
&:not(:last-child)::before {
|
|
content: '';
|
|
position: absolute;
|
|
left: 10rpx;
|
|
top: 24rpx;
|
|
width: 2rpx;
|
|
height: calc(100% - 20rpx);
|
|
background: #e5e5e5;
|
|
}
|
|
|
|
.timeline-dot {
|
|
position: absolute;
|
|
left: 0;
|
|
top: 8rpx;
|
|
width: 20rpx;
|
|
height: 20rpx;
|
|
border-radius: 50%;
|
|
background: #e5e5e5;
|
|
border: 2rpx solid #fff;
|
|
}
|
|
|
|
&.active .timeline-dot {
|
|
background: #7b68ee;
|
|
}
|
|
|
|
.timeline-content {
|
|
.timeline-text {
|
|
display: block;
|
|
font-size: 28rpx;
|
|
color: #333;
|
|
line-height: 1.5;
|
|
margin-bottom: 8rpx;
|
|
}
|
|
|
|
.timeline-time {
|
|
display: block;
|
|
font-size: 24rpx;
|
|
color: #666;
|
|
margin-bottom: 4rpx;
|
|
}
|
|
|
|
.timeline-location {
|
|
font-size: 22rpx;
|
|
color: #999;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
</style> |