数据库分析和对应不同角色页面

This commit is contained in:
not-like-juvenile
2026-02-06 15:10:18 +08:00
parent 33030bd20b
commit 56ae71babf
30 changed files with 3510 additions and 21 deletions

View File

@@ -0,0 +1,97 @@
# 配送端逻辑说明(概要与建议)(舍弃)
**概览**
- 本文档总结 `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 并实现。

View File

@@ -0,0 +1,37 @@
# 问题修复汇总报告 (2026-02-03)
## 1. 登录后无法进入首页的问题
**现象**:用户登录成功后页面无跳转,或者直接跳到了管理/分析后台。
**原因**
- `pages.json``pages/mall/admin/homePage/index` 排在首位,导致默认入口偏向管理端。
- `ak/config.uts` 中的 `IS_TEST_MODE` 开启时,登录页和启动页禁用了自动重定向。
- 登录逻辑中缺少对 `setIsLoggedIn` 的调用,导致全局状态未激活。
**修复方案**
- 修改 `pages/user/login.uvue`,无论是否在测试模式,登录成功后显式执行 `uni.switchTab` 跳转至 `/pages/mall/consumer/index`
- 补全了 `utils/store.uts` 中相关状态管理函数的导入。
## 2. 分析页面 (Profile) 报错
**现象**:编译时提示 `Unexpected token`,页面无法打开。
**原因**
- `pages/mall/analytics/profile.uvue` 中的 `loadReportCounts` 函数缺少一个闭合花括号 `}`,导致语法解析异常。
**修复方案**
-`pages/mall/analytics/profile.uvue` 中补全了完整的代码结构。
## 3. H5 页面刷新后数据消失 (0数据)
**现象**:在配送端或用户中心,刷新页面后“今日统计”或“用户信息”变为 0 或空。
**原因**
- 在 H5 环境下刷新会导致内存中的变量Vue Reactive State重置。
- 如果 Supabase Session 恢复较慢,或者使用了模拟账号(如 `admin`),会导致系统判定用户未登录,从而查询不到 ID。
**修复方案**
- **增强持久化**:在 `utils/store.uts``getCurrentUserId` 函数中加入了本地存储LocalStorage兜底。
- **登录保存**:在登录成功瞬间,将 `user_id` 写入 `uni.setStorageSync('user_id', ...)`
- **模拟账号优化**:针对 `admin` 账号在刷新后不会因为没有远程 Session 而被踢出。
---
## 待核对事项
- **首页顺序**:如果需要默认进入移动全商城而非管理后台,请调整 `pages.json` 的数组顺序。
- **订单数据**:目前“附近订单”在日志中显示有数据,但若在界面显示不全,请检查 `ml_delivery_tasks` 表中的 `status` 是否符合筛选条件。

View File

@@ -0,0 +1,81 @@
# 状态 15 行为与代码位置说明
本文档针对 `ml_delivery_tasks.status` 中 15 的状态,逐项列出在 delivery 页面中涉及的展示、查询、更新位置、按钮/动作与已发现的不一致点与建议。
## 状态 1 — 待接取
- 映射文本/样式
- `index.uvue`: `getTaskStatusClass` -> `task-pending`(见 index.uvue getTaskStatusClass
- `index.uvue`: `getTaskStatusText` case 1 -> '待接取'index.uvue#L571
- `order-history.uvue`: 同样映射order-history.uvue#L230, #L242
- 查询/展示
- `loadAvailableOrders` 查询:`supa.from('ml_delivery_tasks').is('driver_id','null').eq('status', 1)`index.uvue loadAvailableOrders
- 在可接订单列表与当前任务区显示“接受任务/接受订单”按钮index.uvue#L81、order card accept button
- 更新/操作
- 接单时更新为 `status = 2``supa.from('ml_delivery_tasks').update({ driver_id: driverId, status: 2 }).eq('id', ...)`index.uvue acceptTask / acceptOrderindex.uvue#L602,#L756
- 建议/注意
- 接单使用条件更新或后端 RPC 避免抢单竞态(目前无 WHERE driver_id IS NULL 条件)。
## 状态 2 — 已接取
- 映射文本/样式
- `index.uvue` 文本 '已接取'index.uvue#L572),样式 `task-accepted`index.uvue#L560
- `order-history.uvue` 相应映射order-history.uvue#L243
- 查询/展示
- 当前任务区显示“开始取货”按钮index.uvue#L82
- `order-detail.uvue``order.status === 2` 显示“前往取货/正在取货”order-detail.uvue#L169-L170
- 更新/操作
- `startPickup()` 会将 task 状态更新为 3index.uvue startPickup
- 接单后代码尝试同步 `ml_orders.order_status = 2`index.uvue#L766
- 建议/注意
- 同步 ml_orders 的操作应做失败回退处理或在服务端做原子事务。
## 状态 3 — 取货中
- 映射文本/样式
- `index.uvue` 文本 '取货中'index.uvue#L573),样式 `task-picking`index.uvue#L561
- `order-history.uvue` 同步映射order-history.uvue#L244
- 查询/展示
- 当前任务区显示“确认取货”按钮index.uvue#L83
- `order-detail.uvue` 在 route 区显示“确认取货”按钮order-detail.uvue#L55,#L173
- 更新/操作
- `confirmPickup()` 将 status -> 4 并写入 `pickup_time`,同时尝试把 `ml_orders.order_status = 4`index.uvue & order-detail
- 建议/注意
- 确认取货应当原子更新任务与订单状态,或由后端封装接口完成。
## 状态 4 — 已取货
- 映射文本/样式
- `index.uvue` 文本 '已取货'index.uvue#L574),样式 `task-picked`index.uvue#L562
- `order-history.uvue` 文本 '已取货'order-history.uvue#L245
- 查询/展示
- 当前任务区显示“开始配送”按钮index.uvue#L84
- `order-detail.uvue` 显示“确认送达”按钮order-detail.uvue#L68,#L176
- 更新/操作
- `startDelivery()` 将 status -> 5index.uvue startDelivery
- 建议/注意
- 明确 4 与 5 的边界并在统计/历史中统一口径(是否将 5 视作已完成)。
## 状态 5 — 配送中
- 映射文本/样式
- `index.uvue` 文本 '配送中'index.uvue#L575),样式 `task-delivering`index.uvue#L563
- `order-history.uvue` 在样式处标为 `status-delivered`order-history.uvue#L234)且文本处 `case 5: return '已完成'`order-history.uvue#L246)——存在不一致。
- 查询/展示
- 当前任务区显示“确认送达”入口index.uvue#L85 -> showConfirmDeliveryDialog
- `order-detail.uvue` 在状态 >=5 时进度条显示为已送达getStatusDesc
- 更新/操作
- `confirmDelivery()` 将 task.status -> 6 并写入 `delivered_time`,再尝试同步 `ml_orders.order_status = 5`index.uvue#L679-691
- 建议/注意
- 目前统计(如 todayStats`status >= 5` 视作“已完成”计数,而 UI 有时把 5 显示为“配送中”,建议统一规则(推荐:把 6 视作真正完成5 为配送中)。
## 跨页不一致与改进建议(摘要)
- 不一致点:`status = 5` 在不同页面既被视作“配送中”,又被视作“已完成”;`confirmDelivery` 设置 task=6但统计使用 `>=5` 判断完成,导致计数或展示差异。
- 建议:
1. 明确“完成”阈值推荐status === 6 为已完成status === 5 为配送中并在所有统计、过滤、UI 映射处统一实现。
2. 将状态映射抽到共享工具文件 `utils/deliveryStatus.uts` 并替换硬编码。
3. 接单、确认取货、确认送达等关键操作应使用后端事务或条件更新避免竞态与不一致。
---
文档已生成于 `pages/mall/delivery/STATE_1-5_LOGIC.md`。要我现在:
- A) 将 `getTaskStatusText` / `getOrderStatusText` 抽到 `utils/deliveryStatus.uts` 并替换页面中的映射,或
- B) 实现接单的条件更新补丁(修改 `acceptTask` / `acceptOrder`),或
- C) 仅把“5 是否计作完成”的规范改写回 `DELIVERY_LOGIC.md` 并提交。
请选择一项继续。

View File

@@ -0,0 +1,51 @@
## 1. 功能概述
`all.uvue` 是为配送端设计的全量订单抓取页面。当首页待接订单超过 5 个时,用户可通过此页面查看并抢单。
## 2. 核心设计说明
根据最新 UI 指标,该页面采用了**现代垂直流布局**
- **中心费用展示**:订单金额在卡片顶部居中加粗显示,强化利益点。
- **垂直路径流**:采用垂直排布的取货(📍)与送达(🏠)地址,中间以箭头连接,更符合手机屏阅读习惯。
- **全宽操作按钮**:底部采用 100% 宽度的按钮,提高抢单操作的触达率。
- **实时空态处理**:当订单被他人抢先接走时,列表会自动更新。
## 3. 技术实现要点
### 3.1 数据安全与并发控制
在执行 `acceptOrder`(抢单)时,通过数据库约束确保操作的原子性:
```uts
// 增加 driver_id 为空的前提条件,防止已被他人接单
const res = await supa.from('ml_delivery_tasks')
.update({
driver_id: driverId,
status: 2,
accepted_at: new Date().toISOString()
})
.eq('id', taskId)
.is('driver_id', 'null') // 关键:确保单子还没被接
.execute();
```
### 3.2 数据结构转换 (`_transformTask`)
为了兼容数据库存储的 JSON 字符串格式与 UI 组件所需的 Object 格式,页面内置了转换逻辑:
- 自动解析 `pickup_address``delivery_address` JSON 字符串。
- 格式化 `delivery_fee` 为保留两位小数。
- 映射状态码到对应的 UI 标签。
### 3.3 路由与交互
- **路由路径**`pages/mall/delivery/all`
- **导航栏**:配置了 `navigationBarTitleText: "待接订单"`,并开启了原生的回退功能。
- **动态跳转**:支持从详情页返回后自动刷新列表(通过 `onShow` 触发)。
## 4. 样式规范
- 布局Flexbox (Column)
- 配色:
- 取货点Pink (`#ff4d94`)
- 送达点Blue (`#2196F3`)
- 主按钮Green (`#4CAF50`)
- 间距:标准 30rpx 外边距,卡片内 40rpx 内边距。
## 5. 开发历史
- **2026-02-03**: 页面初版创建。
- **2026-02-03**: 完成从水平卡片到垂直流卡片的 UI 重构。
- **2026-02-03**: 接入 Supabase 实现秒级抢单逻辑与状态同步。

