|
|
@ -0,0 +1,288 @@ |
|
|
|
<template> |
|
|
|
<view class="logistics-page"> |
|
|
|
<!-- 顶部导航 --> |
|
|
|
<view class="nav-bar"> |
|
|
|
<view class="back" @tap="goBack"> |
|
|
|
<uni-icons type="left" size="20" color="#222" /> |
|
|
|
</view> |
|
|
|
<text class="nav-title">物流轨迹</text> |
|
|
|
</view> |
|
|
|
|
|
|
|
<!-- 物流信息卡片 --> |
|
|
|
<view class="logistics-card"> |
|
|
|
<view class="express-info"> |
|
|
|
<view class="express-company">{{ expressCompany }}</view> |
|
|
|
<view class="express-number">运单号:{{ wuliuNo }}</view> |
|
|
|
</view> |
|
|
|
</view> |
|
|
|
|
|
|
|
<!-- 物流轨迹列表 --> |
|
|
|
<view class="trace-list"> |
|
|
|
<view |
|
|
|
v-for="(item, index) in traceList" |
|
|
|
:key="index" |
|
|
|
class="trace-item" |
|
|
|
:class="{ 'active': index === 0 }" |
|
|
|
> |
|
|
|
<view class="trace-dot"> |
|
|
|
<view class="dot-inner"></view> |
|
|
|
</view> |
|
|
|
<view class="trace-line" v-if="index < traceList.length - 1"></view> |
|
|
|
<view class="trace-content"> |
|
|
|
<view class="trace-desc">{{ item.description }}</view> |
|
|
|
<view class="trace-time">{{ item.time }}</view> |
|
|
|
<view class="trace-location">{{ item.site }}</view> |
|
|
|
</view> |
|
|
|
</view> |
|
|
|
</view> |
|
|
|
|
|
|
|
<!-- 加载状态 --> |
|
|
|
<view v-if="loading" class="loading"> |
|
|
|
<uni-load-more status="loading" :content-text="loadingText"></uni-load-more> |
|
|
|
</view> |
|
|
|
|
|
|
|
<!-- 无数据状态 --> |
|
|
|
<view v-if="!loading && traceList.length === 0" class="empty-state"> |
|
|
|
<image src="/static/empty-logistics.png" class="empty-icon" mode="aspectFit"></image> |
|
|
|
<text class="empty-text">暂无物流信息</text> |
|
|
|
</view> |
|
|
|
</view> |
|
|
|
</template> |
|
|
|
|
|
|
|
<script> |
|
|
|
export default { |
|
|
|
data() { |
|
|
|
return { |
|
|
|
wuliuNo: '', |
|
|
|
expressCompany: '', |
|
|
|
traceList: [], |
|
|
|
loading: false, |
|
|
|
loadingText: { |
|
|
|
contentdown: '上拉显示更多', |
|
|
|
contentrefresh: '正在加载...', |
|
|
|
contentnomore: '没有更多数据了' |
|
|
|
} |
|
|
|
} |
|
|
|
}, |
|
|
|
onLoad(options) { |
|
|
|
if (options.wliuNo) { |
|
|
|
this.wuliuNo = options.wliuNo |
|
|
|
} |
|
|
|
if (options.expressCompany) { |
|
|
|
this.expressCompany = options.expressCompany |
|
|
|
} |
|
|
|
this.fetchLogisticsTrace() |
|
|
|
}, |
|
|
|
methods: { |
|
|
|
goBack() { |
|
|
|
uni.navigateBack() |
|
|
|
}, |
|
|
|
async fetchLogisticsTrace() { |
|
|
|
if (!this.wuliuNo) { |
|
|
|
uni.showToast({ title: '运单号不能为空', icon: 'none' }) |
|
|
|
return |
|
|
|
} |
|
|
|
|
|
|
|
this.loading = true |
|
|
|
|
|
|
|
try { |
|
|
|
this.$api('queryTrace', { |
|
|
|
wuliuNo: this.wuliuNo |
|
|
|
}, res => { |
|
|
|
this.loading = false |
|
|
|
|
|
|
|
if (res && res.code === 200 && res.result && res.result.responseParam) { |
|
|
|
const traceData = res.result.responseParam |
|
|
|
this.traceList = traceData.trace_list || [] |
|
|
|
|
|
|
|
if (this.traceList.length === 0) { |
|
|
|
uni.showToast({ title: '暂无物流信息', icon: 'none' }) |
|
|
|
} |
|
|
|
} else { |
|
|
|
uni.showToast({ title: res?.message || '获取物流信息失败', icon: 'none' }) |
|
|
|
} |
|
|
|
}) |
|
|
|
} catch (error) { |
|
|
|
this.loading = false |
|
|
|
uni.showToast({ title: '网络错误,请重试', icon: 'none' }) |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
</script> |
|
|
|
|
|
|
|
<style lang="scss" scoped> |
|
|
|
.logistics-page { |
|
|
|
min-height: 100vh; |
|
|
|
background: #f8f8f8; |
|
|
|
padding-bottom: 40rpx; |
|
|
|
} |
|
|
|
|
|
|
|
.nav-bar { |
|
|
|
display: flex; |
|
|
|
align-items: center; |
|
|
|
height: calc(150rpx + var(--status-bar-height)); |
|
|
|
padding: 0 32rpx; |
|
|
|
padding-top: var(--status-bar-height); |
|
|
|
background: #fff; |
|
|
|
position: fixed; |
|
|
|
top: 0; |
|
|
|
left: 0; |
|
|
|
right: 0; |
|
|
|
z-index: 999; |
|
|
|
box-sizing: border-box; |
|
|
|
box-shadow: 0 2rpx 8rpx rgba(0,0,0,0.03); |
|
|
|
|
|
|
|
.back { |
|
|
|
padding: 20rpx; |
|
|
|
margin-left: -20rpx; |
|
|
|
} |
|
|
|
|
|
|
|
.nav-title { |
|
|
|
flex: 1; |
|
|
|
text-align: center; |
|
|
|
font-size: 32rpx; |
|
|
|
font-weight: 500; |
|
|
|
color: #222; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
.logistics-card { |
|
|
|
margin: calc(150rpx + var(--status-bar-height) + 24rpx) 24rpx 24rpx 24rpx; |
|
|
|
background: #fff; |
|
|
|
border-radius: 24rpx; |
|
|
|
padding: 32rpx; |
|
|
|
box-shadow: 0 4rpx 16rpx rgba(0,0,0,0.04); |
|
|
|
|
|
|
|
.express-info { |
|
|
|
.express-company { |
|
|
|
font-size: 32rpx; |
|
|
|
font-weight: bold; |
|
|
|
color: #222; |
|
|
|
margin-bottom: 12rpx; |
|
|
|
} |
|
|
|
|
|
|
|
.express-number { |
|
|
|
font-size: 28rpx; |
|
|
|
color: #666; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
.trace-list { |
|
|
|
margin: 0 24rpx; |
|
|
|
background: #fff; |
|
|
|
border-radius: 24rpx; |
|
|
|
padding: 32rpx; |
|
|
|
box-shadow: 0 4rpx 16rpx rgba(0,0,0,0.04); |
|
|
|
position: relative; |
|
|
|
} |
|
|
|
|
|
|
|
.trace-item { |
|
|
|
display: flex; |
|
|
|
align-items: flex-start; |
|
|
|
position: relative; |
|
|
|
padding-bottom: 32rpx; |
|
|
|
|
|
|
|
&:last-child { |
|
|
|
padding-bottom: 0; |
|
|
|
} |
|
|
|
|
|
|
|
&.active { |
|
|
|
.trace-dot { |
|
|
|
background: #ff9c00; |
|
|
|
border-color: #ff9c00; |
|
|
|
} |
|
|
|
|
|
|
|
.trace-content { |
|
|
|
.trace-desc { |
|
|
|
color: #222; |
|
|
|
font-weight: bold; |
|
|
|
} |
|
|
|
|
|
|
|
.trace-time { |
|
|
|
color: #ff9c00; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
.trace-dot { |
|
|
|
width: 24rpx; |
|
|
|
height: 24rpx; |
|
|
|
border-radius: 50%; |
|
|
|
background: #ddd; |
|
|
|
border: 4rpx solid #f0f0f0; |
|
|
|
margin-right: 24rpx; |
|
|
|
margin-top: 8rpx; |
|
|
|
flex-shrink: 0; |
|
|
|
position: relative; |
|
|
|
z-index: 2; |
|
|
|
|
|
|
|
.dot-inner { |
|
|
|
width: 8rpx; |
|
|
|
height: 8rpx; |
|
|
|
border-radius: 50%; |
|
|
|
background: #fff; |
|
|
|
position: absolute; |
|
|
|
top: 50%; |
|
|
|
left: 50%; |
|
|
|
transform: translate(-50%, -50%); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
.trace-line { |
|
|
|
position: absolute; |
|
|
|
left: 12rpx; |
|
|
|
top: 32rpx; |
|
|
|
width: 2rpx; |
|
|
|
height: calc(100% - 32rpx); |
|
|
|
background: #f0f0f0; |
|
|
|
z-index: 1; |
|
|
|
} |
|
|
|
|
|
|
|
.trace-content { |
|
|
|
flex: 1; |
|
|
|
min-width: 0; |
|
|
|
|
|
|
|
.trace-desc { |
|
|
|
font-size: 28rpx; |
|
|
|
color: #666; |
|
|
|
line-height: 1.5; |
|
|
|
margin-bottom: 8rpx; |
|
|
|
word-break: break-all; |
|
|
|
} |
|
|
|
|
|
|
|
.trace-time { |
|
|
|
font-size: 24rpx; |
|
|
|
color: #999; |
|
|
|
margin-bottom: 4rpx; |
|
|
|
} |
|
|
|
|
|
|
|
.trace-location { |
|
|
|
font-size: 24rpx; |
|
|
|
color: #bbb; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
.loading { |
|
|
|
margin: 40rpx 24rpx; |
|
|
|
text-align: center; |
|
|
|
} |
|
|
|
|
|
|
|
.empty-state { |
|
|
|
margin: 120rpx 24rpx; |
|
|
|
text-align: center; |
|
|
|
|
|
|
|
.empty-icon { |
|
|
|
width: 200rpx; |
|
|
|
height: 200rpx; |
|
|
|
margin-bottom: 24rpx; |
|
|
|
} |
|
|
|
|
|
|
|
.empty-text { |
|
|
|
font-size: 28rpx; |
|
|
|
color: #999; |
|
|
|
} |
|
|
|
} |
|
|
|
</style> |