--- schema: "hl-changelog/v2" ticket: "8741" title: "供应商注册提交:证件图片地址不对直接返回 395065,状态与审批记录不再出现「建单失败」" consumer: "admin" author: "lc(GIT)" change_type: "修改接口" backend_status: "deployed" gateway_status: "verified" frontend_status: "not_required" frontend_owner: "" frontend_ref: "" target_release: "" verified_at: "" status_note: "新增一种失败返回,前端按现有方式展示 message;状态展示名少了「建单失败」,若前端有按该文案着色或筛选的逻辑请一并去掉" updated_at: "2026-10-04" base: "dev-v3" --- # 供应商: 注册提交校验证件图片地址,去掉「建单失败」状态 > **服务**: hl-resource-service、hl-user-service > **PR**: #8758 > **Issue**: #8741 > **日期**: 2026-10-04 > **影响范围**: 管理端供应商「提交审批」(注册审批)、供应商列表与详情的状态、供应商审批记录 --- ## ⚠️ 关键变化 - 提交注册审批时,法人身份证人像面、国徽面、营业执照三张图片中任一张的地址不是本平台图片服务器地址(各环境不同,取文件中心配置),接口当场返回 `395065`「图片地址不对」。供应商保持草稿,不产生审批记录。以前会先受理,后台建企业微信审批单失败后才退回草稿,并显示「建单失败」。 - 供应商列表、详情的状态展示名不再出现「建单失败」,原来显示「建单失败」的供应商显示「草稿」。供应商审批记录、审批记录列表的层级与状态文案中的「建单失败」也改为「草稿」。 - 企业微信审批单内容(不影响管理端接口):「收款账户」显示银行名 + 完整账号;「明细 → 结算信息」每个账户显示账户名称、账户类型、开户行、支行、账号;「注册资本」为纯数字时显示为数值加「万」(如 500 → 500万)。 --- ## 二、变更接口清单 | # | 接口 | 方法 | 路径 | 变更类型 | 说明 | |---|------|------|------|----------|------| | 1 | 提交供应商注册审批 | POST | `/admin/supplier/items/{supplierId}/submit` | 新增一种失败返回 | 证件图片地址不对时返回 395065 | | 2 | 供应商分页 | GET | `/admin/supplier/items/page` | 返回值文案变化 | `statusName` 不再返回「建单失败」,改为「草稿」 | | 3 | 供应商有界查询 | GET | `/admin/supplier/items/list` | 返回值文案变化 | 同上 | | 4 | 供应商基本信息 | GET | `/admin/supplier/items/{supplierId}/basic-info/view` | 返回值文案变化 | 同上 | | 5 | 供应商审批记录 | GET | `/admin/supplier/items/{supplierId}/approval-history/page` | 返回值文案变化 | `approvalStatusName`、`chainLevelText` 不再返回「建单失败」,改为「草稿」 | | 6 | 审批记录列表 | GET | `/admin/supplier/items/approval-records/page` | 返回值文案变化 | `chainLevelText` 不再返回「建单失败」,改为「草稿」 | --- ## 三、接口详情 ### 1. 提交供应商注册审批 `POST /admin/supplier/items/{supplierId}/submit` **VO**: `SupplierSubmitReqVO` → `SupplierApprovalCommandRespVO` #### 使用场景 管理员把草稿供应商提交注册审批。 #### 入参 | 字段 | 位置 | 类型 | 必填 | 约束 | 说明 | |------|------|------|------|------|------| | supplierId | Path | Long | ✅ | 正整数 | 草稿供应商 ID | | expectedUpdateTime | Body | String | ✅ | `yyyy-MM-dd HH:mm:ss` | 乐观锁,取详情里的 updateTime | | legalRepresentativeIdCardFrontUrl | Body | String | - | 非空时须为本平台图片地址 | 法人身份证人像面 | | legalRepresentativeIdCardBackUrl | Body | String | - | 非空时须为本平台图片地址 | 法人身份证国徽面 | | licenseImageUrl | Body | String | - | 非空时须为本平台图片地址 | 营业执照 | | 其余注册资料字段 | Body | - | - | 同现有提交接口 | 本次未改 | 本平台图片地址即管理端文件上传返回的地址(TEST 形如 `https://hlgl-test.oss-cn-beijing.aliyuncs.com/test/...`,正式环境前缀为 `prod`)。 #### 出参 `Result` | 字段 | 类型 | 说明 | |------|------|------| | approvalLogId | String | 审批记录 ID | | requestNo | String | 幂等请求号 | | provider | String | 审批方式,企业微信为 `WECOM` | | approvalStatus | String | 审批状态,提交后为 `PENDING` | | approvalStatusName | String | 审批状态中文名 | | spNo | String | 企业微信审批单号,异步建单完成前为空 | | syncStatus | String | 同步状态 | | submittedAt | String | 提交时间 | 本次出参不变。 #### 请求示例 ```json { "expectedUpdateTime": "2026-10-03 11:31:05", "fullName": "鄂温克族自治旗巴彦呼硕草原牧家乐有限公司", "legalRepresentativeIdCardFrontUrl": "https://hlgl-test.oss-cn-beijing.aliyuncs.com/test/other/2026/10/03/9c21c0b068c00baa227cfd450e6706ae.png", "legalRepresentativeIdCardBackUrl": "https://hlgl-test.oss-cn-beijing.aliyuncs.com/test/other/2026/10/03/a1d6e23d67830251b1fdd251c6d885ad.png", "licenseImageUrl": "https://hlgl-test.oss-cn-beijing.aliyuncs.com/test/other/2026/10/03/1f287826963710fa564639f4c0de8aac.png" } ``` #### 响应示例 ```json { "code": 200, "message": "成功", "data": { "approvalLogId": "2106260000000000001", "provider": "WECOM", "approvalStatus": "PENDING", "approvalStatusName": "审核中", "syncStatus": "REQUESTING" }, "success": true } ``` #### 空数据 / 降级响应 本接口没有空数据。文件中心暂不可用、取不到本平台图片地址时不放行,返回 `100903`「远程服务暂不可用: 文件中心」,供应商保持草稿、不产生审批记录,稍后重试即可。 #### 错误响应 ```json { "code": 395065, "message": "图片地址不对", "success": false } ``` #### 业务边界 - 鉴权、权限、乐观锁、必填校验与现有提交接口相同。 - 三张证件图只校验非空的那几张;为空的维持现状(不上传该附件)。 - 任一张不是本平台图片地址:返回 395065,本次提交的资料不保存、不产生审批记录、供应商仍为草稿(零写入)。 - 已有在途注册审批时重复提交,仍按原规则返回在途结果。 - 修正图片后可直接重新提交。 ### 2. 供应商分页 `GET /admin/supplier/items/page` **VO**: `SupplierPageReqVO` → `PageResult` #### 使用场景 管理端供应商列表。 #### 入参 | 字段 | 位置 | 类型 | 必填 | 约束 | 说明 | |------|------|------|------|------|------| | keyword | Query | String | - | - | 编号/名称关键字 | | status | Query | String | - | 生命周期编码 | 状态筛选,不变 | | typeCode | Query | String | - | - | 供应商类型 | | creditLevel | Query | String | - | A/B/C/D | 信用等级 | | creatorId | Query | Long | - | - | 创建人 | | page | Query | Integer | - | ≥1 | 页码 | | pageSize | Query | Integer | - | ≥1 | 每页条数 | 本次入参不变。 #### 出参 `Result>` | 字段 | 类型 | 说明 | |------|------|------| | status | String | 生命周期编码,不变 | | statusName | String | 展示名;明确建单失败的草稿供应商由「建单失败」改为「草稿」 | 其余字段不变。 #### 请求示例 ```http GET /admin/supplier/items/page?keyword=SUP260262&page=1&pageSize=20 ``` #### 响应示例 ```json { "code": 200, "data": { "list": [ { "supplierNo": "SUP260262", "status": "DRAFT", "statusName": "草稿" } ] }, "success": true } ``` #### 空数据 / 降级响应 无数据时返回空列表或原有空值,本次不变。 #### 错误响应 本次没有新增错误码,沿用现有错误返回,例如: ```json { "code": 395001, "message": "供应商不存在", "success": false } ``` #### 业务边界 - 鉴权与数据权限、分页与筛选不变;只有状态展示名从「建单失败」改为「草稿」,`status` 编码与按状态筛选不变。 ### 3. 供应商有界查询 `GET /admin/supplier/items/list` **VO**: `SupplierListReqVO` → `List` #### 使用场景 下拉或关联选择时有界查询供应商。 #### 入参 | 字段 | 位置 | 类型 | 必填 | 约束 | 说明 | |------|------|------|------|------|------| | keyword | Query | String | - | - | 编号/名称关键字 | | status | Query | String | - | 生命周期编码 | 状态筛选,不变 | | typeCode | Query | String | - | - | 供应商类型 | | resourceModule | Query | String | - | 与 resourceId 同时传 | 资源模块 | | resourceId | Query | Long | - | 与 resourceModule 同时传 | 资源 ID | | limit | Query | Integer | - | 默认 50,最多 200 | 返回条数 | 本次入参不变。 #### 出参 `Result>` | 字段 | 类型 | 说明 | |------|------|------| | status | String | 生命周期编码,不变 | | statusName | String | 展示名;明确建单失败的草稿供应商由「建单失败」改为「草稿」 | 其余字段不变。 #### 请求示例 ```http GET /admin/supplier/items/list?keyword=SUP260262 ``` #### 响应示例 ```json { "code": 200, "data": [ { "supplierNo": "SUP260262", "status": "DRAFT", "statusName": "草稿" } ], "success": true } ``` #### 空数据 / 降级响应 无数据时返回空列表或原有空值,本次不变。 #### 错误响应 本次没有新增错误码,沿用现有错误返回,例如: ```json { "code": 395001, "message": "供应商不存在", "success": false } ``` #### 业务边界 - 鉴权与数据权限、分页与筛选不变;只有状态展示名从「建单失败」改为「草稿」,`status` 编码与按状态筛选不变。 ### 4. 供应商基本信息 `GET /admin/supplier/items/{supplierId}/basic-info/view` **VO**: `—(Path 参数)` → `SupplierBasicInfoRespVO` #### 使用场景 供应商详情与编辑页回显。 #### 入参 | 字段 | 位置 | 类型 | 必填 | 约束 | 说明 | |------|------|------|------|------|------| | supplierId | Path | Long | ✅ | 正整数 | 供应商 ID | 本次入参不变。 #### 出参 `Result` | 字段 | 类型 | 说明 | |------|------|------| | status | String | 生命周期编码,不变 | | statusName | String | 展示名;明确建单失败的草稿供应商由「建单失败」改为「草稿」 | 其余字段不变。 #### 请求示例 ```http GET /admin/supplier/items/2105983859848060929/basic-info/view ``` #### 响应示例 ```json { "code": 200, "data": { "supplierNo": "SUP260262", "status": "DRAFT", "statusName": "草稿" }, "success": true } ``` #### 空数据 / 降级响应 无数据时返回空列表或原有空值,本次不变。 #### 错误响应 本次没有新增错误码,沿用现有错误返回,例如: ```json { "code": 395001, "message": "供应商不存在", "success": false } ``` #### 业务边界 - 鉴权与数据权限、分页与筛选不变;只有状态展示名从「建单失败」改为「草稿」,`status` 编码与按状态筛选不变。 ### 5. 供应商审批记录 `GET /admin/supplier/items/{supplierId}/approval-history/page` **VO**: `SupplierApprovalHistoryPageReqVO` → `PageResult` #### 使用场景 供应商详情页的审批记录。 #### 入参 | 字段 | 位置 | 类型 | 必填 | 约束 | 说明 | |------|------|------|------|------|------| | supplierId | Path | Long | ✅ | 正整数 | 供应商 ID | | bizType | Query | String | - | - | 审批类型 | | approvalStatus | Query | String | - | - | 审批状态编码 | | action | Query | String | - | - | 业务动作 | | from / to | Query | String | - | `yyyy-MM-dd HH:mm:ss`,需同时传 | 提交时间范围 | | sortBy / sortDirection | Query | String | - | 默认 submittedAt / DESC | 排序 | | page | Query | Integer | - | ≥1 | 页码 | | pageSize | Query | Integer | - | ≥1 | 每页条数 | 本次入参不变。 #### 出参 `Result>` | 字段 | 类型 | 说明 | |------|------|------| | approvalStatus | String | 审批状态编码,不变(如 `FAILED`) | | approvalStatusName | String | 注册明确未建单由「建单失败」改为「草稿」 | | chainLevelText | String | 注册明确未建单由「建单失败」改为「草稿」 | 其余字段不变。 #### 请求示例 ```http GET /admin/supplier/items/2105983859848060929/approval-history/page?page=1&pageSize=50 ``` #### 响应示例 ```json { "code": 200, "data": { "list": [ { "approvalStatus": "FAILED", "approvalStatusName": "草稿", "chainLevelText": "草稿", "actionName": "提交草稿" } ] }, "success": true } ``` #### 空数据 / 降级响应 无数据时返回空列表或原有空值,本次不变。 #### 错误响应 本次没有新增错误码,沿用现有错误返回,例如: ```json { "code": 395001, "message": "供应商不存在", "success": false } ``` #### 业务边界 - 鉴权、分页、筛选与行数不变;只有注册明确未建单那一行的展示文案从「建单失败」改为「草稿」,`approvalStatus` 编码不变。 ### 6. 审批记录列表 `GET /admin/supplier/items/approval-records/page` **VO**: `SupplierApprovalLogPageReqVO` → `PageResult` #### 使用场景 跨供应商的审批记录列表。 #### 入参 | 字段 | 位置 | 类型 | 必填 | 约束 | 说明 | |------|------|------|------|------|------| | supplierNo | Query | String | - | - | 供应商编号 | | fullName | Query | String | - | - | 供应商名称 | | bizType | Query | String | - | - | 审批类型 | | approvalStatus | Query | String | - | - | 审批状态编码 | | from / to | Query | String | - | `yyyy-MM-dd HH:mm:ss` | 提交时间范围 | | page | Query | Integer | - | ≥1 | 页码 | | pageSize | Query | Integer | - | ≥1 | 每页条数 | 本次入参不变。 #### 出参 `Result>` | 字段 | 类型 | 说明 | |------|------|------| | approvalStatus | String | 审批状态编码,不变 | | chainLevelText | String | 注册明确未建单由「建单失败」改为「草稿」 | 其余字段不变。 #### 请求示例 ```http GET /admin/supplier/items/approval-records/page?supplierNo=SUP260262&page=1&pageSize=50 ``` #### 响应示例 ```json { "code": 200, "data": { "list": [ { "supplierNo": "SUP260262", "approvalStatus": "FAILED", "chainLevelText": "草稿" } ] }, "success": true } ``` #### 空数据 / 降级响应 无数据时返回空列表或原有空值,本次不变。 #### 错误响应 本次没有新增错误码,沿用现有错误返回,例如: ```json { "code": 395001, "message": "供应商不存在", "success": false } ``` #### 业务边界 - 鉴权、分页、筛选与行数不变;只有注册明确未建单那一行的展示文案从「建单失败」改为「草稿」,`approvalStatus` 编码不变。 --- ## 四、契约约束与正确调用方式(接口类必写) ### ✅ 正确 / ❌ 错误 payload 对照 | 场景 | payload | |------|---------| | ✅ 三张图都是文件上传返回的地址 | `{ "licenseImageUrl": "https://hlgl-test.oss-cn-beijing.aliyuncs.com/test/other/2026/10/03/a.png", ... }` | | ✅ 某张图为空 | `{ "legalRepresentativeIdCardBackUrl": null, ... }` | | ❌ 外站地址 | `{ "licenseImageUrl": "https://img.hlbe-travel.com/supplier/2026/1002/x.jpg" }` → 395065 | | ❌ 其他环境的地址(如 TEST 提交正式环境 `prod/` 前缀地址) | `{ "licenseImageUrl": "https://hlgl-test.oss-cn-beijing.aliyuncs.com/prod/x.png" }` → 395065 | ### 切换状态时的必要动作 收到 395065 时,让用户重新上传三张证件图(用管理端文件上传返回的地址),再带最新 `expectedUpdateTime` 重新提交。 --- ## 五、数据库行为(涉及写操作时必写) | 提交结果 | 供应商资料 | 供应商状态 | 审批记录 | |----------|-----------|-----------|---------| | 图片地址都对 | 按提交内容保存 | 进入注册审核中 | 新增 1 条 | | 任一张图片地址不对(395065) | 不保存(本次提交整体回滚) | 保持草稿 | 不新增 | | 文件中心不可用(100903) | 不保存 | 保持草稿 | 不新增 | --- ## 六、边界行为 - 未登录 → 401(网关拦截);无权限 → 沿用现有错误。 - 图片地址为空 → 不校验该张,照原规则提交。 - 文件中心不可用 → 100903,不放行。 - 历史上显示「建单失败」的供应商 → 现在直接显示「草稿」,可修正图片后重新提交。 --- ## 六.6、修改前后对比(修改/删除类接口必写,新增跳过) ### 字段级对比 | 字段 | 改前 | 改后 | |------|------|------| | `statusName`(列表、详情) | 明确建单失败时为「建单失败」 | 「草稿」 | | `approvalStatusName`、`chainLevelText`(审批记录) | 「建单失败」 | 「草稿」 | | `chainLevelText`(审批记录列表) | 「建单失败」 | 「草稿」 | ### 行为级对比 | 行为 | 改前 | 改后 | |------|------|------| | 证件图在外站时提交注册审批 | 接口先受理,后台建企业微信审批单失败,自动重提后退回草稿并显示「建单失败」 | 接口当场返回 395065「图片地址不对」,零写入 | | 企业微信审批单「收款账户」 | 银行名 尾号xxxx | 银行名 完整账号 | | 企业微信审批单「明细 → 结算信息」 | 银行名 尾号xxxx | 每个账户:账户名称、账户类型、开户行、支行、账号 | | 企业微信审批单「注册资本」 | 原样(如 500) | 纯数字补「万」(如 500万),已带单位的原样 | ## 六.7、影响评估(修改/删除类必写) - **是否破坏向后兼容**: 否(新增一种失败返回;展示文案少了「建单失败」一种取值) - **前端是否必须同步上线**: 否 - **前端 workaround 清理点**: 如有按「建单失败」文案着色、筛选或提示的逻辑,可以去掉 ## 七、不影响范围(显式声明, 帮前端/QA 缩小排查面) - **仅影响**: 供应商注册「提交审批」接口;供应商状态展示名与审批记录文案中的「建单失败」 - **零影响**: - 供应商生命周期状态编码、状态筛选、状态机 - 合作中资料变更审批、状态变更审批、收款账户审批 - 主档注册资本存值与管理端展示(「万」只加在企业微信审批单上) --- ## 八、测试环境已验证 TEST 已部署 dev-v3 `df99bfedf`(包含合并提交 `a73f015e7`),经 Gateway 实测: ``` SUP260262、SUP260260(证件图在外站)重新提交 → 395065「图片地址不对」,仍为草稿,审批记录仍各 3 条 ✓ 自造草稿 SUP260266 只把营业执照换成外站地址提交 → 395065,仍为草稿、营业执照未被改写、无审批记录 ✓ 两家列表与详情状态展示「草稿」,审批记录与审批记录列表无「建单失败」;供应商列表整表 256 家无「建单失败」 ✓ SUP260266 三张图为本平台地址时提交 → 受理并生成企业微信审批单 202610040008 ✓ ``` --- ## 十、相关文档 - 关联 Issue: [wx/HL#8741](https://git.1814.love/wx/HL/issues/8741) - 关联 PR: [wx/HL#8758](https://git.1814.love/wx/HL/pulls/8758) ## 关联 / 联系人 ### 链接 - **Issue**: [#8741](https://git.1814.love/wx/HL/issues/8741) - **PR**: [#8758](https://git.1814.love/wx/HL/pulls/8758) - **Merge commit**: [a73f015e7](https://git.1814.love/wx/HL/commit/a73f015e7) ### 联系人 - **后端负责人**: @lc