View File

@@ -0,0 +1,170 @@
# Delivery 模块 — 总体架构
## 概要
本文件给出配送delivery模块的总体架构说明覆盖前端视图组件、后端数据表与 API 交互、关键业务流、并发/事务策略与建议改进方向,便于开发者与运维快速理解与修改。
## 架构概览
- 前端Uni-app / .uvue 组件):负责页面渲染、用户交互与轻量校验,主要文件位于 `pages/mall/delivery/`
- 后端Supabase/Postgres + RPC负责数据持久化、原子操作、权限校验与并发控制。建议将关键并发操作例如“接单”放在后端 RPC/函数中执行。
- 数据层Postgres 表):主表包括 `ml_orders``ml_order_items``ml_shops``ml_delivery_tasks``ml_delivery_drivers` 等。
- 通信:前端通过 Supabase 客户端或后端 HTTP RPC 调用进行读写;推荐对写操作使用后端受限 RPC减小竞态风险。
## 前端组件映射(关键文件)
- 入口与导航:`pages/mall/delivery/index.uvue`(模块入口)
- 任务列表 / 历史:`pages/mall/delivery/tasks.uvue``pages/mall/delivery/order-history.uvue`
- 任务详情 / 订单详情:`pages/mall/delivery/task-detail.uvue``pages/mall/delivery/order-detail.uvue`
- 配送员信息:`pages/mall/delivery/profile.uvue` / `profile-edit.uvue`
- 收益 / 统计:`pages/mall/delivery/earnings.uvue`
- 车辆管理:`pages/mall/delivery/vehicle.uvue``vehicle-add.uvue``vehicle-edit.uvue`
- 帮助/反馈/测试:`help-center.uvue``feedback.uvue``test.uvue`
对应文档(开发说明)位于 `pages/mall/delivery/doc/`,每个视图对应一个 `.md` 说明文件(例如 `order-detail.md``tasks.md` 等)。
## 数据模型(常用字段 / 表)
- `ml_orders`: id, cid, order_no, user_id, merchant_id, order_status / status, total_amount, shipping_fee, paid_amount, shipping_address, remark, created_at
- `ml_order_items`: id, order_id, product_id, product_name, quantity, price, image_url
- `ml_shops`: id, merchant_id, shop_name, contact_name, contact_phone, address
- `ml_delivery_tasks`: id, order_id, driver_id, status, distance, estimated_time, pickup_time, delivered_time, created_at
- `ml_delivery_drivers`: id, user_id, vehicle_id, status
字段命名在代码中可能存在兼容写法(如 `order_status` vs `status``shipping_fee` vs `delivery_fee`),建议在前端统一使用一个转换函数 `normalizeOrderRow(row)` 做映射。
## 关键业务流(简要)
- 接单Accept
- 不要在前端直接做盲写;推荐后端 RPC 原子化操作:
- SQL 示例(后端执行):
```sql
UPDATE ml_delivery_tasks
SET driver_id = $1, status = 2
WHERE order_id = $2 AND (driver_id IS NULL OR driver_id = '')
RETURNING *;
```
- 前端调用 RPC根据返回行数判断是否接单成功若返回 0 行则提示“已被其他配送员接单”。
- 确认取货 / 确认送达
- 后端更新 `ml_delivery_tasks` 的时间戳字段(`pickup_time` / `delivered_time`)并更新 `ml_orders.order_status`,前端在成功回调后同步 UI 状态并展示时间戳。
- 读取详情页order-detail
- 并行查询 `ml_orders`, `ml_order_items`, `ml_shops`, `ml_delivery_tasks` 并合并结果,务必对空值做兼容处理(地址可能是字符串或对象)。
## 并发与事务策略
- 将所有会改变接单归属或状态的操作放在数据库事务或后端函数中执行,前端仅调用并根据返回结果更新 UI。
- 使用行级条件(`WHERE driver_id IS NULL` / `WHERE order_status = expected`)与 `RETURNING` 判断是否成功,避免乐观锁冲突。
- 在前端增加防重loading 标志位、按钮禁用)和超时重试策略,并记录幂等请求 ID如必要
## 错误处理与监控
- 前端对所有写操作展示用户友好错误(网络错误 / 已被接单 / 权限不足)。
- 后端应记录关键操作日志(接单、拒单、确认取货/送达),并导出指标(接单失败率、并发冲突数)。
## 权限与安全
- 接单/确认类操作必须在后端校验当前用户是合法配送员(基于 `ml_delivery_drivers.user_id`),并确保 RPC 仅对认证用户开放。
## 开发与测试建议
- 在 `pages/mall/delivery/test/create_test_orders.sql` 中准备自动化测试数据,用于本地/CI 环境的集成测试。
- 在前端加入单元测试/集成测试用例,模拟并发接单场景,验证后端 RPC 行为。
## 建议改进(优先级)
- 高:把接单逻辑迁移为后端 RPC前端只调用并根据返回结果更新 UI。
- 高:在所有变更接口返回受影响行数与最新状态,便于前端做幂等与回退。
- 中:统一并导出状态常量(例如 `ORDER_STATUS`)供前端与文档引用,避免魔法数字。
- 中:为详情页加入字段规范示例(在 `order-detail.md` 中补充),并同步到 API 文档。
---
(如需将 `order-detail.uvue` 的接单逻辑改为调用 RPC 并添加 loading 状态,我可以继续提交补丁。)
# Delivery 模块文档
本文档为 `pages/mall/delivery` 模块的开发与运维手册,已按与 `analytics` 模块相近的结构补充:概览、文件清单、技术特性、页面架构、实现要点、部署与测试建议、下一步计划与代码质量指引。
## 概览
配送端Delivery面向配送员覆盖司机状态管理、任务与订单流转、配送记录/历史、收入统计、个人资料与车辆管理、帮助与反馈。页面既包含前端聚合逻辑也与后端Supabase / RPC交互实现关键业务。
## 文件清单(快速索引)
- [about.uvue](pages/mall/delivery/about.uvue) — 关于我们(静态)
- [index.uvue](pages/mall/delivery/index.uvue) — 配送端首页(司机信息、今日统计、可接订单)
- [tasks.uvue](pages/mall/delivery/tasks.uvue) — 任务列表(筛选、分页)
- [task-detail.uvue](pages/mall/delivery/task-detail.uvue) — 任务详情(联系、取货、完成)
- [order-detail.uvue](pages/mall/delivery/order-detail.uvue) — 订单详情(多表聚合、状态流转)
- [order-history.uvue](pages/mall/delivery/order-history.uvue) — 历史订单(本地合并刚完成订单显示)
- [earnings.uvue](pages/mall/delivery/earnings.uvue) — 收入明细(按 `order_no` 聚合)
- [profile.uvue](pages/mall/delivery/profile.uvue) — 个人中心与入口
- [profile-edit.uvue](pages/mall/delivery/profile-edit.uvue) — 编辑资料(头像、服务区域)
- [vehicle.uvue](pages/mall/delivery/vehicle.uvue) — 车辆管理(列表/新增/编辑)
- [vehicle-add.uvue](pages/mall/delivery/vehicle-add.uvue) — 添加车辆表单
- [vehicle-edit.uvue](pages/mall/delivery/vehicle-edit.uvue) — 编辑车辆
- [feedback.uvue](pages/mall/delivery/feedback.uvue) — 意见反馈(图片、关联订单)
- [help-center.uvue](pages/mall/delivery/help-center.uvue) — 帮助中心/FAQ
- [ratings.uvue](pages/mall/delivery/ratings.uvue) — 评价记录(分页/筛选)
- [settings.uvue](pages/mall/delivery/settings.uvue) — 设置页
- [test.uvue](pages/mall/delivery/test.uvue) — Supabase 连接/权限诊断
## 技术特性
- UTS / Uni-app 页面实现(`.uvue`),兼容 UTS Android 规范类型定义、UTSJSONObject 使用等)。
- 使用 `supa`(项目内 Supabase 封装进行数据读取、RPC 调用与认证。示例:`supa.from('ml_delivery_tasks')`、`supa.rpc('rpc_analytics_top_products', params)`analytics 模式的参考)。
- 本模块使用本地存储做页面间临时数据传递(`uni.setStorageSync`),并在部分页面(如 `vehicle`、`order-history`)合并本地临时项以支持无后端或原型场景。
- 对接建议:关键写操作(接单/状态变更)必须依赖后端原子性保护(事务或 WHERE driver_id IS NULL 的更新语句)。
## 页面架构与实现要点
- 首页(`index.uvue`):聚合 `driver`、`todayStats`、`currentTask` 与 `availableOrders`;包含 `_transformTask` 用于兼容多种地址/联系人字段格式。
- 订单详情(`order-detail.uvue`):按 id 格式选择查询字段(`id`/`cid`/`order_no`),并联查 `ml_order_items`, `ml_shops`, `ml_delivery_tasks`;提供接单/拒单/确认取货/确认送达等操作。
- 任务流(`tasks` / `task-detail`):任务筛选(待接单/进行中/已完成)与详情页的状态变更操作;完成时应记录时间戳与凭证以便对账。
- 收入(`earnings`):前端按 `order_no` 聚合并补齐来源类型,建议后端提供已聚合接口以提升性能与准确性。
- 个人/车辆页:使用图片上传、表单校验与本地缓存作为临时方案;生产应对接车辆管理 API 并保存到服务端。
## 典型 DB / RPC 示例
Supabase (supa) 示例:
```
// 查询司机信息
await supa.from('ml_delivery_drivers').select('*').eq('user_id', userId).limit(1).execute()
// 查询可接任务(示例)
await supa.from('ml_delivery_tasks').select('*').is('driver_id', null).eq('status', 1).order('created_at', { ascending: false }).range(offset, offset+size-1).execute()
// 接单(需后端并发保护)
await supa.from('ml_delivery_tasks').update({ driver_id: driverId, status: 2 }).eq('id', taskId).eq('driver_id', null).execute()
```
## 样式与 UI 设计
- 推荐采用与 `analytics` 模块相同的卡片式布局与 KPI 卡片样式(便于统一风格);关键组件(任务卡、订单明细卡、统计卡)应抽象成可复用组件以减少重复代码。
## 部署与配置
- 环境变量:确认 `SUPA_URL`/`SUPA_KEY` 在 `ak/config.uts` 或环境配置中正确配置。
- 本地测试:使用 `pages/mall/delivery/test.uvue` 验证 Supabase 连接与权限(避免在仓库暴露明文 key
## 测试建议
- 功能测试:接单并发测试、状态流转(取货/送达)、图片上传与表单校验、分页与历史数据展示。
- 兼容性Android/不同屏幕尺寸测试UTS Android 兼容性须验证)。
- 性能:大量任务/历史记录分页测试,收入聚合在后端做性能验证。
## 下一步计划
1. 抽取并复用 UI 组件(任务卡、订单详情卡、统计 KPI 卡)。
2. 将前端聚合逻辑(如 `earnings`)迁移或补充后端聚合接口以提升性能。
3. 用后端事务或乐观锁增强接单并发保护,并在前端实现失败回退提示。
4. 添加自动化测试用例覆盖关键流程(接单/确认/拒单/结算)。
---
Generated on: 2026-02-02
## 快速参考(已合并页摘要)
- `about.uvue`:关于我们(静态信息,运营可从 CMS 拉取版本/更新日志)。
- `help-center.uvue`:帮助中心 / FAQ本地数组或后端搜索支持分类与全文检索
- `settings.uvue`:设置页(通知、语言、隐私、登出),存储建议使用 `uni.setStorageSync` + 后端同步。
- `feedback.uvue`:意见反馈(文本 + 图片 + 关联订单),图片需先上传再提交 URL。
- `ratings.uvue`:评价记录列表(分页筛选,可能需要后端审核/屏蔽)。
- `profile.uvue` / `profile-edit.uvue`:个人中心与编辑(头像上传、服务区域、车辆信息),建议在保存后同步刷新缓存。
- `vehicle*.uvue`:车辆管理相关(列表/新增/编辑),当前以本地存储为演示,生产应对接 REST 接口并做权限校验。
(已把上述 per-page md 移动到 `pages/mall/delivery/doc/archive/`,保留历史版本以便追溯。)
---
Generated on: 2026-02-02
---
Generated on: 2026-02-02

