test(cache): 修复CacheConfigTest边界值测试
- 修改 shouldVerifyCacheManager_withMaximumIntegerTtl 为 shouldVerifyCacheManager_withMaximumAllowedTtl - 使用正确的最大TTL值(10080分钟,7天)而不是 Integer.MAX_VALUE - 新增 shouldThrowException_whenTtlExceedsMaximum 测试验证边界检查 - 所有1266个测试用例通过 - 覆盖率: 指令81.89%, 行88.48%, 分支51.55% docs: 添加项目状态报告 - 生成 PROJECT_STATUS_REPORT.md 详细记录项目当前状态 - 包含质量指标、已完成功能、待办事项和技术债务
This commit is contained in:
296
docs/api.md
296
docs/api.md
@@ -2,6 +2,63 @@
|
||||
|
||||
本文档详细说明了活动管理和API密钥管理相关的API端点。
|
||||
|
||||
## 统一响应封装
|
||||
|
||||
除图片/HTML/CSV等非 JSON 响应外,所有接口返回 `ApiResponse`:
|
||||
|
||||
- 成功响应:
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 200,
|
||||
"message": "success",
|
||||
"data": {},
|
||||
"meta": {
|
||||
"pagination": {
|
||||
"page": 0,
|
||||
"size": 20,
|
||||
"total": 100,
|
||||
"totalPages": 5,
|
||||
"hasNext": true,
|
||||
"hasPrevious": false
|
||||
}
|
||||
},
|
||||
"timestamp": "2025-09-30T12:34:56",
|
||||
"traceId": "trace-id"
|
||||
}
|
||||
```
|
||||
|
||||
- 错误响应:
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 400,
|
||||
"message": "请求参数校验失败",
|
||||
"error": {
|
||||
"message": "activityId 不能为空",
|
||||
"details": { "activityId": "must not be null" },
|
||||
"code": "VALIDATION_ERROR"
|
||||
},
|
||||
"timestamp": "2025-09-30T12:34:56",
|
||||
"traceId": "trace-id"
|
||||
}
|
||||
```
|
||||
|
||||
## 认证与鉴权
|
||||
|
||||
- `/api/**` 需要 `X-API-Key`。
|
||||
- `/api/v1/me/**`、`/api/v1/activities/**`、`/api/v1/api-keys/**`、`/api/v1/share/**` 需要 `Authorization: Bearer <token>`。
|
||||
- `/r/**`、`/actuator/**` 不需要认证。
|
||||
|
||||
## 错误码
|
||||
|
||||
- `VALIDATION_ERROR` → 400:请求参数校验失败(字段缺失/格式不符)。
|
||||
- `BAD_REQUEST` → 400:业务数据不合法(如结束时间早于开始时间、上传文件不支持)。
|
||||
- `FORBIDDEN` → 403:无权访问资源或操作。
|
||||
- `NOT_FOUND` → 404:资源不存在(活动、API密钥等)。
|
||||
- `INTERNAL_ERROR` → 500:服务器内部错误。
|
||||
- `INVALID_API_KEY` → 401:提供的 API 密钥无效或已吊销。
|
||||
|
||||
## 1. 活动管理 (Activities)
|
||||
|
||||
### 1.1 创建活动
|
||||
@@ -22,11 +79,15 @@
|
||||
|
||||
```json
|
||||
{
|
||||
"id": 1,
|
||||
"name": "春季特惠活动",
|
||||
"startTime": "2025-03-01T10:00:00+08:00",
|
||||
"endTime": "2025-03-31T23:59:59+08:00",
|
||||
// ... 其他活动属性
|
||||
"code": 201,
|
||||
"message": "success",
|
||||
"data": {
|
||||
"id": 1,
|
||||
"name": "春季特惠活动",
|
||||
"startTime": "2025-03-01T10:00:00+08:00",
|
||||
"endTime": "2025-03-31T23:59:59+08:00"
|
||||
},
|
||||
"timestamp": "2025-03-01T10:00:00"
|
||||
}
|
||||
```
|
||||
|
||||
@@ -48,7 +109,7 @@
|
||||
}
|
||||
```
|
||||
|
||||
- **成功响应 (200 OK)**: 返回更新后的活动对象。
|
||||
- **成功响应 (200 OK)**: `ApiResponse<Activity>`,`data` 为更新后的活动对象。
|
||||
- **失败响应**:
|
||||
- `400 Bad Request`: 如果请求数据无效。
|
||||
- `404 Not Found`: 如果指定的 `id` 不存在。
|
||||
@@ -58,7 +119,7 @@
|
||||
- **Endpoint**: `GET /api/v1/activities/{id}`
|
||||
- **描述**: 获取指定ID的活动详情。
|
||||
- **路径参数**: `id` (long) - 活动的唯一标识符。
|
||||
- **成功响应 (200 OK)**: 返回活动对象。
|
||||
- **成功响应 (200 OK)**: `ApiResponse<Activity>`,`data` 为活动对象。
|
||||
- **失败响应**:
|
||||
- `404 Not Found`: 如果指定的 `id` 不存在。
|
||||
|
||||
@@ -81,7 +142,12 @@
|
||||
|
||||
```json
|
||||
{
|
||||
"apiKey": "a1b2c3d4-e5f6-7890-1234-567890abcdef"
|
||||
"code": 201,
|
||||
"message": "success",
|
||||
"data": {
|
||||
"apiKey": "a1b2c3d4-e5f6-7890-1234-567890abcdef"
|
||||
},
|
||||
"timestamp": "2025-03-01T10:00:00"
|
||||
}
|
||||
```
|
||||
|
||||
@@ -94,6 +160,218 @@
|
||||
- **Endpoint**: `DELETE /api/v1/api-keys/{id}`
|
||||
- **描述**: 吊销(删除)一个API密钥。
|
||||
- **路径参数**: `id` (long) - API密钥的唯一标识符。
|
||||
- **成功响应 (204 No Content)**: 无响应体。
|
||||
- **成功响应 (200 OK)**: `ApiResponse<Void>`,`data` 为 `null`。
|
||||
- **失败响应**:
|
||||
- `404 Not Found`: 如果指定的 `id` 不存在。
|
||||
|
||||
### 2.3 使用/校验 API 密钥
|
||||
|
||||
- Endpoint: `POST /api/v1/api-keys/{id}/use`
|
||||
- 描述: 校验提供的明文 API 密钥是否与 `id` 对应的密钥匹配;校验成功将更新 `last_used_at`。
|
||||
- 请求体: `application/json`
|
||||
|
||||
```json
|
||||
{
|
||||
"apiKey": "a1b2c3d4-e5f6-7890-1234-567890abcdef"
|
||||
}
|
||||
```
|
||||
|
||||
- 成功响应 (200 OK): `ApiResponse<Void>`,`data` 为 `null`。
|
||||
- 失败响应:
|
||||
- `401 Unauthorized` + `INVALID_API_KEY`:密钥错误或已吊销。
|
||||
- `404 Not Found`:`id` 不存在。
|
||||
|
||||
### 2.4 通过前缀校验 API 密钥(无需 ID)
|
||||
|
||||
- Endpoint: `POST /api/v1/api-keys/validate`
|
||||
- 描述: 仅凭明文 API 密钥进行校验(服务端使用前缀快速定位候选密钥,再进行哈希校验)。校验成功将更新 `last_used_at`。
|
||||
- 请求体: `application/json`
|
||||
|
||||
```json
|
||||
{
|
||||
"apiKey": "a1b2c3d4-e5f6-7890-1234-567890abcdef"
|
||||
}
|
||||
```
|
||||
|
||||
- 成功响应 (200 OK): `ApiResponse<Void>`,`data` 为 `null`。
|
||||
- 失败响应:
|
||||
- `401 Unauthorized` + `INVALID_API_KEY`:密钥错误或已吊销。
|
||||
|
||||
## 3. 缓存管理 (Cache)
|
||||
|
||||
### 3.1 清空某类缓存
|
||||
|
||||
- Endpoint: `DELETE /api/v1/cache/{cacheName}`
|
||||
- 描述: 清空指定缓存空间(如 `leaderboards`、`activities`、`activity_stats`、`activity_graph`)。
|
||||
- 成功响应 (204 No Content)
|
||||
|
||||
### 3.2 失效某个缓存键
|
||||
|
||||
- Endpoint: `DELETE /api/v1/cache/{cacheName}/{key}`
|
||||
- 描述: 失效指定缓存空间下的某个键。
|
||||
- 成功响应 (204 No Content)
|
||||
|
||||
## 4. 数据分析 (Analytics)
|
||||
|
||||
### 4.1 获取排行榜
|
||||
|
||||
- Endpoint: `GET /api/v1/activities/{id}/leaderboard`
|
||||
- 描述: 返回指定活动的排行榜(已启用缓存 `leaderboards`)。支持分页与 TopN。
|
||||
- 查询参数:
|
||||
- `topN` 可选:只取前 N 名(先截断再分页)。
|
||||
- `page` 可选,默认 `0`:页码(从 0 开始)。
|
||||
- `size` 可选,默认 `20`:每页条数。
|
||||
- 成功响应 (200 OK):
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 200,
|
||||
"message": "success",
|
||||
"data": [
|
||||
{ "userId": 1, "userName": "用户A", "score": 1500 },
|
||||
{ "userId": 2, "userName": "用户B", "score": 1200 }
|
||||
],
|
||||
"meta": {
|
||||
"pagination": {
|
||||
"page": 0,
|
||||
"size": 20,
|
||||
"total": 2,
|
||||
"totalPages": 1,
|
||||
"hasNext": false,
|
||||
"hasPrevious": false
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 4.2 导出排行榜CSV
|
||||
|
||||
- Endpoint: `GET /api/v1/activities/{id}/leaderboard/export`
|
||||
- 描述: 导出排行榜为CSV文件并下载。支持 `topN` 仅导出前 N 名。
|
||||
- 成功响应 (200 OK): 响应头 `Content-Type: text/csv;charset=UTF-8`,`Content-Disposition: attachment; filename="leaderboard_{id}.csv"`
|
||||
- CSV示例:
|
||||
|
||||
```csv
|
||||
userId,userName,score
|
||||
1,用户A,1500
|
||||
2,用户B,1200
|
||||
```
|
||||
|
||||
### 4.3 获取裂变网络图
|
||||
|
||||
- Endpoint: `GET /api/v1/activities/{id}/graph`
|
||||
- 描述: 返回指定活动的裂变网络图。支持以某个用户为根、限定层级与结果规模。
|
||||
- 查询参数:
|
||||
- `rootUserId` 可选:作为根节点的用户ID;为空则返回全量图(受 `limit` 限制)。
|
||||
- `maxDepth` 可选,默认 `3`:最大层级深度(从根出发,`1` 表示仅直推)。
|
||||
- `limit` 可选,默认 `1000`:返回的最大边数(超出将截断)。
|
||||
- 成功响应 (200 OK):
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 200,
|
||||
"message": "success",
|
||||
"data": {
|
||||
"nodes": [ { "id": "1", "label": "用户1" } ],
|
||||
"edges": [ { "from": "1", "to": "2" } ]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 4.4 获取仪表盘统计
|
||||
|
||||
- Endpoint: `GET /api/v1/activities/{id}/stats`
|
||||
- 描述: 汇总 `daily_activity_stats` 表的数据(已启用缓存 `activity_stats`)。`participants` 对应每日新增注册数聚合。
|
||||
- 成功响应 (200 OK):
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 200,
|
||||
"message": "success",
|
||||
"data": {
|
||||
"totalParticipants": 220,
|
||||
"totalShares": 110,
|
||||
"dailyStats": [
|
||||
{ "date": "2025-09-28", "participants": 100, "shares": 50 },
|
||||
{ "date": "2025-09-29", "participants": 120, "shares": 60 }
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 5. 短链接 (Short Links)
|
||||
|
||||
### 5.1 生成短链接(内部)
|
||||
|
||||
- Endpoint: `POST /api/v1/internal/shorten`
|
||||
- 描述: 生成短链接记录,仅供内部服务或管理端调用。
|
||||
- 请求体:
|
||||
|
||||
```json
|
||||
{ "originalUrl": "https://example.com/landing?ref=abc" }
|
||||
```
|
||||
|
||||
- 成功响应 (201 Created):
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 201,
|
||||
"message": "success",
|
||||
"data": { "code": "abc12345", "path": "/r/abc12345", "originalUrl": "https://example.com/landing?ref=abc" }
|
||||
}
|
||||
```
|
||||
|
||||
### 5.2 短链接重定向(公开)
|
||||
|
||||
- Endpoint: `GET /r/{code}`
|
||||
- 描述: 302 跳转到短链对应的原始地址。
|
||||
- 成功响应 (302 Found): 响应头 `Location: <originalUrl>`
|
||||
|
||||
## 6. 用户端体验 (User Experience)
|
||||
|
||||
### 6.1 获取用户专属邀请信息
|
||||
|
||||
- Endpoint: `GET /api/v1/me/invitation-info`
|
||||
- 描述: 返回当前用户的专属短链接(示例以 query 参数的 `activityId`/`userId` 代替鉴权)。
|
||||
- Query: `activityId`, `userId`
|
||||
- 成功响应 (200 OK):
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 200,
|
||||
"message": "success",
|
||||
"data": { "code": "inv12345", "path": "/r/inv12345", "originalUrl": "https://example.com/landing?activityId=1&inviter=2" }
|
||||
}
|
||||
```
|
||||
|
||||
### 6.2 获取邀请好友列表(分页)
|
||||
|
||||
- Endpoint: `GET /api/v1/me/invited-friends`
|
||||
- Query: `activityId`, `userId`, `page`(默认0), `size`(默认20)
|
||||
- 成功响应 (200 OK):
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 200,
|
||||
"message": "success",
|
||||
"data": [ { "nickname": "用户10", "maskedPhone": "138****0010", "status": "registered" } ],
|
||||
"meta": {
|
||||
"pagination": {
|
||||
"page": 0,
|
||||
"size": 20,
|
||||
"total": 1,
|
||||
"totalPages": 1,
|
||||
"hasNext": false,
|
||||
"hasPrevious": false
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 6.3 生成海报
|
||||
|
||||
- 图片:`GET /api/v1/me/poster/image`
|
||||
- HTML:`GET /api/v1/me/poster/html`
|
||||
- 配置:`GET /api/v1/me/poster/config`
|
||||
- Query: `activityId`, `userId`, `template`(`template` 可选)
|
||||
- 描述:图片/HTML 端点返回二进制或 HTML;配置端点返回 `ApiResponse<PosterConfigDto>`,`data` 包含 `template`、`imageUrl`、`htmlUrl`。
|
||||
|
||||
Reference in New Issue
Block a user