增加了api文档

This commit is contained in:
2026-09-01 18:17:37 +08:00
parent e0e57a7eb4
commit 73e770db80
25 changed files with 913 additions and 140 deletions
+105 -10
View File
@@ -2,7 +2,7 @@
> 仓颉版 SimApiASP.NET Core 风格 API 基础框架,移植自 [SimApi](https://github.com/SimcuTeam/simapi-net)。
提供**统一响应格式、异常拦截、Token 认证、缓存、工具集、HTTP 客户端、S3 存储、声明式注解**等 API 基础能力。
提供**统一响应格式、异常拦截、Token 认证、缓存、工具集、HTTP 客户端、S3 存储、声明式注解、OpenAPI 文档**等 API 基础能力。
---
@@ -118,7 +118,13 @@ simapi-cj/
│ ├── logger/ # SimApiLogger, SimApiLoggerProvider(彩色日志)
│ ├── macros/ # ReadTomlVersion(编译期读版本号)、EnumString(枚举字符串双向转换)
│ ├── middlewares/ # SimApiExceptionMiddleware, SimApiAuthMiddleware, SimApiRequestLogMiddleware
── models/ # SimApiBaseModel(实体基类)
── models/ # SimApiBaseModel(实体基类)
│ └── openapi/ # OpenAPI 文档生成 + Swagger UI 内置资源
│ ├── annotations/ # @SimApiDoc(文档元数据注解)
│ ├── metadata/ # IApiGroupNamesProvider, IApiResponseTypeMetadata 等元数据接口
│ ├── models/ # OpenApiDocument, OpenApiSchema, OpenApiInfo 等 OpenAPI 模型
│ ├── services/ # OpenApiDocumentService(文档生成), OpenApiSchemaService, OpenApiOptions
│ └── infrastructure/ # OpenApiConstants
```
---
@@ -380,7 +386,7 @@ SimApiExtensions.addSimApi(builder) { options =>
| ----------------- | -------- | ---------------------------- | -------------------------- |
| `/user/info` | POST | `enableSimApiAuth` | 需登录,返回 LoginInfo |
| `/auth/logout` | POST | `enableSimApiAuth` | 退出登录 |
| `/exception/{code}` | GET | 始终 | 错误反馈(抛 SimApiException |
| `/exception/{code}` | GET | 始终 | 错误反馈(抛 SimApiException,不出现在文档中 |
路由路径可自定义(`configureSimApiRoute`):
@@ -394,7 +400,7 @@ options.configureSimApiRoute { route =>
### 7. 认证后处理 Hook — SimApiAuthChecker
实现后每次认证成功都会调用(配合 `@SimApiAuth` 注解或手动 `requireLogin`):
实现后每次认证成功都会调用(配合 `@SimApiAuth` 注解):
```cangjie
import simcu::simapi.interfaces.*
@@ -440,7 +446,89 @@ iam.checkPermission(profileId, "app:create") // 无权限抛 403
---
## 宏(编译期)
## OpenAPI 文档 — enableSimApiDoc
`enableSimApiDoc = true` 时自动生成 OpenAPI 3.0 JSON 文档并内置 Swagger UI 静态资源(无需外部文件,打包后不失效)。
### 文档分组
支持多个文档组,未标注 `@SimApiDoc` 的接口默认进入默认组文档:
```cangjie
SimApiExtensions.addSimApi(builder) { options =>
options.enableSimApiDoc = true
options.configureSimApiDoc { doc =>
doc.apiGroups.add(SimApiDocGroup("api", name: "App接口", description: "对接App相关接口"))
doc.apiGroups.add(SimApiDocGroup("admin", name: "后台管理接口", description: "后台管理接口"))
}
}
```
- `SimApiDocGroup(id, name!, description!, isDefault!)``name` 默认取 `id`
- `distinctGroups()`:按 id 去重,**用户配置覆盖默认值**(保留最后出现)
- 若所有组均未标记 `isDefault`,第一个组视为默认组
### @SimApiDoc 注解
```cangjie
import simcu::simapi.openapi.annotations.*
@SimApiDoc[tags: "登录", summary: "用户登录"]
@SimApiDoc[tags: "认证", summary: "后台登录", groupNames: "admin"]
@SimApiDoc[tags: "公共", groupNames: "api,admin"] // 同时出现在 api 和 admin 文档
@SimApiDoc[tags: "公共", groupNames: "*"] // 出现在所有文档
@SimApiDoc[ignore: true] // 不出现在文档中
```
- `groupNames`:逗号分隔多个组名,`*` 表示所有文档,空串表示未分组(仅进默认文档)
- `ignore: true`:从文档中隐藏
### 路由前缀
```cangjie
options.configureSimApiDoc { doc =>
doc.urlPrefix = "docs" // 默认值,可自定义
}
```
| 路由 | 说明 |
|------|------|
| `/{prefix}/all.html` | 多文档切换页(顶部栏下拉选择所有文档) |
| `/{prefix}/{id}.html` | 单文档页(无顶部栏,自动加载 `{id}.json` |
| `/{prefix}/urls` | 文档列表 JSON(供 Swagger UI 下拉) |
| `/{prefix}/{id}.json` | OpenAPI 文档 JSON |
> Swagger UI 静态资源(CSS/JS/HTML)以 Base64 内联编译,运行时由 `OpenApiUIMiddleware` 解码输出。资源更新后运行 `pwsh tools/gen-swagger-ui-resources.ps1` 重新生成。
### 响应封装与文档
接口返回值自动封装为统一响应格式,**文档中 response schema 也体现封装**
| 返回类型 | `@OriginResponse` | 文档 response schema |
|----------|-------------------|---------------------|
| `SimApiBaseResponse`/`SimApiResponse<T>`/`SimApiDataResponse` | - | 原样不封装 |
| 任意类型 | ✓ | 原样不封装 |
| `Unit` (void) | ✗ | `{code: int64, message: string}` |
| `String` | ✗ | `{code, message, data: {type: string}}` |
| DTO | ✗ | `{code, message, data: {$ref: DTO}}` |
### 认证锁图标
仅标注了 `@SimApiAuth` 的接口在文档中显示锁图标(operation 级 `security`),未标注的接口不显示。
动态注册的路由(lambda)需用 `withSimApiAuth` 扩展方法手动添加认证元数据:
```cangjie
host.mapPost(route, { context => ... })
.withOpenApi(SimApiDoc(tags: "认证", summary: "获取用户信息"))
.withSimApiAuth(SimApiAuth())
.withResponseType(TypeInfo.of<SimApiLoginItem>())
```
- `withSimApiAuth`:添加 `@SimApiAuth` 元数据(显示锁图标)
- `withResponseType`:添加响应类型元数据(动态路由无 `ControllerActionDescriptor`,需手动指定返回类型才能生成 response schema
---
### EnumString — 枚举字符串双向转换
@@ -499,6 +587,7 @@ SimApiExtensions.addSimApi(builder) { options =>
options.enableSimApiResponseFilter = true // 响应统一封装
options.enableSimApiHttpClient = false // HTTP 客户端
options.enableSimApiAuthGate = false // 认证中心 SDK + 网关中间件
options.enableSimApiDoc = false // OpenAPI 文档 + Swagger UI
options.enableRequestLog = false // 请求日志中间件
options.enableCors = true // 全量 CORS
options.enableLogger = true // 控制台日志
@@ -509,6 +598,11 @@ SimApiExtensions.addSimApi(builder) { options =>
route.logoutRoute = Some("/auth/logout")
route.webConfigRoute = Some("/config")
}
options.configureSimApiDoc { doc =>
doc.urlPrefix = "docs" // 文档路由前缀(默认 "docs"
doc.apiGroups.add(SimApiDocGroup("api", name: "App接口", description: "App接口文档"))
doc.apiGroups.add(SimApiDocGroup("admin", name: "后台管理", description: "后台管理接口"))
}
options.configureSimApiRequestLog { opt =>
opt.showFullResponse = true
opt.showFullHeader = false
@@ -535,14 +629,14 @@ simapi 提供 Spire MVC 控制器(继承 `SimApiBaseController`),`addSimAp
|--------|------|------|
| `SimApiCommonController` | `/exception/{code}``/config``/user/info` | 通用内置路由 |
| `SimApiAuthController` | `/auth/logout` | 退出登录 |
| `SimApiBaseController` | — | 基类:`loginInfo` / `loginToken` / `requireLogin()` / `getLogin()` |
| `SimApiBaseController` | — | 基类:`loginInfo` / `loginToken`(访问时自动校验登录,未登录抛 401) |
```cangjie
import simcu::simapi.controllers.*
import simcu::simapi.annotations.{SimApiAuth}
// 控制器写法:继承 SimApiBaseController,注解路由 + DI 注入
@SimApiAuth // 类级鉴权(可选,替代 requireLogin
@SimApiAuth // 类级鉴权
public class MyController <: SimApiBaseController {
private let _auth: SimApiAuth
public init(auth: SimApiAuth) { this._auth = auth }
@@ -560,15 +654,14 @@ public class MyController <: SimApiBaseController {
## 未实现模块(选项占位)
以下原包功能因仓颉生态暂无对应库(Hangfire/MQTT/Swashbuckle),**选项保留但未实现**
以下原包功能因仓颉生态暂无对应库(Hangfire/MQTT),**选项保留但未实现**:
| 选项 | 原功能 | 状态 |
|------|--------|------|
| `enableSimApiDoc` | Swagger 文档(可换 soulsoft_web_openapi | ❌ 未实现 |
| `enableSynapse` | MQTT 通信 | ❌ 未实现 |
| `enableJob` | Hangfire 任务调度 | ❌ 未实现 |
> ✅ 已实现(曾为占位):`enableSimApiStorage`S3/MinIO,自实现 AWS SigV4)、`enableSimApiAuthGate`AuthSDK 认证中心)、`SimApiAesUtil`(纯仓颉 AES-256-CBC)、`SimApiAuthChecker`、`@SimApiSign` / `@AesBody` 声明式注解、内置路由自定义路径。
> ✅ 已实现(曾为占位):`enableSimApiDoc`OpenAPI 文档 + Swagger UI)、`enableSimApiStorage`S3/MinIO,自实现 AWS SigV4)、`enableSimApiAuthGate`AuthSDK 认证中心)、`SimApiAesUtil`(纯仓颉 AES-256-CBC)、`SimApiAuthChecker`、`@SimApiSign` / `@AesBody` 声明式注解、内置路由自定义路径。
---
@@ -583,8 +676,10 @@ public class MyController <: SimApiBaseController {
| `simcu::serialization`path 依赖) | JSON 序列化(simapi 自研,反射免标注) |
| `redis`pkg.cangjie-lang.cn | Redis 客户端(认证/缓存 Redis 模式) |
| `stdx`CANGJIE_STDX_PATH | 标准扩展库(md5/sha1/base64/http/tls |
| `soulsoft_web_mvc` | MVC 框架(控制器路由、模型绑定) |
> 构建前需设置 `CANGJIE_STDX_PATH` 指向本地 stdx 的 `static/stdx` 目录。
> OpenAPI Swagger UI 静态资源内置(Base64 内联),更新资源后运行 `pwsh tools/gen-swagger-ui-resources.ps1`。
---