View File

@@ -0,0 +1,92 @@
# earnings.uvue — 收入明细
## 概要
`order_no` 聚合展示配送员收入明细(配送费、用户打赏、商家打赏),支持分页加载与按时间区间统计。
## 数据结构
- `EarningItem`
- `id: string`
- `order_no: string`
- `date: string`
- `amount: number`
- `source: 'delivery_fee' | 'user_tip' | 'merchant_tip' | string`
- `distance?: number`
- `OrderEarning`
- `order_no: string`
- `date: string`
- `distance?: number`
- `totalAmount: number`
- `details: EarningItem[]`
## 关键方法
- `loadAllEarnings()`
- 从后端或本地数据源取原始 `EarningItem[]`,按 `order_no` 聚合成 `OrderEarning[]`
- 对每个 `OrderEarning.details` 补齐三类来源占位项amount=0以保证前端渲染顺序稳定。
- `calculateTotalStats()`
- 计算 `totalEarnings`, `totalUserTips`, `totalMerchantTips`
- `loadPage()` / `loadMore()`
- 基于 `pageSize` 控制分页渲染,避免一次性载入全部历史记录。
## 聚合示例(核心)
```
const orderMap = new Map()
raw.forEach(item => {
let order = orderMap.get(item.order_no)
if (!order) {
order = { order_no: item.order_no, date: item.date, distance: item.distance, totalAmount: 0, details: [] }
orderMap.set(item.order_no, order)
}
order.totalAmount += Number(item.amount || 0)
order.details.push(item)
})
// 补齐三类来源
orderMap.forEach(order => {
const has = type => order.details.some(d => d.source === type)
;['delivery_fee','merchant_tip','user_tip'].forEach(t => { if (!has(t)) order.details.push({ id: `${order.order_no}_${t}`, order_no: order.order_no, amount: 0, source: t }) })
})
const result = Array.from(orderMap.values())
```
## 接口 / DB 建议
- 推荐后端提供按订单聚合的接口:
- GET `/api/driver/{id}/earnings?start=&end=&page=&size=`
- 返回 `OrderEarning[]` 已聚合的数据以减轻前端压力
## 数据源更新包含已接订单Accepted
- 需求说明为了与“历史订单”页面保持一致收入统计应包含配送员已接取accepted/assigned的订单不仅限于已完成订单。也就是说只要 `ml_delivery_tasks``driver_id` = 当前司机且 `status >= 2`(已接取或进行中),其对应的订单都应计入收入统计范围。
- 需求说明(已采纳):收入统计以 `ml_delivery_tasks` 为数据源之一:只要任务记录显示 `driver_id` = 当前司机且 `status >= 2`(已接取或进行中),其对应订单即应计入统计范围。注意:部分 `ml_delivery_tasks` 可能没有可匹配的 `ml_orders``order_id` 为空或在 `ml_orders` 中找不到),页面/后端应对缺失 `order_no` 做回退显示并记录供核查。
- 推荐 Supabase 查询示例(后端或前端按需实现):
```
-- 查询分配给当前司机且已接取的任务对应的订单ID
SELECT DISTINCT order_id FROM ml_delivery_tasks WHERE driver_id = :driverId AND status >= 2;
-- 基于 order_id 查询订单及收入项示例ml_orders + ml_delivery_tips
SELECT o.id,o.order_no,o.created_at,o.distance,o.delivery_fee, t.amount as tip_amount, 'user_tip' as tip_source
FROM ml_orders o
LEFT JOIN ml_delivery_tips t ON t.order_id = o.id
WHERE o.id IN (<order_id_list>)
ORDER BY o.created_at DESC
LIMIT :size OFFSET :offset;
```
- 若在前端直接使用 `supabase-js`
```js
const taskRes = await supa.from('ml_delivery_tasks').select('order_id').eq('driver_id', uid).gte('status', 2).execute()
const orderIds = taskRes.data.map(r => r.order_id)
// 对于 order_id 为空或找不到的情况server 端应记录这些 id 以便排查
const ordersRes = await supa.from('ml_orders').select('*,ml_delivery_tips(*)').in('id', orderIds).order('created_at',{ascending:false}).limit(size).execute()
```
注意:若订单很多,务必在后端做分页/聚合以减轻客户端开销。
## 注意事项
- 在金额计算中使用整数 cents 或 BigInt 或固定小数处理,避免浮点误差。
- 大量数据应后端分页/聚合并支持过滤(按时间、按来源)。

