fix(changelog): 按 TEST 代码修正行政区划契约 (#6438)
changelog-filename-gate / validate (pull_request) Successful in 2s
changelog-filename-gate / validate (pull_request) Successful in 2s
这个提交包含在:
@@ -12,7 +12,7 @@ frontend_owner: "mmg"
|
|||||||
frontend_ref: "7acd1cb0"
|
frontend_ref: "7acd1cb0"
|
||||||
target_release: "v2.1"
|
target_release: "v2.1"
|
||||||
verified_at: "2026-08-26"
|
verified_at: "2026-08-26"
|
||||||
status_note: "主工单 #6350 及补充工单 #6384、#6389、#6395、#6399、#6409 的六个 PR 均已合并 dev-v3。精确提交 b62054035a139e3c689179ef75e2d052d08dde52 已部署 TEST;真实管理员经 Gateway 完成未认证、读取、失败零写入、创建、CAS 更新、数据库和 Redis 一致性验收。#6422 已按 CHANGELOG_TEMPLATE.md 补齐四个接口的前端联调契约。"
|
status_note: "主工单 #6350 及补充工单 #6384、#6389、#6395、#6399、#6409 的六个 PR 均已合并 dev-v3。精确提交 b62054035a139e3c689179ef75e2d052d08dde52 已部署 TEST;真实管理员经 Gateway 完成未认证、读取、失败零写入、创建、CAS 更新、数据库和 Redis 一致性验收。#6422 已按 CHANGELOG_TEMPLATE.md 补齐四个接口的前端联调契约,三级联动由 mmg 以 ref 7acd1cb0 完成验证;#6438 再按 TEST 代码修正种子父链、聚合节点、可扩展编码命名空间、异步缓存刷新和 extension 更新限制。"
|
||||||
updated_at: "2026-08-26"
|
updated_at: "2026-08-26"
|
||||||
base: "dev-v3"
|
base: "dev-v3"
|
||||||
---
|
---
|
||||||
@@ -23,7 +23,7 @@ base: "dev-v3"
|
|||||||
>
|
>
|
||||||
> **PR**: #6359、#6387、#6393、#6398、#6402、#6412
|
> **PR**: #6359、#6387、#6393、#6398、#6402、#6412
|
||||||
>
|
>
|
||||||
> **Issue**: #6350、#6384、#6389、#6395、#6399、#6409
|
> **Issue**: #6350、#6384、#6389、#6395、#6399、#6409、#6422、#6438
|
||||||
>
|
>
|
||||||
> **日期**: 2026-08-26
|
> **日期**: 2026-08-26
|
||||||
>
|
>
|
||||||
@@ -36,6 +36,8 @@ base: "dev-v3"
|
|||||||
- 本次补文档不改变 TEST 上已经部署的接口行为;它把原 Changelog 中分散的说明整理为可直接联调的完整契约。
|
- 本次补文档不改变 TEST 上已经部署的接口行为;它把原 Changelog 中分散的说明整理为可直接联调的完整契约。
|
||||||
- 前端不得再把行政区划 ID 当 JavaScript number:响应中的所有行政区划 ID 均为 JSON string,缺失层级保持真正的 `null`。
|
- 前端不得再把行政区划 ID 当 JavaScript number:响应中的所有行政区划 ID 均为 JSON string,缺失层级保持真正的 `null`。
|
||||||
- 三级联动不允许通过行政区编码截位推断父子关系;必须逐级调用 `children`,编辑回显先调用 `path`。
|
- 三级联动不允许通过行政区编码截位推断父子关系;必须逐级调用 `children`,编辑回显先调用 `path`。
|
||||||
|
- `PREFECTURE` 是第二层导航层,不保证一定是可选择的法定地级行政区;直辖市等链路会返回 `AGGREGATION` 聚合节点,必须继续下钻且不得作为最终业务值。
|
||||||
|
- 当前没有单节点详情接口,读响应也不返回 `extension`;更新接口省略或传 `null` 都会清空该字段,前端不能把它理解成“保持原值”。
|
||||||
- 业务失败可能仍使用 HTTP 200,调用方必须同时判断响应体 `code`、`success`、`message` 和 `data`。
|
- 业务失败可能仍使用 HTTP 200,调用方必须同时判断响应体 `code`、`success`、`message` 和 `data`。
|
||||||
|
|
||||||
---
|
---
|
||||||
@@ -46,10 +48,10 @@ base: "dev-v3"
|
|||||||
|
|
||||||
- 省、市、县三级选择器逐级加载;
|
- 省、市、县三级选择器逐级加载;
|
||||||
- 编辑历史业务数据时,从任意节点恢复完整父链;
|
- 编辑历史业务数据时,从任意节点恢复完整父链;
|
||||||
- 具有专用权限的管理员创建自定义行政区或导航聚合节点;
|
- 具有专用权限的管理员创建自定义行政区、带来源证据的新法定版本或导航聚合节点;
|
||||||
- 使用 `rowVersion` 防止两位管理员并发更新时互相覆盖。
|
- 使用 `rowVersion` 防止两位管理员并发更新时互相覆盖。
|
||||||
|
|
||||||
接口当前只开放省、市、县三级写入,层级代码依次为 `PROVINCE`、`PREFECTURE`、`COUNTY`。接口返回的示例 ID 仅用于展示字符串类型,前端不得硬编码。
|
接口当前只开放省、市、县三级写入,层级代码依次为 `PROVINCE`、`PREFECTURE`、`COUNTY`。第二层可能是 `AGGREGATION` 导航分组,不等同于可提交的法定地级行政区。下文读取示例使用 TEST migration 中的北京链路 `1 → 35 → 376`,仅用于说明响应结构,业务代码仍不得硬编码。
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -59,7 +61,7 @@ base: "dev-v3"
|
|||||||
|---|---|---|---|---|---|
|
|---|---|---|---|---|---|
|
||||||
| 1 | 单级联动列表 | GET | `/admin/region/children` | 新增接口 | 加载根层省级或指定父节点的当前有效直接子节点 |
|
| 1 | 单级联动列表 | GET | `/admin/region/children` | 新增接口 | 加载根层省级或指定父节点的当前有效直接子节点 |
|
||||||
| 2 | 父链回显 | GET | `/admin/region/{id}/path` | 新增接口 | 从任意省/市/县节点恢复省级根到目标节点的完整路径 |
|
| 2 | 父链回显 | GET | `/admin/region/{id}/path` | 新增接口 | 从任意省/市/县节点恢复省级根到目标节点的完整路径 |
|
||||||
| 3 | 创建行政区划节点 | POST | `/admin/region` | 新增接口 | 创建自定义行政区或不可选择的导航聚合节点 |
|
| 3 | 创建行政区划节点 | POST | `/admin/region` | 新增接口 | 创建自定义行政区、新法定版本或不可选择的导航聚合节点 |
|
||||||
| 4 | 更新行政区划节点 | PUT | `/admin/region/{id}` | 新增接口 | 使用完整可变字段和 `rowVersion` 执行 CAS 更新 |
|
| 4 | 更新行政区划节点 | PUT | `/admin/region/{id}` | 新增接口 | 使用完整可变字段和 `rowVersion` 执行 CAS 更新 |
|
||||||
|
|
||||||
---
|
---
|
||||||
@@ -119,7 +121,7 @@ base: "dev-v3"
|
|||||||
#### 请求示例
|
#### 请求示例
|
||||||
|
|
||||||
```http
|
```http
|
||||||
GET /admin/region/children?parentId=2090000000000000001&selectedId=2090000000000000035 HTTP/1.1
|
GET /admin/region/children?parentId=1&selectedId=35 HTTP/1.1
|
||||||
Host: api.test.1814.love:9443
|
Host: api.test.1814.love:9443
|
||||||
Authorization: Bearer <管理员令牌>
|
Authorization: Bearer <管理员令牌>
|
||||||
Accept: application/json
|
Accept: application/json
|
||||||
@@ -141,30 +143,30 @@ Accept: application/json
|
|||||||
"code": 200,
|
"code": 200,
|
||||||
"message": "成功",
|
"message": "成功",
|
||||||
"data": {
|
"data": {
|
||||||
"parentId": "2090000000000000001",
|
"parentId": "1",
|
||||||
"items": [
|
"items": [
|
||||||
{
|
{
|
||||||
"id": "2090000000000000035",
|
"id": "35",
|
||||||
"parentId": "2090000000000000001",
|
"parentId": "1",
|
||||||
"codeStandard": "GB/T 2260",
|
"codeStandard": "HL_GROUP",
|
||||||
"regionCode": "110100",
|
"regionCode": "HL-GROUP-110000",
|
||||||
"levelCode": "PREFECTURE",
|
"levelCode": "PREFECTURE",
|
||||||
"depth": 2,
|
"depth": 2,
|
||||||
"name": "北京市",
|
"name": "北京市辖区",
|
||||||
"shortName": null,
|
"shortName": null,
|
||||||
"nodeKind": "ADMINISTRATIVE",
|
"nodeKind": "AGGREGATION",
|
||||||
"navigable": true,
|
"navigable": true,
|
||||||
"selectable": true,
|
"selectable": false,
|
||||||
"hasChildren": true,
|
"hasChildren": true,
|
||||||
"currentlyEffective": true,
|
"currentlyEffective": true,
|
||||||
"status": "ACTIVE",
|
"status": "ACTIVE",
|
||||||
"validFrom": "2025-12-31",
|
"validFrom": "2025-12-31",
|
||||||
"validTo": null,
|
"validTo": null,
|
||||||
"sortOrder": 100,
|
"sortOrder": 2000000001,
|
||||||
"rowVersion": 0
|
"rowVersion": 0
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"defaultId": "2090000000000000035"
|
"defaultId": "35"
|
||||||
},
|
},
|
||||||
"traceId": "a1b2c3d4-e5f6-7890",
|
"traceId": "a1b2c3d4-e5f6-7890",
|
||||||
"success": true
|
"success": true
|
||||||
@@ -173,14 +175,14 @@ Accept: application/json
|
|||||||
|
|
||||||
#### 空数据 / 降级响应
|
#### 空数据 / 降级响应
|
||||||
|
|
||||||
父节点存在但没有当前有效直接子节点时,返回成功空数组:
|
父节点存在但没有当前有效直接子节点时,返回成功空数组。Redis 读取失败时服务会降级查数据库,成功结构不变:
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"code": 200,
|
"code": 200,
|
||||||
"message": "成功",
|
"message": "成功",
|
||||||
"data": {
|
"data": {
|
||||||
"parentId": "2090000000000000035",
|
"parentId": "376",
|
||||||
"items": [],
|
"items": [],
|
||||||
"defaultId": null
|
"defaultId": null
|
||||||
},
|
},
|
||||||
@@ -207,6 +209,7 @@ Accept: application/json
|
|||||||
- `selectedId` 不在本次 `items` 中时不会报错,而是稳定回退到排序后的第一项;空列表回退为 `null`。
|
- `selectedId` 不在本次 `items` 中时不会报错,而是稳定回退到排序后的第一项;空列表回退为 `null`。
|
||||||
- 排序固定为 `sortOrder`、`regionCode`、`id`,前端不得另用行政区编码推断顺序或父子关系。
|
- 排序固定为 `sortOrder`、`regionCode`、`id`,前端不得另用行政区编码推断顺序或父子关系。
|
||||||
- `navigable` 控制能否继续向下加载,`selectable` 控制能否作为最终值;两者不能相互替代。
|
- `navigable` 控制能否继续向下加载,`selectable` 控制能否作为最终值;两者不能相互替代。
|
||||||
|
- `defaultId` 只表示本级默认导航项,不保证 `selectable=true`;例如北京第二层默认项 `"35"` 是不可提交的聚合节点。
|
||||||
- 未登录返回业务码 `401`;`parentId=0` 等非正整数参数返回业务码 `400`。
|
- 未登录返回业务码 `401`;`parentId=0` 等非正整数参数返回业务码 `400`。
|
||||||
|
|
||||||
---
|
---
|
||||||
@@ -217,7 +220,7 @@ Accept: application/json
|
|||||||
|
|
||||||
#### 使用场景
|
#### 使用场景
|
||||||
|
|
||||||
编辑已有业务数据时,后端只保存了一个最终行政区 ID。前端先调用本接口得到完整省/市/县父链,再按父链逐层调用 `children` 加载每一级可选项。
|
编辑已有业务数据时,后端只保存了一个最终行政区 ID。前端先调用本接口得到完整三级父链,再按父链逐层调用 `children` 加载每一级导航项。父链的第二层可能是不可选择的 `AGGREGATION`,不能仅凭 `prefectureId` 字段名判断它一定是法定地级行政区。
|
||||||
|
|
||||||
#### 入参
|
#### 入参
|
||||||
|
|
||||||
@@ -235,9 +238,10 @@ Accept: application/json
|
|||||||
| `code` | Integer | `200` 表示成功;业务失败读取具体业务码 |
|
| `code` | Integer | `200` 表示成功;业务失败读取具体业务码 |
|
||||||
| `message` | String | 响应说明 |
|
| `message` | String | 响应说明 |
|
||||||
| `success` | Boolean | 仅当 `code=200` 时为 `true` |
|
| `success` | Boolean | 仅当 `code=200` 时为 `true` |
|
||||||
|
| `traceId` | String / null | 链路追踪 ID;报错排查时提供给后端 |
|
||||||
| `data.selectedId` | String | 调用方传入并成功解析的目标节点 ID |
|
| `data.selectedId` | String | 调用方传入并成功解析的目标节点 ID |
|
||||||
| `data.provinceId` | String | 父链中的省级 ID |
|
| `data.provinceId` | String | 父链中的省级 ID |
|
||||||
| `data.prefectureId` | String / null | 父链中的地级 ID;目标为省级时为 `null` |
|
| `data.prefectureId` | String / null | 父链第二层 ID,可能是地级行政区或聚合导航节点;目标为省级时为 `null` |
|
||||||
| `data.countyId` | String / null | 父链中的县级 ID;目标高于县级时为 `null` |
|
| `data.countyId` | String / null | 父链中的县级 ID;目标高于县级时为 `null` |
|
||||||
| `data.path` | Array | 从省级根到目标节点的完整有序父链 |
|
| `data.path` | Array | 从省级根到目标节点的完整有序父链 |
|
||||||
| `data.path[].id` | String | 节点 ID,始终为字符串 |
|
| `data.path[].id` | String | 节点 ID,始终为字符串 |
|
||||||
@@ -262,7 +266,7 @@ Accept: application/json
|
|||||||
#### 请求示例
|
#### 请求示例
|
||||||
|
|
||||||
```http
|
```http
|
||||||
GET /admin/region/2090000000000000376/path HTTP/1.1
|
GET /admin/region/376/path HTTP/1.1
|
||||||
Host: api.test.1814.love:9443
|
Host: api.test.1814.love:9443
|
||||||
Authorization: Bearer <管理员令牌>
|
Authorization: Bearer <管理员令牌>
|
||||||
Accept: application/json
|
Accept: application/json
|
||||||
@@ -275,13 +279,13 @@ Accept: application/json
|
|||||||
"code": 200,
|
"code": 200,
|
||||||
"message": "成功",
|
"message": "成功",
|
||||||
"data": {
|
"data": {
|
||||||
"selectedId": "2090000000000000376",
|
"selectedId": "376",
|
||||||
"provinceId": "2090000000000000001",
|
"provinceId": "1",
|
||||||
"prefectureId": "2090000000000000035",
|
"prefectureId": "35",
|
||||||
"countyId": "2090000000000000376",
|
"countyId": "376",
|
||||||
"path": [
|
"path": [
|
||||||
{
|
{
|
||||||
"id": "2090000000000000001",
|
"id": "1",
|
||||||
"parentId": null,
|
"parentId": null,
|
||||||
"codeStandard": "GB/T 2260",
|
"codeStandard": "GB/T 2260",
|
||||||
"regionCode": "110000",
|
"regionCode": "110000",
|
||||||
@@ -297,32 +301,32 @@ Accept: application/json
|
|||||||
"status": "ACTIVE",
|
"status": "ACTIVE",
|
||||||
"validFrom": "2025-12-31",
|
"validFrom": "2025-12-31",
|
||||||
"validTo": null,
|
"validTo": null,
|
||||||
"sortOrder": 100,
|
"sortOrder": 10,
|
||||||
"rowVersion": 0
|
"rowVersion": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "2090000000000000035",
|
"id": "35",
|
||||||
"parentId": "2090000000000000001",
|
"parentId": "1",
|
||||||
"codeStandard": "GB/T 2260",
|
"codeStandard": "HL_GROUP",
|
||||||
"regionCode": "110100",
|
"regionCode": "HL-GROUP-110000",
|
||||||
"levelCode": "PREFECTURE",
|
"levelCode": "PREFECTURE",
|
||||||
"depth": 2,
|
"depth": 2,
|
||||||
"name": "北京市",
|
"name": "北京市辖区",
|
||||||
"shortName": null,
|
"shortName": null,
|
||||||
"nodeKind": "ADMINISTRATIVE",
|
"nodeKind": "AGGREGATION",
|
||||||
"navigable": true,
|
"navigable": true,
|
||||||
"selectable": true,
|
"selectable": false,
|
||||||
"hasChildren": true,
|
"hasChildren": true,
|
||||||
"currentlyEffective": true,
|
"currentlyEffective": true,
|
||||||
"status": "ACTIVE",
|
"status": "ACTIVE",
|
||||||
"validFrom": "2025-12-31",
|
"validFrom": "2025-12-31",
|
||||||
"validTo": null,
|
"validTo": null,
|
||||||
"sortOrder": 100,
|
"sortOrder": 2000000001,
|
||||||
"rowVersion": 0
|
"rowVersion": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "2090000000000000376",
|
"id": "376",
|
||||||
"parentId": "2090000000000000035",
|
"parentId": "35",
|
||||||
"codeStandard": "GB/T 2260",
|
"codeStandard": "GB/T 2260",
|
||||||
"regionCode": "110101",
|
"regionCode": "110101",
|
||||||
"levelCode": "COUNTY",
|
"levelCode": "COUNTY",
|
||||||
@@ -337,18 +341,19 @@ Accept: application/json
|
|||||||
"status": "ACTIVE",
|
"status": "ACTIVE",
|
||||||
"validFrom": "2025-12-31",
|
"validFrom": "2025-12-31",
|
||||||
"validTo": null,
|
"validTo": null,
|
||||||
"sortOrder": 100,
|
"sortOrder": 20,
|
||||||
"rowVersion": 0
|
"rowVersion": 0
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"traceId": "a1b2c3d4-e5f6-7890",
|
||||||
"success": true
|
"success": true
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
#### 空数据 / 降级响应
|
#### 空数据 / 降级响应
|
||||||
|
|
||||||
本接口不返回“成功但空父链”。目标不存在、父链不完整或超过安全深度时使用错误响应,不返回部分路径。
|
本接口不返回“成功但空父链”。目标不存在、父链不完整或超过当前三级安全边界时使用错误响应,不返回部分路径。Redis 不可用时整条父链降级为同一数据库事务快照读取,不拼接缓存与数据库的半条路径。
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
@@ -376,7 +381,8 @@ Accept: application/json
|
|||||||
|
|
||||||
- `path` 必须从省级根开始,`parentId`、`depth` 和 `levelCode` 逐级连续,最后一个节点必须等于 `selectedId`。
|
- `path` 必须从省级根开始,`parentId`、`depth` 和 `levelCode` 逐级连续,最后一个节点必须等于 `selectedId`。
|
||||||
- 目标为省级时 `prefectureId`、`countyId` 均为 `null`;目标为地级时只有 `countyId=null`,绝不会返回字符串 `"null"`。
|
- 目标为省级时 `prefectureId`、`countyId` 均为 `null`;目标为地级时只有 `countyId=null`,绝不会返回字符串 `"null"`。
|
||||||
- 历史停用节点允许回显,节点自身 `currentlyEffective=false`;前端只能展示历史值,不能把它重新加入当前可选列表。
|
- `prefectureId` 只是路径第二层快捷 ID;直辖市等链路可指向 `nodeKind=AGGREGATION && selectable=false` 的聚合节点。
|
||||||
|
- 历史停用或过期节点允许回显,节点自身 `currentlyEffective=false`,且后端会把该节点的 `navigable`、`selectable` 强制返回 `false`;前端只能展示历史值,不能把它重新加入当前可选列表。
|
||||||
- 父链异常时整体失败,不返回可被误用的部分路径。
|
- 父链异常时整体失败,不返回可被误用的部分路径。
|
||||||
- 未登录返回业务码 `401`;不存在节点返回 `210801`。
|
- 未登录返回业务码 `401`;不存在节点返回 `210801`。
|
||||||
|
|
||||||
@@ -388,14 +394,14 @@ Accept: application/json
|
|||||||
|
|
||||||
#### 使用场景
|
#### 使用场景
|
||||||
|
|
||||||
具有 `system:region:create` 权限的管理员创建自定义业务行政区,或创建只用于层级导航、不可作为最终业务值的聚合节点。
|
具有 `system:region:create` 权限的管理员可以创建自定义业务行政区、带完整来源证据且不与旧版本重叠的 `GB/T 2260` 新版本,或只用于层级导航、不可作为最终业务值的聚合节点。
|
||||||
|
|
||||||
#### 入参
|
#### 入参
|
||||||
|
|
||||||
| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 |
|
| 字段 | 位置 | 类型 | 必填 | 约束 | 说明 |
|
||||||
|---|---|---|---|---|---|
|
|---|---|---|---|---|---|
|
||||||
| `Authorization` | Header | String | ✅ | `Bearer <token>` 且具有 `system:region:create` | 管理端登录令牌 |
|
| `Authorization` | Header | String | ✅ | `Bearer <token>` 且具有 `system:region:create` | 管理端登录令牌 |
|
||||||
| `codeStandard` | Body | String | ✅ | 1~32 字符;聚合节点必须为 `HL_GROUP` | 编码命名空间,自定义行政区推荐 `HL_CUSTOM` |
|
| `codeStandard` | Body | String | ✅ | 1~32 字符;服务端去空白并转大写;聚合节点必须为 `HL_GROUP` | 可扩展编码命名空间,自定义行政区推荐 `HL_CUSTOM` |
|
||||||
| `regionCode` | Body | String | ✅ | 1~64 字符;首字符为字母或数字;仅含字母、数字、`.`、`_`、`:`、`-` | 编码标准内的唯一地区代码;服务端转大写 |
|
| `regionCode` | Body | String | ✅ | 1~64 字符;首字符为字母或数字;仅含字母、数字、`.`、`_`、`:`、`-` | 编码标准内的唯一地区代码;服务端转大写 |
|
||||||
| `parentId` | Body | String / null | ❌ | 十进制正整数;创建省级根节点时为 `null` | 父节点 ID |
|
| `parentId` | Body | String / null | ❌ | 十进制正整数;创建省级根节点时为 `null` | 父节点 ID |
|
||||||
| `levelCode` | Body | String | ✅ | 1~32 字符;省/市/县必须匹配派生深度 | `PROVINCE`、`PREFECTURE`、`COUNTY` |
|
| `levelCode` | Body | String | ✅ | 1~32 字符;省/市/县必须匹配派生深度 | `PROVINCE`、`PREFECTURE`、`COUNTY` |
|
||||||
@@ -421,6 +427,7 @@ Accept: application/json
|
|||||||
| `code` | Integer | `200` 表示创建成功 |
|
| `code` | Integer | `200` 表示创建成功 |
|
||||||
| `message` | String | 响应说明 |
|
| `message` | String | 响应说明 |
|
||||||
| `success` | Boolean | 创建成功为 `true` |
|
| `success` | Boolean | 创建成功为 `true` |
|
||||||
|
| `traceId` | String / null | 链路追踪 ID;报错排查时提供给后端 |
|
||||||
| `data` | String | 新节点 ID,始终为 JSON string |
|
| `data` | String | 新节点 ID,始终为 JSON string |
|
||||||
|
|
||||||
#### 请求示例
|
#### 请求示例
|
||||||
@@ -434,7 +441,7 @@ Content-Type: application/json
|
|||||||
{
|
{
|
||||||
"codeStandard": "HL_CUSTOM",
|
"codeStandard": "HL_CUSTOM",
|
||||||
"regionCode": "DEMO-COUNTY-001",
|
"regionCode": "DEMO-COUNTY-001",
|
||||||
"parentId": "2090000000000000035",
|
"parentId": "35",
|
||||||
"levelCode": "COUNTY",
|
"levelCode": "COUNTY",
|
||||||
"nodeKind": "ADMINISTRATIVE",
|
"nodeKind": "ADMINISTRATIVE",
|
||||||
"name": "示例业务区",
|
"name": "示例业务区",
|
||||||
@@ -460,13 +467,14 @@ Content-Type: application/json
|
|||||||
"code": 200,
|
"code": 200,
|
||||||
"message": "成功",
|
"message": "成功",
|
||||||
"data": "2090000000000001001",
|
"data": "2090000000000001001",
|
||||||
|
"traceId": "a1b2c3d4-e5f6-7890",
|
||||||
"success": true
|
"success": true
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
#### 空数据 / 降级响应
|
#### 空数据 / 降级响应
|
||||||
|
|
||||||
本接口成功时一定返回字符串 ID,不存在 `data=null` 的成功语义。失败时不创建节点。
|
本接口成功时一定返回字符串 ID,不存在 `data=null` 的成功语义。失败时事务回滚且不创建节点;本接口没有“Redis 不可用仍受理写入”的公开降级承诺。
|
||||||
|
|
||||||
#### 错误响应
|
#### 错误响应
|
||||||
|
|
||||||
@@ -486,7 +494,8 @@ Content-Type: application/json
|
|||||||
- 当前最大写入深度为 3;省、市、县层级必须分别使用 `PROVINCE`、`PREFECTURE`、`COUNTY`。
|
- 当前最大写入深度为 3;省、市、县层级必须分别使用 `PROVINCE`、`PREFECTURE`、`COUNTY`。
|
||||||
- 父节点必须存在、可导航、有效期完整覆盖子节点,并且不会让写入深度超过三级。
|
- 父节点必须存在、可导航、有效期完整覆盖子节点,并且不会让写入深度超过三级。
|
||||||
- `AGGREGATION` 必须同时满足 `codeStandard=HL_GROUP`、`navigable=true`、`selectable=false`;它只能导航,不能作为最终业务值。
|
- `AGGREGATION` 必须同时满足 `codeStandard=HL_GROUP`、`navigable=true`、`selectable=false`;它只能导航,不能作为最终业务值。
|
||||||
- `ADMINISTRATIVE` 不得占用 `HL_GROUP`;旧命名空间 `HL_INTERNAL` 不允许产生新写入。
|
- `ADMINISTRATIVE` 不得占用 `HL_GROUP`;除 `HL_GROUP`、`HL_INTERNAL` 的限制外,`codeStandard` 不是封闭枚举,自定义命名空间可扩展,推荐使用 `HL_CUSTOM`。
|
||||||
|
- 旧命名空间 `HL_INTERNAL` 不允许产生新写入;`GB/T 2260` 只允许六位数字 `regionCode`,并要求完整的 `sourceVersion`、`sourceRef`。
|
||||||
- 同一 `codeStandard + regionCode` 的版本有效期不得重叠;有效期采用左闭右开 `[validFrom, validTo)`。
|
- 同一 `codeStandard + regionCode` 的版本有效期不得重叠;有效期采用左闭右开 `[validFrom, validTo)`。
|
||||||
- 缺少权限返回 `210802`;空请求或格式错误返回 `400`;全部失败路径零业务写入。
|
- 缺少权限返回 `210802`;空请求或格式错误返回 `400`;全部失败路径零业务写入。
|
||||||
|
|
||||||
@@ -498,7 +507,7 @@ Content-Type: application/json
|
|||||||
|
|
||||||
#### 使用场景
|
#### 使用场景
|
||||||
|
|
||||||
具有 `system:region:update` 权限的管理员更新节点名称、父级、层级、可导航/可选状态、有效期、排序和扩展信息。请求必须携带最近读取到的完整可变字段和 `rowVersion`。
|
具有 `system:region:update` 权限的管理员更新节点名称、父级、层级、可导航/可选状态、有效期、排序和扩展信息。请求必须携带完整可变字段快照和最近读取到的 `rowVersion`;这不是局部 PATCH。
|
||||||
|
|
||||||
#### 入参
|
#### 入参
|
||||||
|
|
||||||
@@ -515,8 +524,8 @@ Content-Type: application/json
|
|||||||
| `validFrom` | Body | String | ✅ | `yyyy-MM-dd` | 生效日期 |
|
| `validFrom` | Body | String | ✅ | `yyyy-MM-dd` | 生效日期 |
|
||||||
| `validTo` | Body | String / null | ❌ | 必须严格晚于 `validFrom` | 失效日期 |
|
| `validTo` | Body | String / null | ❌ | 必须严格晚于 `validFrom` | 失效日期 |
|
||||||
| `status` | Body | String | ✅ | `ACTIVE` 或 `INACTIVE` | 节点状态 |
|
| `status` | Body | String | ✅ | `ACTIVE` 或 `INACTIVE` | 节点状态 |
|
||||||
| `sortOrder` | Body | Integer | ✅ | 0~2,000,000,000 | 同级排序号 |
|
| `sortOrder` | Body | Integer | ✅ | 0~2,000,000,000;部分初始化聚合节点的只读返回值大于此上限 | 同级排序号;不能无脑回填超限旧值 |
|
||||||
| `extension` | Body | Object / null | ❌ | 必须是 JSON object,最多 4000 字符 | 结构化扩展;旧别名 `extJson` 仍兼容 |
|
| `extension` | Body | Object / null | ❌ | 必须是 JSON object,最多 4000 字符;省略与显式 `null` 都会清空 | 结构化扩展;旧别名 `extJson` 仍兼容 |
|
||||||
| `rowVersion` | Body | Integer | ✅ | 大于等于 0,必须等于当前版本 | CAS 并发版本,成功后自动加 1 |
|
| `rowVersion` | Body | Integer | ✅ | 大于等于 0,必须等于当前版本 | CAS 并发版本,成功后自动加 1 |
|
||||||
|
|
||||||
`codeStandard`、`regionCode`、`nodeKind`、`sourceVersion` 和 `sourceRef` 不属于更新接口,不能通过请求改写。
|
`codeStandard`、`regionCode`、`nodeKind`、`sourceVersion` 和 `sourceRef` 不属于更新接口,不能通过请求改写。
|
||||||
@@ -528,6 +537,7 @@ Content-Type: application/json
|
|||||||
| `code` | Integer | `200` 表示更新成功 |
|
| `code` | Integer | `200` 表示更新成功 |
|
||||||
| `message` | String | 成功时为“行政区划更新成功” |
|
| `message` | String | 成功时为“行政区划更新成功” |
|
||||||
| `success` | Boolean | 更新成功为 `true` |
|
| `success` | Boolean | 更新成功为 `true` |
|
||||||
|
| `traceId` | String / null | 链路追踪 ID;报错排查时提供给后端 |
|
||||||
| `data` | null | 更新接口不返回业务数据 |
|
| `data` | null | 更新接口不返回业务数据 |
|
||||||
|
|
||||||
#### 请求示例
|
#### 请求示例
|
||||||
@@ -539,7 +549,7 @@ Authorization: Bearer <具有 system:region:update 的管理员令牌>
|
|||||||
Content-Type: application/json
|
Content-Type: application/json
|
||||||
|
|
||||||
{
|
{
|
||||||
"parentId": "2090000000000000035",
|
"parentId": "35",
|
||||||
"levelCode": "COUNTY",
|
"levelCode": "COUNTY",
|
||||||
"name": "示例业务区(更新)",
|
"name": "示例业务区(更新)",
|
||||||
"shortName": "示例区",
|
"shortName": "示例区",
|
||||||
@@ -563,13 +573,14 @@ Content-Type: application/json
|
|||||||
"code": 200,
|
"code": 200,
|
||||||
"message": "行政区划更新成功",
|
"message": "行政区划更新成功",
|
||||||
"data": null,
|
"data": null,
|
||||||
|
"traceId": "a1b2c3d4-e5f6-7890",
|
||||||
"success": true
|
"success": true
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
#### 空数据 / 降级响应
|
#### 空数据 / 降级响应
|
||||||
|
|
||||||
本接口成功时 `data=null` 是固定契约,调用方以 `code=200 && success=true` 判断成功。
|
本接口成功时 `data=null` 是固定契约,调用方以 `code=200 && success=true` 判断成功。本接口没有“Redis 不可用仍受理写入”的公开降级承诺,也不会返回更新后的节点快照。
|
||||||
|
|
||||||
#### 错误响应
|
#### 错误响应
|
||||||
|
|
||||||
@@ -586,12 +597,14 @@ Content-Type: application/json
|
|||||||
|
|
||||||
#### 业务边界
|
#### 业务边界
|
||||||
|
|
||||||
- 更新采用完整可变字段快照,不是局部 PATCH;前端必须先读取最新节点信息再提交。
|
- 更新采用完整可变字段快照,不是局部 PATCH;省略 `extension` 不表示保持原值,而是写成 `null`。
|
||||||
|
- 当前 `children` / `path` 响应不包含 `extension`,也没有单节点详情接口。前端无法仅靠这四个公开接口保留未知的非空扩展值;在补充详情契约前,不应开放此类节点的通用编辑入口。
|
||||||
|
- TEST 初始化聚合节点可返回大于 `2,000,000,000` 的 `sortOrder`(例如北京第二层为 `2,000,000,001`),而更新请求上限是 `2,000,000,000`;直接回填会返回 `400`,这类节点也不能按无损通用编辑处理。
|
||||||
- `rowVersion` 冲突返回 `210807` 且零写入;前端应重新加载,而不是自动覆盖重试。
|
- `rowVersion` 冲突返回 `210807` 且零写入;前端应重新加载,而不是自动覆盖重试。
|
||||||
- 有子节点的分支禁止移动父级或改变层级,返回 `210810`。
|
- 有子节点的分支禁止移动父级或改变层级,返回 `210810`。
|
||||||
- 父节点提前停用、取消导航或缩短有效期,导致现有子节点失去合法父级时返回 `210814`。
|
- 父节点提前停用、取消导航或缩短有效期,导致现有子节点失去合法父级时返回 `210814`。
|
||||||
- 已到生效日的 `GB/T 2260` 法定节点不能原位改写历史属性;应先关闭旧版本,再创建有效期不重叠的新版本。
|
- 已到生效日的 `GB/T 2260` 法定节点不能原位改写历史属性;代码只允许在其他历史字段(包含 `extension`)完全不变时关闭状态/结束时间。由于当前读接口不返回 `extension`,前端不能把“关闭已有法定版本”当成已具备的安全通用操作。
|
||||||
- 成功后 `rowVersion` 增加 1;再次编辑必须使用新版本号。
|
- 成功后数据库中的 `rowVersion` 增加 1,但响应不返回新版本;再次编辑前需重新读取可见节点,且要考虑提交后缓存异步刷新的短暂窗口。
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -603,7 +616,7 @@ Content-Type: application/json
|
|||||||
GET /admin/region/children
|
GET /admin/region/children
|
||||||
→ 用户选择 provinceId
|
→ 用户选择 provinceId
|
||||||
GET /admin/region/children?parentId={provinceId}
|
GET /admin/region/children?parentId={provinceId}
|
||||||
→ 用户选择 prefectureId
|
→ 用户选择第二层导航项 prefectureId(可能是不可提交的 AGGREGATION)
|
||||||
GET /admin/region/children?parentId={prefectureId}
|
GET /admin/region/children?parentId={prefectureId}
|
||||||
→ 用户选择 countyId
|
→ 用户选择 countyId
|
||||||
→ 业务表单最终保存 countyId(或业务允许的上级 selectable 节点)
|
→ 业务表单最终保存 countyId(或业务允许的上级 selectable 节点)
|
||||||
@@ -627,6 +640,7 @@ GET /admin/region/{savedRegionId}/path
|
|||||||
| ✅ 加载市级 | `GET /admin/region/children?parentId={provinceId}` |
|
| ✅ 加载市级 | `GET /admin/region/children?parentId={provinceId}` |
|
||||||
| ✅ 编辑回显 | 先 `GET /admin/region/{savedId}/path`,再逐层加载 `children` |
|
| ✅ 编辑回显 | 先 `GET /admin/region/{savedId}/path`,再逐层加载 `children` |
|
||||||
| ✅ 比较 ID | 全程以 string 比较,例如 `item.id === selectedId` |
|
| ✅ 比较 ID | 全程以 string 比较,例如 `item.id === selectedId` |
|
||||||
|
| ✅ 判断最终值 | 只提交 `selectable=true` 的节点;`defaultId`、`prefectureId` 本身不等于可提交 |
|
||||||
| ❌ 根层传 0 | `GET /admin/region/children?parentId=0` → 400 |
|
| ❌ 根层传 0 | `GET /admin/region/children?parentId=0` → 400 |
|
||||||
| ❌ 截行政区编码推父级 | 根据 `110101` 截取 `110100`;父子关系只能以接口返回的 ID 为准 |
|
| ❌ 截行政区编码推父级 | 根据 `110101` 截取 `110100`;父子关系只能以接口返回的 ID 为准 |
|
||||||
| ❌ 把聚合节点当最终值 | `nodeKind=AGGREGATION && selectable=false` 时仍提交为业务行政区 |
|
| ❌ 把聚合节点当最终值 | `nodeKind=AGGREGATION && selectable=false` 时仍提交为业务行政区 |
|
||||||
@@ -650,10 +664,10 @@ if (response.code !== 200 || response.success !== true) {
|
|||||||
|---|---|---|
|
|---|---|---|
|
||||||
| 查询 `children` | 只读,不改变节点、版本或审计 | 不写入 |
|
| 查询 `children` | 只读,不改变节点、版本或审计 | 不写入 |
|
||||||
| 查询 `path` | 只读,不改变节点、版本或审计 | 不写入,不返回部分父链 |
|
| 查询 `path` | 只读,不改变节点、版本或审计 | 不写入,不返回部分父链 |
|
||||||
| 创建节点 | 成功新增一个节点,初始 `rowVersion=0`;事务提交后联动和父链读取可见 | 参数、权限、父链、有效期或唯一性失败时不新增节点 |
|
| 创建节点 | 成功新增一个节点,初始 `rowVersion=0`;数据库事务提交后异步刷新节点和父级列表缓存 | 参数、权限、父链、有效期或唯一性失败时不新增节点 |
|
||||||
| 更新节点 | 成功更新一个节点并令 `rowVersion+1`;事务提交后联动和父链返回新值 | 版本冲突或业务 guard 失败时原节点保持不变 |
|
| 更新节点 | 成功更新一个节点并令 `rowVersion+1`;数据库事务提交后异步刷新节点、旧/新父级及上层列表缓存 | 版本冲突或业务 guard 失败时原节点保持不变 |
|
||||||
|
|
||||||
前端无需理解或操作物理表、缓存键和审计表,也不得通过其他接口绕过创建/更新权限和版本检查。
|
写接口成功只证明数据库事务已经提交,不承诺紧随其后的第一个缓存读取已经反映新值。前端不得自行操作缓存;需要立即回显时应短暂重读,并始终以新的 `rowVersion` 为准。读取阶段 Redis 故障会降级数据库;写入口还受公共幂等保护,不能据此推导“Redis 故障时写入一定成功”。
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -672,6 +686,7 @@ if (response.code !== 200 || response.success !== true) {
|
|||||||
- 父链异常:`210811`,不返回部分路径。
|
- 父链异常:`210811`,不返回部分路径。
|
||||||
- `extension` 不是 JSON object 或过长:`210812`。
|
- `extension` 不是 JSON object 或过长:`210812`。
|
||||||
- 层级代码与父链深度不一致:`210813`。
|
- 层级代码与父链深度不一致:`210813`。
|
||||||
|
- 写接口命中五秒参数幂等键:`100502`;这是拒绝重复提交,不会回放第一次成功响应。
|
||||||
- 老数据兼容:停用历史节点可由 `path` 回显;旧缓存中的数字 ID 可由后端读取,但当前 API 响应始终输出 string ID。
|
- 老数据兼容:停用历史节点可由 `path` 回显;旧缓存中的数字 ID 可由后端读取,但当前 API 响应始终输出 string ID。
|
||||||
|
|
||||||
### 业务错误码
|
### 业务错误码
|
||||||
@@ -680,6 +695,7 @@ if (response.code !== 200 || response.success !== true) {
|
|||||||
|---:|---|---|
|
|---:|---|---|
|
||||||
| `400` | 参数校验失败文案 | 任一接口的 ID 非正整数、Body 缺少必填字段或格式不合法 |
|
| `400` | 参数校验失败文案 | 任一接口的 ID 非正整数、Body 缺少必填字段或格式不合法 |
|
||||||
| `401` | 未认证文案 | 任一接口未携带有效管理端身份 |
|
| `401` | 未认证文案 | 任一接口未携带有效管理端身份 |
|
||||||
|
| `100502` | 请勿重复提交 | `create` / `update` 在五秒内命中相同参数幂等键;失败不会返回第一次结果 |
|
||||||
| `210801` | 行政区划节点不存在 | `children` 父节点或 `path`/`update` 目标不存在 |
|
| `210801` | 行政区划节点不存在 | `children` 父节点或 `path`/`update` 目标不存在 |
|
||||||
| `210802` | 无行政区划维护权限 | `create` / `update` 缺少专用写权限 |
|
| `210802` | 无行政区划维护权限 | `create` / `update` 缺少专用写权限 |
|
||||||
| `210803` | 行政区划父节点不合法 | 父级不可导航、已失效或有效期不能覆盖子级 |
|
| `210803` | 行政区划父节点不合法 | 父级不可导航、已失效或有效期不能覆盖子级 |
|
||||||
@@ -732,15 +748,19 @@ if (response.code !== 200 || response.success !== true) {
|
|||||||
| `ACTIVE` | 启用 | 位于有效期时可进入当前联动列表 |
|
| `ACTIVE` | 启用 | 位于有效期时可进入当前联动列表 |
|
||||||
| `INACTIVE` | 停用 | 不进入当前联动列表,但历史父链仍可回显 |
|
| `INACTIVE` | 停用 | 不进入当前联动列表,但历史父链仍可回显 |
|
||||||
|
|
||||||
### `codeStandard`(编码命名空间)
|
### `codeStandard`(可扩展编码命名空间)
|
||||||
|
|
||||||
**所属字段**: `AdministrativeRegionCreateReqVO.codeStandard`、`AdministrativeRegionItemVO.codeStandard` | **类型**: `String`
|
**所属字段**: `AdministrativeRegionCreateReqVO.codeStandard`、`AdministrativeRegionItemVO.codeStandard` | **类型**: `String`
|
||||||
|
|
||||||
| 值 | 中文 | 说明 |
|
`codeStandard` 不是封闭枚举。服务端会去除首尾空白并转成大写;下表仅列出内置/保留语义:
|
||||||
|
|
||||||
|
| 值或类别 | 中文 | 说明 |
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
| `GB/T 2260` | 法定行政区编码 | `regionCode` 必须为六位数字;生效历史受不可变保护 |
|
| `GB/T 2260` | 法定行政区编码 | `regionCode` 必须为六位数字;生效历史受不可变保护 |
|
||||||
| `HL_CUSTOM` | 自定义行政区编码 | 管理端创建普通自定义行政区的推荐命名空间 |
|
| `HL_CUSTOM` | 自定义行政区编码 | 管理端创建普通自定义行政区的推荐命名空间 |
|
||||||
| `HL_GROUP` | 导航聚合编码 | 只能与 `AGGREGATION` 搭配 |
|
| `HL_GROUP` | 导航聚合编码 | 只能与 `AGGREGATION` 搭配 |
|
||||||
|
| `HL_INTERNAL` | 旧内部命名空间 | 仅兼容识别旧缓存,新写入固定拒绝并返回 `210809` |
|
||||||
|
| 其他非空值 | 扩展命名空间 | 最多 32 字符;可供 `ADMINISTRATIVE` 使用,但不得冒充 `HL_GROUP` |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -755,6 +775,7 @@ if (response.code !== 200 || response.success !== true) {
|
|||||||
| 所有行政区划 Long ID | 小数值可能被全局序列化规则输出为 JSON number | 一律输出 JSON string |
|
| 所有行政区划 Long ID | 小数值可能被全局序列化规则输出为 JSON number | 一律输出 JSON string |
|
||||||
| 缺失父级/层级 | 可能被调用方误当字符串处理 | 保持真正的 JSON `null` |
|
| 缺失父级/层级 | 可能被调用方误当字符串处理 | 保持真正的 JSON `null` |
|
||||||
| `extension` 历史入参 | 旧调用方可能使用 `extJson` | 请求继续兼容 `extJson`,当前文档统一使用 `extension` |
|
| `extension` 历史入参 | 旧调用方可能使用 `extJson` | 请求继续兼容 `extJson`,当前文档统一使用 `extension` |
|
||||||
|
| TEST 北京第二层示例 | 曾被文档误写为可选择的 `GB/T 2260` 地级节点 | 实际为 `id="35"`、`HL_GROUP`、`AGGREGATION`、`selectable=false` 的导航分组 |
|
||||||
|
|
||||||
### 行为级对比
|
### 行为级对比
|
||||||
|
|
||||||
@@ -763,20 +784,23 @@ if (response.code !== 200 || response.success !== true) {
|
|||||||
| 三级联动 | 无统一公开接口,容易截行政区编码推断 | 逐级调用 `children`,以后端父子关系为准 |
|
| 三级联动 | 无统一公开接口,容易截行政区编码推断 | 逐级调用 `children`,以后端父子关系为准 |
|
||||||
| 编辑回显 | 调用方自行拼装父链 | 调用 `path` 返回完整有序父链和三级快捷 ID |
|
| 编辑回显 | 调用方自行拼装父链 | 调用 `path` 返回完整有序父链和三级快捷 ID |
|
||||||
| 并发更新 | 无本接口旧语义 | 必须提交 `rowVersion`,冲突返回 `210807` 且零写入 |
|
| 并发更新 | 无本接口旧语义 | 必须提交 `rowVersion`,冲突返回 `210807` 且零写入 |
|
||||||
|
| 写后读取 | 文档曾表述为提交后立即可见 | 代码为事务提交后异步刷新缓存,存在短暂最终一致窗口 |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 六.7、影响评估
|
## 六.7、影响评估
|
||||||
|
|
||||||
- **是否破坏向后兼容**: 否;这是新增接口,且正式前端接入前已经固定字符串 ID 契约。
|
- **是否破坏向后兼容**: 否;这是新增接口,且正式前端接入前已经固定字符串 ID 契约。
|
||||||
- **前端是否必须同步上线**: 是;`frontend_status=pending`,管理端需接入三级选择器、历史回显和主数据维护。
|
- **前端接入状态**: `frontend_status=verified`;mmg 已完成三级联动接入验证(`frontend_ref=7acd1cb0`)。该验证不扩大为通用主数据编辑能力,后者仍受 `extension` 不可回读等限制,不能按“完整 CRUD 已具备”上线。
|
||||||
- **前端 workaround 清理点**: 不得保留行政区编码截位、Long ID 转 number、只判断 HTTP status 或把 `hasChildren` 等同于 `selectable` 的临时逻辑。
|
- **前端 workaround 清理点**: 不得保留行政区编码截位、Long ID 转 number、只判断 HTTP status、把 `hasChildren` / `defaultId` / `prefectureId` 等同于 `selectable`,或把省略 `extension` 理解成保持原值的临时逻辑。
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 七、不影响范围
|
## 七、不影响范围
|
||||||
|
|
||||||
- **仅影响**: 管理后台行政区划维护、省/市/县三级选择器及历史行政区值回显。
|
- **仅影响**: 管理后台行政区划维护、省/市/县三级选择器及历史行政区值回显。
|
||||||
|
- **当前未提供**: 单节点详情、历史版本列表、按编码查询、删除、批量导入/导出接口;四个已发布接口不能组成无损的完整 CRUD。
|
||||||
|
- **前端接入边界**: 三级选择与父链回显可直接接入;对已有非空 `extension`、超出更新上限的初始化 `sortOrder`、已生效法定节点关闭等需要无损回读/回填的场景暂不具备完整公开契约。
|
||||||
- **零影响**:
|
- **零影响**:
|
||||||
- 小程序端现有行政区接口;
|
- 小程序端现有行政区接口;
|
||||||
- Product、Order、Resource 和 Fleet 现有业务接口;
|
- Product、Order、Resource 和 Fleet 现有业务接口;
|
||||||
@@ -790,15 +814,17 @@ if (response.code !== 200 || response.success !== true) {
|
|||||||
|
|
||||||
```text
|
```text
|
||||||
GET /admin/region/children → 根级/子级列表、defaultId、string/null ID ✓
|
GET /admin/region/children → 根级/子级列表、defaultId、string/null ID ✓
|
||||||
GET /admin/region/{id}/path → 省市县完整父链、缺失层级 null、string ID ✓
|
GET /admin/region/{id}/path → 三级完整父链、缺失层级 null、string ID ✓
|
||||||
POST /admin/region → 创建成功返回 string ID,数据库与缓存读取一致 ✓
|
POST /admin/region → 创建成功返回 string ID,数据库与缓存读取一致 ✓
|
||||||
PUT /admin/region/{id} → CAS 更新成功,rowVersion 0→1,联动与父链同步 ✓
|
PUT /admin/region/{id} → CAS 更新成功,rowVersion 0→1,提交后缓存刷新完成再读取一致 ✓
|
||||||
GET /admin/region/children(未认证) → 401 ✓
|
GET /admin/region/children(未认证) → 401 ✓
|
||||||
POST /admin/region(缺参/非法节点类型) → 400 且零业务写入 ✓
|
POST /admin/region(缺参/非法节点类型) → 400 且零业务写入 ✓
|
||||||
GET /admin/region/{missingId}/path → 210801 ✓
|
GET /admin/region/{missingId}/path → 210801 ✓
|
||||||
```
|
```
|
||||||
|
|
||||||
- TEST 精确提交:`b62054035a139e3c689179ef75e2d052d08dde52`,包含六个相关 PR 的合并提交。
|
- TEST 精确提交:`b62054035a139e3c689179ef75e2d052d08dde52`,包含六个相关 PR 的合并提交。
|
||||||
|
- 本次代码优先复核确认:该提交的 `AdminRegionController` 只有本文四个公开端点;`AdministrativeRegionItemVO` 不含 `extension`;缓存刷新注册在事务 `afterCommit` 后交给独立执行器;migration 中北京链路为 `1 → 35 → 376`,其中 `35` 规范化后为不可选择的 `HL_GROUP/AGGREGATION`。
|
||||||
|
- 2026-08-26 本次复核还通过 TEST Gateway 匿名请求确认 `/admin/region/children` 当前可达且返回业务码 `401`、`success=false`;未使用伪造身份,也未产生业务写入。
|
||||||
- Deploy Panel API 任务:`52771074`(`hl-user-service`)和 `b1db24b2`(`hl-gateway`),终态均为 `success`,双实例、Nacos、滚动采样及部署窗口日志检查通过。
|
- Deploy Panel API 任务:`52771074`(`hl-user-service`)和 `b1db24b2`(`hl-gateway`),终态均为 `success`,双实例、Nacos、滚动采样及部署窗口日志检查通过。
|
||||||
- 真实 TEST 管理员经 Gateway 完成未认证、读取、失败零写入、创建、CAS 更新、持久化结果和缓存一致性验收。
|
- 真实 TEST 管理员经 Gateway 完成未认证、读取、失败零写入、创建、CAS 更新、持久化结果和缓存一致性验收。
|
||||||
- 验收创建的临时节点已精确清理;数据库数量与测试命名空间恢复基线,四个缓存快照按原值和绝对过期时间恢复,登录会话已注销;操作审计按系统设计保留。
|
- 验收创建的临时节点已精确清理;数据库数量与测试命名空间恢复基线,四个缓存快照按原值和绝对过期时间恢复,登录会话已注销;操作审计按系统设计保留。
|
||||||
@@ -822,6 +848,7 @@ GET /admin/region/{missingId}/path → 210801 ✓
|
|||||||
|
|
||||||
- 主 Issue: [wx/HL#6350](https://git.1814.love:8443/wx/HL/issues/6350)
|
- 主 Issue: [wx/HL#6350](https://git.1814.love:8443/wx/HL/issues/6350)
|
||||||
- ID 字符串补充 Issue: [wx/HL#6409](https://git.1814.love:8443/wx/HL/issues/6409)
|
- ID 字符串补充 Issue: [wx/HL#6409](https://git.1814.love:8443/wx/HL/issues/6409)
|
||||||
|
- 代码优先核对修正 Issue: [wx/HL#6438](https://git.1814.love:8443/wx/HL/issues/6438)
|
||||||
- 主 PR: [wx/HL#6359](https://git.1814.love:8443/wx/HL/pulls/6359)
|
- 主 PR: [wx/HL#6359](https://git.1814.love:8443/wx/HL/pulls/6359)
|
||||||
- ID 字符串 PR: [wx/HL#6412](https://git.1814.love:8443/wx/HL/pulls/6412)
|
- ID 字符串 PR: [wx/HL#6412](https://git.1814.love:8443/wx/HL/pulls/6412)
|
||||||
- 本次文档补充 Issue: [wx/HL#6422](https://git.1814.love:8443/wx/HL/issues/6422)
|
- 本次文档补充 Issue: [wx/HL#6422](https://git.1814.love:8443/wx/HL/issues/6422)
|
||||||
@@ -830,7 +857,7 @@ GET /admin/region/{missingId}/path → 210801 ✓
|
|||||||
|
|
||||||
## 撤回
|
## 撤回
|
||||||
|
|
||||||
本次 #6422 仅补充 Changelog 和模板校验,不改变后端制品。若文档补充需要撤回,从最新 `hl-api-changelog/main` 创建独立分支,revert #6422 对应合并提交并重新运行仓库全部校验;TEST 行政区划 API、数据、配置、Redis 和 MQ 均不需要回退。撤回后前端暂以当前 Controller/VO 契约为准,并重新提交一份通过模板门禁的自包含文档。
|
本次 #6438 代码优先核对只修改 Changelog,不改变后端制品。若本次文档修正需要撤回,从最新 `hl-api-changelog/main` 创建独立分支,revert 本次文档合并提交并重新运行仓库全部校验;TEST 行政区划 API、数据库、配置、Redis 和 MQ 均不需要回退。撤回后前端必须以 TEST 对应提交的 Controller、VO、Service 与 migration 为准,不能恢复使用被本次指出的错误聚合节点示例或同步缓存假设。
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -840,6 +867,7 @@ GET /admin/region/{missingId}/path → 210801 ✓
|
|||||||
|
|
||||||
- **Issue**: [#6350](https://git.1814.love:8443/wx/HL/issues/6350)
|
- **Issue**: [#6350](https://git.1814.love:8443/wx/HL/issues/6350)
|
||||||
- **补充文档 Issue**: [#6422](https://git.1814.love:8443/wx/HL/issues/6422)
|
- **补充文档 Issue**: [#6422](https://git.1814.love:8443/wx/HL/issues/6422)
|
||||||
|
- **代码核对修正 Issue**: [#6438](https://git.1814.love:8443/wx/HL/issues/6438)
|
||||||
- **PR**: [#6359](https://git.1814.love:8443/wx/HL/pulls/6359)
|
- **PR**: [#6359](https://git.1814.love:8443/wx/HL/pulls/6359)
|
||||||
- **ID 契约 PR**: [#6412](https://git.1814.love:8443/wx/HL/pulls/6412)
|
- **ID 契约 PR**: [#6412](https://git.1814.love:8443/wx/HL/pulls/6412)
|
||||||
- **最终后端提交**: [b62054035](https://git.1814.love:8443/wx/HL/commit/b62054035a139e3c689179ef75e2d052d08dde52)
|
- **最终后端提交**: [b62054035](https://git.1814.love:8443/wx/HL/commit/b62054035a139e3c689179ef75e2d052d08dde52)
|
||||||
|
|||||||
在新工单中引用
屏蔽一个用户