docs: add miniprogram ETC vehicle recharge apply design.

Captures approved scope for driver/escort mine-vehicles filtering, menu perms, and reuse of existing apply APIs.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
zlwuandCursor committed 2026-09-27 18:18:49 +08:00
1 parent a3fbb92595
commit 3d7d999f48
1 file changed
+277
@@ -0,0 +1,277 @@
# 小程序 · ETC加油充值申请 — 设计文档
> **日期**: 2026-09-27
> **状态**: 已批准(待实现)
> **前置**:
> - Web 申请/审批/发放:`docs/superpowers/specs/2026-06-29-pl-vehicle-recharge-design.md`
> - 审批工作流:`docs/superpowers/specs/2026-09-26-pl-vehicle-recharge-workflow-design.md`
> - 小程序菜单/角色模式:`docs/superpowers/specs/2026-09-13-mini-pl-driver-plan-design.md`
> - UI 参考:`miniprogram/pages/pl/fuel-register/`
> **界面规范**: `docs/miniprogram-ui-spec-sanqiang.md`
---
## 1. 目标与范围
### 1.1 目标
在小程序「运输管理」下新增 **【ETC加油充值申请】**,供 **司机 / 押运员** 角色:
1. 查看 **本人车辆**(`pl_vehicle_personnel` 含当前用户关联人员)上的全部充值申请(含他人代申请);
2. 新建申请(草稿 / 保存并提交)、草稿与驳回可编辑再提交、本人单可作废;
3. 详情展示申请信息 + 审批进度/历史 + 发放信息(对齐 Web 申请详情);
4. 交互与视觉对齐现有 **【加油登记】**。
### 1.2 已确认决策
| # | 项 | 决策 |
|---|-----|------|
| D1 | 列表范围 | 车牌 ∈ 当前用户关联人员所在车辆(`pl_vehicle_personnel`);**含他人代申请** |
| D2 | 充值类型 | 可选 **ETC / 加油**(与 Web 一致) |
| D3 | 操作闭环 | 新建 → 草稿 → 提交;草稿/驳回可编辑再提交;**本人**单可作废;他人代申请 **仅查看** |
| D4 | 详情 | 申请信息 + 审批进度/历史 + 发放信息 |
| D5 | 实现方案 | **复用** Web `/transport/vehicle-recharge-apply/*`,增加 `mineVehicles` 作用域;不新建一套业务 API |
| D6 | 申请人 | 小程序强制为当前登录用户(不可改选) |
| D7 | 车牌 | 仅本人挂靠车辆;多车下拉;仅一辆时自动选中 |
| D8 | 角色 | `sys_role.role_name IN ('司机', '押运员')`(按名匹配;测试库可幂等补建) |
### 1.3 非目标
- 小程序端审批、发放登记
- 改动 Web「ETC加油充值申请 / 审批 / 发放管理」三页业务逻辑(除后端对 `mineVehicles` 的兼容)
- 改动充值审批流程配置
- 纯前端过滤全量列表(禁止)
---
## 2. 架构
```
小程序 list / form
→ GET/POST/PUT … /transport/vehicle-recharge-apply/*?mineVehicles=true
→ GET /transport/vehicle?mineVehicles=true(车牌下拉)
→ 服务端:
user.id
→ pl_personnel.sys_user_id
→ pl_vehicle_personnel.personnel_id
→ pl_vehicle.license_plate 集合
列表:license_plate IN 集合
写:车牌 ∈ 集合;申请人 = 当前用户;编辑/提交/作废仅本人申请
Web 申请 / 审批 / 发放 不传 mineVehicles,行为不变
```
**推荐方案说明(相对独立小程序 API)**:复用同一状态机与审批/发放数据,避免双端漂移;仅增加车辆人员作用域校验。
---
## 3. 菜单与权限
### 3.1 菜单树
```
移动端根 (id=1)
└─ 运输管理 (MINI_PL_ROOT) ← 复用
├─ 加油登记 (MINI_PL_FUEL_REG) ← 不动
├─ ETC加油充值申请 (MINI_PL_VEHICLE_RECHARGE_APPLY) ← 新建
├─ …(现场运输计划单 / 运输计划 / 司机运输计划单等现有项)
```
| 字段 | 值 |
|------|-----|
| id | `MINI_PL_VEHICLE_RECHARGE_APPLY` |
| menu_name | `ETC加油充值申请` |
| parent_id | `MINI_PL_ROOT` |
| menu_type | `C` |
| path | `vehicle-recharge-apply` |
| perms | `mini:pl:vehicleRechargeApply:list` |
| order_num | 建议紧接加油登记之后(如 `2`;冲突以迁移 SQL 为准) |
### 3.2 角色授权
- 按 `sys_role.role_name IN ('司机', '押运员') AND del_flag = 0` 匹配(不写死 role id)
- **测试库**:角色不存在则幂等创建,再绑菜单
- **生产库**:角色已存在则只做菜单 + `sys_role_menu`
- 绑定菜单:`1`、`MINI_PL_ROOT`、`MINI_PL_VEHICLE_RECHARGE_APPLY`
### 3.3 交付 SQL
`docs/sql/migrations/2026-09-27-mini-pl-vehicle-recharge-apply-menus.sql`
(菜单 + 角色补齐 + 授权;幂等 `NOT EXISTS`)
### 3.4 前端工作台配置
| 文件 | 改动 |
|------|------|
| `miniprogram/config/workbench-menus.js` | 运输管理下增加菜单项 |
| `miniprogram/config/api.js` | `PAGE_PATHS` + `WORKBENCH_ROUTE_MAP` |
| `miniprogram/pages.json` | 分包注册 list / form |
- code: `pl-vehicle-recharge-apply`
- perms: `mini:pl:vehicleRechargeApply:list`
- 工作台按 `menuCodes` 过滤(`workbenchMenuFilter.js`),无 perms 则不可见
---
## 4. 页面与交互
### 4.1 页面路径
| 页面 | 路径 |
|------|------|
| 列表 | `miniprogram/pages/pl/vehicle-recharge-apply/list.vue` |
| 表单/详情 | `miniprogram/pages/pl/vehicle-recharge-apply/form.vue` |
样式:复用 `@/styles/bx-theme.scss` 与加油登记同类 class(`bx-page`、`topbar`、`expense-card`、`fab-add`、`bx-sheet`、`form-card`、`bottom-action-bar` 等)。
### 4.2 列表
- 顶栏标题:`ETC加油充值申请`;右下角 FAB 新建
- 搜索:申请单号 / 车牌(`q`)
- 状态 Tab:全部 / 草稿 / 审批中 / 已驳回 / 已发放 / 已作废
(状态值:`draft` / `in_approval` / `rejected` / `disbursed` / `cancelled`;不单独展示历史 `pending`)
- 卡片:车牌主标题 + 状态 Tag;KV:申请单号、充值类型、申请日期、申请人、期初公里数、备注(有则显示)
- 操作:
- 本人且 `draft|rejected`:编辑 / 提交 / 作废
- 其余:查看
- 下拉刷新 + 上拉分页;请求统一带 `mineVehicles=true`
### 4.3 表单 / 详情(同一 form 页)
**可编辑(本人且 `draft|rejected`,或新建)**
| 字段 | 规则 |
|------|------|
| 申请单号 | 只读(新建无) |
| 申请人 | 锁定当前用户展示名 |
| 车牌号 | 必填;底部 sheet 选本人车辆;1 辆自动选中 |
| 充值类型 | 必填;分段 ETC / 加油 |
| 申请日期 | 必填;默认今天 |
| 期初公里数 | 选填 |
| 备注 | 选填 |
| 附件 | 选填;`uni.chooseImage` + 上传;folder=`pl/vehicle-recharge/apply` |
**只读块(详情有数据时展示)**
- 审批进度 / 历史(对齐 Web `approvalFlow` / `approvalHistory`)
- 发放信息:充值订单号、充值日期、金额、卡号、加油站/渠道、发放人、备注、发放附件;无发放时显示「暂无」
**底栏**
- 可编辑:`保存`、`保存并提交`
- 本人草稿/驳回:可作废(确认框)
- 他人代申请或不可编辑状态:无写操作按钮
### 4.4 车牌选择
- UI:与加油登记相同的 `bx-sheet` 模糊检索
- 数据:`GET /transport/vehicle?mineVehicles=true`(pageSize 足够覆盖本人车辆;可选本地 keyword 过滤)
- 0 辆:提示「暂无可用车辆」/「未关联驾押人员,请联系管理员」(按是否解析到人员区分)
---
## 5. 后端 API / 数据范围
### 5.1 参数
在现有申请相关接口增加查询/写作用域参数:
- `mineVehicles`(bool,alias 同名;默认 `false`)
- Web 管理端 **不传**,行为与现网一致
### 5.2 行为矩阵
| 方法 | 路径 | `mineVehicles=true` |
|------|------|---------------------|
| GET | `/transport/vehicle-recharge-apply/` | `license_plate ∈ 本人车辆车牌集` |
| GET | `/transport/vehicle-recharge-apply/{id}` | 不在集合 → **403** |
| POST | `/transport/vehicle-recharge-apply/` | 申请人强制当前用户;车牌须在集合 |
| PUT | `/{id}` | 须 **本人申请** + 可编辑状态;车牌须在集合 |
| POST | `/{id}/submit` | 须 **本人申请** + 可编辑状态 |
| POST | `/{id}/cancel` | 须 **本人申请** + 草稿/驳回 |
| GET | `/transport/vehicle` | 仅返回本人挂靠车辆 |
### 5.3 本人车辆车牌集
```
current_user.id
→ pl_personnel WHERE sys_user_id = user.id AND del_flag = 0
→ pl_vehicle_personnel WHERE personnel_id = … AND del_flag = 0
→ pl_vehicle.license_plate(同租户、del_flag = 0)
```
- 复用 `resolve_personnel_for_user`(`pl_driver_plan_service` 已有)
- 无关联人员 → 空集合(列表空;写操作拒绝并提示)
### 5.4 建议实现落点
| 位置 | 内容 |
|------|------|
| `pl_vehicle_recharge_service`(或共享 helper) | `_license_plates_for_user_personnel`、`_assert_mine_vehicle_plate`、`_assert_own_apply_for_write`;`list_applies` / `get` / `create` / `update` / `submit` / `cancel` 接入 `mine_vehicles` |
| `api/pl/vehicle_recharge.py` | 解析 `mineVehicles` 并传入 service |
| `api/pl/base_data.py` `list_vehicles` | 支持 `mineVehicles` 过滤 |
| 测试 | 车辆人员过滤、他人代申请可见只读、越权 403、Web 默认路径回归 |
### 5.5 状态机(不改)
`draft` → `in_approval` → `disbursed`;`rejected` 可改再提;`cancelled` 终态。
可编辑集合仍为 `draft` / `rejected`。
---
## 6. 小程序 API 封装
文件:`miniprogram/api/pl.js`(或同目录扩展)
```js
// 示意:所有申请接口默认带 mineVehicles: true
vehicleRechargeApplyApi = {
list, get, create, update, submit, cancel
}
// 车辆:fetchVehicleOptions(q, { mineVehicles: true })
```
上传路径须在 `API_ENCRYPT_EXCLUDE_PATHS` 已覆盖的既有上传通道内(与加油登记一致)。
---
## 7. 错误处理
| 场景 | HTTP / 行为 | 小程序提示方向 |
|------|-------------|----------------|
| 未绑定人员 | 空列表;新建拦截 | 未关联驾押人员,请联系管理员 |
| 无挂靠车辆 | 下拉空 | 暂无可用车辆 |
| 车牌不在集合 | 400/403 | 只能选择本人车辆 |
| 编辑/提交/作废他人单 | 403 | 只能操作本人申请 |
| 非可编辑状态改写 | 400 | 沿用后端文案 |
| 流程未配置节点 | 400 | 充值审批流程未配置节点 |
---
## 8. 验收清单
1. 司机/押运员工作台可见「ETC加油充值申请」;无该 perms 的角色不可见
2. 列表仅本人车辆申请(含他人代申请)
3. 新建:车牌=本人车辆;多车可选;申请人锁定本人;类型可选 ETC/加油
4. 保存草稿 → 提交 → `in_approval`;Web 审批端可见该单
5. 驳回后可改再提;本人草稿/驳回可作废
6. 他人代申请:可看详情(审批+发放),无编辑/提交/作废
7. 详情字段对齐 Web(申请 + 审批流 + 发放)
8. UI 对齐加油登记(topbar / card / FAB / sheet / 底栏)
9. Web 申请列表不传 `mineVehicles`,数据范围与现网一致
---
## 9. 实现文件清单(预期)
| 端 | 文件 |
|----|------|
| SQL | `docs/sql/migrations/2026-09-27-mini-pl-vehicle-recharge-apply-menus.sql` |
| Backend | `backend/app/api/pl/vehicle_recharge.py`、`base_data.py`;`backend/app/services/pl_vehicle_recharge_service.py`(+ 可选 helper);测试 |
| Mini | `pages/pl/vehicle-recharge-apply/list.vue`、`form.vue`;`api/pl.js`;`config/workbench-menus.js`;`config/api.js`;`pages.json` |
---
## 10. 与「加油登记」差异说明
现有加油登记小程序使用 `mineOnly`:**按登记人 = 当前用户** 过滤,**不是**按车辆人员。
本功能按产品要求采用 **车辆人员归属**(D1),仅 UI/页面骨架参考加油登记;后端过滤语义不同,勿混用 `mineOnly` 参数名以免误解。