爱简收旧衣按件回收前端代码仓库
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

288 lines
5.9 KiB

<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>