Files
CN_Tool/tools/mms-mapping/API-getIcdMmsJson.md
2026-04-23 11:06:04 +08:00

372 lines
14 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# getIcdMmsJson 标准 API 调试文档
## 1. 文档范围
本文档用于说明 `mms-mapping` 模块统一调试接口 `getIcdMmsJson` 的标准调用方式、请求结构、响应规则和联调注意事项。
本文档内容以当前源码为准,主要对照以下实现:
- `tools/mms-mapping/src/main/java/com/njcn/gather/icd/mapping/controller/MappingController.java`
- `tools/mms-mapping/src/main/java/com/njcn/gather/icd/mapping/component/MappingRequestConverter.java`
- `tools/mms-mapping/src/main/java/com/njcn/gather/icd/mapping/component/MappingResponseConverter.java`
- `tools/mms-mapping/src/main/java/com/njcn/gather/icd/mapping/service/impl/MappingTaskServiceImpl.java`
- `tools/mms-mapping/src/main/java/com/njcn/gather/icd/mapping/component/MappingGenerationService.java`
- `tools/mms-mapping/src/main/java/com/njcn/gather/icd/mapping/pojo/param/GenerateMappingFromIcdRequest.java`
- `tools/mms-mapping/src/main/java/com/njcn/gather/icd/mapping/pojo/vo/MappingTaskResponse.java`
说明:
- 本文档仅描述接口契约和调试方式,不改动业务代码。
- 本次未执行 `mvn` 编译、打包或真实接口联调。
- 如文档与运行结果冲突,以源码和实际部署配置为准。
## 2. 接口基本信息
| 项 | 说明 |
| --- | --- |
| 接口名称 | `getIcdMmsJson` |
| 请求方法 | `POST` |
| 请求路径 | `/api/mms-mapping/get-icd-mms-json` |
| Content-Type | `multipart/form-data` |
| 控制器入口 | `MappingController#getIcdMmsJson` |
| 请求组成 | `icdFile` 文件 Part + `request` JSON Part |
| 正常业务响应体 | `MappingTaskResponse` |
## 3. 接口职责
该接口是 `mms-mapping` 模块的统一调试入口,串联以下两个阶段:
1. 上传 ICD 文件并完成解析,生成 `icdDocument``indexCandidates`
2. 根据 `request.indexSelection` 判断是否继续生成正式 `mappingJson`
接口行为分为三种典型结果:
1. `request.indexSelection` 未传或为空
返回 `NEED_INDEX_SELECTION`,用于引导前端或调试人员先确认标签与 `lnInst` 的绑定关系。
2. `request.indexSelection` 已传但校验不通过
返回 `NEED_INDEX_SELECTION`,同时通过 `problems` 给出不合法原因,要求重新选择。
3. `request.indexSelection` 校验通过
返回 `SUCCESS`,输出正式 `mappingJson`,必要时同时落盘并返回 `savedPath`
补充说明:
- 该接口每次都会重新解析上传的 ICD 文件,因此第二次调试仍然必须重新上传 ICD 文件。
- 该接口正常进入业务编排后,返回体类型为 `MappingTaskResponse`
- 如果异常发生在控制器参数绑定或请求转换阶段例如文件为空、Part 缺失、JSON Part 解析失败,则由全局异常处理器统一包装为 `HttpResult<String>`,而不是 `MappingTaskResponse`
## 4. 请求规范
### 4.1 multipart/form-data Part 说明
| Part 名称 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `icdFile` | File | 是 | ICD 文件,不能为空 |
| `request` | JSON Part | 是 | 生成参数,必须按 `application/json` 发送 |
说明:
- `request` Part 不能省略。即使第一次只想拿候选结果,也必须传一个最小 JSON。
- `request.indexSelection` 可以省略或传空数组,此时接口只返回候选结果,不生成正式映射。
### 4.2 request JSON 结构
```json
{
"version": "2026-04-22",
"author": "debug-user",
"saveToDisk": false,
"prettyJson": true,
"outputDir": "D:/temp/mms-output",
"indexSelection": [
{
"groupKey": "harm",
"groupDesc": "谐波数据",
"bindings": [
{
"reportName": "brcbStHarm",
"dataSetName": "dsStHarm",
"label": "A相",
"lnInst": "1"
}
]
}
]
}
```
### 4.3 request 字段说明
| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `version` | String | 否 | 输出版本号。未传或空白时,后端按当天日期补齐,格式为 `yyyy-MM-dd` |
| `author` | String | 否 | 作者。未传或空白时,回退到配置项 `icd.mapping.default-author`,默认值为 `system` |
| `saveToDisk` | boolean | 否 | 是否将生成结果写入磁盘 |
| `prettyJson` | boolean | 否 | 是否输出格式化 JSON。`true` 为美化 JSON`false` 为紧凑 JSON |
| `outputDir` | String | 否 | 输出目录。未传或空白时,先回退到配置项 `icd.mapping.default-output-dir`;如果配置也为空,最终落到当前工作目录 |
| `indexSelection` | Array | 否 | 标签与 `lnInst` 的最终绑定关系。未传或为空时,只返回候选结果 |
### 4.4 indexSelection 字段说明
| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `groupKey` | String | 是 | 分组唯一键,必须使用第一次响应里返回的原值 |
| `groupDesc` | String | 否 | 分组中文描述,便于调试查看 |
| `bindings` | Array | 是 | 当前业务分组下最终确认的绑定关系列表 |
### 4.5 bindings 字段说明
| 字段 | 类型 | 必填 | 说明 |
| --- | --- | --- | --- |
| `reportName` | String | 是 | 绑定发生在哪个报告上,例如 `brcbStHarm` |
| `dataSetName` | String | 是 | 绑定发生在哪个数据集上,例如 `dsStHarm` |
| `label` | String | 是 | 业务标签,例如 `A相``最大值``实时数据` |
| `lnInst` | String | 是 | 标签最终绑定到的逻辑节点实例值,例如 `1``2``3` |
## 5. 标准调试流程
### 5.1 第一次调试:只获取候选结果
用途:
- 上传 ICD 文件
- 获取 `icdDocument`
- 获取 `indexCandidates`
- 确认每个业务分组下可选的 `reportName``dataSetName``availableLnInstValues`
调用要求:
- `request` Part 仍然必须传
- `request.indexSelection` 可以不传,或传空数组
预期结果:
- `status = NEED_INDEX_SELECTION`
- 响应中返回 `icdDocument`
- 响应中返回 `indexCandidates`
### 5.2 第二次调试:带索引绑定生成正式结果
用途:
- 根据第一次返回的 `indexCandidates` 组装 `request.indexSelection`
- 再次上传同一个 ICD 文件
- 生成正式 `mappingJson`
调用要求:
- 必须继续上传 `icdFile`
- `groupKey` 必须沿用第一次返回值
- `reportName``dataSetName``lnInst` 必须与第一次返回的候选结果匹配
预期结果:
- `status = SUCCESS`
- 响应中返回 `mappingJson`
-`saveToDisk = true` 时,响应中额外返回 `savedPath`
### 5.3 第二次调试但绑定不合法
适用场景:
- `groupKey` 与候选结果不匹配
- `reportName``dataSetName` 不在候选集中
- `lnInst` 不在 `availableLnInstValues`
- 绑定关系缺失、不完整或结构错误
预期结果:
- `status = NEED_INDEX_SELECTION`
- 响应中仍然返回 `icdDocument``indexCandidates`
- `problems` 返回具体问题列表,要求重新确认绑定关系
## 6. 响应规范
### 6.1 正常业务响应体
接口正常进入业务编排后,统一返回 `MappingTaskResponse`。该对象使用了 `@JsonInclude(JsonInclude.Include.NON_EMPTY)`,空字段和空集合不会参与序列化。
基础字段说明:
| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `status` | Enum | 本次处理状态,可能为 `SUCCESS``NEED_INDEX_SELECTION``FAILED` |
| `message` | String | 状态说明或错误提示 |
| `icdDocument` | Object | 需要重新选择索引时返回的 ICD 解析结果 |
| `mappingJson` | String | 正式生成成功后的映射 JSON 文本 |
| `savedPath` | String | 结果已落盘时返回的绝对路径 |
| `indexCandidates` | Array | 待绑定状态下返回的索引候选分组 |
| `problems` | Array | 模板校验、候选分析或绑定校验问题 |
字段出现规则:
| 状态 | 必有字段 | 可能出现字段 |
| --- | --- | --- |
| `SUCCESS` | `status``message``mappingJson` | `savedPath``problems` |
| `NEED_INDEX_SELECTION` | `status``message``icdDocument``indexCandidates` | `problems` |
| `FAILED` | `status``message` | `problems` |
### 6.2 NEED_INDEX_SELECTION 响应示例
```json
{
"status": "NEED_INDEX_SELECTION",
"message": "索引配置缺失,请根据候选信息完成标签与数字索引的绑定后重新提交",
"icdDocument": {
"fileName": "demo.icd",
"iedName": "IED1",
"ldInst": "LD0",
"ldPrefix": "LD",
"logicalNodes": [
{
"lnInst": "1"
}
]
},
"indexCandidates": [
{
"groupKey": "harm",
"groupDesc": "谐波数据",
"reportCount": 1,
"templateLabels": [
"A相",
"B相",
"C相"
],
"reports": [
{
"reportName": "brcbStHarm",
"dataSetName": "dsStHarm",
"reportDesc": "谐波报告",
"availableLnInstValues": [
"1",
"2",
"3"
]
}
]
}
]
}
```
说明:
- `icdDocument` 实际字段可能比示例更多。
- 如果本次是“索引配置不合法”而不是“索引配置缺失”,通常还会返回 `problems`
### 6.3 SUCCESS 响应示例
```json
{
"status": "SUCCESS",
"message": "映射生成成功",
"mappingJson": "{\n \"version\": \"2026-04-22\",\n \"author\": \"debug-user\",\n \"ied\": \"IED1\",\n \"ld\": \"LD\",\n \"instList\": []\n}"
}
```
说明:
- `mappingJson` 是字符串字段,字段值本身是一段 JSON 文本。
-`saveToDisk = true` 时,响应中还会额外返回 `savedPath`
### 6.4 FAILED 响应示例
```json
{
"status": "FAILED",
"message": "映射生成失败:加载 DefaultCfg.txt 失败默认模板文件不存在template/DefaultCfg.txt",
"problems": [
"加载 DefaultCfg.txt 失败默认模板文件不存在template/DefaultCfg.txt"
]
}
```
说明:
- `FAILED` 主要对应服务编排阶段捕获到的运行异常,例如 ICD 解析、模板加载、映射生成、序列化或落盘失败。
- 并非所有错误都会进入 `FAILED`。如果异常发生在控制器参数绑定或请求转换阶段,会走全局异常处理器,而不是这里的业务响应结构。
## 7. 全局异常响应说明
以下场景通常不会返回 `MappingTaskResponse`,而是由 `GlobalBusinessExceptionHandler` 统一包装:
- `icdFile` 缺失或为空
- `request` Part 缺失
- `request` Part 的 `Content-Type` 不是 `application/json`
- `multipart/form-data` 结构不合法
- JSON 反序列化失败或框架参数绑定失败
这类异常最终会包装为统一的 `HttpResult<String>` 响应,具体字段结构以全局公共响应定义为准,本文不展开其完整协议,只强调:
- 不能把这类错误等同理解为 `MappingTaskResponse.status = FAILED`
- 联调时应先区分“业务响应体”与“全局异常包装”
## 8. 调试示例
### 8.1 curl 示例:第一次调用,只获取候选结果
```powershell
curl.exe -X POST "http://localhost:8080/api/mms-mapping/get-icd-mms-json" `
-H "Accept: application/json" `
-F 'icdFile=@D:/data/demo.icd' `
-F 'request={"prettyJson":true,"saveToDisk":false};type=application/json'
```
### 8.2 curl 示例:第二次调用,带索引绑定直接生成 MMS JSON
```powershell
curl.exe -X POST "http://localhost:8080/api/mms-mapping/get-icd-mms-json" `
-H "Accept: application/json" `
-F 'icdFile=@D:/data/demo.icd' `
-F 'request={"version":"2026-04-22","author":"debug-user","prettyJson":true,"saveToDisk":false,"indexSelection":[{"groupKey":"harm","groupDesc":"谐波数据","bindings":[{"reportName":"brcbStHarm","dataSetName":"dsStHarm","label":"A相","lnInst":"1"},{"reportName":"brcbStHarm","dataSetName":"dsStHarm","label":"B相","lnInst":"2"},{"reportName":"brcbStHarm","dataSetName":"dsStHarm","label":"C相","lnInst":"3"}]}]};type=application/json'
```
## 9. Postman 调试要点
1. `Body` 选择 `form-data`
2. `icdFile` 类型选择 `File`
3. `request` 保持文本输入,但该 Part 的 `Content-Type` 必须显式设置为 `application/json`
4. 第一次调试不要省略 `request` Part只是不传 `indexSelection`
5. 第二次调试时必须继续上传 ICD 文件,并严格按第一次返回的候选结果组装绑定关系
## 10. 常见问题
### 10.1 为什么第一次调试也必须传 `request`
因为控制器方法签名使用的是 `@RequestPart("request") GenerateMappingFromIcdRequest request`,该 Part 本身就是必填参数。第一次调试可以只传最小 JSON但不能完全省略。
### 10.2 为什么没有传 `indexSelection`,却没有返回 `FAILED`
这是接口设计的正常行为。`indexSelection` 缺失或为空时,业务语义不是“接口执行失败”,而是“还需要前端继续确认索引绑定”,因此返回的是 `NEED_INDEX_SELECTION`
### 10.3 `saveToDisk=true` 但没有传 `outputDir`,结果会保存到哪里
处理顺序如下:
1. 先读取请求中的 `outputDir`
2. 如果请求空白,则回退到配置项 `icd.mapping.default-output-dir`
3. 如果配置项也为空,则最终落到当前工作目录
### 10.4 `version` 不传时会变成什么
后端在正式生成映射文档时,会把空白 `version` 自动补成当天日期,格式为 `yyyy-MM-dd`
### 10.5 `mappingJson` 为什么是字符串,不是嵌套对象
因为当前响应结构中 `mappingJson` 定义为 `String`,接口返回的是一段已经序列化好的 JSON 文本,而不是再次展开后的对象结构。
### 10.6 什么情况下会返回 `problems`
`problems` 主要用于承载以下问题:
- 默认模板校验问题
- 索引候选分析问题
- `indexSelection` 绑定校验问题
- 服务编排阶段捕获到的异常原因
## 11. 当前边界
- 当前文档仅覆盖 `getIcdMmsJson` 接口,不覆盖 `get-icd``get-mms-json` 的独立接口文档
- 当前文档重点描述业务返回体与调试方式,不展开全局 `HttpResult` 的完整协议
- 示例中的 `icdDocument``indexCandidates``mappingJson` 为结构化示意,实际字段数量与内容以运行结果为准