# 历史订单 页面说明（order-history.uvue）

## 概要
`order-history.uvue` 用于配送员查看历史订单与近期任务。页面会展示：
- 以 `ml_delivery_tasks` 为配送端“状态真源”的任务记录（只要 `driver_id = 当前司机` 且 `status >= 2`，均会包含在统计/列表中）；
- 页面会批量回填对应 `ml_orders.order_no` 以补全显示（若 `order_no` 缺失会显示回退文本），避免直接以 `ml_orders.order_status` 作为展示依据而导致与配送端不一致。

页面关键点：
- 首次加载时通过 `loadOrderHistory()` 拉取数据；页面每次显示时会检查本地存储 `completed_order_for_history`，并把刚完成订单插入列表表头。
- 使用 Supabase 客户端 `supa` 读取 `ml_delivery_tasks` 与 `ml_orders` 表，并通过 `getCurrentUser()` / `getCurrentUserId()` 获取当前用户/司机 id。

## 行为细节
- 当前实现优先以 `ml_delivery_tasks`（status >= 2）作为数据源，页面会：
  - 查询 `ml_delivery_tasks` 中与 `driver_id` 相关的任务，按时间排序并映射为页面项；
  - 对获取到的 `order_id` 列表做一次批量查询 `ml_orders` 以回填 `order_no` 和订单详情；
  - 对没有匹配到 `ml_orders` 的 `order_id`，页面会用短 id 回退显示并在控制台打印缺失 id 列表，便于后台核查数据不一致的原因。
- 为避免重复展示，页面在将“当前任务对应订单”插入顶部时，会先检查 `orderList` 是否已有相同 `id`。

## 依赖 & 相关文件
- 页面文件：`pages/mall/delivery/order-history.uvue`（当前）
- Supabase 实例：`components/supadb/aksupainstance.uts`（导出 `supa` 与 `supaReady`）
- 用户/会话工具：`utils/store.uts`（`getCurrentUser()`、`getCurrentUserId()`）
- 相关文档：
  - `pages/mall/delivery/doc/earnings.md`（收入聚合与 DB 建议）
  - `pages/mall/delivery/doc/test-user-1_at_123.com.md`（测试用户与 SQL 示例）

## 已实现的防护与诊断信息
- `supaReady` 在会话恢复时可能会进行网络刷新（refreshSession），该步骤可能较慢。为避免页面长时间阻塞，页面中对 `supaReady` 使用了 `Promise.race` 的 1.5s 超时包装：如果超时会打印警告并继续执行（某些依赖用户 id 的查询可能因此为空）。
- 如果 `getCurrentUserId()` 返回空，页面会尝试从 `supa.getSession()` 获取 auth id 并在 `ak_users` 表中查找对应的 `ak_users.id` 作为回退，这能修复 `driver_id` 在数据库中为 `ak_users.id` 的常见映射问题。

## 常见不一致现象说明
- 我们观察到的常见情况：`ml_delivery_tasks` 中的任务显示为“已完成”（配送端），但对应 `ml_orders.order_status` 仍为“已取消”或其它状态，导致不同页面显示冲突。原因通常为：
  - `ml_delivery_tasks.order_id` 为空或格式不一致（UUID vs string）；
  - `ml_orders` 没有相应行（数据尚未同步或被删除）；
  - RLS/权限导致前端不能读取或更新 `ml_orders`。 

建议排查 SQL（例）：
```
SELECT t.id AS task_id, t.order_id, t.status AS task_status, o.order_status
FROM public.ml_delivery_tasks t
LEFT JOIN public.ml_orders o ON o.id = t.order_id
WHERE t.status >= 2
ORDER BY t.created_at DESC
LIMIT 200;
```

如需我为你生成触发器或前端重试队列示例，我可以继续实现。

