# 地磅系统(db)移植实施方案 > **编写日期**:2026-06-07(修订:搬运 + 适配策略) > **状态**:方案已定稿,**旧重写代码已清理**,待按阶段实施 > **源系统**:`simple-dibang-xiaoshou/backend` + `simple-dibang-xiaoshou/art-design-pro` > **目标系统**:`shanxia2.0/backend` + `shanxia2.0/web-admin` > **DDL 基线**:`docs/sql/db_tables.sql`(已写入 `docs/sql/shanxia2.0.sql`) > **对照参考**:[`docs/bx-migration/00-migration-plan.md`](../bx-migration/00-migration-plan.md) --- ## 1. 迁移目标 将原地磅系统五模块迁入山峡一体化门户,实现: 1. **业务等价**:仪表盘、计划、出入库、地磅单、车牌及联动逻辑与原系统一致; 2. **API 契约保持**:路径、HTTP 方法、Query 参数、响应 JSON 结构 **尽量与原系统一致**(直接返回 `list[Read]` / 实体,**不用**门户 CRM 的 `success_response` + `data.list`); 3. **体系融合**:用户/角色/菜单/认证使用门户 `sys_*`;业务表使用 `db_*` + 门户公共字段; 4. **UI 融合**:先拷贝 `art-design-pro` 页面与 `*Api.ts`,再逐步适配 Fresh Mint(第二阶段)。 **不在本次范围**:原 `auth/users/cargos/companies` 独立模块(分别用门户登录、CRM 下拉替代)。 --- ## 2. 核心原则(对齐 bx「搬运 + 适配」) | 原则 | 说明 | |------|------| | **Router 近原样复制** | 从 `simple-dibang-xiaoshou/backend/app/api/routes/` 复制到 `backend/app/api/db/`,仅改 Depends、import、租户、UUID | | **Service/联动逻辑整段迁移** | 尤其 `weighing.py` 的 `_process_weighing_business_logic`、`inventory/create-link-for-plan`、`plans/third-party-page` | | **响应协议保持原样** | 列表返回数组或 Pydantic Read 模型;**禁止**改为 `/web/admin/db/*` + 门户 envelope | | **路径保持原语义** | 挂载后仍为 `/api/plans`、`/api/weighing` 等(router prefix 不含 `/api`,由 `main.py` 统一加 `API_V1_PREFIX`) | | **最小改动** | 不重命名 URL、不改 PATCH→PUT、不删 special endpoints(`related`、`void`、`create-link-for-plan`) | | **门户能力注入** | 认证(`db_auth`)、租户、`tenant_no`、DB Session、MinIO 用 shanxia2.0 现有能力 | | **主数据方案 A** | 产品/客户用 CRM 远程下拉,存名称文本;不建 `cargos`/`companies` 表 | ### 与 bx 的差异(勿混淆) | 项 | bx | 地磅 db | |----|-----|---------| | 响应 envelope | `code:0` + `msg` + `data.rows` | **无 envelope**,FastAPI 直接返回 JSON | | 原 ORM | SQLAlchemy sync | SQLModel **async** → 须改为 sync Session | | 列表分页 | 服务端分页 | 多数列表 **全量返回**,前端筛选/分页 | --- ## 3. 范围边界 ### 3.1 数据库(4 张业务表,DDL 已完成) | 表 | 用途 | DDL | |----|------|-----| | `db_vehicle` | 车牌 | ✅ `docs/sql/db_tables.sql` | | `db_purchase_plan` | 计划 | ✅ | | `db_inbound_outbound` | 出入库 | ✅ | | `db_weighing_slip` | 地磅单 | ✅ | ### 3.2 后端 API(移植清单见 `01-api-inventory.md`) | 模块 | 源文件 | 原 prefix | 优先级 | |------|--------|-----------|--------| | 车牌 | `routes/vehicles.py` | `/vehicles` | P1 | | 计划 | `routes/plans.py` | `/plans` | P1 | | 出入库 | `routes/inventory.py` | `/inventory` | P2 | | 地磅单 | `routes/weighing.py` | `/weighing` | P2(含联动) | | 仪表盘 | `routes/dashboard.py` | `/dashboard` | P3 | **不移植**:`auth.py`、`users.py`、`cargos.py`、`companies.py`。 ### 3.3 前端页面(拷贝 + 适配) | 分组 | 源路径 | 目标 | |------|--------|------| | 计划 | `art-design-pro/src/views/plans` | `web-admin/src/views/db/plans` | | 出入库 | `art-design-pro/src/views/inventory` | `web-admin/src/views/db/inventory` | | 地磅单 | `art-design-pro/src/views/weighing` | `web-admin/src/views/db/weighing` | | 车牌 | master-data 车辆 Tab 或 vehicles 页 | `web-admin/src/views/db/vehicles` | | 仪表盘 | `art-design-pro/src/views/dashboard` | `web-admin/src/views/db/dashboard` | | API | `art-design-pro/src/api/*Api.ts` | `web-admin/src/api/db/*.ts` | --- ## 4. 目标架构 ``` backend/app/ ├── models/db_models.py # 按 db_tables.sql 重写(非 SQLModel) ├── schemas/db/ # 从原 schemas 复制 + id→str ├── services/db/ # 从原 routes 内联逻辑抽出或直接保留在 router(与 bx 一致,优先 router 薄层) ├── core/db_auth.py # 类比 bx_auth:门户 user → DbUserContext └── api/db/ ├── __init__.py # db_router 聚合 ├── vehicles.py # prefix="/vehicles" ├── plans.py # prefix="/plans" ├── inventory.py # prefix="/inventory" ├── weighing.py # prefix="/weighing" └── dashboard.py # prefix="/dashboard" ``` ```python # main.py from app.api.db import db_router app.include_router(db_router, prefix=settings.API_V1_PREFIX) # → /api/plans、/api/weighing ... ``` --- ## 5. 门户适配层 ### 5.1 认证(`core/db_auth.py`) - 原:`get_async_session` + 无统一门户用户 - 新:`Depends(get_db_current_user)`,从 `require_admin_or_super_admin` 或菜单权限取 `tenant_no`、`user_id`、`dept_id` ### 5.2 数据模型改造 | 原 | 新 | |----|-----| | `id: int` | `id: str` UUID | | `is_deleted` | `del_flag` | | `created_at: str` | `create_time: datetime` | | 无租户 | `tenant_no` 必填 | | `remarks` | `remark`(门户公共字段) | ### 5.3 async → sync 原系统使用 SQLModel `AsyncSession`;门户使用同步 `Session`。搬运时: - `await session.exec(select(...))` → `db.query(...).filter(...)` - `await session.commit()` → `db.commit()`(在 router 或 service 层统一) --- ## 6. 分阶段交付 | 阶段 | 内容 | 验收 | |------|------|------| | P0 | ORM + `db_router` 骨架 + `db_auth` + health | `/api/db/health` 或模块 health | | P1 | vehicles + plans(含 fill-link、third-party-page、related) | 端点对照表 P1 全绿 | | P2 | inventory + weighing(含联动、void、related) | 计划→地磅→出入库全链路 | | P3 | dashboard 统计 SQL | 与原 dashboard 数值一致 | | P4 | 定时任务:计划按月自动生成 | 手动触发成功 | | P5 | sys_menu 菜单 SQL | 侧栏五模块可见 | | P6 | 前端拷贝 + API 路径对齐 | 原页面功能可跑通 | | P6-FM | Fresh Mint UI 换皮 | 对照 ui-spec | --- ## 7. 历史数据 - 脚本:`backend/scripts/migrate_dibang_data.py`(**保留原地磅 int id**,写入 `VARCHAR(64)` 如 `"12"`;外键同值传递) - 主键策略:int → 同值字符串(非 UUID);`purchase_plan_id`、`inbound_outbound_id`、`last_weighing_slip_id` 随主键一并保留 --- ## 8. 文档索引 | 文件 | 用途 | |------|------| | [01-api-inventory.md](./01-api-inventory.md) | 端点全量清单(防遗漏) | | [ref-backend-adapt.md](./ref-backend-adapt.md) | Router/Service 改造检查清单 | | [module-status.md](./module-status.md) | 实施进度 | | [../superpowers/specs/2026-06-07-dibang-migration-design.md](../superpowers/specs/2026-06-07-dibang-migration-design.md) | 业务设计(方案 A、联动、单位) | --- ## 9. 已废弃方案说明 2026-06-07 前曾按「门户 CRM 式 CRUD 重写」实现过 `/api/web/admin/db/*` 路由与 Fresh Mint 新页面,**已全部删除**。后续实施 **必须** 以本文档与 `01-api-inventory.md` 为准。