<template>
|
<view class="order-page">
|
<view class="order-page__nav" :style="{ paddingTop: statusBarHeight + 'px' }">
|
<view class="order-page__nav-inner">
|
<text class="order-page__nav-title">我的订单</text>
|
</view>
|
</view>
|
|
<view class="order-page__tabs" :style="{ top: navHeight + 'px' }">
|
<view v-for="tab in displayTabs" :key="tab.value" class="order-page__tab" :class="{ 'order-page__tab--active': activeTab === tab.value }" @click="activeTab = tab.value">
|
<text class="order-page__tab-text">{{ tab.label }}</text>
|
<view v-if="activeTab === tab.value" class="order-page__tab-line"></view>
|
</view>
|
</view>
|
|
<scroll-view class="order-page__body" scroll-y :style="bodyStyle">
|
<view class="order-page__list">
|
<view v-for="item in currentOrders" :key="item.id" class="order-card" @click="goToOrderDetail(item)">
|
<view class="order-card__head">
|
<view class="order-card__head-left">
|
<image class="order-card__badge-icon" :src="getBadgeIcon(item.badge)" mode="widthFix"></image>
|
<text class="order-card__time-text">下单时间: {{ item.orderTime }}</text>
|
</view>
|
<text class="order-card__status" :class="{ 'order-card__status--highlight': item.actions && item.actions.length }">{{ item.statusText }}</text>
|
</view>
|
|
<view class="order-card__route-item">
|
<view class="order-card__point order-card__point--pickup">取</view>
|
<view class="order-card__route-texts">
|
<text class="order-card__route-title">{{ item.pickupName }}</text>
|
<text class="order-card__route-desc">{{ item.pickupAddress }}</text>
|
</view>
|
</view>
|
|
<view class="order-card__route-item order-card__route-item--delivery">
|
<view class="order-card__point order-card__point--delivery">送</view>
|
<view class="order-card__route-texts">
|
<text class="order-card__route-title">{{ item.deliveryName }}</text>
|
<text class="order-card__route-desc">{{ item.deliveryAddress }}</text>
|
</view>
|
</view>
|
|
<view class="order-card__footer">
|
<view class="order-card__arrival">
|
<image class="order-card__clock" src="/static/image/ic_clock@2x.png" mode="aspectFit"></image>
|
<text class="order-card__arrival-text">{{ item.arriveLabel || '送达时间:' }}{{ item.arriveTime }}</text>
|
</view>
|
<view class="order-card__price-wrap">
|
<text v-if="item.priceTag" class="order-card__price-tag">{{ item.priceTag }}</text>
|
<text class="order-card__price">{{ item.price }}</text>
|
</view>
|
</view>
|
|
<view v-if="item.actions && item.actions.length" class="order-card__actions">
|
<button
|
v-for="action in item.actions"
|
:key="action.text"
|
class="order-card__action-btn"
|
:class="['order-card__action-btn--' + action.type, { 'order-card__action-btn--primary-fill': action.fill }]"
|
hover-class="order-card__action-btn--hover"
|
>
|
{{ action.text }}
|
</button>
|
</view>
|
</view>
|
</view>
|
</scroll-view>
|
</view>
|
</template>
|
|
<script>
|
export default {
|
data() {
|
return {
|
statusBarHeight: 0,
|
navHeight: 0,
|
activeTab: 'all',
|
tabs: [
|
{ label: '全部', value: 'all' },
|
{ label: '待取货', value: 'pickup' },
|
{ label: '配送中', value: 'delivering' },
|
{ label: '已完成', value: 'finished' }
|
],
|
orders: [
|
{
|
id: 1,
|
type: 'pickup',
|
badge: '标速达',
|
badgeType: 'blue',
|
orderTime: '2026-04-12 12:09',
|
statusText: '待取货',
|
pickupName: '中铁快运南站旗舰店',
|
pickupAddress: '莲花路200号莲花产业园F栋401',
|
deliveryName: '佳苑巴黎都市3期10栋301室',
|
deliveryAddress: '洞庭湖路与湖北路交叉口西150米',
|
arriveLabel: '',
|
arriveTime: '45分钟内送达',
|
priceTag: '',
|
price: '¥20.5',
|
actions: [
|
{ text: '取消订单', type: 'light', fill: false },
|
{ text: '取货码', type: 'primary', fill: false },
|
{ text: '拍照取货', type: 'primary', fill: true }
|
]
|
},
|
{
|
id: 4,
|
type: 'pickup',
|
badge: '极速达',
|
badgeType: 'red',
|
orderTime: '2026-04-12 12:33',
|
statusText: '待取货',
|
pickupName: '中铁快运南站旗舰店',
|
pickupAddress: '莲花路200号莲花产业园F栋401',
|
deliveryName: '佳苑巴黎都市3期10栋301室',
|
deliveryAddress: '洞庭湖路与湖北路交叉口西150米',
|
arriveLabel: '',
|
arriveTime: '50分钟内送达',
|
priceTag: '',
|
price: '¥20.5',
|
actions: [
|
{ text: '取消订单', type: 'light', fill: false },
|
{ text: '取货码', type: 'primary', fill: false },
|
{ text: '拍照取货', type: 'primary', fill: true }
|
]
|
},
|
{
|
id: 2,
|
type: 'delivering',
|
badge: '极速达',
|
badgeType: 'red',
|
orderTime: '2026-04-12 12:33',
|
statusText: '配送中',
|
pickupName: '中铁快运南站旗舰店',
|
pickupAddress: '莲花路200号莲花产业园F栋401',
|
deliveryName: '佳苑巴黎都市3期10栋301室',
|
deliveryAddress: '洞庭湖路与湖北路交叉口西150米',
|
arriveLabel: '送达时间:',
|
arriveTime: '04-12 12:58',
|
priceTag: '',
|
price: '¥20.5'
|
},
|
{
|
id: 5,
|
type: 'rated',
|
badge: '极速达',
|
badgeType: 'red',
|
orderTime: '2026-04-12 13:08',
|
statusText: '已评价',
|
pickupName: '中铁快运南站旗舰店',
|
pickupAddress: '莲花路200号莲花产业园F栋401',
|
deliveryName: '佳苑巴黎都市3期10栋301室',
|
deliveryAddress: '洞庭湖路与湖北路交叉口西150米',
|
arriveLabel: '送达时间:',
|
arriveTime: '04-12 13:36',
|
priceTag: '',
|
price: '¥18.8'
|
},
|
{
|
id: 6,
|
type: 'cancelled',
|
badge: '标速达',
|
badgeType: 'blue',
|
orderTime: '2026-04-12 13:18',
|
statusText: '已取消',
|
pickupName: '中铁快运南站旗舰店',
|
pickupAddress: '莲花路200号莲花产业园F栋401',
|
deliveryName: '佳苑巴黎都市3期10栋301室',
|
deliveryAddress: '洞庭湖路与湖北路交叉口西150米',
|
arriveLabel: '送达时间:',
|
arriveTime: '04-12 13:52',
|
priceTag: '',
|
price: '¥16.5'
|
},
|
{
|
id: 3,
|
type: 'finished',
|
badge: '极速达',
|
badgeType: 'red',
|
orderTime: '2026-04-12 12:33',
|
statusText: '已完成',
|
pickupName: '中铁快运南站旗舰店',
|
pickupAddress: '莲花路200号莲花产业园F栋401',
|
deliveryName: '佳苑巴黎都市3期10栋301室',
|
deliveryAddress: '洞庭湖路与湖北路交叉口西150米',
|
arriveLabel: '送达时间:',
|
arriveTime: '04-12 12:58',
|
priceTag: '已结算',
|
price: '¥20.5'
|
}
|
]
|
}
|
},
|
computed: {
|
displayTabs() {
|
const countMap = {
|
pickup: this.orders.filter((item) => item.type === 'pickup').length,
|
delivering: this.orders.filter((item) => item.type === 'delivering').length,
|
finished: this.orders.filter((item) => item.type === 'finished').length
|
}
|
|
return this.tabs.map((tab) => {
|
if (!countMap[tab.value]) {
|
return tab
|
}
|
|
return {
|
...tab,
|
label: `${tab.label} ${countMap[tab.value]}`
|
}
|
})
|
},
|
|
bodyStyle() {
|
return {
|
marginTop: this.navHeight + uni.upx2px(88) + 'px',
|
height: `calc(100vh - ${this.navHeight + uni.upx2px(88)}px)`
|
}
|
},
|
currentOrders() {
|
if (this.activeTab === 'all') {
|
return this.orders
|
}
|
|
return this.orders.filter((item) => item.type === this.activeTab)
|
}
|
},
|
onLoad() {
|
const systemInfo = uni.getSystemInfoSync()
|
this.statusBarHeight = systemInfo.statusBarHeight || 0
|
this.navHeight = this.statusBarHeight + uni.upx2px(88)
|
},
|
methods: {
|
getBadgeIcon(badge) {
|
const badgeMap = {
|
'极速达': '/static/image/ic_jisuda@2x.png',
|
'标速达': '/static/image/ic_biaosuda@2x.png'
|
}
|
|
return badgeMap[badge] || ''
|
},
|
goToOrderDetail(item) {
|
uni.navigateTo({
|
url: `/pages/order-detail/order-detail?id=${item.id}&status=${item.type === 'delivering' ? 'delivering' : item.type === 'finished' ? 'finished' : item.type === 'cancelled' ? 'cancelled' : item.type === 'rated' ? 'rated' : 'pickup'}`
|
})
|
}
|
}
|
}
|
</script>
|
|
<style lang="scss" scoped>
|
.order-page {
|
height: 100vh;
|
background: #f5f7fb;
|
overflow: hidden;
|
|
&__nav {
|
position: fixed;
|
left: 0;
|
top: 0;
|
right: 0;
|
z-index: 10;
|
background: linear-gradient(180deg, #1f73f6 0%, #1b6cf2 100%);
|
}
|
|
&__nav-inner {
|
height: 88rpx;
|
display: flex;
|
align-items: center;
|
padding: 0 28rpx;
|
}
|
|
&__nav-title {
|
font-size: 38rpx;
|
font-weight: 700;
|
color: #ffffff;
|
}
|
|
&__tabs {
|
position: fixed;
|
left: 0;
|
right: 0;
|
z-index: 9;
|
height: 88rpx;
|
display: flex;
|
align-items: center;
|
background: #ffffff;
|
box-shadow: 0 10rpx 20rpx rgba(40, 72, 128, 0.04);
|
}
|
|
&__tab {
|
position: relative;
|
flex: 1;
|
height: 100%;
|
display: flex;
|
justify-content: center;
|
align-items: center;
|
|
&--active {
|
.order-page__tab-text {
|
color: #272b33;
|
font-weight: 700;
|
}
|
}
|
}
|
|
&__tab-text {
|
font-size: 30rpx;
|
color: #8f96a3;
|
}
|
|
&__tab-line {
|
position: absolute;
|
left: 26rpx;
|
right: 26rpx;
|
bottom: 0;
|
height: 4rpx;
|
border-radius: 999rpx;
|
background: #1a73f8;
|
}
|
|
&__body {
|
box-sizing: border-box;
|
}
|
|
&__list {
|
padding: 18rpx 22rpx calc(env(safe-area-inset-bottom) + 26rpx);
|
}
|
}
|
|
.order-card {
|
margin-bottom: 18rpx;
|
padding: 20rpx 18rpx 18rpx;
|
border-radius: 20rpx;
|
background: #ffffff;
|
box-shadow: 0 8rpx 20rpx rgba(43, 65, 106, 0.05);
|
|
&__head {
|
display: flex;
|
justify-content: space-between;
|
align-items: center;
|
}
|
|
&__head-left {
|
display: flex;
|
align-items: center;
|
gap: 12rpx;
|
min-width: 0;
|
}
|
|
&__badge {
|
padding: 4rpx 10rpx;
|
border-radius: 10rpx;
|
font-size: 22rpx;
|
line-height: 1.2;
|
font-weight: 600;
|
|
&--blue {
|
border: 1rpx solid #75cfff;
|
color: #27a8f8;
|
background: #eefaff;
|
}
|
|
&--red {
|
border: 1rpx solid #ff8f8f;
|
color: #ff5d5d;
|
background: #fff1f1;
|
}
|
}
|
|
&__badge-icon {
|
width: 108rpx;
|
height: 40rpx;
|
flex-shrink: 0;
|
}
|
|
&__time-text,
|
&__status,
|
&__route-desc,
|
&__arrival-text {
|
font-size: 24rpx;
|
color: #a1a7b2;
|
}
|
|
&__status {
|
flex-shrink: 0;
|
|
&--highlight {
|
color: #ff4a3d;
|
font-weight: 700;
|
}
|
}
|
|
&__route-item {
|
display: flex;
|
align-items: flex-start;
|
margin-top: 22rpx;
|
|
&--delivery {
|
margin-top: 20rpx;
|
}
|
}
|
|
&__point {
|
width: 34rpx;
|
height: 34rpx;
|
line-height: 34rpx;
|
text-align: center;
|
border-radius: 50%;
|
font-size: 22rpx;
|
font-weight: 700;
|
color: #ffffff;
|
flex-shrink: 0;
|
margin-right: 16rpx;
|
|
&--pickup {
|
background: #2ab8ff;
|
}
|
|
&--delivery {
|
background: #ff9d2e;
|
}
|
}
|
|
&__route-texts {
|
flex: 1;
|
min-width: 0;
|
}
|
|
&__route-title {
|
display: block;
|
font-size: 34rpx;
|
font-weight: 700;
|
color: #2d3139;
|
line-height: 1.3;
|
}
|
|
&__route-desc {
|
display: block;
|
margin-top: 8rpx;
|
line-height: 1.4;
|
}
|
|
&__footer {
|
display: flex;
|
justify-content: space-between;
|
align-items: center;
|
margin-top: 22rpx;
|
padding-top: 16rpx;
|
border-top: 1rpx solid #f0f2f6;
|
}
|
|
&__arrival {
|
display: flex;
|
align-items: center;
|
gap: 10rpx;
|
}
|
|
&__clock {
|
width: 24rpx;
|
height: 24rpx;
|
flex-shrink: 0;
|
}
|
|
&__price-wrap {
|
display: flex;
|
align-items: center;
|
gap: 10rpx;
|
}
|
|
&__price-tag {
|
padding: 3rpx 8rpx;
|
border-radius: 8rpx;
|
border: 1rpx solid #ff8f8f;
|
font-size: 22rpx;
|
font-weight: 600;
|
color: #ff6a6a;
|
background: #fff4f4;
|
}
|
|
&__price {
|
font-size: 40rpx;
|
font-weight: 700;
|
color: #ff4030;
|
}
|
|
&__actions {
|
display: flex;
|
justify-content: flex-end;
|
gap: 20rpx;
|
margin-top: 18rpx;
|
padding-top: 18rpx;
|
border-top: 1rpx solid #f0f2f6;
|
}
|
|
&__action-btn {
|
width: 160rpx;
|
height: 64rpx;
|
line-height: 64rpx;
|
padding: 0;
|
border-radius: 34rpx;
|
font-size: 28rpx;
|
font-weight: 500;
|
border: 1rpx solid transparent;
|
background: #ffffff;
|
box-sizing: border-box;
|
|
&::after {
|
border: 0;
|
}
|
|
&--light {
|
border-color: #d7dbe3;
|
color: #8f96a3;
|
}
|
|
&--primary {
|
border-color: #2c7cff;
|
color: #2c7cff;
|
}
|
|
&--primary-fill {
|
background: #2c7cff;
|
color: #ffffff;
|
}
|
|
&--hover {
|
opacity: 0.92;
|
}
|
}
|
}
|
</style>
|