diff --git a/docs/superpowers/specs/2026-09-27-mini-pl-vehicle-recharge-apply-design.md b/docs/superpowers/specs/2026-09-27-mini-pl-vehicle-recharge-apply-design.md new file mode 100644 index 000000000..d6fd42a96 --- /dev/null +++ b/docs/superpowers/specs/2026-09-27-mini-pl-vehicle-recharge-apply-design.md @@ -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` 参数名以免误解。