文件
hl-api-changelog/changelogs-v2/2026-08/29_6643_供应商编辑页地址营业执照与备注回显-修改接口-管理后台.md
T
lc 4621f11e36
changelog-filename-gate / validate (push) Successful in 2s
交接供应商编辑字段回显契约(#6643)
2026-08-29 14:36:10 +08:00

16 KiB
原始文件 Blame 文件历史

schema, ticket, title, consumer, author, change_type, backend_status, gateway_status, frontend_status, frontend_owner, frontend_ref, target_release, verified_at, status_note, updated_at, base
schema ticket title consumer author change_type backend_status gateway_status frontend_status frontend_owner frontend_ref target_release verified_at status_note updated_at base
hl-changelog/v2 6643 供应商编辑页地址营业执照与备注回显 admin lc(GIT) 修改接口 deployed verified pending PR #6645 已合并 dev-v3;hl-resource-service 已通过 Deploy Panel 任务 954419f9 部署提交 d206d1d577a3e3f8cec228e73e139fcb36c00fd5。真实 TEST Gateway 已验证 address、licenseImageUrl、remark 原值回显、更新后回读、空地址保留、营业执照顶层字段权威读取、395014 零写入及测试草稿清理。 2026-08-29 dev-v3

🔧 供应商编辑页地址、营业执照与备注回显

供应商编辑页应直接使用详情根对象的 address、licenseImageUrl、remark 初始化表单。其中 licenseImageUrl 是营业执照上传控件的权威字段,不得再从 qualifications[].imageUrl 推导或覆盖。

本次没有新增接口路径、请求必填项、权限点或业务错误码。

一、关键变化

字段 修改前 修改后
data.address 已有详情字段,但编辑和空值保留规则缺少本次回归锁定 返回已保存地址;提交非空新值后可回读,更新时留空保持原值
data.licenseImageUrl 详情根对象没有稳定的营业执照权威回显,调用方可能从资质数组取值 详情根对象稳定返回营业执照;只读取顶层权威值,不再从资质数组反向派生
data.remark 已有详情字段,但编辑回显和更新规则缺少本次回归锁定 返回已保存内部备注;提交非空新值后可回读

二、变更接口清单

# 接口 方法 路径 变更类型 说明
1 查询供应商基本信息 GET /admin/supplier/items/{supplierId}/basic-info/view 响应修改 根对象稳定返回 address、licenseImageUrl、remark
2 更新供应商资料 PUT /admin/supplier/items/{supplierId}/update 行为修改 三字段按增量更新和并发版本规则保存;写后重新查询可得到新值

三、接口详情

1. 查询供应商基本信息 GET /admin/supplier/items/{supplierId}/basic-info/view

VO: SupplierBasicInfoRespVO

使用场景

管理端进入供应商详情或编辑页时获取完整表单快照。营业执照上传控件必须绑定根对象 data.licenseImageUrl;qualifications[] 继续用于独立资质列表,不是该控件的取值来源。

入参

字段 位置 类型 必填 约束 说明
supplierId Path String 是 正整数 ID 字符串 目标供应商;不得转为 JavaScript Number

无 Query 参数,无请求体。

出参 Result<SupplierBasicInfoRespVO>

字段 类型 说明
data.address String/null 注册地址或经营地址;未填写时为 null
data.licenseImageUrl String/null 营业执照影像权威地址;未填写时为 null
data.remark String/null 供应商主体内部备注;不等同于审批意见或变更原因
data.qualifications[].imageUrl String/null 单项资质影像;与根对象营业执照字段分别读取
data.updateTime String 主体并发版本,格式 yyyy-MM-dd HH:mm:ss

请求示例

GET /admin/supplier/items/2092800000000000001/basic-info/view
Authorization: Bearer <admin-token>

响应示例

{
  "code": 200,
  "message": "成功",
  "success": true,
  "data": {
    "supplierId": "2092800000000000001",
    "supplierNo": "SUP2092800000000000001",
    "fullName": "示例旅行服务有限公司",
    "shortName": "示例旅行",
    "tax_no": "91350211M000100Y46",
    "legalRepresentative": "示例法人",
    "legalRepresentativeIdNo": "11010519491231002X",
    "legalRepresentativeIdNoMask": "11010519491231002X",
    "legalRepresentativeIdCardFrontUrl": null,
    "legalRepresentativeIdCardBackUrl": null,
    "contactPhone": "13800138000",
    "contactPhoneMask": "13800138000",
    "establishDate": "2020-01-01",
    "registeredCapital": "100万元",
    "businessScope": "境内旅游服务",
    "address": "福建省厦门市示例路 2 号",
    "staffScale": "LT50",
    "mainCooperation": "酒店与景区资源合作",
    "licenseImageUrl": "https://files.example.com/supplier/business-license-new.jpg",
    "remark": "地址与营业执照已复核",
    "status": "DRAFT",
    "creditLevel": "B",
    "totalScore": null,
    "types": [],
    "primaryTypeCode": null,
    "primaryTypeName": null,
    "contacts": [],
    "qualifications": [
      {
        "qualificationId": "2092800000000000011",
        "qualType": "BUSINESS_LICENSE",
        "qualTypeName": "营业执照",
        "certNo": null,
        "certNoMask": null,
        "imageUrl": "https://files.example.com/supplier/business-license-new.jpg",
        "expiryDate": null,
        "permanentValid": true,
        "daysUntilExpiry": null,
        "validityStatus": "VALID",
        "validityStatusName": "有效",
        "isRequired": false,
        "expired": false,
        "updateTime": "2026-08-29 14:40:01"
      }
    ],
    "contracts": [],
    "updateTime": "2026-08-29 14:40:02"
  }
}

空数据 / 降级响应

未填写三字段时返回明确的 null,前端显示空控件即可,不要用资质数组补写营业执照:

{
  "code": 200,
  "message": "成功",
  "success": true,
  "data": {
    "supplierId": "2092800000000000001",
    "address": null,
    "licenseImageUrl": null,
    "remark": null,
    "qualifications": [],
    "updateTime": "2026-08-29 14:40:02"
  }
}

错误响应

供应商不存在、已删除或超出可见范围:

{
  "code": 395001,
  "message": "供应商不存在",
  "success": false,
  "data": null
}

业务边界

  • 要求可信管理身份、可读角色、supplier:view 平台权限和既有数据范围。
  • 根对象 licenseImageUrl 是编辑页营业执照的唯一权威回显;即使 qualifications[] 中同类型影像不同,也不得覆盖根对象值。
  • 历史记录没有可用营业执照时返回 null,不猜测默认图片。
  • 本接口只读,不推进版本、不触发审批或其他业务副作用。

2. 更新供应商资料 PUT /admin/supplier/items/{supplierId}/update

VO: SupplierUpdateReqVO / SupplierWriteRespVO

使用场景

管理端保存供应商编辑表单。请求只发送实际修改字段,并携带详情中的最新 updateTime 和本次 changeReason。

入参

字段 位置 类型 必填 约束 说明
supplierId Path String 是 正整数 ID 字符串 目标供应商
address Body String 否 最长 500 字符 非空时更新;省略、null、空串或纯空格时保留原值
licenseImageUrl Body String 否 最长 500 字符 省略时保留;传非空值时更新权威营业执照;传空串时清空
remark Body String 否 - 非空时更新;省略、null、空串或纯空格时保留原值
changeReason Body String 是 去空白后非空,最长 500 字符 本次资料变更原因
expectedUpdateTime Body String 是 yyyy-MM-dd HH:mm:ss 详情最新主体并发版本

其他既有可选字段和集合快照规则保持不变。

出参 Result<SupplierWriteRespVO>

字段 类型 说明
data.supplierId String 供应商 ID
data.supplierNo String 供应商业务编号
data.status String 当前生命周期状态
data.onboardingStage String 当前注册阶段
data.initialAccounts Array 初始收款账户摘要
data.updateTime String 写入后的新主体并发版本

请求示例

PUT /admin/supplier/items/2092800000000000001/update
Authorization: Bearer <admin-token>
Content-Type: application/json

{
  "address": "福建省厦门市示例路 2 号",
  "licenseImageUrl": "https://files.example.com/supplier/business-license-new.jpg",
  "remark": "地址与营业执照已复核",
  "changeReason": "更新供应商编辑资料",
  "expectedUpdateTime": "2026-08-29 14:40:00"
}

响应示例

{
  "code": 200,
  "message": "成功",
  "success": true,
  "data": {
    "supplierId": "2092800000000000001",
    "supplierNo": "SUP2092800000000000001",
    "status": "DRAFT",
    "onboardingStage": "PROFILE_DRAFT",
    "initialAccounts": [],
    "updateTime": "2026-08-29 14:40:02"
  }
}

写响应不重复返回 address、licenseImageUrl、remark。前端需要完整表单时,应使用新 updateTime 重新查询详情。

空数据 / 降级响应

成功更新时 data 恒为写入结果对象,不返回 null。当前请求没有实际变化时不会伪造成功或推进版本,而是返回业务失败:

{
  "code": 400,
  "message": "未检测到实际变化",
  "success": false,
  "data": null
}

错误响应

{
  "code": 395014,
  "message": "数据已被他人修改,请刷新后重试",
  "success": false,
  "data": null
}

收到 395014 后先重新获取详情,由用户确认后再提交;不得用旧表单自动覆盖。

业务边界

  • 要求可信管理身份、FINANCE 或 SUPER_ADMIN 写角色及 supplier:update 平台权限。
  • 成功写入后推进主体 updateTime;权限、参数、状态或并发失败时三字段及版本均不变化。
  • 顶层 licenseImageUrl 更新时会继续兼容同步营业执照资质影像;反向只修改 qualifications[].imageUrl 不会改写顶层权威字段。
  • remark 是主体内部备注;changeReason 是本次变更审计原因,两者不得互相替代。
  • 统一响应可能以 HTTP 200 承载业务失败,调用方必须同时判断 code、success、message 和 data。

四、契约约束与正确调用方式

编辑页初始化

地址输入框       ← data.address
营业执照上传控件 ← data.licenseImageUrl
内部备注输入框   ← data.remark
并发版本         ← data.updateTime

不得把 qualifications.find(item => item.qualType === "BUSINESS_LICENSE").imageUrl 作为营业执照上传控件的回显值或顶层字段兜底。

更新规则对照

场景 请求 结果
更新三个字段 发送三个非空新值 + 原因 + 最新版本 更新成功;重新查询返回三个新值
地址留空,修改备注 address: " ",remark 为新值 地址保持原值,备注更新
省略营业执照 不发送 licenseImageUrl 顶层营业执照保持原值
清空营业执照 licenseImageUrl: "" 顶层营业执照清空,兼容影像同步清空
只改资质数组影像 发送 qualifications[],不发送顶层字段 资质影像独立变化,顶层营业执照保持原值
使用旧版本 发送过期 expectedUpdateTime 返回 395014,零写入

五、数据库行为

本节只描述接口可观察结果,不要求前端感知存储结构:

  • 三字段更新成功后,再次查询详情返回新值,且主体 updateTime 推进。
  • address 或 remark 留空时保存其他字段,重新查询仍返回原地址或原备注。
  • 顶层 licenseImageUrl 更新成功后,详情根对象与兼容营业执照资质影像均返回新值。
  • 只更新资质数组影像时,详情根对象 licenseImageUrl 保持原值。
  • 权限、参数、状态或 395014 并发失败时,三字段和主体版本均不变化。
  • 部署时已对可识别的历史营业执照影像完成一次性兼容初始化;之后详情根对象不再从资质数组动态派生。

六、边界行为

  • 未登录或 Token 无效由 Gateway 拒绝,不产生业务写入。
  • 无 supplier:view 时详情读取失败;无 supplier:update 或不属于允许写角色时更新返回 395002,零写入。
  • 供应商不存在、已删除或不可见时返回 395001。
  • address 或 licenseImageUrl 超过各自长度上限时返回 400,零写入。
  • 缺少 changeReason、缺少 expectedUpdateTime 或没有实际变化时返回 400,零写入。
  • 版本过期返回 395014;客户端必须刷新详情,不能自动覆盖。
  • ARCHIVED 等不可修改状态继续由既有状态门禁拒绝。
  • 业务失败可能仍使用 HTTP 200,客户端必须检查统一响应体。

六.6、修改前后对比

字段级对比

字段 改前 改后
data.address 字段已存在,但本次编辑回归未锁定 原值、更新值及留空保留规则均已锁定
data.licenseImageUrl 根对象没有稳定权威回显 根对象返回可空权威值,不从 qualifications[] 反向派生
data.remark 字段已存在,但本次编辑回归未锁定 原值和更新值均可稳定回读

行为级对比

行为 改前 改后
编辑页初始化营业执照 可能从资质数组搜索影像 固定读取根对象 licenseImageUrl
更新营业执照 根对象回读来源不稳定 提交顶层字段后,写后查询返回同一新值
单独修改资质影像 可能被误当成主体营业执照 不改变根对象营业执照权威值

六.7、影响评估

  • 是否破坏向后兼容:否。详情根对象增加可空字段并固定既有字段行为;旧客户端可忽略未知字段。
  • 前端是否必须同步上线:需要。营业执照上传控件必须改为读取并提交顶层 licenseImageUrl;地址和备注继续直接绑定根对象字段。
  • 前端 workaround 清理点:删除从 qualifications[] 搜索营业执照影像并覆盖表单值的逻辑。
  • QA 重点:已有值回显、三字段更新后刷新、地址留空保留、资质影像与顶层营业执照相互独立、旧版本失败零写入。

七、不影响范围

  • 仅影响:管理后台供应商详情与编辑表单的地址、营业执照和内部备注。
  • 零影响:
    • 接口路径、Gateway 路由和认证级别。
    • 供应商既有角色、平台权限和数据范围。
    • 生命周期状态机、审批、合同、收款账户和资源关系。
    • 既有业务错误码、Redis、MQ、Feign 和其他服务。
    • 小程序、C 端、Web、H5 和桌面端接口。

八、测试环境已验证

  • 本地:供应商定向 62 项通过;hl-resource-service Reactor 全量 2,186 项通过,0 失败、0 错误,38 项既有条件跳过。
  • 合并:后端 PR #6645 已合并,合并提交为 d206d1d577a3e3f8cec228e73e139fcb36c00fd5。
  • 部署:Deploy Panel API 任务 954419f9 成功,TEST 目标与实际提交均为上述合并提交;任务期 6 个采样均至少保持 2 个进程与 2 个健康启用实例匹配,0 个不可用采样。
  • 真实 Gateway:唯一测试草稿依次验证原值回显、资质影像独立变化时顶层营业执照不变、三字段更新后回读、空地址保留、旧版本 395014 零写入及未认证拒绝。
  • 清理:测试草稿已通过业务删除接口软删除并确认详情不可查询;仅保留系统规定的脱敏业务审计事实。

九、撤回

如后端撤回本次契约,前端在回退部署前停止依赖顶层 licenseImageUrl,并以同步发布的撤回 Changelog 为准;不得自行恢复未冻结的资质数组反向覆盖逻辑。地址与备注仍按既有 #6476 契约处理。

十、相关文档

  • 关联 Issue:#6643
  • 关联 PR:#6645
  • 既有地址与备注契约:#6476
  • 当前前端状态:待前端处理;请按根对象字段完成映射后回写本文件的消费状态。

关联 / 联系人

链接

联系人

  • 后端负责人: @lc
  • 管理端负责人: 待认领(frontend_status: pending)