diff --git a/docs/superpowers/specs/2026-08-03-mobile-h5-dibang-adapt-design.md b/docs/superpowers/specs/2026-08-03-mobile-h5-dibang-adapt-design.md new file mode 100644 index 000000000..8722bffc1 --- /dev/null +++ b/docs/superpowers/specs/2026-08-03-mobile-h5-dibang-adapt-design.md @@ -0,0 +1,183 @@ +# mobile-h5 地磅移动端适配一体化后端 — 设计说明 + +**日期:** 2026-08-03 +**状态:** 待用户审阅 +**方案:** 方案 1 — 以改 H5 为主,复用已有 `backend` 地磅 API + +## 1. 背景与目标 + +### 现状 + +- `mobile-h5`:原地磅移动端(Vue 3 + Vant 4),对接旧地磅后端与 `docs/sql/dibang.sql`(自增 int 主键、独立主数据表)。 +- 一体化库:`docs/sql/shanxia2.0.sql` 已含 `db_weighing_slip` / `db_purchase_plan` / `db_inbound_outbound` 等。 +- 一体化后端:`backend/app/api/db/*` 已挂载 `/api/plans|inventory|weighing|dashboard`,协议对齐原 simple-dibang-xiaoshou(camelCase、直接 JSON),且 web-admin「地磅管理」已在用。 + +### 目标 + +将 `mobile-h5` 改造为对接一体化 `backend` + 新 SQL 模型,保留现有业务页面与操作流,尽快可上线。 + +### 非目标 + +- 不重做 H5 视觉 / UI 规范迁移。 +- 不把 CRM / 报销业务做进 H5。 +- 本期不改用 token 现场链接(继续出入库单 id)。 +- 本期不在 H5 增加角色/菜单权限门禁。 +- 不改 web-admin(仅作协议与选择器参考)。 + +## 2. 已确认约束 + +| 项 | 决定 | +|----|------| +| 改造策略 | 方案 1:改 H5 为主;后端仅补缺口 | +| 登录 | 门户 `/api/web/auth/login` + RSA + JWT(对齐 web-admin) | +| 基础资料模块 | 删除整页与 CRUD | +| 往来单位 | 只读选 CRM 客户管理数据 | +| 货物 | 只读选 CRM 产品管理数据;创建须带 `productId` | +| 车牌 | 只读选 PL 车辆(`self` 自有 + `carrier` 承运商/三方) | +| 手输自动建档 | 全端禁止(含现场页);无「手动输入新车牌」/`ensureVehicleExists` | +| 现场填写链 | 继续用出入库单 **id** 打开 `/inventory/fill/:id` | +| H5 权限 UI | **不做任何限制**(不按角色藏菜单/拦入口) | + +## 3. 架构 + +```text +┌─────────────────┐ JWT Bearer ┌──────────────────────┐ +│ mobile-h5 │ ───────────────────► │ backend (FastAPI) │ +│ Vue3 + Vant │ │ │ +│ │ /api/web/auth/* │ RSA 登录 / JWT │ +│ 计划/出入库/ │ /api/plans|inventory │ db_* 地磅业务 │ +│ 地磅/仪表盘 │ /weighing|dashboard │ │ +│ │ /api/web/crm/* │ 客户、产品 │ +│ 选择器只读 │ /api/transport/vehicle│ 自有+承运商车辆 │ +└─────────────────┘ └──────────┬───────────┘ + │ + MySQL shanxia2.0 + db_* / crm_* / pl_vehicle +``` + +### 数据归属 + +| H5 语义 | 读来源 | 写入业务表 | +|---------|--------|------------| +| 往来单位 | CRM 客户 | 名称快照(`customerName` / `partnerCompany` / `supplier`·`consignee` 等) | +| 货物 | CRM 产品 | `productId` + 名称/规格快照 | +| 车牌 | `pl_vehicle`(`vehicle_type` ∈ {`self`,`carrier`}) | 仅 `vehicleNo` 文本,禁止 create 车辆 | + +### 删除范围 + +- 仪表盘「基础资料」入口;`master-data/*` 路由与页面。 +- `companyApi` / `cargoApi` / `vehicleApi` CRUD 封装。 +- `ensureVehicleExists`、「手动输入新车牌」相关 UI/逻辑。 +- 未挂菜单的用户管理页(账号改走门户)。 + +## 4. 登录与 HTTP + +### 登录流程(对齐 web-admin) + +1. `GET /api/web/auth/login-rsa-public-key` → `publicKeyPem` +2. JSEncrypt 加密 `{ username, password, ts }` → `{ encryptedLogin }` +3. `POST /api/web/auth/login` → 门户信封 `{ code, data: { token, refreshToken, expiresIn, userInfo } }` +4. H5 存储 token;请求头 `Authorization: Bearer ` +5. 可选:`POST /api/web/auth/refresh-token`(参考 web-admin) + +### 适配要点 + +- 新增 `loginRsa`(参考 `web-admin/src/utils/loginRsa.ts`);依赖 `jsencrypt`。 +- 登录账号为门户 `sys_user.user_no`。 +- Token 字段:门户 `token` ↔ H5 现有 `accessToken` 映射统一。 +- 响应形态: + - 门户 auth / CRM:`{ code, data, message }` + - 地磅 db API:直接 JSON 实体(与 `web-admin/src/utils/http/db.ts` 一致) +- Dev:Vite 代理 `/api` → backend;生产:`VITE_API_URL`。 +- API 加密:与 web-admin 同策略;登录 RSA 路径与现场免登路径列入排除列表。 +- 集合根路径须带尾斜杠:`/plans/`、`/inventory/`、`/weighing/`(避免 307 丢 Authorization)。 + +### 关于后端 `require_admin_or_super_admin` + +地磅业务接口依赖 `get_db_current_user` → `require_admin_or_super_admin`。 +门户登录时 `resolve_web_role_for_user` 会把几乎所有绑定角色映射为 JWT `admin` / `super_admin`,因此 web-admin 中普通业务账号也能调地磅 API;真正限制门户入口的是**菜单授权**。 + +H5 **不做**前端角色/菜单门禁;能登录即可使用各业务页。403 仅展示接口返回文案。 + +## 5. 主数据选择器 + +| 字段 | 接口参考(web-admin) | 交互 | +|------|----------------------|------| +| 客户 | `POST /api/web/crm/customer/list` 远程搜 | Picker + 搜索;`allowCreate=false` | +| 产品 | `POST /api/web/crm/products/list`(或 options) | 选中写入 `productId` + 名称/规格 | +| 车辆 | `GET /api/transport/vehicle`(`vehicleType`=`self`/`carrier`) | 只选车牌;无手输新建 | + +无匹配时提示「请到门户维护」,不提供新建入口。 +对照:web-admin 地磅用 `DbCrmCustomerSelect` / `DbCrmProductSelect` / `PlVehicleSelect`;H5 同源,但客户亦禁止 create(比门户地磅客户选择更严)。 + +## 6. 业务页适配 + +### 主键与类型 + +全部业务 `id` 及关联外键(`purchasePlanId`、`inboundOutboundId`、`lastWeighingSlipId`、`fillLinkInventoryId`、`productId`)由 `number` 改为 **`string`**。 +路由/query 禁止 `Number(uuid)`。类型对齐 `web-admin/src/api/db/{plans,inventory,weighing}.ts`。 + +### 创建必填 + +计划 / 出入库 / 地磅单创建须传 **`productId`**(后端 Create schema 已要求)。 + +### 模块能力(保留) + +| 模块 | 能力 | +|------|------| +| 仪表盘 | 今日统计、四张 DualBar 图;入口:计划 / 出入库 / 地磅(去掉基础资料) | +| 计划 | 搜索、CRUD、生成出入库、查看关联 | +| 出入库 | 搜索、CRUD、生成地磅、磅单二维码(内容=出入库 id)、查看关联 | +| 地磅单 | 筛选、CRUD、作废、从出入库带入创建 | + +操作流保持:计划 → 出入库 → 地磅单。 + +## 7. 现场免登页 + +- 路由:`/inventory/fill/:id`、`/inventory/plan/:id`(`noAuth`)。 +- 继续用业务 **id** 打开;读写现有免登出入库 get/patch、计划 third-party-page 等。 +- 车牌只选;去掉自动建档。 +- 若车辆列表必须鉴权:后端补**最小只读 options**(免登或带业务上下文校验),仍禁止写入主数据。 +- 二维码 URL 形态:`#/inventory/fill/{id}`。 + +## 8. 后端变更边界 + +优先零改或极少改。仅当下列缺口存在时补丁: + +1. 现场免登场景下的车辆只读检索。 +2. (可选)车辆 self+carrier 合并检索若前端拼两次调用体验差,可加薄聚合 options。 + +不重写 db 业务逻辑;不扩大本期权限模型。 + +## 9. 错误处理 + +- 业务失败:toast `detail` / `message`。 +- 401:清 token → `/login`(免登页除外)。 +- 不做 H5 侧角色预检。 + +## 10. 验收标准 + +1. 门户账号经 RSA 登录 H5 成功。 +2. 仪表盘可用;无「基础资料」入口。 +3. 计划 → 出入库 → 地磅 → 作废全链路成功。 +4. 客户 / 产品 / 车辆只能选择,无法手输新增。 +5. 现场 fill 页用 id 打开可填;车牌只能选。 +6. 主键为 string,无 int 强转导致的故障。 + +## 11. 实现顺序建议 + +1. HTTP / 登录 / 环境变量 / 代理与加密排除。 +2. API 类型与路径对齐(id→string、尾斜杠、productId)。 +3. 选择器接 CRM/PL;删除基础资料与自动建档。 +4. 业务页联调(计划 / 出入库 / 地磅 / 仪表盘)。 +5. 现场页车牌只选 + 后端只读补丁(若需要)。 +6. 验收清单回归。 + +## 12. 参考路径 + +- H5:`mobile-h5/` +- 后端地磅:`backend/app/api/db/`、`backend/app/schemas/db/`、`backend/app/models/db_models.py` +- 门户登录:`backend/app/api/public.py`(`/web/auth/*`)、`web-admin/src/utils/loginRsa.ts` +- web-admin 地磅:`web-admin/src/views/db/`、`web-admin/src/api/db/`、`web-admin/src/utils/http/db.ts` +- 选择器参考:`DbCrmCustomerSelect.vue`、`DbCrmProductSelect.vue`、`PlVehicleSelect` +- SQL:`docs/sql/dibang.sql`(旧)、`docs/sql/shanxia2.0.sql`(新)