View File

@@ -0,0 +1,73 @@
# index.uvue — 配送端首页
## 概要
配送员主界面,包含司机信息、在线/离线切换、今日统计、当前配送任务、附近可接订单与快捷入口。
## 数据结构
- DeliveryDriverType (来自 `ml_delivery_drivers`)
- id, user_id, real_name, avatar_url, work_status, vehicle_type, vehicle_number, rating, service_areas, ...
- CurrentTaskType / AvailableOrderType
- id, order_no, status, pickup_address, delivery_address, pickup_contact, delivery_contact, delivery_fee, distance, estimated_time, created_at
## 关键方法
- `onLoad()`
- 调用 `getCurrentUser()` 确保用户上下文可用
- 执行:`loadDriverInfo()`, `loadTodayStats()`, `loadCurrentTask()`, `loadAvailableOrders()`
- `loadDriverInfo()`
-`ml_delivery_drivers` 表按 `user_id` 查询并更新 `driverInfo`
- `loadTodayStats()`
- 查询 `ml_delivery_tasks` 在当天范围内的记录,计算完成订单数、总收入、配送里程等。
- `loadCurrentTask()`
- 查询 `ml_delivery_tasks` 中 driver_id 的未完成任务status < 5并取最新一条作为当前任务。
- `loadAvailableOrders()`
-`isOnline` 且无 `currentTask`,从 `ml_delivery_tasks` 查询 `driver_id IS NULL` 且 status=1 的订单列表(可按地理位置筛选)。
- `_transformTask(task)`
- 兼容处理 `pickup_address` / `delivery_address``pickup_contact` 的多种格式(对象或 JSON 字符串),输出页面期望结构。
## 关键 DB 查询 示例
```
await supa.from('ml_delivery_drivers').select('*').eq('user_id', userId).limit(1).execute()
await supa.from('ml_delivery_tasks')
.select('id,delivery_fee,distance,created_at,status')
.eq('driver_id', driverId)
.gte('created_at', start)
.lte('created_at', end)
.execute()
```
## 交互与状态流
- `toggleWorkStatus()`:切换 `isOnline` 并调用 `startWork()` / `stopWork()`。上线时会刷新可接订单列表。
- 接单/开始取货/确认取货/开始配送/确认送达等均通过对 `ml_delivery_tasks``update` 操作变更 `status`,并在成功后更新本地 `currentTask`
## UI 行为变动(已生效)
- 当页面检测到存在 `currentTask`(来自 `ml_delivery_tasks`)时,页面不会再弹出“附近可接订单”列表。即:配送端以 `ml_delivery_tasks` 为状态真源,主页面的订单展示不再依赖或回退展示 `ml_orders.order_status`,以避免两表不同步导致的显示冲突。
- 为了减少页面闪烁与重复刷新,`enableAutoRefresh` 在默认实现中已可被关闭(`false`),且 `loadAvailableOrders()` 在检测到 `currentTask` 时会跳过可接订单的渲染。
## 会话与加载保护
- `supaReady` 的会话恢复在某些环境中会较慢,页面中已对其使用 `Promise.race(..., 1500)` 超时包装:超时后页面会打警告并继续渲染以避免长时间阻塞用户界面。依赖用户 id 的查询在超时情况下可能为空,请参照 `order-history.md` 的“已实现的防护”部分进行排查。
## 前端同步尝试(临时)
- 在接单/确认送达流程中前端会尝试向 `ml_orders` 发送更新(将 `order_status` 同步到任务的状态)并记录返回结果用于诊断。但该同步并不保证在所有权限或网络错误下成功,因此更稳妥的方案仍是后端触发器同步或可信服务端接口。
## 注意事项
- 高并发接单场景需后端保证原子性(乐观锁或 DB 事务)以防止竞单冲突。
- `loadAvailableOrders()` 最好按司机服务区域与距离筛选,并使用分页/实时推送代替频繁轮询。
- 日志console.log语句便于调试但生产环境建议使用集中化日志系统。
# index.uvue — 配送端首页
页面目的:配送员主界面,展示司机资料、工作状态、今日统计、当前任务与可接订单。
关键点:
- 数据加载:`onLoad()` 调用 `getCurrentUser()` 后依次调用 `loadDriverInfo()`, `loadTodayStats()`, `loadCurrentTask()`, `loadAvailableOrders()`
- Supabase 交互:通过 `supa.from(...).select(...).eq(...).execute()` 查询 `ml_delivery_drivers``ml_delivery_tasks` 等表。
- 兼容解析:`_transformTask(task)` 将 DB 返回的地址/contact 字段兼容解析为页面所需结构(处理字符串或对象)。
- 操作:接单/开始取货/确认取货/开始配送/确认送达等,会调用 supa 更新 `ml_delivery_tasks` 状态并同步页面状态。
注意:对 supa 操作有大量 try/catch页面对无用户 ID 情况做了保护,适合直接对接真实后端。