## 常见问题与排查步骤
1. 问题：页面没有显示当前已接订单（即使首页显示有当前任务）。
   - 检查控制台日志：页面会打印 `loadOrderHistory: currentUserId=`、`loadOrderHistory: session id fallback=`、`loadOrderHistory: delivery_tasks dtRes=`、`loadOrderHistory: ordersRes=`。把这些日志逐项核对：
     - `currentUserId` 应为 `ak_users.id`（或系统实际使用的 driver id）。
     - `dtRes`（delivery_tasks 查询）应包含对象数组，且数组项含 `order_id`。
     - `ordersRes` 应包含对应的 `ml_orders` 行。
   - 若 `dtRes` 为空且 `session id fallback` 有值，说明 `ak_users` 表中可能没有把 auth id 映射到 `ak_users.id`，需要把 `ak_users.auth_id` 填入或同步。
   - 若 `ordersRes` 为空，但 `dtRes` 非空，请检查 `ml_orders.id` 与 `ml_delivery_tasks.order_id` 的数据类型（例如 UUID vs string）以及 RLS 策略。

2. 问题：页面加载慢或时不时刷新。
   - 原因：多个页面在 `onShow`/`onLoad` 时发起多次 supa 查询，且 `supaReady` 恢复会话有时较慢，导致累积延迟。已在 `index.uvue` 增加了防抖与 `enableAutoRefresh` 开关来禁止自动刷新。
   - 排查：查看控制台是否有 `supaReady timeout/failed` 警告（若有，则说明会话恢复慢或失败）。

## 性能与安全建议
- 若数据量大，请在后端做分页与聚合（只返回必要字段）；避免一次性查询大量 `ml_orders` 字段。参见 `earnings.md` 中的后端接口建议。
- 长期建议：修改 `components/supadb/aksupainstance.uts` 中会话恢复逻辑，让刷新在后台异步进行或提供可配置的超时策略，避免阻塞页面加载。

## 测试步骤（快速）
1. 使用测试用户（参见 `test-user-1_at_123.com.md`）创建一个 `ml_delivery_tasks` 记录，`driver_id` 对应当前司机，且 `status >= 2`。
2. 在首页确认当前任务显示；然后打开“历史订单”页面，观察顶部是否显示该订单。若未显示，贴上控制台中 `loadOrderHistory:` 的相关日志给开发者排查。

## 变更历史
- 2026-02-02：添加回退 mapping（session -> ak_users.id）、supaReady 超时保护的说明、调试日志建议及性能建议。

---

如需我把文档翻译为英文或生成 README 风格的一页说明，我可以继续补充。
# order-history.uvue — 历史订单

## 概要
显示配送员历史订单（已完成/已取消等），并支持按时间范围过滤、分页和插入刚完成订单以做到“即时显示”。

## 数据结构
- `HistoryOrder`
	- `order_no`, `id`, `status`, `delivered_at`, `total_amount`, `shop_name`

## 关键方法
- `loadOrderHistory({start,end,page,size})`
	- 优先按 `ml_delivery_tasks` 中与 `driver_id` 相关的 `order_id` 拉取任务记录，再批量查询 `ml_orders` 获取详情。
	- 若后端支持直接按 `driver_id` 返回已完成订单则调用后端聚合接口更高效。

- `checkForNewCompletedOrder()`
	- 从 `uni.getStorageSync('completed_order_for_history')` 读取并合并到 `orderHistory` 顶部，随后清除本地缓存键。

## DB 查询示例（伪 SQL / supa）
```
const tasks = await supa.from('ml_delivery_tasks').select('order_id,delivered_at').eq('driver_id', driverId).eq('status', 4).order('delivered_at', { ascending: false }).limit(100).execute()
const orders = await supa.from('ml_orders').select('*').in('id', tasks.map(t=>t.order_id)).execute()
```

## 分页与筛选
- 使用后端分页（`page/size`），前端仅负责渲染和“加载更多”。
- 支持按日期区间和商家名模糊搜索。

## 注意事项
- 当从本地合并刚完成订单时，去重逻辑必不可少（按 `order_no` 或 `id`）。
- 对于大量历史数据，应依赖后端支持归档与按需加载。错误/异常应有兜底 UI（空状态/重试按钮）。

