Files
happy-life-star/docs/superpowers/specs/2026-05-23-endpoint-chinese-docs-and-test-panel-design.md
T
peanut 377821f449 docs: 添加接口管理中文描述与测试面板改造设计文档
- 设计后端 Controller/DTO 注解补全方案(4 个批次)
- 设计前端测试面板表单化改造(参数表单 + JSON 预填充)
- 定义操作列"测试"按钮和 defaultTab 交互
- 补充边缘情况处理和验收标准

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-23 21:17:03 +08:00

275 lines
11 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.
---
author: Peanut
created_at: 2026-05-23
purpose: 设计接口管理页面的中文描述补全和测试面板表单化改造
---
# 接口管理中文描述与测试面板改造设计
## 1. 目标
- 所有接口均有对应的中文描述(summary + description),在接口列表和详情中可直观理解接口用途
- 所有参数均有中文描述,在详情和测试面板中可理解参数含义
- 测试面板从"空白 JSON 输入框"改造为"预填充 JSON 编辑器"——参数 key 和结构预填充,用户只需修改值即可测试
- 操作列增加"测试"按钮,点击直接打开弹窗并切换到测试标签
## 2. 架构
```
后端 Controller (@Operation/@Parameter/@Schema 注解)
→ SpringDoc 自动生成 OpenAPI 3 JSON (/v3/api-docs)
→ ApiEndpointService.syncFromOpenApi() 解析并入库
→ 前端 getEndpointList/getEndpointDetail 展示
→ 前端 EndpointDetailDialog 测试面板渲染预填充 JSON 表单
```
## 3. 后端改造
### 3.1 Controller 注解补全
`backend-single/src/main/java/com/emotion/controller/` 下所有 Controller 补全注解:
**类级别注解:**
```java
@Tag(name = "用户管理", description = "用户的增删改查、状态管理等操作")
public class UserController { ... }
```
**方法级别注解:**
```java
@Operation(summary = "分页查询用户列表", description = "支持按用户名、状态、角色等条件筛选")
@GetMapping("/list")
public Result<Page<UserVO>> list(@Validated UserQueryRequest request) { ... }
```
**参数级别注解(路径参数/查询参数):**
```java
@Parameter(description = "用户ID", required = true)
@RequestParam String userId
```
**DTO 字段注解(请求体参数):**
```java
public class LoginRequest {
@Schema(description = "手机号")
private String phone;
@Schema(description = "短信验证码")
private String smsCode;
}
```
### 3.2 注解补全范围与批次
按优先级分批补全,每批完成后触发同步验证:
**Batch 1 (P0 - 认证与管理,约 5 个 Controller~25 个接口):**
- AuthController, AdminAuthController, GuestUserController, TokenController, AdminController
- 涉及核心请求体:登录/注册/重置密码等,参数描述最关键
**Batch 2 (P1 - AI 与社区,约 8 个 Controller~40 个接口):**
- AiChatController, AiConfigController, AiRoutingController, CozeApiCallController
- CommunityPostController, CommentController, SocialContentController, SocialInsightController
- UserProfileController, UserController
**Batch 3 (P1 - 日记与情绪,约 8 个 Controller~35 个接口):**
- DiaryPostController, DiaryCommentController, GrowthTopicController, TopicInteractionController
- EmotionAnalysisController, EmotionRecordController, EmotionSummaryController, LifeEventController
- ConversationController, MessageController
**Batch 4 (P2 - 其他,约 10+ 个 Controller~30 个接口):**
- DictionaryController, EpicScriptController, LifePathController, AchievementController
- RewardController, UserStatsController, TtsController, AsrController, HealthController
- AnalyticsController, AdminAnalyticsController, ChatWebSocketController
**完成标准:** 每个批次的 Controller 及其关联的 Request/Response DTO 全部注解补全。
### 3.3 同步逻辑
`ApiEndpointServiceImpl.syncFromOpenApi()` 已经正确解析 OpenAPI 规范中的 `summary``description``parameters[].description``requestBody` schema 中的字段描述。补全注解后在管理后台点击"手动同步"即可生效。
## 4. 前端改造
### 4.1 EndpointList.vue — 操作列增加"测试"按钮
在操作列添加"测试"按钮,点击后打开详情弹窗并自动切换到测试标签页:
```vue
<el-table-column label="操作" width="150" align="center">
<template #default="{ row }">
<el-button type="primary" link size="small" @click="showDetail(row)">详情</el-button>
<el-button type="success" link size="small" @click="showTest(row)">测试</el-button>
</template>
</el-table-column>
```
`showTest(row)` 方法:加载详情后,通过 `defaultTab` prop 控制子组件默认打开测试标签。
### 4.2 EndpointDetailDialog.vue — 测试面板改造
#### 4.2.1 新增 defaultTab prop
父组件可控制默认打开的标签页:
```typescript
const props = defineProps<{
modelValue: boolean
detail: ApiEndpointDetail | null
defaultTab?: 'detail' | 'test' // 新增,默认 'detail'
}>()
```
watch 逻辑中:
```typescript
watch(() => props.detail, (ep) => {
if (ep) {
testForm.value.path = ep.path
testForm.value.method = ep.method
testForm.value.params = {}
testForm.value.body = ''
testResult.value = null
activeTab.value = props.defaultTab || 'detail' // 使用传入的默认标签
}
}, { immediate: true })
```
#### 4.2.2 查询参数表单化(GET/DELETE 等无请求体的接口)
对于 `paramType``query``path` 的参数,渲染为表单输入框:
| paramTypeDef | enumValues 有值 | 渲染组件 |
|-------------|----------------|---------|
| string | 有 | `<el-select>` 下拉选择 |
| string | 无 | `<el-input>` 文本输入 |
| integer/number | 有 | `<el-select>` 下拉选择 |
| integer/number | 无 | `<el-input-number>` 数字输入 |
| boolean | - | `<el-switch>` 开关 |
| array | - | `<el-input>` 文本输入(逗号分隔) |
| object | - | 暂不支持,fallback 到文本输入 |
每个参数显示:
- **label**: 参数中文描述(description),无描述则显示参数名(name)
- **placeholder**: 示例值(example)或数据类型提示
- **必填标记**: required=1 时 label 旁显示红色星号
#### 4.2.3 请求体预填充(POST/PUT/PATCH
对于有请求体的接口,使用 JSON 编辑器(`<el-input type="textarea">`)但预填充完整结构:
**预填充算法:**
```
function generateJsonTemplate(schema):
if schema is null or empty object: return ""
result = {}
for each [key, prop] in schema.properties:
if prop.example exists and is not empty:
result[key] = parseExample(prop.example) // 尝试解析为对应类型
else if prop.type == "string":
result[key] = ""
else if prop.type == "integer":
result[key] = 0
else if prop.type == "number":
result[key] = 0.0
else if prop.type == "boolean":
result[key] = false
else if prop.type == "array":
result[key] = []
else if prop.type == "object" and prop.properties:
result[key] = generateJsonTemplate(prop) // 递归
else:
result[key] = null
// 对 required 字段但没有 example 的,保留空值占位
// 对非 required 且无 example 的可选字段,省略该 key
for each key in result:
if key not in schema.required and result[key] in [null, "", 0, false, []]:
delete result[key]
return JSON.stringify(result, null, 2)
```
**数据来源优先级:**
1. 先从 `detail.params` 中找 `paramType === 'body'` 的参数,用其 description/example 填充
2. 如果没有 body 类型参数,从 `detail.requestSchema` 解析 JSON Schema 生成
**UI 展示:**
```
请求体 (JSON)
──────────────────────────────────────────┐
│ { │
│ "phone": "13800138000", │
│ "smsCode": "123456" │
│ } │
└──────────────────────────────────────────┘
💡 参数结构已预填充,修改值后点击"发送请求"即可
```
#### 4.2.4 请求头展示
在参数配置区域下方展示自动添加的请求头(只读):
```
请求头
┌──────────────────────────────────────────┐
│ Authorization: Bearer eyJhbGci...xxx │
│ Content-Type: application/json │
└──────────────────────────────────────────┘
```
- `Authorization`: 根据 tokenSource 自动设置
- `Content-Type`: POST/PUT/PATCH 且有请求体时自动添加
#### 4.2.5 路径处理
测试代理接口要求路径以 `/api` 开头(SSRF 防护)。前端发送测试请求时,自动在 endpoint path 前拼接 `/api`
```typescript
path: '/api' + testForm.value.path // 例如 /api + /auth/login = /api/auth/login
```
### 4.3 边缘情况处理
| 场景 | 处理方式 |
|------|---------|
| `requestSchema``{}``null` | 请求体显示空 textareaplaceholder: "此接口无请求体参数" |
| `params` 数组为空 | 不显示参数表单区域,直接显示请求体或提示"此接口无需参数" |
| 测试请求返回非 200 状态 | 响应结果区域正常显示,status tag 标红,body 正常展示 |
| 网络错误/超时 | testResult.display 显示错误信息,status 显示 0 |
| JSON 预填充解析失败 | 回退到空字符串 `""` |
| 示例值是 JSON 字符串(如 `{"key":"value"}` | 尝试 JSON.parse,失败则作为字符串处理 |
### 4.4 文件改动清单
| 文件 | 改动内容 |
|------|---------|
| `web-admin/src/views/endpoint/EndpointList.vue` | 操作列加"测试"按钮,新增 `showTest` 方法 |
| `web-admin/src/views/endpoint/EndpointDetailDialog.vue` | 新增 `defaultTab` prop,测试面板改造:参数表单 + JSON 预填充 + 请求头展示 |
| `web-admin/src/api/endpoint.ts` | 类型定义无需修改(`operationId` 已存在) |
| `backend-single/src/main/java/com/emotion/controller/*.java` | 补全 @Tag/@Operation/@Parameter/@Schema 注解(按 4 个批次) |
| `backend-single/src/main/java/com/emotion/dto/request/**/*.java` | 补全 @Schema 注解(请求体参数描述来源) |
| `backend-single/src/main/java/com/emotion/dto/response/**/*.java` | 补全 @Schema 注解(响应体参数描述来源,可选) |
## 5. 实施顺序
1. **后端 Batch 1 注解补全** — Auth + Admin 相关 Controller 和 DTO
2. **触发同步 + 验证** — 确认中文描述正确展示
3. **前端操作列加"测试"按钮 + defaultTab** — 简单改动
4. **前端测试面板改造** — 参数表单 + JSON 预填充 + 请求头展示
5. **后端 Batch 2-4 注解补全** — 逐批完成剩余 Controller
6. **浏览器验证** — 打开接口管理页面,确认列表、详情、测试面板均正常
## 6. 验收标准
- [ ] 接口列表中,每个接口的"简述"列显示有意义的中文描述(非空、非英文路径名)
- [ ] 接口详情中,描述字段有中文说明
- [ ] 接口详情中,参数列表的"描述"列有中文说明
- [ ] 操作列有"测试"按钮,点击后打开弹窗并自动切换到测试标签
- [ ] 测试面板中,GET/DELETE 接口的查询参数以表单形式展示(input/select/switch 等),不是空白输入框
- [ ] 测试面板中,POST/PUT 接口的请求体预填充了完整的 JSON 结构(字段名 + 示例值),用户只需改值
- [ ] 请求头区域正确展示 Authorization 和 Content-Type
- [ ] 使用当前管理员 token 测试接口时,请求正常发出并返回结果
- [ ] 响应结果区域正确展示状态码、耗时和响应体
- [ ] 枚举值参数渲染为下拉选择框,非枚举值渲染为对应类型的输入框