6.8 KiB
6.8 KiB
配送端逻辑说明(概要与建议)(舍弃)
概览
- 本文档总结
pages/mall/delivery目录下配送端主要页面的工作流与实现细节,定位到关键数据库表与状态机,列出已识别的并发/同步风险,并给出可执行的改进建议。 - 主要参考页面:
主要数据表(后端)
ml_delivery_drivers:配送员信息与work_status。ml_delivery_tasks:配送任务(配送端主要“真源”),包含driver_id, order_id, status, pickup_time, delivered_time等。ml_orders、ml_order_items:电商订单主表及明细(用于展示订单详情、订单号、商品列表等)。- 其它辅助表:
ml_shops,ak_users(用于 auth->ak id 回退查找)等。
**状态机(关键数值映射 — 汇总)
- ml_delivery_tasks.status(代码中使用):
- 1 = 待接取(pending)
- 2 = 已接取(accepted)
- 3 = 取货中(picking)
- 4 = 已取货(picked)
- 5 = 配送中(delivering / startDelivery 将 status 置 5)
- 6 = 已送达 / 完成(confirmDelivery 将 status 置 6)
- ml_orders.order_status(电商端状态,代码中做同步尝试):
- 2 = 已接取
- 4 = 已取货
- 5 = 已送达
- 7 = 已拒绝
- 注意:两张表的状态值并不一一对应,代码中多处采用“尝试同步”的方式更新
ml_orders.order_status,但没有统一映射抽象,可能造成短时不一致。
页面职责与交互要点
-
index.uvue(配送端首页)- 加载司机信息、今日统计、当前任务(查询
ml_delivery_tasks,lt status < 5)、可接订单(driver_id IS NULL AND status = 1)。 - 提供在线/离线切换(更新
ml_delivery_drivers.work_status),并禁止在存在当前任务时下线。 - 任务操作:接受(status->2)、开始取货(3)、确认取货(4)、开始配送(5)、确认送达(6)。每步都更新
ml_delivery_tasks,并尝试同步ml_orders。 - 使用
supaReady包装并设 1.5s 超时降级,避免阻塞 UI。
- 加载司机信息、今日统计、当前任务(查询
-
order-history.uvue(历史订单)- 以
ml_delivery_tasks为源,查询 driver 相关任务(gte('status', 2)),并映射为历史条目供展示。 - 使用本地存储键
completed_order_for_history:确认送达时(index.confirmDelivery)会把完成的任务写入该键,历史页 onShow 时合并(仅当 status >= 4),之后删除该 key。
- 以
-
profile.uvue(个人中心)- 展示司机统计(今日、最近任务、任务计数),通过
ml_delivery_tasks聚合计算 pending/ongoing/completed 数量。
- 展示司机统计(今日、最近任务、任务计数),通过
-
order-detail.uvue(订单/任务详情)- 支持以订单 ID 或任务 ID 打开:优先查
ml_orders,若未找到则回退查ml_delivery_tasks并用任务数据回填页面。 - 对关键操作(接受/确认取货/确认送达/拒绝)会同时更新
ml_delivery_tasks(按order_id)并尝试更新ml_orders.order_status。
- 支持以订单 ID 或任务 ID 打开:优先查
已识别风险与可改进点
- 状态不一致风险:
ml_delivery_tasks与ml_orders使用不同数值含义,且同步是“尝试式”的,短时内出现不一致或页面显示不同步的可能性高。
- 抢单竞态(race condition):
- 可接订单查询基于
driver_id IS NULL AND status = 1,多个司机并发接受可能造成重复接单。 - 目前接单操作没有使用条件更新(例如
UPDATE ... WHERE id = ? AND driver_id IS NULL),因此依赖后续 reload 作为补救,非原子性操作。
- 可接订单查询基于
- 本地存储同步(
completed_order_for_history):- 以 localStorage 作为页面间同步的手段,适用于单设备单会话,但在多设备或短时间多页面切换(或 crash)场景下不可靠。
- UI 与状态覆盖差异:
- 某些页面/映射未覆盖
status = 6(例如历史页 getOrderStatusText 没有6的友好文本),会显示“未知状态”。
- 某些页面/映射未覆盖
- supaReady 超时策略:
- 使用 1.5s 超时可以避免页面长时间等待,但在 session 刷新尚未完成的情况下可能读到空或旧数据;需要权衡 UX 与数据正确性。
短期可执行修复(优先级排序)
-
接单使用条件更新(高优先)
- 在接单接口/前端更新时改为条件写入:
- SQL/SDK 示例:UPDATE ml_delivery_tasks SET driver_id = :driverId, status = 2 WHERE id = :taskId AND driver_id IS NULL
- 若返回表示 0 行更新,则提示“已被其他人接单”,并刷新列表。
- 目的:避免重复接单的竞态。
- 在接单接口/前端更新时改为条件写入:
-
统一状态映射抽象(中优先)
- 在前端添加一个状态映射工具函数(例如 mapTaskStatusToOrderStatus(status)),并在每处状态同步时使用该映射。集中维护会减少散落的 magic number。
-
增强表间同步可靠性(中优先)
- 将关键同步(例如确认送达)封装为后端事务或 RPC:后端在事务中同时更新
ml_delivery_tasks与ml_orders,并返回原子成功/失败。前端只负责触发该 API。
- 将关键同步(例如确认送达)封装为后端事务或 RPC:后端在事务中同时更新
-
替换 localStorage 同步(低优先)
- 使用队列/事件或服务端记录(例如在确认送达时写入
ml_delivery_tasks,历史页直接查询,不依赖 localStorage 写入),或者使用 WebSocket / 推送通知触发历史刷新。
- 使用队列/事件或服务端记录(例如在确认送达时写入
-
补全 UI 映射(低优先)
- 为
status = 6等补全友好文本和样式,避免“未知状态”展示。
- 为
建议的具体代码调整点(快速指引)
- 在
index.uvue与order-detail.uvue的接单逻辑中替换无条件 update 为条件更新。例如:- 当前(伪代码):
- supa.from('ml_delivery_tasks').update({ driver_id: driverId, status: 2 }).eq('id', orderId)
- 建议(伪代码):
- supa.rpc 或 SQL: UPDATE ml_delivery_tasks SET driver_id = $1, status = 2 WHERE id = $2 AND driver_id IS NULL RETURNING *
- 如果返回行数 === 0 则表示接单失败(已被抢)
- 当前(伪代码):
- 在多个页面里抽象出
statusMap函数并复用:放在utils/deliveryStatus.uts或相应工具文件。
操作建议(下一步)
- 我可以为你:
- 在代码中实现“条件接单”补丁(修改
index.uvue与order-detail.uvue的acceptOrder/acceptTask函数),并提交一个 patch;或者 - 生成一个状态映射工具文件并替换当前页面中的硬编码映射;或者
- 把本文档整理为项目 wiki 条目并打开 PR。
- 在代码中实现“条件接单”补丁(修改
请选择一个你希望我继续执行的项(例如“帮我做 1:实现条件接单补丁”),我会把对应步骤加入 TODO 并实现。