--- schema: "hl-changelog/v2" ticket: "7090" title: "供应商信用等级与公司资料字段" consumer: "admin" author: "lc(GIT)" change_type: "修改接口" backend_status: "deployed" gateway_status: "verified" frontend_status: "verified" frontend_owner: "mmg" frontend_ref: "32a1a289" target_release: "" verified_at: "2026-09-04" status_note: "后端已部署并通过 TEST;前端需在供应商新建和编辑表单接入信用等级、公开电子邮箱、公司类型和办公地址。" updated_at: "2026-09-04" base: "dev-v3" --- # 供应商模块:信用等级与公司资料字段 供应商新建、编辑和注册提交支持 `creditLevel`、`publicEmail`、`companyType`、`officeAddress`,详情新增后三个字段回显。公司类型使用系统字典 `supplier_company_type`。 ## ⚠️ 关键变化 - 新建省略 `creditLevel` 时后端默认值由 B 改为 A;可选值仍与供应商主列表筛选一致,为 A/B/C/D。 - 只有 `SUPER_ADMIN` 可以显式提交 `creditLevel`。其他角色可以展示详情值,但请求体必须省略该字段。 ## 二、变更接口清单 | # | 接口 | 方法 | 路径 | 变更类型 | 说明 | |---|---|---|---|---|---| | 1 | 查询供应商基本信息 | GET | `/admin/supplier/items/{supplierId}/basic-info/view` | 响应新增字段 | 回显公开邮箱、公司类型和办公地址 | | 2 | 查询供应商公司类型字典 | GET | `/admin/dict/data/supplier_company_type` | 新增字典数据 | 返回固定的两个生效选项 | | 3 | 新建供应商草稿 | POST | `/admin/supplier/items/add` | 请求新增字段 | 支持信用等级和三个可选公司资料字段 | | 4 | 修改供应商资料 | PUT | `/admin/supplier/items/{supplierId}/update` | 请求新增字段 | 支持增量维护并保留省略字段 | | 5 | 提交供应商注册 | POST | `/admin/supplier/items/{supplierId}/submit` | 请求新增字段 | 完整表单可携带新增字段进入审批 | ## 三、接口详情 ### 1. 查询供应商基本信息 `GET /admin/supplier/items/{supplierId}/basic-info/view` **VO**: `SupplierBasicInfoRespVO` #### 使用场景 打开供应商详情或编辑页时读取当前字段值和并发版本。 #### 入参 | 字段 | 位置 | 类型 | 必填 | 约束 | 说明 | |---|---|---|---|---|---| | `supplierId` | Path | String | 是 | 正整数 ID | 供应商 ID | #### 出参 `Result` | 字段 | 类型 | 说明 | |---|---|---| | `data.creditLevel` | String | 信用等级 A/B/C/D | | `data.publicEmail` | String/null | 公开电子邮箱 | | `data.companyType` | String/null | `supplier_company_type` 的 `dictValue` | | `data.officeAddress` | String/null | 办公地址 | | `data.updateTime` | String | 编辑请求使用的最新并发版本 | #### 请求示例 ```http GET /admin/supplier/items/2095000000000000001/basic-info/view Authorization: Bearer ``` 无请求体。 #### 响应示例 ```json { "code": 200, "message": "成功", "success": true, "data": { "supplierId": "2095000000000000001", "creditLevel": "A", "publicEmail": "service@example.com", "companyType": "1", "officeAddress": "呼和浩特市示例办公地址", "updateTime": "2026-09-04 20:04:19" } } ``` #### 空数据 / 降级响应 存量数据或新建时未填写三个可选资料字段,分别返回 `null`;接口不使用默认文案代替空值。 #### 错误响应 ```json {"code":395001,"message":"供应商不存在","data":null,"success":false} ``` #### 业务边界 - 沿用供应商详情查看权限;业务失败可能仍使用 HTTP 200,必须检查响应体。 - `companyType` 返回字典值,不返回中文标签;前端用字典接口翻译。 - `creditLevel` 可以展示给有详情权限的用户,是否可编辑按当前角色控制。 ### 2. 查询供应商公司类型字典 `GET /admin/dict/data/supplier_company_type` **VO**: `Result>` #### 使用场景 供应商新建或编辑页加载公司类型下拉选项。 #### 入参 | 字段 | 位置 | 类型 | 必填 | 约束 | 说明 | |---|---|---|---|---|---| | `supplier_company_type` | Path | String | 是 | 固定字典类型 | 不要改成中文名称 | #### 出参 `Result>` | 字段 | 类型 | 说明 | |---|---|---| | `data[].dictValue` | String | 提交给供应商接口的值 | | `data[].dictLabel` | String | 下拉展示文案 | | `data[].sortOrder` | Number | 升序展示顺序 | | `data[].status` | String | 当前均为 `ACTIVE` | #### 请求示例 ```http GET /admin/dict/data/supplier_company_type Authorization: Bearer ``` 无请求体。 #### 响应示例 ```json { "code": 200, "message": "成功", "success": true, "data": [ {"dictValue":"1","dictLabel":"有限责任公司(自然人投资或控股)","sortOrder":10,"status":"ACTIVE"}, {"dictValue":"2","dictLabel":"国企控股","sortOrder":20,"status":"ACTIVE"} ] } ``` #### 空数据 / 降级响应 后端已初始化两个选项;若请求失败或返回空数组,表单不要用本地硬编码选项替代。 #### 错误响应 ```json {"code":401,"message":"未登录或登录已过期","data":null,"success":false} ``` #### 业务边界 - 下拉框展示 `dictLabel`,请求只提交对应的 `dictValue`。 - 当前合法值严格为 `1`、`2`;不要提交中文标签。 - 字典接口需要管理端真实登录态。 ### 3. 新建供应商草稿 `POST /admin/supplier/items/add` **VO**: `SupplierDraftSaveReqVO → SupplierWriteRespVO` #### 使用场景 管理端供应商新建表单保存完整草稿。 #### 入参 | 字段 | 位置 | 类型 | 必填 | 约束 | 说明 | |---|---|---|---|---|---| | `creditLevel` | Body | String | 否 | A/B/C/D;仅 `SUPER_ADMIN` 可显式提交 | 省略时后端默认 A | | `publicEmail` | Body | String | 否 | 邮箱格式,最长 100 | 公开电子邮箱 | | `companyType` | Body | String | 否 | 生效的 `supplier_company_type` 值 | 公司类型 | | `officeAddress` | Body | String | 否 | 最长 500 | 录入方式与 `address` 一致 | | `fullName`、`taxNo` | Body | String | 是 | 沿用现有主体校验 | 供应商名称与主体证件号 | | `types` | Body | Array | 是 | 至少 1 项 | 供应商类型完整集合 | | 法人资料与 `contactPhone` | Body | String | 是 | 沿用现有格式校验 | 法人姓名、身份证三字段和联系电话 | | `establishDate`、`address` | Body | String | 是 | 日期不得晚于当天;地址非空 | 成立日期和注册地址 | | `balance`、`paymentType`、`mainCooperation` | Body | 混合 | 是 | 沿用现有规则 | 结算与合作资料 | | `licenseImageUrl` | Body | String | 是 | 非空 | 营业执照影像 | | `contacts`、`initialAccounts` | Body | Array | 是 | 至少一名联系人;当前一个初始账户 | 聚合子项 | #### 出参 `Result` | 字段 | 类型 | 说明 | |---|---|---| | `data.supplierId` | String | 新供应商 ID | | `data.status` | String | 新建成功为 `DRAFT` | | `data.updateTime` | String | 后续编辑使用的并发版本 | #### 请求示例 ```json { "fullName": "示例供应商有限公司", "taxNo": "91350211M000100Y46", "types": [{"typeCode":"HOTEL"}], "legalRepresentative": "张三", "legalRepresentativeIdNo": "11010519491231002X", "legalRepresentativeIdCardFrontUrl": "https://example.com/id-front.jpg", "legalRepresentativeIdCardBackUrl": "https://example.com/id-back.jpg", "contactPhone": "13800138000", "establishDate": "2020-01-02", "address": "呼和浩特市示例注册地址", "creditLevel": "A", "publicEmail": "service@example.com", "companyType": "1", "officeAddress": "呼和浩特市示例办公地址", "balance": 0, "paymentType": "1", "mainCooperation": "酒店资源合作", "licenseImageUrl": "https://example.com/license.jpg", "contacts": [{"contactName":"李四","contactPhone":"13800138001","contactRole":"contentBus","isPrimary":true}], "initialAccounts": [{"accountType":"CORPORATE","bankName":"示例银行","accountNo":"6222000012345678"}] } ``` #### 响应示例 ```json { "code":200,"message":"成功","success":true, "data":{"supplierId":"2095000000000000001","status":"DRAFT","updateTime":"2026-09-04 20:04:19"} } ``` #### 空数据 / 降级响应 省略 `publicEmail`、`companyType`、`officeAddress` 时保存为未填写,详情返回 `null`;无降级成功响应。 #### 错误响应 ```json {"code":395002,"message":"无权执行该供应商写操作","data":null,"success":false} ``` #### 业务边界 - `creditLevel` 省略时后端固定默认 A;不要再按旧行为假设默认 B。 - 只有 `SUPER_ADMIN` 可显式提交 `creditLevel`;其他可创建供应商的角色必须省略该字段。 - 三个公司资料字段均非必填;显式 `companyType` 必须命中当前生效字典。 - 非法邮箱、信用等级、公司类型或超过 500 字的办公地址返回业务码 `400`,失败不创建草稿。 ### 4. 修改供应商资料 `PUT /admin/supplier/items/{supplierId}/update` **VO**: `SupplierUpdateReqVO → SupplierWriteRespVO` #### 使用场景 编辑页按详情中的最新版本增量保存供应商资料。 #### 入参 | 字段 | 位置 | 类型 | 必填 | 约束 | 说明 | |---|---|---|---|---|---| | `supplierId` | Path | String | 是 | 正整数 ID | 目标供应商 | | `expectedUpdateTime` | Body | String | 是 | `yyyy-MM-dd HH:mm:ss` | 取详情最新 `updateTime` | | `creditLevel` | Body | String | 否 | A/B/C/D;仅 `SUPER_ADMIN` 可显式提交 | 省略保留现值 | | `publicEmail` | Body | String | 否 | 邮箱格式,最长 100 | 省略保留现值 | | `companyType` | Body | String | 否 | 生效的字典值 1/2 | 省略保留现值 | | `officeAddress` | Body | String | 否 | 最长 500 | 省略保留现值 | #### 出参 `Result` | 字段 | 类型 | 说明 | |---|---|---| | `data.supplierId` | String | 供应商 ID | | `data.status` | String | 保存后的状态 | | `data.updateTime` | String | 保存后的新并发版本 | #### 请求示例 ```json { "creditLevel": "B", "publicEmail": "service@example.com", "companyType": "2", "officeAddress": "呼和浩特市示例办公地址", "expectedUpdateTime": "2026-09-04 20:04:19" } ``` #### 响应示例 ```json { "code":200,"message":"成功","success":true, "data":{"supplierId":"2095000000000000001","status":"DRAFT","updateTime":"2026-09-04 20:05:01"} } ``` #### 空数据 / 降级响应 省略新增字段表示保留现值;接口没有空数据成功或降级成功。 #### 错误响应 ```json {"code":395014,"message":"数据已被他人修改,请刷新后重试","data":null,"success":false} ``` #### 业务边界 - 保存前先读取详情并使用最新 `updateTime`;过期版本不写入任何字段。 - 只有 `SUPER_ADMIN` 可显式提交 `creditLevel`。其他角色即使值未改变也必须省略,否则返回 `395002`。 - 省略 `creditLevel` 不会重置为 A;A 只用于新建时的缺省值。 - `companyType` 必须提交字典值;邮箱、公司类型和办公地址的失败校验均不产生部分更新。 ### 5. 提交供应商注册 `POST /admin/supplier/items/{supplierId}/submit` **VO**: `SupplierSubmitReqVO → SupplierApprovalCommandRespVO` #### 使用场景 供应商完整注册表单保存并提交审批。 #### 入参 | 字段 | 位置 | 类型 | 必填 | 约束 | 说明 | |---|---|---|---|---|---| | `supplierId` | Path | String | 是 | 正整数 ID | 草稿供应商 | | `expectedUpdateTime` | Body | String | 是 | 最新并发版本 | 防止覆盖并发编辑 | | `creditLevel` | Body | String | 否 | A/B/C/D;仅 `SUPER_ADMIN` 可显式提交 | 省略保留草稿值 | | `publicEmail` | Body | String | 否 | 邮箱格式,最长 100 | 省略保留草稿值 | | `companyType` | Body | String | 否 | 生效的字典值 1/2 | 省略保留草稿值 | | `officeAddress` | Body | String | 否 | 最长 500 | 省略保留草稿值 | | 完整注册资料 | Body | 混合 | 是 | 沿用现有提交契约 | 主体、类型、联系人、账户及营业执照等 | #### 出参 `Result` | 字段 | 类型 | 说明 | |---|---|---| | `data.approvalLogId` | String | 审批记录 ID | | `data.provider` | String | 审批提供方 | | `data.approvalStatus` | String | 审批状态 | | `data.submittedAt` | String | 提交时间 | #### 请求示例 ```json { "fullName": "示例供应商有限公司", "taxNo": "91350211M000100Y46", "types": [{"typeCode":"HOTEL"}], "legalRepresentative": "张三", "legalRepresentativeIdNo": "11010519491231002X", "legalRepresentativeIdCardFrontUrl": "https://example.com/id-front.jpg", "legalRepresentativeIdCardBackUrl": "https://example.com/id-back.jpg", "contactPhone": "13800138000", "establishDate": "2020-01-02", "address": "呼和浩特市示例注册地址", "creditLevel": "A", "publicEmail": "service@example.com", "companyType": "1", "officeAddress": "呼和浩特市示例办公地址", "balance": 0, "paymentType": "1", "mainCooperation": "酒店资源合作", "licenseImageUrl": "https://example.com/license.jpg", "contacts": [{"contactName":"李四","contactPhone":"13800138001","contactRole":"contentBus","isPrimary":true}], "initialAccounts": [{"accountType":"CORPORATE","bankName":"示例银行","accountNo":"6222000012345678"}], "expectedUpdateTime": "2026-09-04 20:05:01" } ``` #### 响应示例 ```json { "code":200,"message":"成功","success":true, "data":{"approvalLogId":"2095000000000000010","provider":"WECOM","approvalStatus":"PENDING","submittedAt":"2026-09-04 20:05:02"} } ``` #### 空数据 / 降级响应 写接口成功时返回审批受理结果;失败时 `data` 为 `null`,不会以空对象表示成功。 #### 错误响应 ```json {"code":395002,"message":"无权执行该供应商写操作","data":null,"success":false} ``` #### 业务边界 - 新增可选字段省略时沿用既有“保留草稿值”语义,不会清空已保存资料。 - 显式 `creditLevel` 仍只允许 `SUPER_ADMIN`;其他提交角色必须省略该字段。 - 公司类型按提交时生效字典校验;校验失败不会进入审批。 - 审批、幂等、重复主体确认和状态规则保持不变。 ## 四、契约约束与正确调用方式(接口类必写) | 场景 | 正确调用 | |---|---| | 新建页面 | 从主列表相同选项展示 A/B/C/D;初始选中 A | | 非超级管理员 | 可展示信用等级,但新建、编辑、提交请求均省略 `creditLevel` | | 公司类型 | 调字典接口,用 `dictLabel` 展示、用 `dictValue` 提交 | | 编辑保存 | 携带详情最新 `updateTime`;只提交实际允许修改的字段 | | 注册提交 | 三个公司资料字段省略时保留草稿值,不需重复拼接空值 | ## 五、数据库行为 | 前端提交 | 外部可观察结果 | |---|---| | 新建省略 `creditLevel` | 详情返回 `creditLevel: "A"` | | 编辑或提交省略 `creditLevel` | 保留已有等级 | | 新建省略三个公司资料字段 | 详情对应字段返回 `null` | | 填写三个公司资料字段 | 保存成功后详情原值回显 | | 校验或权限失败 | 不产生部分字段写入 | ## 六、边界行为 - 业务失败可能仍为 HTTP 200,必须同时检查 `code`、`success` 和 `message`。 - `creditLevel` 只接受大写 A/B/C/D;非法值返回业务码 `400`。 - `publicEmail` 最长 100,`officeAddress` 最长 500;超限或邮箱格式非法返回业务码 `400`。 - `companyType` 只接受当前生效字典值;字典不可用或值失效时失败关闭。 - 存量供应商三个新增资料字段没有自动推断或回填,详情可返回 `null`。 ## 六.5、枚举 / 数据字典 ### creditLevel **所属字段**: `SupplierDraftSaveReqVO.creditLevel / SupplierUpdateReqVO.creditLevel / SupplierBasicInfoRespVO.creditLevel` | **类型**: `String` | 值 | 中文 | 说明 | |---|---|---| | `A` | A 级 | 新建省略时的默认值 | | `B` | B 级 | 与主列表筛选共用 | | `C` | C 级 | 与主列表筛选共用 | | `D` | D 级 | 与主列表筛选共用 | ### companyType(supplier_company_type) **所属字段**: `SupplierDraftSaveReqVO.companyType / SupplierUpdateReqVO.companyType / SupplierBasicInfoRespVO.companyType` | **类型**: `String` | 值 | 中文 | 说明 | |---|---|---| | `1` | 有限责任公司(自然人投资或控股) | 生效字典值 | | `2` | 国企控股 | 生效字典值 | ## 六.6、修改前后对比 ### 字段级对比 | 字段 | 改前 | 改后 | |---|---|---| | `creditLevel` 请求 | 新建、编辑不能维护 | 新建、编辑、提交可选;仅 `SUPER_ADMIN` 可显式提交 | | `publicEmail` | 无请求或详情字段 | 可选保存并在详情回显 | | `companyType` | 无请求或详情字段 | 可选保存并按系统字典回显 | | `officeAddress` | 无请求或详情字段 | 可选保存并在详情回显 | ### 行为级对比 | 行为 | 改前 | 改后 | |---|---|---| | 新建省略信用等级 | 默认 B | 默认 A | | 编辑省略新增字段 | 无对应字段 | 保留已有值 | | 公司类型选项 | 无集中契约 | 从 `supplier_company_type` 动态读取 | ## 六.7、影响评估 - **是否破坏向后兼容**: 否。旧客户端省略新增字段仍可调用;新建信用缺省业务值由 B 调整为 A。 - **前端是否必须同步上线**: 是。新建和编辑页需展示四个字段并接入公司类型字典。 - **前端 workaround 清理点**: 不要硬编码公司类型;不要再把新建缺省信用等级当作 B;非 `SUPER_ADMIN` 不要序列化 `creditLevel`。 ## 七、不影响范围 - **仅影响**: 管理后台供应商新建、编辑、详情和注册提交表单。 - **零影响**: 供应商主列表信用等级筛选选项、生命周期状态机、审批流程、账户流程和其他前端入口。 ## 八、测试环境已验证 - 公司类型字典真实返回且仅返回两个约定的生效选项。 - 真实新建、编辑和详情调用已逐项保存并回读 A/B/C/D,以及公开邮箱、公司类型 1/2、办公地址。 - 真实新建省略四个字段后,信用等级回读为 A,三个可选公司资料字段回读为 `null`。 - 编辑省略 `creditLevel` 后保持既有等级;两条验收草稿均已通过业务删除接口清理。 - 注册提交沿用同一请求字段、权限和保存逻辑,已通过合并提交的后端契约测试;TEST 未创建外部审批单。 ## 十、相关文档 - 关联 Issue: [wx/HL#7090](https://git.1814.love:8443/wx/HL/issues/7090) - 关联 PR: [wx/HL#7107](https://git.1814.love:8443/wx/HL/pulls/7107) ## 关联 / 联系人 ### 链接 - **Issue**: [#7090](https://git.1814.love:8443/wx/HL/issues/7090) - **PR**: [#7107](https://git.1814.love:8443/wx/HL/pulls/7107) - **Merge commit**: [c1102d62ecb81c24596fba91bba6e704da6e85ff](https://git.1814.love:8443/wx/HL/commit/c1102d62ecb81c24596fba91bba6e704da6e85ff) ### 联系人 - **后端负责人**: @lc