Files
medical-mall/pages/mall/delivery/doc/old/DELIVERY_LOGIC.md
2026-02-06 15:10:18 +08:00

97 lines
6.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 配送端逻辑说明(概要与建议)(舍弃)
**概览**
- 本文档总结 `pages/mall/delivery` 目录下配送端主要页面的工作流与实现细节,定位到关键数据库表与状态机,列出已识别的并发/同步风险,并给出可执行的改进建议。
- 主要参考页面:
- [pages/mall/delivery/index.uvue](pages/mall/delivery/index.uvue)
- [pages/mall/delivery/order-history.uvue](pages/mall/delivery/order-history.uvue)
- [pages/mall/delivery/profile.uvue](pages/mall/delivery/profile.uvue)
- [pages/mall/delivery/order-detail.uvue](pages/mall/delivery/order-detail.uvue)
**主要数据表(后端)**
- `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`
**已识别风险与可改进点**
- 状态不一致风险:
- `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 与数据正确性。
**短期可执行修复(优先级排序)**
1. 接单使用条件更新(高优先)
- 在接单接口/前端更新时改为条件写入:
- SQL/SDK 示例UPDATE ml_delivery_tasks SET driver_id = :driverId, status = 2 WHERE id = :taskId AND driver_id IS NULL
- 若返回表示 0 行更新,则提示“已被其他人接单”,并刷新列表。
- 目的:避免重复接单的竞态。
2. 统一状态映射抽象(中优先)
- 在前端添加一个状态映射工具函数(例如 mapTaskStatusToOrderStatus(status)),并在每处状态同步时使用该映射。集中维护会减少散落的 magic number。
3. 增强表间同步可靠性(中优先)
- 将关键同步(例如确认送达)封装为后端事务或 RPC后端在事务中同时更新 `ml_delivery_tasks``ml_orders`,并返回原子成功/失败。前端只负责触发该 API。
4. 替换 localStorage 同步(低优先)
- 使用队列/事件或服务端记录(例如在确认送达时写入 `ml_delivery_tasks`,历史页直接查询,不依赖 localStorage 写入),或者使用 WebSocket / 推送通知触发历史刷新。
5. 补全 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` 或相应工具文件。
**操作建议(下一步)**
- 我可以为你:
1. 在代码中实现“条件接单”补丁(修改 `index.uvue``order-detail.uvue``acceptOrder/acceptTask` 函数),并提交一个 patch或者
2. 生成一个状态映射工具文件并替换当前页面中的硬编码映射;或者
3. 把本文档整理为项目 wiki 条目并打开 PR。
请选择一个你希望我继续执行的项(例如“帮我做 1实现条件接单补丁”我会把对应步骤加入 TODO 并实现。