campus-errand/miniapp/pages/message/order-notify.vue
2026-03-12 18:12:10 +08:00

228 lines
4.2 KiB
Vue

<template>
<view class="order-notify-page">
<!-- 分类标签 -->
<view class="tabs">
<view
class="tab-item"
:class="{ active: currentTab === tab.value }"
v-for="tab in tabs"
:key="tab.value"
@click="switchTab(tab.value)"
>
<text>{{ tab.label }}</text>
</view>
</view>
<!-- 订单通知列表 -->
<view
class="notify-item"
v-for="item in notifications"
:key="item.id"
>
<view class="notify-header">
<text class="notify-title">{{ item.title }}</text>
<text class="notify-type">{{ formatOrderType(item.orderType) }}</text>
</view>
<view class="notify-body">
<text class="notify-order-no">订单编号:{{ item.orderNo }}</text>
<text class="notify-item-name" v-if="item.itemName">{{ item.itemName }}</text>
</view>
<view class="notify-footer">
<text class="notify-time">{{ formatTime(item.createdAt) }}</text>
<view class="notify-btn" @click="goOrderDetail(item)">
<text class="btn-text">查看订单</text>
</view>
</view>
</view>
<!-- 空状态 -->
<view v-if="notifications.length === 0 && !loading" class="empty">
<text class="empty-text">暂无订单通知</text>
</view>
</view>
</template>
<script>
import { getOrderNotifications } from '../../utils/api'
export default {
data() {
return {
currentTab: '',
tabs: [
{ label: '全部', value: '' },
{ label: '被接单', value: 'accepted' },
{ label: '已完成', value: 'completed' },
{ label: '已取消', value: 'cancelled' }
],
notifications: [],
loading: false
}
},
onLoad() {
this.loadNotifications()
},
methods: {
/** 切换分类标签 */
switchTab(value) {
this.currentTab = value
this.loadNotifications()
},
/** 加载订单通知列表 */
async loadNotifications() {
this.loading = true
try {
const params = {}
if (this.currentTab) {
params.category = this.currentTab
}
const res = await getOrderNotifications(params)
this.notifications = res || []
} catch (e) {
uni.showToast({ title: '加载失败', icon: 'none' })
} finally {
this.loading = false
}
},
/** 跳转订单详情页 */
goOrderDetail(item) {
uni.navigateTo({
url: `/pages/order/order-detail?id=${item.id}`
})
},
/** 格式化订单类型 */
formatOrderType(type) {
const map = {
Pickup: '代取',
Delivery: '代送',
Help: '万能帮',
Purchase: '代购',
Food: '美食街'
}
return map[type] || type
},
/** 格式化时间(精确到年月日时分,) */
formatTime(dateStr) {
if (!dateStr) return ''
const d = new Date(dateStr)
const pad = (n) => String(n).padStart(2, '0')
return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())} ${pad(d.getHours())}:${pad(d.getMinutes())}`
}
}
}
</script>
<style scoped>
.order-notify-page {
padding: 0 24rpx 20rpx;
}
.tabs {
display: flex;
background-color: #ffffff;
padding: 20rpx 0;
margin: 0 -24rpx 20rpx;
padding-left: 24rpx;
padding-right: 24rpx;
position: sticky;
top: 0;
z-index: 10;
}
.tab-item {
flex: 1;
text-align: center;
font-size: 28rpx;
color: #666666;
padding: 12rpx 0;
border-radius: 8rpx;
}
.tab-item.active {
color: #007AFF;
font-weight: 500;
background-color: #e8f4fd;
}
.notify-item {
background-color: #ffffff;
border-radius: 16rpx;
padding: 24rpx 30rpx;
margin-bottom: 16rpx;
}
.notify-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 16rpx;
}
.notify-title {
font-size: 30rpx;
color: #333333;
font-weight: 500;
}
.notify-type {
font-size: 24rpx;
color: #007AFF;
background-color: #e8f4fd;
padding: 4rpx 16rpx;
border-radius: 8rpx;
}
.notify-body {
margin-bottom: 16rpx;
}
.notify-order-no {
font-size: 24rpx;
color: #999999;
display: block;
}
.notify-item-name {
font-size: 26rpx;
color: #666666;
margin-top: 8rpx;
display: block;
}
.notify-footer {
display: flex;
justify-content: space-between;
align-items: center;
}
.notify-time {
font-size: 22rpx;
color: #cccccc;
}
.notify-btn {
background-color: #007AFF;
border-radius: 8rpx;
padding: 8rpx 24rpx;
}
.btn-text {
font-size: 24rpx;
color: #ffffff;
}
.empty {
text-align: center;
padding: 120rpx 0;
}
.empty-text {
font-size: 28rpx;
color: #cccccc;
}
</style>