admin/design.md
2026-04-15 15:25:38 +08:00

476 lines
12 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# OMS 全局设计文档
## 1. 文档目标
本文用于指导 OMS 在当前复刻项目中的整体落地,输出统一的:
- 技术架构与分层职责
- 业务模块边界与核心流程
- 数据库设计原则与表模型映射
- DTO、分页、路由、响应、事务等开发约定
- 文档歧义处理策略
优先级遵循 [开发复刻说明](/d:/my/itfx/admin/开发复刻说明.md),业务内容以 [oms表结构与接口设计2026040802.md](/d:/my/itfx/admin/oms表结构与接口设计2026040802.md) 为准。
## 2. 设计原则
### 2.1 基本原则
- 新系统沿用 `.NET 8 + Fake 模块化 + 分层架构 + SqlSugar + MySQL` 技术基线。
- 新增代码优先遵循复刻说明中的最高优先级约定:出入参模型、分页列表、出入参组织、路由风格、服务职责。
- 数据库采用软删除模型,保留通用审计字段:`IsDeleted`、`CreateUserId`、`CreateTime`、`UpdateUserId`、`UpdateTime`。
- 实体只用于持久化,不直接作为 API 出参。
- 接口响应体只定义业务 `data` 的值,外层 `code/msg` 由框架统一包装。
### 2.2 复刻目标
- 面向跨境物流 OMS 场景,覆盖订单、渠道、操作、客户、充值、系统六大业务域。
- 与现有 admin 技术风格保持一致,避免出现第二套分页、第二套路由、第二套 DTO 命名。
- 让后续开发能按“模块 -> DTO -> Repository -> Service -> API”稳定扩展。
## 3. 技术架构
### 3.1 目标分层
- `src/OMS.Api`
- Web 入口、鉴权、Swagger、异常处理、自动控制器映射、CORS、配置中心接入。
- `src/OMS.Application`
- 应用服务、事务边界、业务编排、对外 HTTP/缓存/消息调用、输入输出模型转换。
- `src/OMS.Domain`
- 实体、公共枚举、常量、转换器、公共 DTO、仓储接口。
- `src/OMS.Repositories`
- `SqlSugar` 访问、分页查询、投影查询、复杂联表、基础设施注册。
### 3.2 基础设施
- 容器:`Autofac`
- 日志:`Serilog`
- 配置中心:`Consul`
- ORM:`SqlSugar`
- 缓存:`FreeRedis`
- 消息:`RabbitMQ`
- 序列化:`Newtonsoft.Json`
### 3.3 模块装配要求
- API 启动链路保留 `CreateSlimBuilder -> AddConsul -> UseAutofac/Serilog -> AddApplication -> AddServiceDefaults -> Build -> InitializeApplication -> Run`。
- Application 模块保留 AutoMapper 扫描、Options 绑定、Redis 初始化、HostService 注册、预热逻辑、命名 HttpClient。
- Repositories 模块保留 MySQL 连接注册、泛型仓储注册、基础设施 Options 注册。
## 4. 业务模块划分
### 4.1 订单域
职责:
- 我的订单:列表、详情、支付、预报、拦截、取消拦截、删除、打印、导出
- 我要查价:按目的国、运输方式、重量、货物类型返回价格方案
- 我要下单:模板下载、Excel 导入、任务跟踪
核心表:
- `t_order`
- `t_order_template`
- `t_order_task`
- `t_order_sender`
- `t_order_recipient`
- `t_order_declaration`
- `t_order_weight`
- `t_order_fee`
### 4.2 渠道域
职责:
- 销售产品维护
- 产品卖价配置与发布
- 排货规则配置
- 服务渠道维护
- 渠道买价配置与发布
- 黑名单区 / 偏远分区 / 预警分区
- 计重规则 / 计重进位
- 自动触发规则
- 标签模板设计
核心表:
- `t_sales_product`
- `t_sales_product_price`
- `t_sales_product_price_factor`
- `t_sales_product_price_detail`
- `t_sales_product_allocation_provider`
- `t_sales_product_publish_record`
- `t_service_channel_group`
- `t_service_channel`
- `t_service_channel_price`
- `t_service_channel_price_factor`
- `t_service_channel_price_detail`
- `t_service_channel_publish_record`
- `t_kpi_area`
- `t_kpi_area_info`
- `t_weight_rule`
- `t_weight_rule_info`
- `t_weight_rounding`
- `t_weight_rounding_info`
- `t_auto_trigger`
- `t_label_template`
### 4.3 操作域
职责:
- 入库扫描
- 出库扫描
- 标签打印与打印记录追踪
核心表:
- `t_inbound_record`
- `t_outbound_record`
- `t_label_print_record`
### 4.4 客户域
职责:
- 客户主账号管理
- 子账号管理
- 登录凭据与客户分组
- 菜单角色与销售/客服归属
核心表:
- `t_customer`
- `t_customer_sub_account`
### 4.5 充值域
职责:
- 提交充值申请
- 审核充值申请
- 审核通过后更新客户余额
- 查询与导出充值记录
核心表:
- `t_recharge_record`
### 4.6 系统域
职责:
- 仓库地址维护
- 收件地址与客服信息维护
核心表:
- `t_warehouse_address`
## 5. 关键业务流程
### 5.1 订单生命周期
主路径:
1. 客户创建订单或上传批量下单文件。
2. 系统保存订单主表、收发件人、申报信息、预报重量。
3. 用户发起预报 / 支付 / 拦截等动作。
4. 仓内进行入库、出库、打印操作。
5. 系统补充收货、发货、签收、费用、下游轨迹等信息。
状态建议:
- `draft`
- `predeclared`
- `received`
- `pendingPayment`
- `pendingShip`
- `pendingOnline`
- `shipping`
- `deliverySuccess`
- `deliveryFailed`
- `problematic`
- `deleted`
- `claimed`
### 5.2 价格与规则发布
适用于销售产品和服务渠道两条线:
1. 先保存当前价格项/规则明细配置。
2. 将当前完整配置快照写入发布记录表。
3. 标识版本号、操作类型、发布时间、发布人。
4. 回滚时读取目标版本 `Content` 快照,重新覆盖现行配置。
说明:
- 发布记录是历史快照,不参与实时计算。
- 实时生效配置仍以业务主表和子表为准。
### 5.3 充值审核
1. 客户提交充值申请。
2. 系统生成流水号并写入 `t_recharge_record`,状态为待审核。
3. 管理员审核通过时,更新记录审核状态、审核时间、审核人。
4. 同事务增加客户余额。
5. 审核驳回时仅更新审核状态与备注。
### 5.4 仓内操作
1. 入库扫描记录重量、尺寸、销售产品、目的国、仓库、操作人。
2. 出库扫描记录运单号、仓库、操作人。
3. 标签打印记录模板、时间、是否成功、操作人。
4. 这些操作应与订单状态推进联动。
## 6. 数据库设计策略
### 6.1 命名与类型
- 表名统一使用 `t_` 前缀。
- 字段名使用 PascalCase,与文档和现有项目习惯保持一致。
- 主键统一 `BIGINT AUTO_INCREMENT`。
- 金额、重量统一 `DECIMAL`,禁止 `float/double`。
- 动态结构统一使用 `JSON`,包括:
- 价格因素值
- 客户组价格映射
- 发布快照内容
- 标签模板内容
- 仓库微信二维码数组
### 6.2 逻辑外键与物理索引
本次 `db.sql` 采用“逻辑外键 + 二级索引”策略,不建立物理外键约束,原因如下:
- 软删除是主流程,物理外键会增加批量导入、历史回滚、数据修复成本。
- OMS 存在多处循环引用或弱约束关系,不适合强外键。
- 发布记录、模板 JSON、动态因子配置更适合松耦合持久化。
索引设计重点:
- 编码、单号、手机号、流水号使用唯一索引。
- 列表检索字段使用组合索引,如客户 + 状态 + 时间、产品 + 状态、渠道 + 状态。
- 子表统一对主表关联字段建索引。
### 6.3 软删除与审计
- 所有业务表保留 `IsDeleted`,默认 `0`。
- 所有写操作必须写入 `CreateUserId/CreateTime`。
- 更新操作必须维护 `UpdateUserId/UpdateTime`。
- Repository 查询默认追加 `IsDeleted = 0` 过滤。
### 6.4 表设计中的特殊处理
#### 订单主子表双向字段
源文档中 `t_order` 同时保留了:
- `SenderId`
- `RecipientId`
- `DeclarationId`
同时子表又有:
- `t_order_sender.OrderId`
- `t_order_recipient.OrderId`
- `t_order_declaration.OrderId`
本次数据库保留了这组字段以兼容原规格,但实现层建议:
- 以子表 `OrderId` 作为真实关联主键
- `SenderId/RecipientId/DeclarationId` 仅作为兼容性或缓存字段使用
- 服务层避免双向来源不一致
#### 排货规则主表缺失
源文档出现了 `t_sales_product_allocation_rule` 命名,但没有给出实际表结构。结合接口与字段定义,确定:
- `Scheme` 存在于 `t_sales_product`
- 服务商列表存在于 `t_sales_product_allocation_provider`
因此本次不额外创建 `t_sales_product_allocation_rule`。
## 7. 应用层设计规范
### 7.1 DTO 分层
- 写模型放 `Application/Dtos/<Domain>/`
- 公共 DTO、分页基类放 `Domain/Dtos/`
- 实体不直接作为 API 出参
命名统一:
- 新增:`CreateXxxInput`
- 修改:`UpdateXxxInput`
- 保存:`SaveXxxInput`
- 删除:`DeleteXxxInput`
- 分页:`XxxPaginatedInput`
- 详情:`XxxOutput`
- 列表:`XxxListOutput` 或 `XxxPaginatedOutput`
### 7.2 分页统一约定
- 所有分页入参继承 `PagedQueryInput`
- 基础字段统一为 `PageIndex`、`PageSize`
- 返回值统一为 `PagedResult<T>`
- Repository 统一使用 `ToPagedListAsync(input.PageIndex, input.PageSize)` 收口
### 7.3 路由约定
复刻项目实现时以复刻说明为准:
- 路由模式:`<Domain>/<Action>`
- 路由使用 PascalCase
- 方法名保留 `Async`,路由不带 `Async`
推荐动作:
- `PaginatedList`
- `GetById`
- `GetDropdownList`
- `Create`
- `Update`
- `Delete`
- `Save`
### 7.4 服务职责
`ApplicationService` 负责:
- 参数校验
- 业务校验
- 事务控制
- DTO 转换
- 调用 Repository / Redis / MQ / 外部 HTTP
`Repository` 负责:
- 单表/多表查询
- 分页
- 子查询
- 只读投影
禁止事项:
- API 层写业务逻辑
- Service 层拼接超长 SQL 查询
- Entity 直接返回前端
## 8. 接口契约冲突与落地方案
### 8.1 响应包装冲突
OMS 文档原始示例里存在 `code/msg/data` 包装,但当前项目框架已统一处理,所以在新设计中:
- 接口文档只写 `data` 对应的业务结构
- 运行时仍由框架统一封装成功/失败响应
### 8.2 分页字段命名冲突
OMS 示例使用:
- `page`
- `pageSize`
复刻说明要求:
- `PageIndex`
- `PageSize`
落地方案:
- 后端内部 DTO 和服务统一使用 `PageIndex/PageSize`
- 如果前端已固定发送 `page/pageSize`,通过序列化别名或适配 DTO 兼容,不在核心服务层扩散两套命名
### 8.3 路由风格冲突
OMS 规格文档展示的是 kebab-case 路径示例,例如:
- `/order/list`
- `/channel/sales-product/list`
复刻说明要求的是 PascalCase 显式路由,例如:
- `Order/PaginatedList`
- `SalesProduct/PaginatedList`
落地建议:
- 新代码主实现使用复刻说明的 PascalCase 路由
- 如果已有前端必须兼容 kebab-case,则在 API 层增加兼容别名或网关转发,不在服务层维护两套业务实现
## 9. 推荐服务拆分
建议至少拆分为以下应用服务:
- `OrderService`
- `OrderPriceCheckService`
- `OrderTemplateService`
- `OrderTaskService`
- `SalesProductService`
- `SalesProductPriceService`
- `SalesProductAllocationService`
- `SalesProductPublishService`
- `ServiceChannelService`
- `ServiceChannelPriceService`
- `ServiceChannelPublishService`
- `KpiAreaService`
- `WeightRuleService`
- `WeightRoundingService`
- `AutoTriggerService`
- `LabelTemplateService`
- `InboundService`
- `OutboundService`
- `LabelPrintService`
- `CustomerService`
- `CustomerSubAccountService`
- `RechargeService`
- `WarehouseAddressService`
## 10. 事务与一致性
以下场景必须显式事务:
- 创建订单时同时写主表、地址、申报、件重尺、费用
- 批量导入任务落库与任务结果回写
- 保存价格项时同时覆盖因素与价格明细
- 发布与回滚时版本快照回写
- 充值审核通过并更新余额
统一写法:
```csharp
using var ts = TransacationHelper.GetReadCommitted();
// 1. 业务校验
// 2. 主表保存
// 3. 子表保存
// 4. 清缓存 / 发事件
ts.Complete();
```
## 11. 安全与运维要求
- 默认全局鉴权开启
- 匿名接口必须显式声明
- 密码字段统一加密存储
- 所有操作写审计日志
- CORS 从配置中心读取
- 代理头开启,保证真实 IP 获取正确
- Swagger 分组按领域组织
## 12. 交付物说明
本次交付包含:
- [db.sql](/d:/my/itfx/admin/db.sql):OMS MySQL 建库建表脚本
- [design.md](/d:/my/itfx/admin/design.md):OMS 全局设计文档
建议下一步按以下顺序继续落地:
1. 先生成 `Domain Entities + Repository Interfaces`
2. 再生成 `Application DTOs + Services`
3. 然后按模块补齐 Repository 实现
4. 最后补控制器映射、权限、缓存、消息与联调