diff --git a/docs/superpowers/specs/2026-09-13-mini-pl-transport-plan-site-design.md b/docs/superpowers/specs/2026-09-13-mini-pl-transport-plan-site-design.md new file mode 100644 index 000000000..48d9b8889 --- /dev/null +++ b/docs/superpowers/specs/2026-09-13-mini-pl-transport-plan-site-design.md @@ -0,0 +1,200 @@ +# 小程序 · 运输计划单(现场记录 / 现场回传)— 设计文档 + +> **日期**: 2026-09-13 +> **状态**: 已确认,待实现 +> **方案**: 方案 1 — 小程序原生页 + 登录态 API(复用现有现场业务逻辑) +> **对齐**: H5 现场链接「现场记录 / 现场回传」;顶栏对齐小程序「备用金申请」 + +## 1. 目标 + +现场人员此前通过管理端「复制现场链接」在微信中打开 H5 免登录页完成回传。现已有微信小程序,需在小程序内提供同等能力: + +- 工作台 **运输管理 → 运输计划单** +- 默认打开等同 H5 **现场记录** 的列表 +- 点击记录进入等同 H5 **现场回传** 的详情 +- 功能与正文样式与现网现场链接页一致;**仅顶栏**改为与备用金申请等同款白底顶栏 + +## 2. 已确认决策 + +| # | 项 | 决策 | +|---|-----|------| +| D1 | 实现路径 | 原生小程序页 + 登录态 API;不复用公开 token 混调;不 web-view | +| D2 | 数据范围 | 与现网 H5 history 一致:本租户、所选日、已安排且带有效 `site_access_token`、存在需现场回传段的计划 | +| D3 | 与微信链接 | **并存**:管理端复制链接 + 公开 H5 全部保留 | +| D4 | 列表顶栏标题 | **运输计划单**(与菜单名一致) | +| D5 | 详情顶栏标题 | **现场回传** | +| D6 | 菜单权限 | 仅角色 **现场人员**(测试库、生产库各执行迁移 SQL,只绑该角色) | +| D7 | 顶栏样式 | 对齐 `miniprogram/pages/bx/advance/list.vue`(白底 sticky、`←`、左对齐标题、安全区);不用 H5 绿色 `van-nav-bar` | +| D8 | 正文 UI | 对齐 `web-admin` 公开页 `transport-site/history.vue` 与 `transport-site/index.vue` | + +## 3. 非目标 + +- 不按现场人员个人指派过滤计划 +- 不改 Web 管理端现场链接展示 / 复制入口 +- 不修改或下线 `/api/public/pl/transport-site/{token}/...` +- 不给「现场人员」自动授权「加油登记」等其他运输菜单 +- 不输出独立 HTML demo + +## 4. 架构 + +```text +小程序登录(JWT) + → 工作台 perms: mini:pl:transportPlan:list + → 列表 pages/pl/transport-plan/list + GET /api/transport/site-plan/history?date=&q= + → 详情 pages/pl/transport-plan/detail?planId= + GET /api/transport/site-plan/{planId} + POST /api/transport/site-plan/{planId}/feedback + POST /api/transport/site-plan/{planId}/attachments + +公开 H5(保留) + /#/public/pl/transport-site/:token[/history] + → /api/public/pl/transport-site/{token}/... +``` + +登录态与公开 API **共用** 列表构建 / 详情构建 / `save_site_stop_feedback` 等 service 逻辑: +公开链路为 `token → transport → tenant/plan`;登录态为 `current_user.tenant_no + planId → transport`。 + +## 5. 菜单与权限 + +### 5.1 菜单树 + +``` +移动端根 (id=1) +└─ 运输管理 (MINI_PL_ROOT) ← 已存在则复用 + ├─ 加油登记 (MINI_PL_FUEL_REG) ← 不动 + └─ 运输计划单 (MINI_PL_TRANSPORT_PLAN) ← 新建 +``` + +| 字段 | 值 | +|------|-----| +| id | `MINI_PL_TRANSPORT_PLAN` | +| menu_name | `运输计划单` | +| parent_id | `MINI_PL_ROOT` | +| menu_type | `C` | +| path | `transport-plan` | +| perms | `mini:pl:transportPlan:list` | +| order_num | `2` | + +### 5.2 角色绑定 + +仅 `sys_role.role_name = '现场人员' AND del_flag = 0`: + +1. 移动端根 `1` +2. `MINI_PL_ROOT` +3. `MINI_PL_TRANSPORT_PLAN` + +按角色名匹配(不写死 role id)。幂等插入。 + +### 5.3 交付 SQL + +- 文件:`docs/sql/migrations/2026-09-13-mini-pl-transport-plan-menus.sql` +- 在**测试环境库**、**生产环境库**各执行一次 + +### 5.4 前端菜单配置 + +- `miniprogram/config/workbench-menus.js`:运输管理下增加菜单项 +- `miniprogram/config/api.js`:`PAGE_PATHS` + `WORKBENCH_ROUTE_MAP`(code:`pl-transport-plan`) +- `miniprogram/pages.json`:分包注册 list / detail + +## 6. 后端 API + +前缀:`/api/transport/site-plan`(挂入现有 `pl_router`,JWT + 租户隔离)。 + +| 方法 | 路径 | 说明 | +|------|------|------| +| GET | `/history?date=YYYY-MM-DD&q=` | 现场记录列表 | +| GET | `/{planId}` | 现场回传详情 | +| POST | `/{planId}/feedback` | 按段保存数量 / 附件 URL / 备注 | +| POST | `/{planId}/attachments` | multipart 附件上传(`name=file`,`formData.folder`) | + +### 6.1 规则 + +- `Depends(get_current_user)`;读写强制当前用户 `tenant_no` +- 列表规则对齐现网 `GET /api/public/pl/transport-site/{token}/history` +- 详情 / 保存:计划属本租户,关联运输有有效现场 token,且存在可回传段;否则 404/400 +- 作废 / 已归档:只读,禁止保存与上传 +- 菜单权限主要用于入口显隐;后端以登录 + 租户为准(同加油登记) +- 附件上传路径遵循小程序拍照凭证基线;若网关加密,路径加入 `API_ENCRYPT_EXCLUDE_PATHS` + +### 6.2 实现约束 + +- 抽出与 token 无关的 service 能力,公开 API 与登录态 API 共用,避免两套业务规则 +- 列表出参对齐公开 history(含 `planId`、车牌、stops、statusLabel 等);小程序用 `planId` 跳详情,不依赖 URL token + +## 7. 小程序页面 + +| 页面 | 路径 | 顶栏标题 | +|------|------|----------| +| 列表 | `miniprogram/pages/pl/transport-plan/list.vue` | 运输计划单 | +| 详情 | `miniprogram/pages/pl/transport-plan/detail.vue` | 现场回传 | + +### 7.1 顶栏 + +与备用金申请 / 加油登记相同结构: + +- 根节点 `class="bx-page"`(或等价复用 `bx-theme` 顶栏样式) +- `topbar` + `safeAreaStyle` +- `topbar-back`(←)+ `topbar-title` +- 白底、底边、左对齐标题;**禁止**绿色渐变顶栏 + +### 7.2 列表 + +- 月历选日(默认今日) +- 搜索:车牌号 / 产品名称 +- 卡片字段与交互对齐 H5 `transport-site/history.vue` +- 点击 → `detail?planId=...` +- 返回:回工作台(同加油登记) + +### 7.3 详情 + +- 计划摘要 + 按 stop 回传区(地址/导航、联系、注意、产品、实际数量、附件、备注) +- 底栏:「现场记录」回列表 + 「保存回传」 +- 附件:`uni.chooseImage` + `uni.uploadFile`(Bearer + folder) +- 作废 / 归档只读,与 H5 一致 +- 保存成功 toast,留在详情并刷新 + +### 7.4 视觉 Token + +正文使用小程序三墙体系(如 `#0a9f6d` / `#059669`),**不**混用 web-admin Fresh Mint `#10b981` 作为主色。 + +## 8. 错误处理 + +| 场景 | 行为 | +|------|------| +| 未登录 | 既有登录拦截 | +| 无菜单权限 | 工作台不展示入口 | +| 无数据 | 空态「暂无现场记录」 | +| planId 无效 / 跨租户 | 详情错误空态 | +| 作废 / 归档写操作 | 业务错误 toast | +| 未填数量上传 | 与 H5 相同拦截提示 | +| 网络失败 | toast,不静默失败 | + +## 9. 验收 + +1. 「现场人员」可见运输管理 → 运输计划单;其他角色不可见该菜单 +2. 列表默认今日;日历 / 搜索 / 卡片与 H5 现场记录一致;可进现场回传 +3. 数量、附件、备注保存后与管理端 / H5 同一套反馈数据 +4. 顶栏对齐备用金申请;正文对齐现网现场链接页 +5. 复制现场链接与公开 H5 仍可用 +6. 测试库、生产库已执行菜单 SQL,仅绑定「现场人员」 + +## 10. 风险 + +| 风险 | 缓解 | +|------|------| +| 公开与登录态逻辑分叉 | 共用 service | +| 小程序日历与 Vant 月历差异 | 交互对齐验收对照 H5 | +| 环境角色改名 | SQL 按 `role_name='现场人员'`,执行前核对 | +| 附件加密网关 | 上传路径按约定排除加解密 | + +## 11. 参考实现 + +| 用途 | 路径 | +|------|------| +| H5 现场记录 | `web-admin/src/views/public/pl/transport-site/history.vue` | +| H5 现场回传 | `web-admin/src/views/public/pl/transport-site/index.vue` | +| 公开 API | `backend/app/api/pl/public_transport_site.py` | +| 顶栏参考 | `miniprogram/pages/bx/advance/list.vue` | +| 运输菜单参考 | `docs/sql/migrations/2026-09-12-mini-pl-fuel-register-menus.sql` | +| 历史设计 | `docs/superpowers/specs/2026-08-21-pl-site-record-history-design.md` |