# MES 托盘码自动生成 - 前端联调方案 ## 涉及页面 - 生产批次管理:新增/编辑批次时选择包装袋型。 - 袋码管理:生成袋码成功后接收自动托盘标签数据。 - 托盘码管理:查看自动生成托盘及其绑定袋数。 - 二维码打印区域:根据标签数据一次渲染同一托盘的 3 份标签并触发一次浏览器打印。 ## 业务流程与数据带入 1. 创建或编辑批次时,必须选择包装袋型:小袋(值 10)或大袋(值 20)。小袋自动托盘阈值为 100 袋,大袋自动托盘阈值为 48 袋。 2. 批次进入生产中后,调用生成袋码接口。袋码的批次号、品种、产线、生产日期和责任人由批次自动带入。 3. 后端在同一事务中统计该批次有效袋码:未逻辑删除且状态不是已作废,并按袋序号升序取完整阈值组。 4. 每个完整阈值组自动创建一个托盘码,并将组内全部袋码写入同一托盘的托盘编号和托盘码。未达到完整阈值的余数袋码保持未绑定。 5. 自动托盘生成后,生成袋码接口响应中的 `autoPallets` 返回本次新建托盘标签数据。每个标签的 `copies` 固定为 3,表示同一托盘二维码打印 3 份,不是生成 3 个托盘。 6. 前端收到 `autoPallets` 后,为每个托盘标签渲染 3 个打印副本,并只调用一次浏览器打印。普通网页打印会打开浏览器打印流程,后端不返回静默打印成功状态。 ## API ### 1. 批次创建/更新 | 方法 | 路径 | 说明 | |---|---|---| | POST | `/mes/pro/batch/create` | 创建生产批次,包装袋型必填 | | PUT | `/mes/pro/batch/update` | 更新生产批次;生成袋码或托盘后不允许修改袋型 | 请求参数新增: | 参数 | 类型 | 必填 | 说明 | |---|---|---|---| | bagType | Integer | 是 | 10 小袋(阈值100),20 大袋(阈值48) | 响应字段新增: | 字段 | 类型 | 说明 | |---|---|---| | bagType | Integer | 当前批次包装袋型 | ### 2. 生成袋码并自动生成托盘 | 方法 | 路径 | 说明 | |---|---|---| | POST | `/mes/pro/bag-code/generate` | 生成袋码;有效袋码达到完整阈值时自动生成托盘并绑定 | 请求参数: | 参数 | 类型 | 必填 | 说明 | |---|---|---|---| | batchId | Long | 是 | 生产中批次编号 | | count | Integer | 是 | 本次生成袋码数量,大于0 | | remark | String | 否 | 袋码备注 | 响应 `data`: | 字段 | 类型 | 说明 | |---|---|---| | uuid | String | 本次袋码生成组 UUID | | autoPallets | Array | 本次自动生成托盘标签列表;未跨过完整阈值时为空 | `autoPallets` 字段: | 字段 | 类型 | 说明 | |---|---|---| | id | Long | 托盘编号 | | code | String | 托盘二维码内容 | | batchId | Long | 生产批次编号 | | batchCode | String | 批次号 | | palletNo | Integer | 批次内托盘序号 | | capacity | Integer | 托盘容量,等于袋型阈值 | | bagCount | Integer | 已装袋数,自动托盘生成后等于容量 | | copies | Integer | 标签打印份数,固定为3 | | itemId/itemCode/itemName/itemSpecification | — | 品种信息 | | lineCode/lineName | String | 产线信息 | | produceDate | String | 生产日期 | | ownerUserId/ownerUserName | — | 责任人信息 | 响应示例: ```json { "code": 0, "data": { "uuid": "生成组UUID", "autoPallets": [ { "id": 1001, "code": "PC20260821L01A001-P01", "batchId": 1024, "batchCode": "PC20260821L01A001", "palletNo": 1, "capacity": 100, "bagCount": 100, "copies": 3, "itemId": 2001, "itemCode": "ITEM001", "itemName": "产品A", "itemSpecification": "规格A", "lineCode": "L01", "lineName": "包装一线", "produceDate": "2026-08-21 08:00:00", "ownerUserId": 1, "ownerUserName": "张三" } ] } } ``` ## 字段展示规则 | 字段 | 展示位置 | 说明 | |---|---|---| | bagType | 批次新增/编辑、批次列表、批次详情 | 通过字典显示小袋/大袋;批次已有袋码或托盘后只读 | | bagQuantity | 批次列表/详情 | 有效袋码累计数量 | | palletQuantity | 批次列表/详情 | 已生成托盘数量,包含手工和自动托盘 | | autoGenerated | 托盘列表/详情 | 标识该托盘是否由阈值自动生成 | | autoPallets[].code | 打印标签 | 作为二维码编码内容,同时显示托盘码文本 | | autoPallets[].copies | 打印控制 | 同一托盘标签打印3份;不要连续调用三次打印 | | autoPallets[].batchCode | 打印标签 | 显示关联批次号 | | autoPallets[].bagCount/capacity | 打印标签或详情 | 自动托盘正常情况下相等,均为对应阈值 | ## 业务规则说明 | 场景 | 规则 | |---|---| | 小袋 | 有效袋码每累计100个自动生成一个托盘 | | 大袋 | 有效袋码每累计48个自动生成一个托盘 | | 有效袋码 | `deleted = 0` 且 `status <> 30`,已绑定人工托盘的袋码不参与自动归集 | | 袋码分组 | 按 `bagNo` 升序,每组必须达到完整阈值;余数不绑定 | | 自动托盘容量 | 固定为当前批次阈值,不使用手工托盘容量 | | 重复生成 | 同一批次请求串行锁定;已绑定袋码不会再次候选,重复调用不重复创建 | | 人工绑定 | 自动流程不改绑已人工绑定袋码;人工绑定和解绑需要在服务端加锁 | | 破损替换 | 新袋码继承旧袋码已有托盘;有效数量不增加,不重复触发新托盘 | | 删除/作废 | 作废袋码不计入有效数;已绑定袋码不允许通过生成组删除 | | 打印 | 后端只返回标签数据;浏览器端一次渲染3份并调用一次 `window.print()`,无法保证静默打印 | ## 注意事项 - 历史批次的 `bagType` 需要在启用自动托盘前补齐,不能由后端猜测。 - 只有生产中批次允许生成袋码和自动托盘。 - 普通浏览器无法绕过系统打印对话框;若要求无人值守打印,需要另行接入本地打印代理或打印控件。 - 不要把 ZIP 下载响应当作自动打印结果;现有 ZIP 接口继续用于批量导出。 - 自动托盘中的袋码完整关联以袋码记录的 `palletId`、`palletCode` 和托盘的 `bagCount` 为准。