| | |
| | | |
| | | <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 v-for="(item, index) in orders" :key="item.id" class="order-card" @click="goToOrderDetail(item, index)"> |
| | | <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> |
| | | <image class="order-card__badge-icon" :src="getBadgeIcon(item)" mode="widthFix"></image> |
| | | <text class="order-card__time-text">{{ item.code }}</text> |
| | | </view> |
| | | <text class="order-card__status" :class="{ 'order-card__status--highlight': item.actions && item.actions.length }">{{ item.statusText }}</text> |
| | | <text class="order-card__status" :class="{ 'order-card__status--highlight': item.status === 3 || item.status === 4 }">{{ getStatusText(item.status) }}</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> |
| | | <text class="order-card__route-title">{{ item.takeName }}</text> |
| | | <text class="order-card__route-desc">{{ item.takeAddress }}</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> |
| | | <text class="order-card__route-title">{{ item.depositShopName }}</text> |
| | | <text class="order-card__route-desc">{{ item.depositShopAddress }}</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> |
| | | <text class="order-card__arrival-text">剩余{{ item.remainMinutes }}分钟</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> |
| | | <text class="order-card__price">¥{{ (item.driverFee / 100).toFixed(2) }}</text> |
| | | </view> |
| | | </view> |
| | | |
| | | <view v-if="item.actions && item.actions.length" class="order-card__actions"> |
| | | <view v-if="getActions(item).length" class="order-card__actions"> |
| | | <button |
| | | v-for="action in item.actions" |
| | | v-for="action in getActions(item)" |
| | | :key="action.text" |
| | | class="order-card__action-btn" |
| | | :class="['order-card__action-btn--' + action.type, { 'order-card__action-btn--primary-fill': action.fill }]" |
| | |
| | | {{ action.text }} |
| | | </button> |
| | | </view> |
| | | </view> |
| | | |
| | | <view v-if="orders.length === 0 && !loading" class="order-page__empty"> |
| | | <image class="order-page__empty-icon" src="/static/image/default_nodata@2x.png" mode="aspectFit"></image> |
| | | </view> |
| | | |
| | | <view v-if="loading" class="order-page__loading"> |
| | | <text>加载中...</text> |
| | | </view> |
| | | </view> |
| | | </scroll-view> |
| | |
| | | return { |
| | | statusBarHeight: 0, |
| | | navHeight: 0, |
| | | activeTab: 'all', |
| | | activeTab: null, |
| | | tabs: [ |
| | | { label: '全部', value: 'all' }, |
| | | { label: '待取货', value: 'pickup' }, |
| | | { label: '配送中', value: 'delivering' }, |
| | | { label: '已完成', value: 'finished' } |
| | | { label: '全部', value: null }, |
| | | { label: '待取货', value: 3 }, |
| | | { label: '配送中', value: 4 }, |
| | | { label: '已完成', value: 7 } |
| | | ], |
| | | 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' |
| | | } |
| | | ] |
| | | orders: [], |
| | | page: 1, |
| | | hasMore: true, |
| | | loading: false |
| | | } |
| | | }, |
| | | 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 |
| | | } |
| | | const countMap = {} |
| | | this.tabs.forEach(tab => { |
| | | if (tab.value === null) { |
| | | countMap[null] = this.orders.length |
| | | } else { |
| | | countMap[tab.value] = this.orders.filter((item) => item.status === tab.value).length |
| | | } |
| | | }) |
| | | |
| | | return this.tabs.map((tab) => { |
| | | if (!countMap[tab.value]) { |
| | |
| | | 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) |
| | | this.getOrderList() |
| | | }, |
| | | onShow() { |
| | | this.page = 1 |
| | | this.hasMore = true |
| | | this.orders = [] |
| | | this.getOrderList() |
| | | }, |
| | | onReachBottom() { |
| | | if (!this.hasMore || this.loading) return |
| | | this.page++ |
| | | this.getOrderList() |
| | | }, |
| | | watch: { |
| | | activeTab() { |
| | | this.page = 1 |
| | | this.hasMore = true |
| | | this.orders = [] |
| | | this.getOrderList() |
| | | } |
| | | }, |
| | | methods: { |
| | | getBadgeIcon(badge) { |
| | | const badgeMap = { |
| | | '极速达': '/static/image/ic_jisuda@2x.png', |
| | | '标速达': '/static/image/ic_biaosuda@2x.png' |
| | | } |
| | | |
| | | return badgeMap[badge] || '' |
| | | getBadgeIcon(item) { |
| | | return item.isUrgent ? '/static/image/ic_jisuda@2x.png' : '/static/image/ic_biaosuda@2x.png' |
| | | }, |
| | | goToOrderDetail(item) { |
| | | getStatusText(status) { |
| | | const map = { |
| | | 2: '待接单', |
| | | 3: '待取货', |
| | | 4: '配送中', |
| | | 7: '已完成', |
| | | 99: '已取消' |
| | | } |
| | | return map[status] || '' |
| | | }, |
| | | getActions(item) { |
| | | if (item.status === 3) { |
| | | return [ |
| | | { text: '取消订单', type: 'light', fill: false }, |
| | | { text: '取货码', type: 'primary', fill: false }, |
| | | { text: '拍照取货', type: 'primary', fill: true } |
| | | ] |
| | | } |
| | | if (item.status === 4) { |
| | | return [ |
| | | { text: '存件码', type: 'primary', fill: false } |
| | | ] |
| | | } |
| | | return [] |
| | | }, |
| | | getOrderList() { |
| | | if (this.loading) return |
| | | this.loading = true |
| | | this.$u.api.orderPage({ |
| | | capacity: 10, |
| | | page: this.page, |
| | | model: { |
| | | status: this.activeTab |
| | | } |
| | | }).then(res => { |
| | | if (res.code === 200) { |
| | | const list = res.data.records || [] |
| | | if (this.page === 1) { |
| | | this.orders = list |
| | | } else { |
| | | this.orders = [...this.orders, ...list] |
| | | } |
| | | this.hasMore = list.length >= 10 |
| | | } |
| | | }).catch((err) => { |
| | | console.log(err) |
| | | }).finally(() => { |
| | | this.loading = false |
| | | }) |
| | | }, |
| | | goToOrderDetail(item, index) { |
| | | 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'}` |
| | | url: `/pages/order-detail/order-detail?id=${item.id}&index=${index + 1}` |
| | | }) |
| | | } |
| | | } |
| | |
| | | &__list { |
| | | padding: 18rpx 22rpx calc(env(safe-area-inset-bottom) + 26rpx); |
| | | } |
| | | |
| | | &__empty { |
| | | display: flex; |
| | | flex-direction: column; |
| | | align-items: center; |
| | | justify-content: center; |
| | | padding-top: 200rpx; |
| | | } |
| | | |
| | | &__empty-icon { |
| | | width: 320rpx; |
| | | height: 320rpx; |
| | | } |
| | | |
| | | &__loading { |
| | | display: flex; |
| | | justify-content: center; |
| | | align-items: center; |
| | | padding: 30rpx 0; |
| | | color: #8f96a3; |
| | | font-size: 26rpx; |
| | | } |
| | | } |
| | | |
| | | .order-card { |