kt-template-online-api/API.md
sunlei 7291fed682 feat: 支持数据库字典映射并整理公共能力
- 新增 dict 实体表,字典查询改为从数据库读取
- 使用 childrenKey 实现组件一级类型到二级字典的关系映射
- Component 查询后通过 DecodeDictKey 和 AfterLoad 自动补充翻译字段
- 移除 ComponentDto、本地字典常量和本地 seed 文件
- 将 common 能力按 decorators/interceptors/services/swagger 重新分层
- 使用全局 SaveBodyInterceptor 替代 SaveMiddleware 统一处理 save 请求
- 更新 MinIO、组件、字典接口的 Swagger 响应和少量关键注释
- 重写 README.md 和 API.md,补充项目功能、目录结构和接口说明

BREAKING CHANGE: 字典数据依赖数据库 dict 表维护,不再使用本地字典常量。
2026-05-13 15:33:38 +08:00

373 lines
9.8 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.

# KT Template Online API
后端服务默认监听 `48085`Swagger 地址为 `/api`OpenAPI JSON 地址为 `/api-json`
除文件下载接口外,接口统一返回:
```json
{
"code": 200,
"msg": "操作成功",
"data": {}
}
```
失败时仍使用相同结构,常见为:
```json
{
"code": 400,
"msg": "操作失败",
"data": null
}
```
## 功能模块
| 模块 | 说明 |
| --------- | --------------------------------------------------------------------- |
| Component | 组件/图表模板的列表、详情、新增、编辑、逻辑删除 |
| Dict | 数据库字典查询,以及组件一级类型到二级类型的数据库关系映射 |
| MinIO | Bucket 检查/创建、文件上传、列表、临时访问地址、下载和删除 |
| Common | 统一响应 Swagger 注解、字典翻译注解、`POST */save` 请求体规范化拦截器 |
## 通用规则
### Save 请求体规范化
系统全局注册 `SaveBodyInterceptor`,默认会对 `POST */save` 请求删除 `body.id`,避免新增接口因为前端误传 `id` 而走指定主键保存。
如果个别接口需要保留 `id`,可在对应 Controller 方法上使用 `@SkipSaveBodyNormalize()`
### 数据库字典翻译
字典数据维护在数据库 `dict` 表中。`Component.typeMsg`、`Component.componentTypeMsg` 会在 TypeORM `AfterLoad` 阶段根据字典缓存自动映射。
`dict` 表核心字段:
| 字段 | 类型 | 说明 |
| ----------- | ------- | ------------------------------------------------------ |
| id | string | 字典 ID |
| dictKey | string | 字典分组,例如 `COMPONENT_TYPE`、`CHART`、`COMPONENT` |
| label | string | 展示文本 |
| value | string | 字典值 |
| childrenKey | string | 子字典分组,例如 `COMPONENT_TYPE.value=1` 指向 `CHART` |
| sort | number | 排序 |
| is_deleted | boolean | 逻辑删除标记 |
当前数据库示例关系:
| dictKey | value | label | childrenKey |
| -------------- | ----- | ----- | ----------- |
| COMPONENT_TYPE | 1 | 图表 | CHART |
| COMPONENT_TYPE | 2 | 组件 | COMPONENT |
## 数据结构
### Component
| 字段 | 类型 | 说明 |
| ---------------- | ------- | ---------------------------------- |
| id | string | 组件 ID新增时由后端生成 |
| name | string | 组件名称 |
| type | number | 一级类型,实际含义由 `dict` 表维护 |
| componentType | number | 二级类型,实际含义由 `dict` 表维护 |
| typeMsg | string | 一级类型文本,查询后自动映射 |
| componentTypeMsg | string | 二级类型文本,查询后自动映射 |
| image | string | 封面图或封面图地址 |
| template | string | Playground 序列化模板内容 |
| createTime | string | 创建时间 |
| updateTime | string | 更新时间 |
| is_deleted | boolean | 逻辑删除标记 |
### Dict
接口返回的字典项结构:
| 字段 | 类型 | 说明 |
| ----- | ------------- | -------- |
| label | string | 展示文本 |
| value | number/string | 字典值 |
### MinIO
`bucketName` 未传时默认读取环境变量 `MINIO_BUCKET`,缺省值为 `kt-template-online`
## Root
### GET `/`
重定向到 Swagger 文档页 `/api#/`HTTP 状态码为 `301`
## Component 接口
### GET `/component/allList`
获取全部组件。
响应 `data``Component[]`。
示例:
```json
{
"code": 200,
"msg": "操作成功",
"data": [
{
"id": "1d8d3dd2-99f0-4d10-9a44-0cf9566b37c9",
"name": "基础折线图",
"type": 1,
"componentType": 1,
"typeMsg": "图表",
"componentTypeMsg": "折线图",
"image": "",
"template": "%7B%22version%22%3A%221.0%22%7D",
"createTime": "2026-05-13T02:30:00.000Z",
"updateTime": "2026-05-13T02:30:00.000Z",
"is_deleted": false
}
]
}
```
### GET `/component/list`
分页获取组件列表。列表默认过滤 `is_deleted=false`,并支持按名称模糊搜索。
Query
| 参数 | 类型 | 必填 | 说明 |
| ------------- | ------ | ---- | ---------------- |
| pageNo | number | 是 | 页码 |
| pageSize | number | 是 | 每页条数 |
| name | string | 否 | 组件名称模糊搜索 |
| type | number | 否 | 一级类型 |
| componentType | number | 否 | 二级类型 |
响应 `data`
```ts
{
list: Component[]
total: number
}
```
### GET `/component/detail`
获取组件详情。
Query
| 参数 | 类型 | 必填 | 说明 |
| ---- | ------ | ---- | ------- |
| id | string | 是 | 组件 ID |
响应 `data``Component`。
### POST `/component/save`
新增组件。全局 `SaveBodyInterceptor` 会删除 `body.id`,新增时不需要传 `id`
Body
```json
{
"name": "基础折线图",
"type": 1,
"componentType": 1,
"image": "",
"template": "%7B%22version%22%3A%221.0%22%7D"
}
```
响应 `data`:新增组件 ID。
```json
{
"code": 200,
"msg": "操作成功",
"data": "1d8d3dd2-99f0-4d10-9a44-0cf9566b37c9"
}
```
### POST `/component/update`
编辑组件。
Body
```json
{
"id": "1d8d3dd2-99f0-4d10-9a44-0cf9566b37c9",
"name": "基础折线图",
"type": 1,
"componentType": 1,
"image": "",
"template": "%7B%22version%22%3A%221.0%22%7D"
}
```
响应 `data``true` 表示更新成功。
### POST `/component/remove`
逻辑删除组件。
Query
| 参数 | 类型 | 必填 | 说明 |
| ---- | ------ | ---- | ------- |
| id | string | 是 | 组件 ID |
响应 `data``true` 表示删除成功。
## Dict 接口
### GET `/dict/getDictByKey`
根据字典分组获取字典项。
Query
| 参数 | 类型 | 必填 | 说明 |
| ------- | ------ | ---- | ---------------------- |
| dictKey | string | 是 | 字典分组,例如 `CHART` |
响应示例:
```json
{
"code": 200,
"msg": "操作成功",
"data": [
{
"label": "折线图",
"value": 1
}
]
}
```
### GET `/dict/getComponentDictByType`
根据组件一级类型获取对应的二级类型字典。
查询逻辑:先查 `dictKey=COMPONENT_TYPE``value=type` 的字典项,再使用该项的 `childrenKey` 查询子字典。
Query
| 参数 | 类型 | 必填 | 说明 |
| ---- | ------ | ---- | -------- |
| type | number | 是 | 一级类型 |
响应 `data``Array<{ label: string; value: number | string }>`。
## MinIO 接口
### GET `/minio/check`
检查 MinIO 连接和 bucket 状态。
Query
| 参数 | 类型 | 必填 | 说明 |
| ---------- | ------ | ---- | ----------- |
| bucketName | string | 否 | bucket 名称 |
响应 `data``{ bucketName: string; exists: boolean }`。
### POST `/minio/bucket`
创建 bucket已存在时跳过。
Query
| 参数 | 类型 | 必填 | 说明 |
| ---------- | ------ | ---- | ----------- |
| bucketName | string | 否 | bucket 名称 |
响应 `data`bucket 名称。
### POST `/minio/upload`
上传文件,请求类型为 `multipart/form-data`
Body
| 参数 | 类型 | 必填 | 说明 |
| ---------- | ------ | ---- | ---------------------- |
| file | File | 是 | 文件 |
| bucketName | string | 否 | bucket 名称 |
| objectName | string | 否 | 对象名,不传时自动生成 |
响应示例:
```json
{
"code": 200,
"msg": "操作成功",
"data": {
"bucketName": "kt-template-online",
"objectName": "uploads/1715580000000-a1b2c3-demo.png",
"etag": "9b2cf535f27731c974343645a3985328",
"size": 2048,
"mimeType": "image/png",
"url": "http://127.0.0.1:9000/kt-template-online/uploads/demo.png"
}
}
```
### GET `/minio/list`
获取文件列表。
Query
| 参数 | 类型 | 必填 | 说明 |
| ---------- | ------ | ---- | ----------------------------- |
| bucketName | string | 否 | bucket 名称 |
| prefix | string | 否 | 对象名前缀 |
| recursive | string | 否 | 是否递归,传 `false` 时不递归 |
响应 `data`MinIO 对象数组,常见字段为 `name`、`size`、`etag`、`lastModified`。
### GET `/minio/url`
获取文件临时访问地址。
Query
| 参数 | 类型 | 必填 | 说明 |
| ---------- | ------ | ---- | --------------------------- |
| objectName | string | 是 | 对象名 |
| bucketName | string | 否 | bucket 名称 |
| expiry | string | 否 | 有效期秒数,默认 `86400` 秒 |
响应 `data`:临时访问 URL。
### GET `/minio/download`
下载文件,直接返回文件流。
Query
| 参数 | 类型 | 必填 | 说明 |
| ---------- | ------ | ---- | ----------- |
| objectName | string | 是 | 对象名 |
| bucketName | string | 否 | bucket 名称 |
### DELETE `/minio/remove`
删除文件。
Query
| 参数 | 类型 | 必填 | 说明 |
| ---------- | ------ | ---- | ----------- |
| objectName | string | 是 | 对象名 |
| bucketName | string | 否 | bucket 名称 |
响应 `data``true` 表示删除成功。