小程序开发日记②:订单列表、详情与支付状态

用户下单后最关心三件事:现在是什么状态、下一步要做什么、什么时候能送到。订单模块就围绕这三件事组织,而不是简单照搬管理端字段。
1. 列表状态分组
订单页提供“全部、待支付、待调度、配送中、已完成”五个标签。接口返回的后台状态比标签更多,因此需要状态映射,而不能直接用标签文本请求。
const tabStatusMap = { 0: null, 1: ['UNPAID'], 2: ['PENDING_AUDIT', 'WAIT_DISPATCH'], 3: ['DELIVERING'], 4: ['COMPLETED', 'CANCELED', 'REJECTED', 'DELIVERY_FAILED']}页面请求时增加版本号,用户快速切换标签后,只接收最后一次查询结果,避免慢请求把新标签的数据覆盖掉。
let queryVersion = 0
async function loadOrders() { const requestId = ++queryVersion const response = await OrderApi.getOrderList(params.value) if (requestId !== queryVersion) return orders.value = response.rows || []}2. 订单卡片是视图模型
OrderStatusCard 统一处理状态颜色、右上角状态形状、价格、摘要和按钮。卡片不直接决定业务,只接收已经转换好的展示属性。
为了让背景图片覆盖整个盒子,图片层使用绝对定位,内容层单独抬高层级:
.order-card { position: relative; overflow: hidden; }.order-card__background { position: absolute; inset: 0; width: 100%; height: 100%;}.order-card__content { position: relative; z-index: 1; }右上角状态区域单独绘制与主题相近、但有区分度的色块,解决背景图边缘在圆角裁剪时露白的问题。
3. 详情页聚合数据
pages/order/detail.vue 同时读取订单详情、进度记录和凭证图片。详情加载成功后,再根据状态构建页面头部、时间线和操作按钮。
async function loadDetail(showPageLoading = true) { if (!orderId.value || refreshing.value) return refreshing.value = true try { const [detailResult, progressResult] = await Promise.all([ OrderApi.getOrderDetail(orderId.value), OrderApi.getOrderProgress(orderId.value) ]) detail.value = detailResult.data || {} progressRecords.value = progressResult.rows || [] await loadProofImages() } finally { refreshing.value = false }}页面支持下拉刷新,并在可变状态下每 30 秒轻量刷新一次。离开页面必须清除计时器,避免隐藏页面继续请求。
4. 支付倒计时
待支付订单根据创建或更新时间计算剩余时间:
const baseTime = Number.isNaN(updateTime) ? createTime : updateTimeconst remain = PAYMENT_TIMEOUT - (Date.now() - baseTime)倒计时归零后页面主动刷新详情,由服务端确认订单最终状态。前端不能擅自把订单改为取消,因为支付回调可能正在路上。
5. 支付与取消
支付按钮设置 paying 防重复触发,调用支付接口后根据结果更新页面。取消操作先弹确认框,用户确认后调用 cancelOrder,成功再刷新详情。
点击取消 ↓确认风险与结果 ↓调用取消接口 ↓重新读取订单详情对于已驳回订单,详情页提供“重新提交”,跳回对应类型表单并携带 orderId 与 resubmit=1。表单回显原数据,用户修改后走专门的重提接口。
6. 进度时间线
时间线不是根据当前状态虚构节点,而是优先使用真实 process logs。只有后端暂未返回记录时才使用基础状态生成占位。审核、调度、起飞、签收都显示真实操作时间,用户才能知道订单究竟停在哪里。
7. 本篇小结
前后台状态的解释差异
管理端关心“待审核”和“待调度”的操作区别,用户端更关心“平台正在确认”和“等待安排配送”。页面没有修改原始枚举,而是通过视图函数提供用户文案。这样接口与排查日志仍使用统一状态,界面表达则更自然。
轮询的边界
只有 UNPAID、PENDING_AUDIT、WAIT_DISPATCH、DELIVERING 等可变状态需要轮询。订单进入完成、取消、驳回等终态后停止计时器。页面隐藏时也停止,重新显示再立即拉取一次,避免小程序在后台持续耗电和请求。
详情中的价格、来源订单号、MMSI 和流程时间都通过统一格式化函数处理。缺失值显示 --,金额固定两位小数,订单号始终使用业务 orderNo。这些规则看起来零碎,但正是用户判断“是不是我的那张订单”的依据。
订单模块让我意识到,“状态”不是卡片右上角的四个字,而是接口、按钮、倒计时、时间线和跳转共同遵守的规则。只改颜色不改行为,就像给红灯刷成绿色,路还是会堵。
支持与分享
如果这篇文章对你有帮助,欢迎分享给更多人或打赏支持!





























