# 种子二维码标签国标合规 - 前端联调方案 ## 背景 依据《农作物种子标签二维码编码规则》与《农作物种子标签通则》(GB 20464-2024), 每个二维码对应唯一的最小销售单元种子且不得重复使用,二维码必须包含四项信息并按顺序排列: 1. 品种名称 2. 生产经营者名称(进口种子为进口商名称) 3. 单元识别代码(不超过 20 个字符,数字或字母数字组合) 4. 追溯网址 本次改造将「生产经营者名称」与「追溯网址」收敛为后端统一数据源,并让已作废的追溯码对外失效。 ## 涉及页面 - H5 扫码溯源页 `trace.html`(已完成改造,无需前端另行处理) - 管理后台 - 赋码管理页(菜单 `mes/pro/bagCode/index`,前端工程中**当前缺失**,需新建) - 管理后台 - 托盘码管理页 / 批次生产管理页(二维码预览与导出,如有) ## API | 方法 | 路径 | 说明 | 鉴权 | |------|------|------|------| | GET | `/public/mes/trace/config` | **新增**:获得溯源页配置(生产经营者名称、追溯网址) | 免登录 | | GET | `/public/mes/trace/query` | 追溯查询,**响应新增 3 个字段** | 免登录 | | GET | `/admin-api/mes/pro/bag-code/export-qr` | 导出二维码标签 ZIP,**新增校验与拒绝逻辑** | `mes:pro-bag-code:export` | | GET | `/admin-api/mes/pro/bag-code/export-excel` | 导出袋码 Excel | `mes:pro-bag-code:export` | ### 1. 新增:获得溯源页配置 `GET /public/mes/trace/config` **请求参数:** 无 **响应示例:** ```json { "code": 0, "data": { "operatorName": "新疆塔里木河种业股份有限公司", "traceUrl": "http://1.95.78.124:9008/prod/trace.html", "imported": false }, "msg": "" } ``` **响应字段:** | 字段 | 类型 | 说明 | |------|------|------| | operatorName | String | 生产经营者名称;`imported=true` 时为进口商名称 | | traceUrl | String | 追溯网址,与二维码内容前缀完全一致(不含 `code` 参数) | | imported | Boolean | 是否进口种子场景;为 true 时页面字段名应显示「进口商名称」 | ### 2. 追溯查询响应新增字段 `GET /public/mes/trace/query?code=xxx` **响应字段新增:** | 字段 | 类型 | 说明 | |------|------|------| | codeStatus | String | `VALID`-有效 / `CANCELED`-已作废 | | operatorName | String | 生产经营者名称(与标签印刷内容同源) | | traceUrl | String | 追溯网址(与标签印刷内容同源) | **响应示例:** ```json { "code": 0, "data": { "sourceType": "BAG", "requestCode": "0286267849370923", "codeStatus": "VALID", "operatorName": "新疆塔里木河种业股份有限公司", "traceUrl": "http://1.95.78.124:9008/prod/trace.html", "batchBound": false, "itemCode": "xxx", "itemName": "塔河4号", "itemUnitMeasureName": "48千克" } } ``` ## 字段展示规则 ### H5 溯源页(追溯查询区块) 四要素必须按国标顺序展示,其余信息排列其后: | 顺序 | 字段 | 取值来源 | 说明 | |------|------|----------|------| | 1 | 品种名称 | `itemName` + `itemSpecification` | 国标要素① | | 2 | 生产经营者 / 进口商名称 | `operatorName`,退回 `/config` 的 `operatorName` | 国标要素②;`imported=true` 时标签改为「进口商名称」 | | 3 | 单元识别代码 | `requestCode` 去 URL 后的码值 | 国标要素③。**仅袋码(`sourceType=BAG`)使用此名称**;托盘码/批次码展示为「托盘码(非最小销售单元)」「批次码(非最小销售单元)」,避免误导 | | 4 | 追溯网址 | `traceUrl`,退回 `/config` 的 `traceUrl` | 国标要素④,可点击跳转 | | 5+ | 计量单位、追溯类型、批次号、生产日期、产线 | 各自字段 | 辅助信息 | ### H5 溯源页(生产明细折叠区) 国标要求追溯网址应可查询「种子加工批次」及「物流销售信息」,因此以下区块**对外展示**(默认折叠不展开): | 区块 | 数据来源 | 说明 | |------|----------|------| | 生产批次信息 | `batchCode`、`batchStatusName`、`produceDate`、`lineName`、`planQuantity` 等 | 对应国标「种子加工批次」;`batchBound=false`(未录入批次)时**不展示该区块**,避免暗示无加工批次 | | 种子流向信息 | `seedFlows`(销售出库 bizType=119)或 `salesTargets` | 对应国标「物流销售信息」,含来源单号、客户、数量、仓库/库区 | | 加工流转 | `processTraces` | 加工节点流转记录 | 以下区块**仅内部可见,不对外展示**(如需一并展示,将 `detailSections(d, false)` 改为 `detailSections(d, true)`): | 区块 | 不展示原因 | |------|-----------| | 生产人员 | 涉及个人信息 | | 质检信息、托盘信息、袋码列表、采购来源 | 内部明细,非消费者关切 | ### 管理后台 - 赋码管理页 | 字段 | 展示位置 | 说明 | |------|----------|------| | 品种名称 | 列表、详情 | 袋码绑定的品种 | | 单元识别代码 | 列表、详情 | 即袋码 `code` | | 状态 | 列表 | 已生成 / 已导出印刷 / 已作废 | ## 业务规则说明 | 场景 | 规则 | |------|------| | 导出二维码标签 | 四要素任一缺失则**拒绝导出并报错**,不再静默跳过空字段 | | 四要素缺失提示 | 缺少品种名称 → 1040750021;缺少生产经营者 → 1040750022;缺少单元识别代码 → 1040750023;未配置追溯网址 → 1040750020 | | 单元识别代码格式 | 必须为 1~20 位数字或字母数字组合,含连字符等符号时报 1040750024 | | 扫码命中已作废袋码 | 返回 `codeStatus=CANCELED`,页面显示「该追溯码已作废,非本公司有效产品,谨防假冒」,且不再展示溯源详情 | | 已作废码被扫描 | **仍记录扫码事件**(作废码被扫是重要防伪信号),不计为查询失败 | | 未配置追溯网址 | 非 local 环境启动时直接失败;local 环境可通过 `mes.allow-plain-qr-code=true` 兼容历史码 | | 导出二维码标签 | **已作废的袋码不再导出**(按批次/生成组导出时均排除)。作废码标签若印出并贴到产品上,消费者扫码会被提示「该追溯码已作废,谨防假冒」,导致真品被误判为假货 | ## 配置项 后端配置项(`application-*.yaml` 的 `mes` 前缀): | 配置项 | 必填 | 说明 | |--------|------|------| | `mes.trace-base-url` | 是 | 追溯网址,必须为公众可访问地址。非 local 环境若为内网 IP / localhost / 占位符将**拒绝启动** | | `mes.operator-name` | 是 | 生产经营者名称。未配置则无法导出标签(启动时告警) | | `mes.importer-name` | 否 | 进口商名称,进口种子场景填写 | | `mes.imported` | 否 | 是否进口种子场景,默认 false | | `mes.allow-plain-qr-code` | 否 | 是否允许二维码编码纯码值,仅供本地兼容历史码,默认 false | ## 注意事项 - **前端禁止再硬编码生产经营者名称与追溯网址**,必须通过 `/public/mes/trace/config` 获取,否则会与二维码内容不一致。 - 追溯网址在二维码内容与页面展示之间只有 `mes.trace-base-url` 一个真值源,前端展示时不要自行拼接 `/prod` 等路径。 - 已作废码的判定覆盖三种入口:袋码(状态 30)、托盘码(状态 20)、批次码(状态 40),三者的作废枚举值不同,前端不要共用常量判断。 - **存量标签需重新导出**:改造前导出的二维码内容已固化,其中追溯网址可能为内网地址且标签缺少四要素,需重新导出印刷。 - **袋序号改为原子分配**:原先由「查库内最大值再 +1」得到,并发生成会产生重复袋序号(袋序号会印在标签上);现已改为 Redis 原子自增分配,并用库内最大值校正基准。序号**只保证不重复、不回退,不保证连续**(并发下不同请求拿到不同区段,属正常)。 - 管理后台赋码管理页面(`mes/pro/bagCode/index`)在前端工程中缺失,业务人员目前无法自助查看/导出二维码,建议补充。