微信小程序实战案例 - 餐馆点餐系统 阶段 4 - 订单列表 & 状态

发布于:2025-04-14 ⋅ 阅读:(20) ⋅ 点赞:(0)

✅ 阶段 4 – 订单列表 & 状态

目标

  1. 展示用户「我的订单」列表
  2. 支持状态筛选(全部 / 待处理 / 已完成)
  3. 支持分页加载和实时刷新
  4. 使用原生组件编写

✅ 1. 页面结构:文件结构

pages/orders/
  ├─ index.json
  ├─ index.wxml
  ├─ index.js
  └─ index.wxss

✅ 2. 页面配置 index.json

{
  "navigationBarTitleText": "我的订单"
}

✅ 3. 页面模板 index.wxml

<view class="tabs">
  <text class="tab {{activeTab==0 ? 'active' : ''}}" data-index="0" bindtap="onTabChange">全部</text>
  <text class="tab {{activeTab==1 ? 'active' : ''}}" data-index="1" bindtap="onTabChange">待处理</text>
  <text class="tab {{activeTab==2 ? 'active' : ''}}" data-index="2" bindtap="onTabChange">已完成</text>
</view>

<view wx:if="{{orders.length}}">
  <block wx:for="{{orders}}" wx:key="orderNo">
    <view class="order-card">
      <view class="order-header">
        <text>订单号:{{item.orderNo}}</text>
        <text class="status {{item.status}}">{{item.status == 'PENDING' ? '待处理' : '已完成'}}</text>
      </view>
      <view class="order-body">
        <text>共 {{item.totalCount}} 件商品</text>
        <text>合计:¥{{item.totalPrice}}</text>
      </view>
      <view class="order-time">{{item.timeStr}}</view>
    </view>
  </block>
</view>

<view wx:else class="empty">
  <text>暂无订单</text>
</view>

✅ 4. 样式 index.wxss

.tabs {
  display: flex;
  border-bottom: 1px solid #eee;
  background: #f8f8f8;
}
.tab {
  flex: 1;
  text-align: center;
  padding: 20rpx 0;
  font-size: 30rpx;
  color: #888;
}
.tab.active {
  color: #333;
  border-bottom: 4rpx solid #07c160;
  font-weight: bold;
}

.order-card {
  background: #fff;
  margin: 20rpx;
  padding: 20rpx;
  border-radius: 12rpx;
  box-shadow: 0 4rpx 12rpx rgba(0,0,0,0.04);
}
.order-header {
  display: flex;
  justify-content: space-between;
  font-weight: bold;
}
.status {
  font-size: 28rpx;
}
.status.PENDING {
  color: #ff9900;
}
.status.DONE {
  color: #07c160;
}
.order-body {
  margin-top: 10rpx;
  font-size: 28rpx;
  display: flex;
  justify-content: space-between;
}
.order-time {
  font-size: 24rpx;
  color: #999;
  margin-top: 10rpx;
  text-align: right;
}
.empty {
  text-align: center;
  color: #999;
  font-size: 28rpx;
  padding: 100rpx 0;
}

✅ 5. 页面逻辑 index.js

const db = wx.cloud.database()
const PAGE_SIZE = 10

Page({
  data: {
    activeTab: 0,
    orders: [],
    page: 0,
    finished: false
  },

  onShow() {
    this.resetAndLoad()
    this.timer = setInterval(() => this.refresh(), 5000)
  },

  onHide() {
    clearInterval(this.timer)
  },
  onUnload() {
    clearInterval(this.timer)
  },

  onTabChange(e) {
    this.setData({ activeTab: Number(e.currentTarget.dataset.index) })
    this.resetAndLoad()
  },

  resetAndLoad() {
    this.setData({ orders: [], page: 0, finished: false })
    this.loadPage()
  },

  async loadPage(isRefresh = false) {
    if (this.data.finished) return

    const statusMap = ['', 'PENDING', 'DONE']
    const filter = statusMap[this.data.activeTab]

    let query = db.collection('orders')
    if (filter) {
      query = query.where({ status: filter })
    }

    const res = await query
      .orderBy('createdAt', 'desc')
      .skip(this.data.page * PAGE_SIZE)
      .limit(PAGE_SIZE)
      .get()

    const list = res.data.map(o => ({
      ...o,
      totalCount: o.items.reduce((sum, i) => sum + i.count, 0),
      timeStr: this.formatTime(o.createdAt)
    }))

    this.setData({
      orders: isRefresh ? list : this.data.orders.concat(list),
      page: this.data.page + 1,
      finished: list.length < PAGE_SIZE
    })
  },

  refresh() {
    this.setData({ page: 0, finished: false })
    this.loadPage(true)
  },

  formatTime(ts) {
    const date = new Date(ts)
    return `${date.getMonth()+1}-${date.getDate()} ${date.getHours()}:${date.getMinutes().toString().padStart(2, '0')}`
  }
})

在这里插入图片描述

✅ 6. 自测 Checklist

  • 能切换订单状态:全部 / 待处理 / 已完成
  • 正确显示订单号、商品数量、金额
  • 页面卡片样式清晰
  • 页面首次进入加载数据
  • 每 5 秒自动刷新状态(模拟店员更新)
  • 无订单时显示「暂无订单」