docs: 设计子卷包装关系批量新增
This commit is contained in:
@@ -0,0 +1,232 @@
|
||||
# 子卷包装关系批量新增设计
|
||||
|
||||
## 1. 背景与目标
|
||||
|
||||
子卷包装关系列表目前仅支持单条新增。新增“批量新增”功能,用户可在同一个弹窗中录入多条 `lms_sub_package_relation` 数据,并在卡片视图与表格视图之间自由切换。两种视图共享同一份数据,切换时不丢失输入。
|
||||
|
||||
实现以 `docs/prototype_design/design/2026-08-17-sub-package-relation-card-batch-design.html` 中的“自由切换批量新增”为交互参考,不追求额外视觉扩展,重点是稳定录入、分组校验、部分成功保存和逐行错误反馈。
|
||||
|
||||
## 2. 范围
|
||||
|
||||
### 2.1 本次包含
|
||||
|
||||
- 在子卷包装关系列表工具栏增加“批量新增”按钮。
|
||||
- 在 `src/views/lms/subpackagerelation/modules` 中封装独立批量新增弹窗组件。
|
||||
- 支持卡片和表格两种批量录入视图,并可自由切换。
|
||||
- 复用现有木箱类型选择弹窗选择木箱类型并回填尺寸。
|
||||
- 复用字典管理中的 `sub_package_status` 状态字典,默认状态为 `0`。
|
||||
- 新增独立批量创建 API、请求 VO、响应 VO 和服务方法。
|
||||
- 按“木箱码 + 木箱类型”分组校验 `lms_box_type.max_num`。
|
||||
- 合法分组保存;失败分组返回到前端逐行展示,不影响其他合法分组。
|
||||
|
||||
### 2.2 本次不包含
|
||||
|
||||
- 不修改现有单条新增、修改接口及其请求实体。
|
||||
- 不调整列表查询、删除、导出功能。
|
||||
- 不新增权限标识,批量新增沿用 `lms:sub-package-relation:create`。
|
||||
- 不修改数据库表结构。
|
||||
- 不增加原型之外的批量导入、Excel 粘贴、拖拽排序等功能。
|
||||
|
||||
## 3. 前端设计
|
||||
|
||||
### 3.1 页面接入
|
||||
|
||||
在子卷包装关系列表页接入批量新增弹窗,并在工具栏增加“批量新增”按钮。按钮使用 `lms:sub-package-relation:create` 权限。
|
||||
|
||||
批量新增全部成功时关闭弹窗并刷新列表;部分成功时保持弹窗打开,同时刷新列表以显示已保存的数据。
|
||||
|
||||
### 3.2 组件职责
|
||||
|
||||
在 `apps/web-antdv-next/src/views/lms/subpackagerelation/modules` 下新增独立批量新增弹窗组件。该组件负责:
|
||||
|
||||
- 维护统一的批量记录数组 `rows`。
|
||||
- 渲染卡片视图或表格视图。
|
||||
- 新增、复制、删除和清空记录。
|
||||
- 打开木箱类型选择弹窗并回填当前行。
|
||||
- 执行前端必填校验。
|
||||
- 提交批量请求并将失败结果映射回具体记录。
|
||||
|
||||
每条前端记录包含稳定且不重复的 `clientKey`。切换视图、增删记录和提交失败后均保留该标识。后端原样返回失败记录的 `clientKey`,前端以此定位错误行,不使用可能变化的数组下标作为唯一标识。
|
||||
|
||||
### 3.3 录入字段
|
||||
|
||||
批量新增只录入以下字段:
|
||||
|
||||
| 字段 | 必填 | 交互 |
|
||||
| --- | --- | --- |
|
||||
| `packageBoxSn` | 是 | 输入木箱唯一码 |
|
||||
| `boxType` | 是 | 点击只读输入区域,打开木箱类型选择弹窗 |
|
||||
| `boxLength` | 否 | 选择木箱类型后自动回填,只读 |
|
||||
| `boxWidth` | 否 | 选择木箱类型后自动回填,只读 |
|
||||
| `boxHigh` | 否 | 选择木箱类型后自动回填,只读 |
|
||||
| `qualityGuaranPeriod` | 是 | 输入保质期 |
|
||||
| `dateOfFgInbound` | 是 | 选择入库日期 |
|
||||
| `containerName` | 是 | 输入子卷号 |
|
||||
| `status` | 是 | 使用 `sub_package_status` 字典,默认 `0` |
|
||||
|
||||
木箱类型选择复用:
|
||||
|
||||
`apps/web-antdv-next/src/views/lms/boxtype/components/BoxTypeSelectModal.vue`
|
||||
|
||||
组件记录当前正在选择木箱类型的 `clientKey`。选择完成后,将 `boxType`、`boxLength`、`boxWidth` 和 `boxHigh` 回填到该记录。
|
||||
|
||||
### 3.4 卡片与表格切换
|
||||
|
||||
- 弹窗初始存在一条空记录,默认显示表格视图。
|
||||
- 卡片和表格只负责展示与编辑,数据源始终是同一个 `rows` 数组。
|
||||
- 视图切换不创建数据副本,不触发提交,也不清理校验错误。
|
||||
- 卡片视图按记录展示字段和错误信息。
|
||||
- 表格视图按行展示字段,宽度不足时使用横向滚动。
|
||||
|
||||
### 3.5 行操作
|
||||
|
||||
- 新增:在末尾添加一条空记录,状态默认 `0`。
|
||||
- 复制:复制木箱类型、尺寸、保质期、入库日期和状态;清空木箱唯一码、子卷号,并生成新的 `clientKey`。
|
||||
- 删除:删除目标记录;组件至少保留一条空记录。
|
||||
- 清空:清除全部输入和错误,并恢复为一条状态为 `0` 的空记录。
|
||||
|
||||
### 3.6 前端校验和结果处理
|
||||
|
||||
提交前检查所有必填字段。有缺失时不发送请求,在卡片或表格对应行显示错误。
|
||||
|
||||
后端响应后:
|
||||
|
||||
- 全部成功:关闭弹窗,提示成功,触发列表刷新。
|
||||
- 部分成功:刷新列表;删除已保存记录,只保留失败记录;根据 `clientKey` 写入错误信息;弹窗保持打开。
|
||||
- 全部失败:保留全部记录,根据 `clientKey` 展示错误信息。
|
||||
|
||||
## 4. 后端接口设计
|
||||
|
||||
### 4.1 接口
|
||||
|
||||
新增独立接口:
|
||||
|
||||
`POST /lms/sub-package-relation/batch-create`
|
||||
|
||||
权限:`lms:sub-package-relation:create`
|
||||
|
||||
现有 `POST /create` 和 `PUT /update` 不变。
|
||||
|
||||
### 4.2 请求实体
|
||||
|
||||
新增批量请求 VO 和批量行 VO,避免复用现有包含大量必填校验的 `SubPackageRelationSaveReqVO`。
|
||||
|
||||
批量请求包含非空记录列表;每条记录包含:
|
||||
|
||||
- `clientKey`
|
||||
- `packageBoxSn`
|
||||
- `boxType`
|
||||
- `boxLength`
|
||||
- `boxWidth`
|
||||
- `boxHigh`
|
||||
- `qualityGuaranPeriod`
|
||||
- `dateOfFgInbound`
|
||||
- `containerName`
|
||||
- `status`
|
||||
|
||||
后端对 `clientKey` 和业务必填字段再次校验。批量行 VO 不包含 `id`,该接口只执行新增。
|
||||
|
||||
### 4.3 响应实体
|
||||
|
||||
响应包含:
|
||||
|
||||
- `successCount`:成功保存条数。
|
||||
- `failureCount`:失败条数。
|
||||
- `failures`:失败记录列表。
|
||||
|
||||
每条失败记录包含:
|
||||
|
||||
- `clientKey`:前端记录标识。
|
||||
- `rowIndex`:请求中的一基行号,用于辅助展示和日志定位。
|
||||
- `errorCode`:稳定的错误类型。
|
||||
- `message`:面向用户的中文错误信息。
|
||||
|
||||
预期错误类型至少包括必填校验失败、木箱类型不存在、木箱容量超限和分组保存失败。
|
||||
|
||||
## 5. 业务校验与保存流程
|
||||
|
||||
### 5.1 分组规则
|
||||
|
||||
请求记录按 `packageBoxSn + boxType` 分组。每个分组是容量校验和保存事务的最小业务单元。
|
||||
|
||||
### 5.2 木箱类型校验
|
||||
|
||||
根据请求中去重后的 `boxType` 批量查询 `lms_box_type`。不存在的木箱类型对应分组全部失败,每条记录均返回错误。
|
||||
|
||||
后端容量判断使用数据库中 `lms_box_type` 的 `max_num`,不信任前端回填数据。请求携带的长、宽、高作为本次关系记录的保存值;木箱类型不存在时不保存。
|
||||
|
||||
### 5.3 容量校验
|
||||
|
||||
对每个“木箱码 + 木箱类型”分组,统计数据库中相同木箱码和木箱类型的现有有效关系数量,并计算:
|
||||
|
||||
`数据库已有数量 + 本次分组数量 <= lms_box_type.max_num`
|
||||
|
||||
满足条件时分组可保存;超过上限时整个分组失败,本次分组内一条都不保存。错误信息包含木箱码、类型、最大容量、已有数量和本次提交数量,例如:
|
||||
|
||||
`木箱 BX001(类型 A)最多容纳 3 个子卷,已有 2 个,本次提交 2 个`
|
||||
|
||||
逻辑删除数据不计入已有数量,沿用 MyBatis-Plus 的逻辑删除过滤规则。
|
||||
|
||||
### 5.4 分组隔离保存
|
||||
|
||||
通过独立事务执行器或等价的可生效事务边界逐组保存,禁止依赖同类方法自调用触发事务。
|
||||
|
||||
- 合法分组在独立事务中写入。
|
||||
- 分组内任意一条写入失败,该组事务全部回滚。
|
||||
- 一个分组失败不影响其他分组继续保存。
|
||||
- 保存失败时,该组每条记录均返回同一分组写入错误。
|
||||
|
||||
接口本身正常返回结构化结果;仅在无法继续处理整个请求的系统级异常时返回通用接口错误。
|
||||
|
||||
### 5.5 并发边界
|
||||
|
||||
本次仅在服务层执行“查询已有数量后判断”的容量校验,不新增数据库锁、唯一约束或表结构。并发请求同时操作相同木箱码和类型时,仍可能产生竞态;该问题不在本次“不修改数据库结构、不过度设计”的实现范围内。
|
||||
|
||||
## 6. 错误展示
|
||||
|
||||
前端在记录级别保存后端错误:
|
||||
|
||||
- 卡片视图:显示在卡片头部或卡片内容上方。
|
||||
- 表格视图:显示在对应行的错误区域,并保留该行所有输入。
|
||||
- 顶部汇总提示成功条数和失败条数。
|
||||
|
||||
错误记录在用户修改对应行后可清除;再次提交时只提交弹窗中保留的失败记录。
|
||||
|
||||
## 7. 验证方案
|
||||
|
||||
### 7.1 后端测试
|
||||
|
||||
- 未超 `max_num` 时正常保存。
|
||||
- 数据库已有数量加本次数量刚好等于 `max_num` 时正常保存。
|
||||
- 超过 `max_num` 时该组全部失败。
|
||||
- 多个分组中一组超限,其他组正常保存。
|
||||
- 木箱类型不存在时该组失败。
|
||||
- 某组写入异常时该组回滚,其他组不受影响。
|
||||
- `clientKey`、一基行号、成功数和失败数返回正确。
|
||||
|
||||
### 7.2 前端验证
|
||||
|
||||
- 卡片和表格切换后输入、行标识和错误不丢失。
|
||||
- 新增、复制、删除和清空行为正确。
|
||||
- 木箱类型弹窗回填到当前记录,并带出长、宽、高。
|
||||
- `sub_package_status` 字典加载正确,新增行默认状态为 `0`。
|
||||
- 前端必填校验能定位具体记录。
|
||||
- 部分成功后只保留失败记录并展示原因。
|
||||
|
||||
### 7.3 完成前命令验证
|
||||
|
||||
- 运行 LMS 后端受影响模块的定向测试或编译。
|
||||
- 运行前端目标应用的类型检查。
|
||||
- 对新增和修改的前端文件执行可用的静态检查。
|
||||
- 若项目工具链自身异常,保留失败输出并在交付说明中区分代码问题和环境问题。
|
||||
|
||||
## 8. 成功标准
|
||||
|
||||
- 用户可从列表页打开批量新增弹窗。
|
||||
- 用户可在卡片和表格视图间自由切换,输入不丢失。
|
||||
- 木箱类型通过现有选择弹窗选择,尺寸正确回填。
|
||||
- 状态来自 `sub_package_status` 字典,默认值为 `0`。
|
||||
- 后端按“木箱码 + 木箱类型”结合数据库已有数量校验 `max_num`。
|
||||
- 超限分组全部失败,合法分组正常保存。
|
||||
- 前端准确显示每条失败记录及错误原因,并允许修改后重试。
|
||||
- 现有单条新增、修改及列表功能不受影响。
|
||||
Reference in New Issue
Block a user