View File

@@ -0,0 +1,118 @@
## 目的
当“附近订单”过多时,在主页面展示前 N 条(当前为 20 条),需要提供“更多”入口,跳转到单独页面展示所有可接取的订单并支持翻页/上拉加载。
## 路由与文件
- 主入口:在 `pages/mall/delivery/index.uvue` 的“附近订单”区块新增“更多”按钮,导航到新页面。
- 新页面文件:`pages/mall/delivery/all.uvue`(建议路径)
- 文档说明文件:`pages/mall/delivery/doc/more-orders.md`(本文件)
## 用户流程
1. 用户在 `index.uvue` 看到“附近订单”列表(最多 20 条)。
2. 当可接取订单数量 >= 20 时,显示“更多”按钮。
3. 点击“更多”跳转到 `all.uvue`,展示可接取订单的完整列表(分页或无限滚动)。
4. 用户可在新页面接受订单或刷新列表。
## 后端 / 查询设计示例Supabase 客户端)
- 建议分页参数:`pageSize = 50`(可配置)。
- 前端通过 offset/pagination 请求:
示例(首次加载 page=0, size=50
```ts
const page = 0
const size = 50
const res = await supa.from('ml_delivery_tasks')
.select('*')
.is('driver_id', 'null')
.eq('status', 1)
.order('created_at', { ascending: false })
.range(page*size, page*size + size - 1)
.execute()
```
- 翻页时将 `page` 增加;上拉加载时继续请求下一段 `range`
- 后端/数据库建议对 `ml_delivery_tasks` 建立索引status, driver_id, created_at以加速查询。
## 前端实现建议
- `index.uvue`:在 `availableOrders` 列表下方加入:
- 条件显示:`availableOrders.length >= 20` 时显示“更多”按钮。
- 点击处理函数:`uni.navigateTo({ url: '/pages/mall/delivery/all' })`
- `all.uvue` 页面职责:
- 使用与 `index.uvue` 相同的 `supa` 客户端和 `_transformTask` 方法复用数据格式化逻辑。
- 支持分页page + pageSize或无限滚动onReachBottom 加载下一页)。
- 显示空状态、加载中状态和错误提示。
示例数据加载片段(伪代码):
```ts
data() { return { page: 0, pageSize: 50, items: [], loading: false, finished: false } }
async loadPage() {
if (this.loading || this.finished) return
this.loading = true
const res = await supa.from('ml_delivery_tasks')
.select('*')
.is('driver_id', 'null')
.eq('status', 1)
.order('created_at', { ascending: false })
.range(this.page * this.pageSize, (this.page+1)*this.pageSize - 1)
.execute()
const rows = Array.isArray(res.data) ? res.data : []
if (rows.length < this.pageSize) this.finished = true
this.items.push(...rows.map(r => this._transformTask(r)))
this.page += 1
this.loading = false
}
```
## 并发与安全
- 接单时应在服务器端/数据库层做原子性判断,避免竞态:
- 示例(伪 SQL
UPDATE ml_delivery_tasks
SET driver_id = :driverId, status = 2
WHERE id = :taskId AND driver_id IS NULL AND status = 1
RETURNING id
- 前端在发起“接受订单”请求后,基于返回结果确认是否成功;若失败需提示用户订单已被接取。
## 接受标准/验收条件
-`index.uvue` 点击“更多”能跳转到 `all.uvue`
- `all.uvue` 能正确加载 >20 条可接订单并支持继续加载直到无更多数据。
- 接单操作的竞态由后端或事务性查询处理,前端能正确反馈成功/失败。
## 测试数据与验证
- 使用现有文档 `doc_mall/database/realistic_mock_data.sql` 创建若干测试订单;也可循环插入多条 `ml_delivery_tasks`status=1, driver_id=NULL用于分页测试。
示例快速生成Postgres 伪 SQL
```sql
INSERT INTO public.ml_delivery_tasks (order_id, pickup_address, delivery_address, delivery_fee, status, created_at, updated_at)
SELECT uuid_generate_v4(), '{"detail":"店铺"}'::jsonb, '{"detail":"用户地址"}'::jsonb, 5.0, 1, NOW() - (i || ' minutes')::interval, NOW()
FROM generate_series(1,200) as s(i);
```
## 开发任务清单(简要)
1.`pages/mall/delivery/index.uvue` 增加“更多”按钮並导航。
2. 新建 `pages/mall/delivery/all.uvue`,实现分页/上拉加载并复用 `_transformTask`
3. 后端或 DB 层确保接单操作的原子性。
4. 编写 E2E 或手动测试脚本验证加载与接单行为。
## 是否需要我实现?
如果你需要,我可以:
- 直接在 `index.uvue` 添加“更多”按钮示例(小改动)。
- 新增 `pages/mall/delivery/all.uvue` 的样板实现并提交 PR 样例。
---
文档已创建:`pages/mall/delivery/doc/more-orders.md`

View File

@@ -0,0 +1,47 @@
# order-detail.uvue — 订单详情
## 概要
展示单笔订单全部信息并提供状态流转(接单、确认取货、确认送达、拒单等)。页面会联合查询 `ml_orders``ml_order_items``ml_shops``ml_delivery_tasks`
## 数据结构(常用字段)
- `Order`
- `id: string | number`
- `order_no: string`
- `cid?: number` (兼容旧字段)
- `shipping_address | pickup_address`: object/string
- `shipping_fee`, `total_amount`, `status`
- `OrderItem`
- `id`, `order_id`, `product_name`, `qty`, `price`
- `DeliveryTask`
- `id`, `order_id`, `driver_id`, `status`, `accepted_at`, `picked_at`, `delivered_at`
## 关键方法
- `onLoad(options)`
- 解析 `options.id``options.status`,调用 `loadOrderDetail(id)`
- `loadOrderDetail(id)`
- **加载保护**:对 `supaReady` 采用 1.5s 超时策略包装,防止会话刷新阻塞页面加载。
- **智能 ID 回查**:优先从 `ml_orders` (UUID/cid/order_no) 查找。若未找到,则尝试从未分配任务表 `ml_delivery_tasks` 中根据 ID 查找,再反查关联订单。
- **降级机制Fallback**:当 `ml_orders` 行缺失时,自动回退到从 `ml_delivery_tasks` 提取地址、手机号、配送费及距离等基础信息进行展示,并在 UI 上显示回退加载提示。
- **清理加载状态**:在 `finally` 块中统一切除加载动画 (`uni.hideLoading`),防止界面挂起。
## 交互与样式优化2026-02-03 更新)
- **联系人信息解析**:地址栏(取货/送货)现在仅在“联系人姓名”存在时显示分隔点 `·`。若无姓名,则仅显示手机号,避免显示为 `. 手机号`
- **联系方式布局优化**:为了防止手机号在不同屏幕宽度下被图标遮挡,联系人区域采用**垂直居中布局**(图标在上,姓名电话在下),显著拉高了边框高度 (`min-height: 180rpx`) 并增加了垂直间距。
- **文本显示优化**
- 商品区域的“**订单号**”增加了加粗显示 (`bold`),提升核对便利性。
- 展示给配送员的联系手机号调大了字号并加粗,确保清晰可见。
- 修复了在 Uni-app x 下由于类型推断导致的手机号无法通过点语法访问的问题(改用索引访问)。
## 示例:地址兼容解析逻辑
```typescript
// 兼容 JSON 字符串及对象格式的地址字段
let shipping = {}
if (typeof raw == 'string') {
try { shipping = JSON.parse(raw) } catch (e) { shipping = { detail: raw } }
} else { shipping = raw || {} }
// 访问方式:(address as UTSJSONObject)['phone']
```

View File

@@ -0,0 +1,106 @@
# 历史订单 页面说明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添加回退 mappingsession -> 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空状态/重试按钮)。

View File

@@ -0,0 +1,25 @@
# profile-edit.uvue — 编辑资料
## 概要
编辑配送员个人资料(姓名、电话、头像、服务区域、车辆信息等),并将修改提交到后端保存。
## 数据结构
- `ProfileForm`
- `real_name`, `phone`, `avatar_url`, `service_areas[]`, `vehicle`{
`type`, `model`, `plate_no`
}
## 关键方法
- `chooseAvatar()``uni.chooseImage` 获取本地图片并调用 `uploadAvatar()` 上传。
- `uploadAvatar(file)`:上传到文件存储并返回 URL更新 `form.avatar_url`
- `saveProfile()`:表单校验后调用后端 API 更新 `ml_delivery_drivers``users` 表。
## 接口示例
```
await api.put('/driver/profile', { ...form })
```
## 注意事项
- 上传图片应限制大小并在客户端压缩以减少带宽。
- 服务区域通常是数组或 GeoJSON保存时与后端约定格式以支持范围匹配。

View File

@@ -0,0 +1,26 @@
# profile.uvue — 个人中心
## 概要
配送员个人中心,展示司机基本信息、当前工作状态、统计摘要(今日订单/收入)、常用入口(车辆管理/收入/设置/帮助)以及最近任务预览。
## 数据结构
- `DriverInfo`
- `id`, `user_id`, `real_name`, `avatar_url`, `work_status`, `rating`, `vehicle`(简要信息)
## 关键方法
- `loadDriverInfo()`:从 `ml_delivery_drivers``users` 表加载司机信息并设置 `driverInfo`
- `toggleWorkStatus()`:切换上线/下线并触发 `loadAvailableOrders()`(上线时)。
- `relocate()`:请求定位权限并更新司机服务位置(可调用后端保存)。
## 交互示例
```
async toggleWorkStatus() {
await supa.from('ml_delivery_drivers').update({ work_status: newStatus }).eq('id', driverInfo.id)
this.driverInfo.work_status = newStatus
}
```
## 注意事项
- 工作状态变更应通知后端并尽量在服务端发出状态变更事件WebSocket/推送)。
- 个人信息编辑应跳转到 `profile-edit`,并在保存后同步更新本页缓存。