docs: 精简6710前端变更记录
changelog-filename-gate / validate (push) Successful in 2s

这个提交包含在:
lc
2026-08-30 10:24:09 +08:00
父节点 a45b51d8a8
当前提交 5c52926269
@@ -12,30 +12,20 @@ frontend_owner: ""
frontend_ref: ""
target_release: ""
verified_at: ""
status_note: "PR #6712 已合并 dev-v3,合并提交 7f3f944bf361b7ae41424c43b29262fb634fe791 已精确部署 TEST。真实 Gateway 已验证联系人详情返回的 updateTime 可直接作为条目级并发版本回传,并能一次新增多个姓名、联系电话重复的联系人;验收草稿已清理。当前前端已经回传 updateTime,无需修改代码;本记录按用户确认更正为无需前端处理。"
status_note: "当前前端已回传联系人 updateTime,无需修改代码;后端现已兼容该字段。TEST 已验证重复姓名、电话的多个联系人可保存。当前状态:无需前端处理。"
updated_at: "2026-08-30"
base: "dev-v3"
---
# 供应商联系人快照版本字段兼容
供应商编辑接口现已兼容详情响应中的 `contacts[].updateTime`:管理端保留已有联系人并新增多个联系人时,可以将详情联系人对象原样回传,不再因版本字段名不一致收到“联系人快照项不合法”。联系人姓名和联系电话允许重复。
当前管理端已按上述方式回传 `updateTime`,无需修改前端代码。本文件是在“前端无需改代码则不推送 Changelog”规则确认前已经发布的记录,现仅保留为历史审计并更正为无需前端处理,不构成前端任务。
后端现已兼容详情联系人字段 `contacts[].updateTime`。当前前端已经回传该字段,无需修改代码;本记录仅保留历史审计,不构成前端任务。
## 二、变更接口清单
| # | 接口 | 方法 | 路径 | 变更类型 | 说明 |
|---:|---|---|---|---|---|
| 1 | 编辑供应商 | PUT | `/admin/supplier/items/{supplierId}/update` | 请求字段兼容 | 已有联系人条目同时接受 `expectedUpdateTime` 和详情字段 `updateTime` 作为并发版本 |
详情接口路径和响应结构未修改:
| 接口 | 方法 | 路径 | 本次用途 |
|---|---|---|---|
| 查询供应商基本信息 | GET | `/admin/supplier/items/{supplierId}/basic-info/view` | 返回主体 `updateTime`、联系人 `contactId` 和联系人 `updateTime` |
业务失败可能仍返回 HTTP 200,调用方必须同时判断统一响应中的 `code`、`success`、`message` 和 `data`。
| 1 | 编辑供应商 | PUT | `/admin/supplier/items/{supplierId}/update` | 请求兼容 | 已有联系人可用 `updateTime` 作为条目级并发版本 |
## 三、接口详情
@@ -45,183 +35,105 @@ base: "dev-v3"
#### 使用场景
管理端编辑供应商时,需要保留详情中的已有联系人并在同一次保存中新增一个或多个联系人。调用方可以直接使用详情返回的联系人 `updateTime` 作为该条目的并发版本。
保留已有联系人并在一次编辑中新增多个联系人。
#### 入参
| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 |
|---|---|---|---:|---|---|
| `supplierId` | Path | String | 是 | 正整数 ID 字符串 | 目标供应商 |
| `expectedUpdateTime` | Body | String | 是 | `yyyy-MM-dd HH:mm:ss` | 供应商主体并发版本,取详情顶层 `updateTime` |
| `contacts` | Body | Array | 否 | 最多 100 项 | 完整联系人快照;省略表示不修改,空数组表示清空 |
| `contacts[].contactId` | Body | String | 已有项是 | 正整数 ID 字符串 | 为空表示新增联系人 |
| `contacts[].expectedUpdateTime` | Body | String | 已有项二选一 | `yyyy-MM-dd HH:mm:ss` | 规范的联系人条目级并发版本字段 |
| `contacts[].updateTime` | Body | String | 已有项二选一 | `yyyy-MM-dd HH:mm:ss` | 本次新增兼容名,可直接使用详情响应值 |
| `contacts[].contactName` | Body | String | 新增项按既有规则 | 最长 500 字符 | 允许与已有或同批新增联系人重复 |
| `contacts[].contactPhone` | Body | String | 新增项按既有规则 | 7~20 位合法电话格式 | 允许与已有或同批新增联系人重复 |
| `contacts[].contactRole` | Body | String | 新增项是 | 当前生效的 `sup_content_role.dictValue` | 沿用既有角色字典校验 |
| `contacts[].isPrimary` | Body | Boolean | 否 | 非空快照最终恰好一个默认联系人 | 沿用既有默认联系人规则 |
| `expectedUpdateTime` | Body | String | 是 | `yyyy-MM-dd HH:mm:ss` | 主体并发版本 |
| `contacts` | Body | Array | 否 | 最多 100 项 | 联系人完整快照 |
| `contacts[].contactId` | Body | String | 已有项是 | 正整数 | 为空表示新增 |
| `contacts[].expectedUpdateTime` / `updateTime` | Body | String | 已有项二选一 | 时间格式同上 | 条目级并发版本 |
已有联系人仍必须提供 `contactId`,并通过 `expectedUpdateTime` 或 `updateTime` 携带条目级并发版本;本次只兼容字段名,没有取消并发校验。新增联系人不发送 `contactId` 和版本字段。
姓名和联系电话允许与已有联系人或同批新增联系人重复。新增项仍按既有规则提供姓名、电话和角色,不传 ID 与版本。
#### 出参 `Result<SupplierWriteRespVO>`
| 字段 | 类型 | 说明 |
|---|---|---|
| `code` | Number | 业务码;成功为 `200` |
| `success` | Boolean | 业务是否成功 |
| `data.supplierId` | String | 供应商 ID |
| `data.supplierNo` | String | 供应商业务编号 |
| `data.status` | String | 保存后的供应商状态 |
| `data.onboardingStage` | String | 当前建档阶段 |
| `data.initialAccounts` | Array | 当前初始结算账户摘要 |
| `data.updateTime` | String | 保存后的主体并发版本 |
#### 请求示例
以下请求保留一名已有联系人,并新增两名姓名、电话相同的联系人:
```json
{
"expectedUpdateTime": "2026-08-30 10:04:18",
"contacts": [
{
"contactId": "2093000000000000001",
"contactName": "张三",
"contactPhone": "18501941408",
"contactRole": "contentBus",
"isPrimary": true,
"updateTime": "2026-08-30 10:04:19"
},
{
"contactName": "张三",
"contactPhone": "18501941408",
"contactRole": "contentMoney",
"isPrimary": false
},
{
"contactName": "张三",
"contactPhone": "18501941408",
"contactRole": "contentMoney",
"isPrimary": false
}
]
}
{"expectedUpdateTime":"2026-08-30 10:04:18","contacts":[{"contactId":"2093000000000000001","contactName":"张三","contactPhone":"18501941408","contactRole":"contentBus","updateTime":"2026-08-30 10:04:19"},{"contactName":"张三","contactPhone":"18501941408","contactRole":"contentMoney"}]}
```
#### 响应示例
```json
{
"code": 200,
"message": "成功",
"success": true,
"data": {
"supplierId": "2093000000000000000",
"supplierNo": "SUP2093000000000000000",
"status": "DRAFT",
"onboardingStage": "PROFILE_DRAFT",
"initialAccounts": [],
"updateTime": "2026-08-30 10:04:29"
}
}
{"code":200,"message":"成功","success":true,"data":{"updateTime":"2026-08-30 10:04:29"}}
```
#### 空数据 / 降级响应
- 省略 `contacts` 或传 `null` 表示本次不修改联系人;传空数组表示按既有快照语义清空联系人。
- 本次不新增降级返回;联系人角色字典等既有依赖异常时继续失败关闭,不产生部分写入。
- 省略 `contacts` 或传 `null`:联系人不变。
- 依赖异常:沿用既有失败关闭语义,不产生部分写入。
#### 错误响应
已有联系人缺少两种版本字段时,继续返回既有快照校验错误:
版本过期时:
```json
{
"code": 400,
"message": "联系人快照项不合法",
"success": false,
"data": null
}
{"code":395014,"message":"数据已被他人修改,请刷新后重试","success":false,"data":null}
```
联系人版本已过期时,继续返回既有并发错误:
```json
{
"code": 395014,
"message": "数据已被他人修改,请刷新后重试",
"success": false,
"data": null
}
```
已有联系人未携带任一版本字段时,仍返回 `400`、`联系人快照项不合法`。
#### 业务边界
- 快照字段和版本均有效时返回 `code=200`、`success=true`,并返回新的主体 `data.updateTime`。
- 已有联系人缺少两种版本字段时,继续返回业务码 `400`、消息“联系人快照项不合法”。
- 联系人版本已过期时,继续返回业务码 `395014`、消息“数据已被他人修改,请刷新后重试”,整次请求零写入。
- 姓名或联系电话重复本身不是拒绝条件,不新增重复值错误码。
- 接口继续要求有效管理端身份、既有可信角色和服务端供应商写权限。
- 本次不改变供应商状态门禁、聚合锁、幂等、审计或事务边界。
- 已有联系人仍须提供 `contactId` 和有效版本;本次没有取消并发校验。
- 姓名或联系电话重复本身不是错误条件。
- 权限、状态、默认联系人及角色字典规则均不变。
## 四、契约约束与正确调用方式
1. 进入编辑页先读取供应商详情,保留顶层 `updateTime` 及每个已有联系人的 `contactId`、`updateTime`。
2. 提交时把顶层 `updateTime` 放入请求的 `expectedUpdateTime`。
3. 已有联系人可以保留详情对象的 `updateTime` 字段原样提交;新增联系人不要伪造 `contactId` 或版本。
4. 保存成功后重新读取详情,以新的主体和联系人版本作为下一次编辑的并发基线。
1. 主体详情 `updateTime` 放入请求顶层 `expectedUpdateTime`。
2. 已有联系人的 `updateTime` 可原样回传;新增联系人不传 ID 和版本。
3. 保存后重新读取详情,使用最新版本继续编辑。
## 五、数据库行为
- 本次不新增或修改数据库 migration、索引及唯一约束。
- 姓名和联系电话继续按既有方式存储;没有按这两个字段新增去重或唯一性限制。
- 联系人新增、更新、软删除、默认项归一、审计及主体版本推进仍在既有供应商聚合事务内完成。
- 参数、权限或并发校验失败时不产生联系人部分写入。
- 不新增数据库结构或姓名、电话唯一约束。
- 校验失败时联系人和主体均不写入。
## 六、边界行为
- 未登录请求继续由 Gateway 拒绝;本次不改变认证级别。
- 无供应商写权限、供应商不存在、状态不允许或主体并发版本过期时继续按既有错误语义失败。
- 联系人 `contactId` 必须属于当前供应商;重复 ID、无效 ID 或已软删除 ID 继续被拒绝。
- 新增联系人仍需满足姓名、电话格式、角色字典和默认联系人等既有规则;只允许姓名或电话的业务值重复。
- 成功保存后应重新读取详情,使用服务端返回的新版本继续编辑。
- 未登录、无权限、供应商不存在或版本过期时沿用既有错误。
- `contacts=[]` 沿用既有清空语义。
- 业务失败可能仍为 HTTP 200,调用方同时判断 `code` 和 `success`。
## 六.6、修改前后对比
| 项目 | 修改前 | 修改后 |
|---|---|---|
| 已有联系人版本字段 | 请求只识别 `contacts[].expectedUpdateTime`;详情对象原样回传的 `updateTime` 未被识别 | 同时识别规范字段 `expectedUpdateTime` 和详情字段 `updateTime` |
| 条目级乐观并发 | 已有联系人必须携带有效版本 | 保持不变 |
| 姓名、电话重复 | 无重复值限制 | 保持不变;重复值不会被拒绝 |
| 响应字段 | 详情返回 `contacts[].updateTime` | 保持不变 |
| 联系人版本字段 | 仅识别 `expectedUpdateTime` | 同时识别 `expectedUpdateTime`、`updateTime` |
| 姓名、电话重复 | 允许 | 继续允许 |
## 六.7、影响评估
- **是否破坏向后兼容**:否;继续发送 `contacts[].expectedUpdateTime` 的调用方不受影响。
- **前端是否必须同步上线**:否;当前管理端已回传详情联系人 `updateTime`,后端兼容后可直接工作。
- **前端 workaround 清理点**:无;本次不要求新增、删除或调整任何前端逻辑。
- **响应与错误码影响**:响应结构和错误码不变,仅扩展请求字段兼容名。
- **是否破坏向后兼容**:否。
- **前端是否必须同步上线**:否,当前前端已回传 `updateTime`。
- **前端 workaround 清理点**:无。
- **响应与错误码影响**:无。
## 七、不影响范围
- 不修改供应商创建、提交审批、合同、账户、状态机或资源关系接口。
- 不修改 Gateway 路由、认证策略、角色、权限点、幂等、聚合锁或事务边界。
- 不修改数据库结构、历史数据、配置、Redis 或 MQ 契约。
- 本工单仅交付后端,不修改任何前端源码或资源;本记录只保留已发布历史并标记无需前端处理。
- 不修改其他供应商接口、权限或状态机。
- 不修改数据库结构、配置、Redis 或 MQ。
- 不修改任何前端代码。
## 八、测试环境已验证
- 合并提交 `7f3f944bf361b7ae41424c43b29262fb634fe791` 已精确部署到 TEST。
- 通过真实 TEST Gateway 将详情返回的已有联系人 `updateTime` 原样放入编辑快照,并在同一请求新增两名姓名、联系电话均与已有联系人相同的联系人;返回 `code=200`,详情回读为 3 名联系人。
- 使用过期联系人 `updateTime` 再次提交返回 `395014`;随后回读主体版本及 3 名联系人均未变化。
- 未认证详情请求返回业务码 `401`;验收草稿已通过正式删除接口清理,删除后详情返回 `395001`。
- 详情 `updateTime` 原样回传后,可保留已有联系人并新增多个联系人。
- 多个联系人姓名、电话重复时保存成功。
- 过期版本返回 `395014` 且零写入;验收草稿已清理。
## 十、相关文档
- Issue [#6710](https://git.1814.love:8443/wx/HL/issues/6710)
- PR [#6712](https://git.1814.love:8443/wx/HL/pulls/6712)
- 合并提交 [7f3f944bf361b7ae41424c43b29262fb634fe791](https://git.1814.love:8443/wx/HL/commit/7f3f944bf361b7ae41424c43b29262fb634fe791)
- [Issue #6710](https://git.1814.love:8443/wx/HL/issues/6710)
- [PR #6712](https://git.1814.love:8443/wx/HL/pulls/6712)
## 关联 / 联系人