diff --git a/docs/API_DOCUMENTATION_SETUP.md b/docs/API_DOCUMENTATION_SETUP.md new file mode 100644 index 0000000..9fca69d --- /dev/null +++ b/docs/API_DOCUMENTATION_SETUP.md @@ -0,0 +1,198 @@ +# API 文档配置指南 + +## 概览 + +本项目使用 Swagger/OpenAPI 3.0 规范生成完整的 API 文档,支持在线测试和接口调试。 + +## 访问文档 + +启动项目后,可通过以下地址访问API文档: + +- **交互式文档**: http://localhost:3000/api/docs +- **JSON格式**: http://localhost:3000/api/docs-json +- **YAML格式**: http://localhost:3000/api/docs-yaml + +## 文档配置 + +### 1. 主配置文件 + +文件位置: `src/config/swagger.config.ts` + +包含以下配置: +- API基础信息(标题、描述、版本) +- JWT认证配置 +- 标签分类 +- 多环境服务器配置 +- UI自定义选项 + +### 2. DTO文档化 + +#### 通用响应格式 +- `src/dto/common-response.dto.ts` - 统一响应格式 +- `src/dto/error-response.dto.ts` - 错误响应格式 + +#### 模板系统DTO +- `src/dto/template.dto.ts` - 模板相关数据传输对象 + - `CreateTemplateDto` - 创建模板 + - `UpdateTemplateDto` - 更新模板 + - `TemplateExecuteDto` - 执行模板 + - `TemplateListDto` - 模板列表 + - `BatchExecuteDto` - 批量执行 + +#### 平台用户DTO +- `src/platform/dto/platform-login.dto.ts` - 平台登录相关 + +### 3. Controller文档化 + +#### 装饰器使用 +```typescript +@ApiTags('功能模块') // 分组标签 +@ApiOperation({ summary: '接口摘要', description: '详细描述' }) +@ApiResponse({ status: 200, description: '成功', type: ResponseDto }) +@ApiParam({ name: 'id', description: '参数描述' }) +@ApiQuery({ name: 'filter', required: false }) +@ApiBody({ type: RequestDto }) +@ApiBearerAuth('JWT-auth') // JWT认证 +``` + +#### 通用装饰器 +- `src/decorators/api-common-responses.decorator.ts` + - `@ApiCommonResponses()` - 通用错误响应 + - `@ApiAuthResponses()` - 认证相关错误 + +## 支持的功能模块 + +### 1. 用户管理 (`用户管理`) +- 多平台统一登录 +- 用户信息获取与更新 +- 平台账号绑定/解绑 +- 支持的平台列表查询 + +### 2. AI模板系统 (`AI模板系统`) +- 模板列表查询(支持类型筛选) +- 模板详情获取 +- 模板执行(单个/批量) +- 模板推荐 +- 模板管理(创建/更新/删除) + +### 3. 平台适配 (`平台适配`) +- 各平台特定接口 +- 数据同步功能 + +### 4. 积分系统 (`积分系统`) +- 积分获取、消耗、查询管理 + +### 5. 扩展服务 (`扩展服务`) +- 预留的扩展功能接口 + +## API 规范 + +### 统一响应格式 + +```json +{ + "code": 200, + "message": "success", + "data": {}, + "timestamp": 1703001000000, + "traceId": "trace-uuid" +} +``` + +### 错误码规范 + +- **1000-1999**: 系统级错误 +- **2000-2999**: 业务级错误 +- **3000-3999**: 平台特定错误 +- **4000-4999**: 客户端错误 +- **5000-5999**: 服务端错误 + +### 认证方式 + +使用 JWT Bearer Token 进行接口认证: + +```bash +Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9... +``` + +## 开发指南 + +### 1. 添加新接口文档 + +1. **创建DTO类**: +```typescript +export class NewFeatureDto { + @ApiProperty({ description: '字段描述', example: '示例值' }) + @IsString() + field: string; +} +``` + +2. **Controller添加装饰器**: +```typescript +@ApiTags('功能模块') +@ApiCommonResponses() +export class NewController { + @Post() + @ApiOperation({ summary: '接口摘要', description: '详细描述' }) + @ApiBody({ type: NewFeatureDto }) + @ApiResponse({ status: 200, description: '成功' }) + async newEndpoint() {} +} +``` + +### 2. 生成静态文档 + +```bash +# 生成 Swagger JSON 文档 +npm run docs:generate + +# 启动文档服务 +npm run docs:serve +``` + +### 3. 文档验证 + +启动项目后访问 http://localhost:3000/api/docs 验证: +- 接口分组是否正确 +- 参数描述是否完整 +- 响应格式是否标准 +- 认证配置是否生效 + +## 部署注意事项 + +### 生产环境配置 + +生产环境默认禁用 Swagger 文档,确保安全性: + +```typescript +// 仅在非生产环境启用 Swagger +if (process.env.NODE_ENV !== 'production') { + setupSwagger(app); +} +``` + +### 自定义域名配置 + +需要在 `swagger.config.ts` 中更新服务器配置: + +```typescript +.addServer('https://your-domain.com', '生产环境') +``` + +## 维护指南 + +### 1. 定期更新 +- 新增接口后及时添加文档 +- 保持DTO和实际接口同步 +- 更新示例数据和错误信息 + +### 2. 版本管理 +- API版本变更时更新文档版本号 +- 重要变更添加changelog说明 +- 保持向后兼容性文档说明 + +### 3. 团队协作 +- 代码审查包含文档完整性检查 +- 新团队成员参考文档快速上手 +- 前端开发基于文档进行接口对接 \ No newline at end of file diff --git a/docs/api-spec.json b/docs/api-spec.json new file mode 100644 index 0000000..7d6c640 --- /dev/null +++ b/docs/api-spec.json @@ -0,0 +1,1972 @@ +{ + "openapi": "3.0.0", + "paths": { + "/api/v1/templates": { + "get": { + "operationId": "AppController_getTemplates", + "parameters": [], + "responses": { + "200": { + "description": "" + } + }, + "tags": [ + "App" + ] + }, + "post": { + "operationId": "AppController_executeTemplate", + "parameters": [], + "responses": { + "201": { + "description": "" + } + }, + "tags": [ + "App" + ] + } + }, + "/api/v1/templates/{templateCode}": { + "get": { + "operationId": "AppController_getTemplate", + "parameters": [ + { + "name": "templateCode", + "required": true, + "in": "path", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "" + } + }, + "tags": [ + "App" + ] + } + }, + "/api/v1/templates/callback": { + "post": { + "operationId": "AppController_callback", + "parameters": [], + "responses": { + "201": { + "description": "" + } + }, + "tags": [ + "App" + ] + } + }, + "/templates/{templateId}/execute": { + "post": { + "description": "根据模板ID执行AI生成任务,支持图片和视频生成", + "operationId": "TemplateController_executeTemplateById", + "parameters": [ + { + "name": "templateId", + "required": true, + "in": "path", + "description": "模板ID", + "schema": { + "example": 1, + "type": "number" + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TemplateExecuteDto" + } + } + } + }, + "responses": { + "200": { + "description": "执行成功", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TemplateExecuteResponseDto" + } + } + } + }, + "400": { + "description": "参数错误", + "content": { + "application/json": { + "schema": { + "example": { + "code": 400, + "message": "imageUrl is required", + "data": null + } + } + } + } + }, + "401": { + "description": "未授权访问", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponseDto" + } + } + } + }, + "500": { + "description": "服务器内部错误", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponseDto" + } + } + } + } + }, + "summary": "执行模板生成", + "tags": [ + "AI模板系统" + ] + } + }, + "/templates/code/{code}/execute": { + "post": { + "description": "根据模板代码执行AI生成任务,支持图片和视频生成", + "operationId": "TemplateController_executeTemplateByCode", + "parameters": [ + { + "name": "code", + "required": true, + "in": "path", + "description": "模板代码", + "schema": { + "example": "character_figurine_v1", + "type": "string" + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TemplateExecuteDto" + } + } + } + }, + "responses": { + "200": { + "description": "执行成功", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TemplateExecuteResponseDto" + } + } + } + }, + "400": { + "description": "请求参数错误", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponseDto" + } + } + } + }, + "401": { + "description": "未授权访问", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponseDto" + } + } + } + }, + "500": { + "description": "服务器内部错误", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponseDto" + } + } + } + } + }, + "summary": "通过代码执行模板", + "tags": [ + "AI模板系统" + ] + } + }, + "/templates/{templateId}/batch-execute": { + "post": { + "description": "批量执行模板生成任务,支持多张图片同时处理", + "operationId": "TemplateController_batchExecuteTemplate", + "parameters": [ + { + "name": "templateId", + "required": true, + "in": "path", + "description": "模板ID", + "schema": { + "example": 1, + "type": "number" + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BatchExecuteDto" + } + } + } + }, + "responses": { + "200": { + "description": "批量执行成功", + "content": { + "application/json": { + "schema": { + "example": { + "success": true, + "data": { + "templateId": 1, + "totalCount": 2, + "results": [ + { + "inputUrl": "image1.jpg", + "outputUrl": "output1.jpg" + }, + { + "inputUrl": "image2.jpg", + "outputUrl": "output2.jpg" + } + ] + } + } + } + } + } + }, + "400": { + "description": "请求参数错误", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponseDto" + } + } + } + }, + "401": { + "description": "未授权访问", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponseDto" + } + } + } + }, + "500": { + "description": "服务器内部错误", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponseDto" + } + } + } + } + }, + "summary": "批量执行模板", + "tags": [ + "AI模板系统" + ] + } + }, + "/templates": { + "get": { + "description": "获取所有可用的AI生成模板,支持按类型筛选", + "operationId": "TemplateController_getAllTemplates", + "parameters": [], + "responses": { + "200": { + "description": "获取成功", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/TemplateListDto" + } + } + } + } + }, + "400": { + "description": "请求参数错误", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponseDto" + } + } + } + }, + "401": { + "description": "未授权访问", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponseDto" + } + } + } + }, + "500": { + "description": "服务器内部错误", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponseDto" + } + } + } + } + }, + "summary": "获取所有模板列表", + "tags": [ + "AI模板系统" + ] + }, + "post": { + "description": "创建一个新的AI生成模板", + "operationId": "TemplateController_createTemplate", + "parameters": [], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateTemplateDto" + } + } + } + }, + "responses": { + "200": { + "description": "创建成功", + "content": { + "application/json": { + "schema": { + "example": { + "success": true, + "data": { + "id": 1, + "code": "new_template_v1", + "name": "新模板" + } + } + } + } + } + }, + "400": { + "description": "请求参数错误", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponseDto" + } + } + } + }, + "401": { + "description": "未授权访问", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponseDto" + } + } + } + }, + "409": { + "description": "模板代码已存在" + }, + "500": { + "description": "服务器内部错误", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponseDto" + } + } + } + } + }, + "summary": "创建新模板", + "tags": [ + "AI模板系统" + ] + } + }, + "/templates/image": { + "get": { + "description": "获取所有图片类型的AI生成模板", + "operationId": "TemplateController_getImageTemplates", + "parameters": [], + "responses": { + "200": { + "description": "获取成功", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/TemplateListDto" + } + } + } + } + }, + "400": { + "description": "请求参数错误", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponseDto" + } + } + } + }, + "401": { + "description": "未授权访问", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponseDto" + } + } + } + }, + "500": { + "description": "服务器内部错误", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponseDto" + } + } + } + } + }, + "summary": "获取图片模板列表", + "tags": [ + "AI模板系统" + ] + } + }, + "/templates/video": { + "get": { + "description": "获取所有视频类型的AI生成模板", + "operationId": "TemplateController_getVideoTemplates", + "parameters": [], + "responses": { + "200": { + "description": "获取成功", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/TemplateListDto" + } + } + } + } + }, + "400": { + "description": "请求参数错误", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponseDto" + } + } + } + }, + "401": { + "description": "未授权访问", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponseDto" + } + } + } + }, + "500": { + "description": "服务器内部错误", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponseDto" + } + } + } + } + }, + "summary": "获取视频模板列表", + "tags": [ + "AI模板系统" + ] + } + }, + "/templates/recommend": { + "get": { + "description": "根据用户偏好标签推荐适合的模板", + "operationId": "TemplateController_recommendTemplates", + "parameters": [ + { + "name": "tags", + "required": false, + "in": "query", + "description": "用户偏好标签,逗号分隔", + "schema": { + "example": "人物,手办", + "type": "string" + } + }, + { + "name": "limit", + "required": false, + "in": "query", + "description": "推荐数量", + "schema": { + "example": 5, + "type": "number" + } + } + ], + "responses": { + "200": { + "description": "推荐成功", + "content": { + "application/json": { + "schema": { + "example": { + "success": true, + "data": { + "userTags": [ + "人物", + "手办" + ], + "recommendedTemplates": [] + } + } + } + } + } + }, + "400": { + "description": "请求参数错误", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponseDto" + } + } + } + }, + "401": { + "description": "未授权访问", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponseDto" + } + } + } + }, + "500": { + "description": "服务器内部错误", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponseDto" + } + } + } + } + }, + "summary": "推荐模板", + "tags": [ + "AI模板系统" + ] + } + }, + "/templates/{templateId}": { + "get": { + "description": "根据模板ID获取详细信息", + "operationId": "TemplateController_getTemplateById", + "parameters": [ + { + "name": "templateId", + "required": true, + "in": "path", + "description": "模板ID", + "schema": { + "example": 1, + "type": "number" + } + } + ], + "responses": { + "200": { + "description": "获取成功", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TemplateListDto" + } + } + } + }, + "400": { + "description": "请求参数错误", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponseDto" + } + } + } + }, + "401": { + "description": "未授权访问", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponseDto" + } + } + } + }, + "404": { + "description": "模板不存在" + }, + "500": { + "description": "服务器内部错误", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponseDto" + } + } + } + } + }, + "summary": "获取模板详情", + "tags": [ + "AI模板系统" + ] + }, + "put": { + "description": "更新指定模板的配置信息", + "operationId": "TemplateController_updateTemplate", + "parameters": [ + { + "name": "templateId", + "required": true, + "in": "path", + "description": "模板ID", + "schema": { + "example": 1, + "type": "number" + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UpdateTemplateDto" + } + } + } + }, + "responses": { + "200": { + "description": "更新成功", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TemplateListDto" + } + } + } + }, + "400": { + "description": "请求参数错误", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponseDto" + } + } + } + }, + "401": { + "description": "未授权访问", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponseDto" + } + } + } + }, + "404": { + "description": "模板不存在" + }, + "409": { + "description": "模板代码已存在" + }, + "500": { + "description": "服务器内部错误", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponseDto" + } + } + } + } + }, + "summary": "更新模板", + "tags": [ + "AI模板系统" + ] + }, + "delete": { + "operationId": "TemplateController_deleteTemplate", + "parameters": [ + { + "name": "templateId", + "required": true, + "in": "path", + "schema": { + "type": "number" + } + } + ], + "responses": { + "200": { + "description": "" + }, + "400": { + "description": "请求参数错误", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponseDto" + } + } + } + }, + "401": { + "description": "未授权访问", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponseDto" + } + } + } + }, + "500": { + "description": "服务器内部错误", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponseDto" + } + } + } + } + }, + "tags": [ + "AI模板系统" + ] + } + }, + "/templates/execution/{taskId}/progress": { + "get": { + "operationId": "TemplateController_getExecutionProgress", + "parameters": [ + { + "name": "taskId", + "required": true, + "in": "path", + "schema": { + "type": "number" + } + } + ], + "responses": { + "200": { + "description": "" + }, + "400": { + "description": "请求参数错误", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponseDto" + } + } + } + }, + "401": { + "description": "未授权访问", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponseDto" + } + } + } + }, + "500": { + "description": "服务器内部错误", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponseDto" + } + } + } + } + }, + "tags": [ + "AI模板系统" + ] + } + }, + "/templates/executions/user/{userId}": { + "get": { + "operationId": "TemplateController_getUserExecutions", + "parameters": [ + { + "name": "userId", + "required": true, + "in": "path", + "schema": { + "type": "string" + } + }, + { + "name": "status", + "required": true, + "in": "query", + "schema": { + "type": "string" + } + }, + { + "name": "limit", + "required": true, + "in": "query", + "schema": { + "type": "number" + } + } + ], + "responses": { + "200": { + "description": "" + }, + "400": { + "description": "请求参数错误", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponseDto" + } + } + } + }, + "401": { + "description": "未授权访问", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponseDto" + } + } + } + }, + "500": { + "description": "服务器内部错误", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponseDto" + } + } + } + } + }, + "tags": [ + "AI模板系统" + ] + } + }, + "/templates/admin/{templateId}": { + "get": { + "operationId": "TemplateController_getTemplateForAdmin", + "parameters": [ + { + "name": "templateId", + "required": true, + "in": "path", + "schema": { + "type": "number" + } + } + ], + "responses": { + "200": { + "description": "" + }, + "400": { + "description": "请求参数错误", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponseDto" + } + } + } + }, + "401": { + "description": "未授权访问", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponseDto" + } + } + } + }, + "500": { + "description": "服务器内部错误", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponseDto" + } + } + } + } + }, + "tags": [ + "AI模板系统" + ] + } + }, + "/templates/admin": { + "get": { + "operationId": "TemplateController_getAllTemplatesForAdmin", + "parameters": [ + { + "name": "page", + "required": true, + "in": "query", + "schema": { + "type": "number" + } + }, + { + "name": "limit", + "required": true, + "in": "query", + "schema": { + "type": "number" + } + }, + { + "name": "type", + "required": true, + "in": "query", + "schema": { + "type": "string" + } + }, + { + "name": "isActive", + "required": true, + "in": "query", + "schema": { + "type": "boolean" + } + } + ], + "responses": { + "200": { + "description": "" + }, + "400": { + "description": "请求参数错误", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponseDto" + } + } + } + }, + "401": { + "description": "未授权访问", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponseDto" + } + } + } + }, + "500": { + "description": "服务器内部错误", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponseDto" + } + } + } + } + }, + "tags": [ + "AI模板系统" + ] + } + }, + "/users/login": { + "post": { + "description": "支持微信、支付宝、百度、字节跳动等8大平台的统一登录接口", + "operationId": "UnifiedUserController_login", + "parameters": [], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PlatformLoginDto" + } + } + } + }, + "responses": { + "200": { + "description": "登录成功", + "content": { + "application/json": { + "schema": { + "example": { + "code": 200, + "message": "登录成功", + "data": { + "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...", + "refreshToken": "refresh_token_string", + "userInfo": { + "id": "user-uuid", + "nickname": "用户昵称", + "avatarUrl": "https://example.com/avatar.jpg" + } + } + } + } + } + } + }, + "400": { + "description": "请求参数错误" + }, + "401": { + "description": "平台授权失败" + } + }, + "summary": "多平台统一登录", + "tags": [ + "用户管理" + ] + } + }, + "/users/register": { + "post": { + "description": "支持多平台用户注册,自动创建统一用户身份", + "operationId": "UnifiedUserController_register", + "parameters": [], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PlatformLoginDto" + } + } + } + }, + "responses": { + "200": { + "description": "注册成功", + "content": { + "application/json": { + "schema": { + "example": { + "code": 200, + "message": "注册成功", + "data": { + "userId": "user-uuid", + "unifiedUserId": "unified-user-123" + } + } + } + } + } + } + }, + "summary": "多平台统一注册", + "tags": [ + "用户管理" + ] + } + }, + "/users/profile": { + "get": { + "description": "获取当前登录用户的详细信息和平台绑定状态", + "operationId": "UnifiedUserController_getProfile", + "parameters": [], + "responses": { + "200": { + "description": "获取成功", + "content": { + "application/json": { + "schema": { + "example": { + "code": 200, + "message": "获取成功", + "data": { + "id": "user-uuid", + "unifiedUserId": "unified-user-123", + "nickname": "用户昵称", + "avatarUrl": "https://example.com/avatar.jpg", + "phone": "13800138000", + "email": "user@example.com", + "platformUsers": [] + } + } + } + } + } + }, + "401": { + "description": "未授权访问" + } + }, + "security": [ + { + "JWT-auth": [] + } + ], + "summary": "获取用户档案", + "tags": [ + "用户管理" + ] + }, + "put": { + "description": "更新当前用户的基本信息(昵称、头像等)", + "operationId": "UnifiedUserController_updateProfile", + "parameters": [], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UserInfoUpdateDto" + } + } + } + }, + "responses": { + "200": { + "description": "更新成功", + "content": { + "application/json": { + "schema": { + "example": { + "code": 200, + "message": "更新成功" + } + } + } + } + }, + "401": { + "description": "未授权访问" + } + }, + "security": [ + { + "JWT-auth": [] + } + ], + "summary": "更新用户信息", + "tags": [ + "用户管理" + ] + } + }, + "/users/bind-platform": { + "post": { + "description": "将其他平台账号绑定到当前统一用户身份", + "operationId": "UnifiedUserController_bindPlatform", + "parameters": [], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PlatformBindDto" + } + } + } + }, + "responses": { + "200": { + "description": "绑定成功", + "content": { + "application/json": { + "schema": { + "example": { + "code": 200, + "message": "绑定成功" + } + } + } + } + }, + "401": { + "description": "未授权访问" + }, + "409": { + "description": "平台账号已绑定其他用户" + } + }, + "security": [ + { + "JWT-auth": [] + } + ], + "summary": "绑定平台账号", + "tags": [ + "用户管理" + ] + } + }, + "/users/unbind-platform/{platform}": { + "delete": { + "description": "解除指定平台账号与当前用户的绑定关系", + "operationId": "UnifiedUserController_unbindPlatform", + "parameters": [ + { + "name": "platform", + "required": true, + "in": "path", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "解绑成功", + "content": { + "application/json": { + "schema": { + "example": { + "code": 200, + "message": "解绑成功" + } + } + } + } + }, + "401": { + "description": "未授权访问" + }, + "404": { + "description": "平台绑定不存在" + } + }, + "security": [ + { + "JWT-auth": [] + } + ], + "summary": "解绑平台账号", + "tags": [ + "用户管理" + ] + } + }, + "/users/platforms": { + "get": { + "description": "获取系统支持的所有平台类型和相关信息", + "operationId": "UnifiedUserController_getSupportedPlatforms", + "parameters": [], + "responses": { + "200": { + "description": "获取成功", + "content": { + "application/json": { + "schema": { + "example": { + "code": 200, + "message": "获取成功", + "data": [ + { + "type": "wechat", + "name": "微信小程序", + "supported": true + }, + { + "type": "alipay", + "name": "支付宝小程序", + "supported": true + } + ] + } + } + } + } + } + }, + "summary": "获取支持的平台列表", + "tags": [ + "用户管理" + ] + } + } + }, + "info": { + "title": "多平台小程序统一后台API", + "description": "支持微信、支付宝、百度、字节跳动等多平台的统一后台服务", + "version": "1.0.0", + "contact": {} + }, + "tags": [ + { + "name": "用户管理", + "description": "用户注册、登录、信息管理" + }, + { + "name": "平台适配", + "description": "各平台特定接口和数据同步" + }, + { + "name": "AI模板系统", + "description": "AI图片/视频生成模板管理" + }, + { + "name": "积分系统", + "description": "积分获取、消耗、查询管理" + }, + { + "name": "扩展服务", + "description": "预留的扩展功能接口" + } + ], + "servers": [], + "components": { + "securitySchemes": { + "JWT-auth": { + "scheme": "bearer", + "bearerFormat": "JWT", + "type": "http", + "name": "JWT", + "description": "Enter JWT token", + "in": "header" + } + }, + "schemas": { + "ErrorResponseDto": { + "type": "object", + "properties": { + "code": { + "type": "number", + "description": "错误状态码", + "example": 400 + }, + "message": { + "type": "string", + "description": "错误消息", + "example": "请求参数错误" + }, + "timestamp": { + "type": "number", + "description": "时间戳", + "example": 1703001000000 + }, + "traceId": { + "type": "string", + "description": "追踪ID", + "example": "trace-uuid-123" + }, + "details": { + "description": "详细错误信息", + "example": [ + "字段验证失败" + ], + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "code", + "message", + "timestamp", + "traceId" + ] + }, + "TemplateExecuteDto": { + "type": "object", + "properties": { + "imageUrl": { + "type": "string", + "description": "输入图片URL", + "example": "https://cdn.example.com/upload/image.jpg" + } + }, + "required": [ + "imageUrl" + ] + }, + "TemplateExecuteResponseDto": { + "type": "object", + "properties": { + "success": { + "type": "boolean", + "description": "执行状态", + "example": true + }, + "imageUrl": { + "type": "string", + "description": "生成结果URL(图片模板)" + }, + "videoUrl": { + "type": "string", + "description": "生成结果URL(视频模板)" + }, + "thumbnailUrl": { + "type": "string", + "description": "缩略图URL" + }, + "taskId": { + "type": "string", + "description": "任务ID", + "example": "req_1704067200_abc123" + }, + "executionTime": { + "type": "number", + "description": "执行耗时(毫秒)", + "example": 5000 + }, + "creditCost": { + "type": "number", + "description": "消耗积分", + "example": 28 + } + }, + "required": [ + "success", + "taskId", + "executionTime", + "creditCost" + ] + }, + "BatchExecuteDto": { + "type": "object", + "properties": { + "imageUrls": { + "description": "输入图片URL数组", + "example": [ + "https://cdn.example.com/upload/image1.jpg", + "https://cdn.example.com/upload/image2.jpg" + ], + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "imageUrls" + ] + }, + "TemplateListDto": { + "type": "object", + "properties": { + "id": { + "type": "number", + "description": "模板ID", + "example": 1 + }, + "code": { + "type": "string", + "description": "模板代码", + "example": "character_figurine_v1" + }, + "name": { + "type": "string", + "description": "模板名称", + "example": "人物手办" + }, + "description": { + "type": "string", + "description": "模板描述", + "example": "将人物照片制作成精细的角色手办模型" + }, + "templateType": { + "type": "string", + "enum": [ + "image", + "video" + ], + "description": "模板类型", + "example": "video" + }, + "creditCost": { + "type": "number", + "description": "积分消耗", + "example": 28 + }, + "version": { + "type": "string", + "description": "版本号", + "example": "1.0.0" + }, + "inputExampleUrl": { + "type": "string", + "description": "输入示例URL" + }, + "outputExampleUrl": { + "type": "string", + "description": "输出示例URL" + }, + "tags": { + "description": "标签数组", + "example": [ + "人物", + "手办", + "模型" + ], + "type": "array", + "items": { + "type": "string" + } + }, + "isActive": { + "type": "boolean", + "description": "是否启用", + "example": true + }, + "createdAt": { + "format": "date-time", + "type": "string", + "description": "创建时间", + "example": "2024-01-01T00:00:00Z" + } + }, + "required": [ + "id", + "code", + "name", + "description", + "templateType", + "creditCost", + "version", + "tags", + "isActive", + "createdAt" + ] + }, + "CreateTemplateDto": { + "type": "object", + "properties": { + "code": { + "type": "string", + "description": "模板代码", + "example": "character_figurine_v1" + }, + "name": { + "type": "string", + "description": "模板名称", + "example": "人物手办" + }, + "description": { + "type": "string", + "description": "模板描述", + "example": "将人物照片制作成精细的角色手办模型" + }, + "creditCost": { + "type": "number", + "description": "积分消耗", + "example": 28, + "minimum": 0 + }, + "version": { + "type": "string", + "description": "版本号", + "example": "1.0.0" + }, + "inputExampleUrl": { + "type": "string", + "description": "输入示例URL", + "example": "https://example.com/input.jpg" + }, + "outputExampleUrl": { + "type": "string", + "description": "输出示例URL", + "example": "https://example.com/output.jpg" + }, + "tags": { + "description": "标签数组", + "example": [ + "人物", + "手办", + "模型" + ], + "type": "array", + "items": { + "type": "string" + } + }, + "templateType": { + "type": "string", + "description": "模板类型", + "enum": [ + "image", + "video" + ], + "example": "image" + }, + "templateClass": { + "type": "string", + "description": "模板类名", + "example": "CharacterFigurineTemplate" + }, + "imageModel": { + "type": "string", + "description": "图片模型", + "example": "flux-dev" + }, + "imagePrompt": { + "type": "string", + "description": "图片提示词模板" + }, + "videoModel": { + "type": "string", + "description": "视频模型", + "example": "runway-gen3" + }, + "videoPrompt": { + "type": "string", + "description": "视频提示词模板" + }, + "duration": { + "type": "number", + "description": "视频时长(秒)", + "example": 10, + "minimum": 1, + "maximum": 300 + }, + "aspectRatio": { + "type": "string", + "description": "宽高比", + "example": "16:9" + }, + "isActive": { + "type": "boolean", + "description": "是否启用", + "example": true + }, + "sortOrder": { + "type": "number", + "description": "排序权重", + "example": 100 + } + }, + "required": [ + "code", + "name", + "description", + "creditCost", + "version", + "templateType", + "templateClass" + ] + }, + "UpdateTemplateDto": { + "type": "object", + "properties": { + "code": { + "type": "string", + "description": "模板代码", + "example": "character_figurine_v1" + }, + "name": { + "type": "string", + "description": "模板名称", + "example": "人物手办" + }, + "description": { + "type": "string", + "description": "模板描述", + "example": "将人物照片制作成精细的角色手办模型" + }, + "creditCost": { + "type": "number", + "description": "积分消耗", + "example": 28, + "minimum": 0 + }, + "version": { + "type": "string", + "description": "版本号", + "example": "1.0.1" + }, + "inputExampleUrl": { + "type": "string", + "description": "输入示例URL", + "example": "https://example.com/input.jpg" + }, + "outputExampleUrl": { + "type": "string", + "description": "输出示例URL", + "example": "https://example.com/output.jpg" + }, + "tags": { + "description": "标签数组", + "example": [ + "人物", + "手办", + "模型" + ], + "type": "array", + "items": { + "type": "string" + } + }, + "templateType": { + "type": "string", + "description": "模板类型", + "enum": [ + "image", + "video" + ] + }, + "templateClass": { + "type": "string", + "description": "模板类名", + "example": "CharacterFigurineTemplate" + }, + "imageModel": { + "type": "string", + "description": "图片模型", + "example": "flux-dev" + }, + "imagePrompt": { + "type": "string", + "description": "图片提示词模板" + }, + "videoModel": { + "type": "string", + "description": "视频模型", + "example": "runway-gen3" + }, + "videoPrompt": { + "type": "string", + "description": "视频提示词模板" + }, + "duration": { + "type": "number", + "description": "视频时长(秒)", + "example": 10, + "minimum": 1, + "maximum": 300 + }, + "aspectRatio": { + "type": "string", + "description": "宽高比", + "example": "16:9" + }, + "isActive": { + "type": "boolean", + "description": "是否启用", + "example": true + }, + "sortOrder": { + "type": "number", + "description": "排序权重", + "example": 100 + } + } + }, + "PlatformType": { + "type": "string", + "enum": [ + "wechat", + "alipay", + "baidu", + "bytedance", + "jd", + "qq", + "feishu", + "kuaishou", + "h5", + "rn" + ], + "description": "平台类型" + }, + "PlatformLoginDto": { + "type": "object", + "properties": { + "platform": { + "description": "平台类型", + "example": "wechat", + "allOf": [ + { + "$ref": "#/components/schemas/PlatformType" + } + ] + }, + "code": { + "type": "string", + "description": "平台授权码", + "example": "081234567890abcdef" + }, + "encryptedData": { + "type": "string", + "description": "加密用户数据(微信小程序)" + }, + "iv": { + "type": "string", + "description": "加密向量(微信小程序)" + }, + "userInfo": { + "type": "object", + "description": "用户基础信息" + }, + "anonymousCode": { + "type": "string", + "description": "匿名授权码(抖音小程序)" + } + }, + "required": [ + "platform", + "code" + ] + }, + "UserInfoUpdateDto": { + "type": "object", + "properties": { + "nickname": { + "type": "string", + "description": "用户昵称" + }, + "avatarUrl": { + "type": "string", + "description": "头像URL" + }, + "phone": { + "type": "string", + "description": "手机号码" + }, + "email": { + "type": "string", + "description": "电子邮箱" + } + } + }, + "PlatformBindDto": { + "type": "object", + "properties": { + "platform": { + "type": "string", + "description": "平台类型", + "enum": [ + "wechat", + "alipay", + "baidu", + "bytedance", + "jd", + "qq", + "feishu", + "kuaishou", + "h5", + "rn" + ] + }, + "code": { + "type": "string", + "description": "平台授权码" + }, + "encryptedData": { + "type": "string", + "description": "加密用户数据(微信小程序)" + }, + "iv": { + "type": "string", + "description": "加密向量(微信小程序)" + }, + "userInfo": { + "type": "object", + "description": "用户基础信息" + } + }, + "required": [ + "platform", + "code" + ] + } + } + } +} \ No newline at end of file diff --git a/package.json b/package.json index e811260..842808b 100644 --- a/package.json +++ b/package.json @@ -25,7 +25,9 @@ "migration:run": "npm run typeorm -- migration:run", "migration:revert": "npm run typeorm -- migration:revert", "schema:sync": "npm run typeorm -- schema:sync", - "schema:drop": "npm run typeorm -- schema:drop" + "schema:drop": "npm run typeorm -- schema:drop", + "docs:generate": "nest build && node dist/generate-swagger-json.js", + "docs:serve": "nest start --watch" }, "dependencies": { "@nestjs/axios": "^4.0.1", diff --git a/src/config/swagger.config.ts b/src/config/swagger.config.ts new file mode 100644 index 0000000..43b1951 --- /dev/null +++ b/src/config/swagger.config.ts @@ -0,0 +1,79 @@ +import { DocumentBuilder, SwaggerModule } from '@nestjs/swagger'; +import { INestApplication } from '@nestjs/common'; + +export function setupSwagger(app: INestApplication): void { + const config = new DocumentBuilder() + .setTitle('多平台小程序统一后台API') + .setDescription(` + ## 功能特性 + - 🔐 统一用户认证 (微信/支付宝/百度/字节跳动等) + - 🎨 AI模板系统 (图片/视频生成) + - 💰 积分系统 (积分获取、消耗、管理) + - 📱 多平台适配 (8大平台支持) + - 🧩 扩展数据存储 (灵活的JSON数据) + + ## 认证方式 + 使用JWT Bearer Token进行API认证 + + ## 响应格式 + 所有API响应都遵循统一格式: + \`\`\`json + { + "code": 200, + "message": "success", + "data": {}, + "timestamp": 1703001000000, + "traceId": "trace-uuid" + } + \`\`\` + `) + .setVersion('1.0.0') + .setContact('开发团队', 'https://example.com', 'dev@example.com') + .setLicense('MIT', 'https://opensource.org/licenses/MIT') + .addBearerAuth( + { + type: 'http', + scheme: 'bearer', + bearerFormat: 'JWT', + name: 'JWT', + description: 'Enter JWT token', + in: 'header', + }, + 'JWT-auth', + ) + .addTag('用户管理', '用户注册、登录、信息管理') + .addTag('平台适配', '各平台特定接口和数据同步') + .addTag('AI模板系统', 'AI图片/视频生成模板管理') + .addTag('积分系统', '积分获取、消耗、查询管理') + .addTag('扩展服务', '预留的扩展功能接口') + .addServer('http://localhost:3000', '开发环境') + .addServer('https://api-dev.example.com', '测试环境') + .addServer('https://api.example.com', '生产环境') + .build(); + + const document = SwaggerModule.createDocument(app as any, config, { + operationIdFactory: (controllerKey: string, methodKey: string) => methodKey, + }); + + console.log('🔧 Setting up Swagger documentation...'); + SwaggerModule.setup('docs', app as any, document, { + swaggerOptions: { + persistAuthorization: true, + tagsSorter: 'alpha', + operationsSorter: 'alpha', + docExpansion: 'none', + filter: true, + showRequestDuration: true, + }, + customSiteTitle: '多平台API文档', + customfavIcon: '/favicon.ico', + customJs: [ + 'https://cdnjs.cloudflare.com/ajax/libs/swagger-ui/4.15.5/swagger-ui-bundle.min.js', + 'https://cdnjs.cloudflare.com/ajax/libs/swagger-ui/4.15.5/swagger-ui-standalone-preset.min.js', + ], + customCssUrl: [ + 'https://cdnjs.cloudflare.com/ajax/libs/swagger-ui/4.15.5/swagger-ui.min.css', + ], + }); + console.log('✅ Swagger documentation setup completed at /api/docs'); +} \ No newline at end of file diff --git a/src/controllers/template.controller.ts b/src/controllers/template.controller.ts index 45edc66..3446d14 100644 --- a/src/controllers/template.controller.ts +++ b/src/controllers/template.controller.ts @@ -11,21 +11,35 @@ import { HttpException, HttpStatus, } from '@nestjs/common'; +import { + ApiTags, + ApiOperation, + ApiResponse, + ApiParam, + ApiQuery, + ApiBody, +} from '@nestjs/swagger'; import { N8nTemplateFactoryService } from '../services/n8n-template-factory.service'; import { N8nTemplateEntity, TemplateType, } from '../entities/n8n-template.entity'; -import { CreateTemplateDto, UpdateTemplateDto } from '../dto/template.dto'; +import { + CreateTemplateDto, + UpdateTemplateDto, + TemplateExecuteDto, + TemplateExecuteResponseDto, + TemplateListDto, + BatchExecuteDto, +} from '../dto/template.dto'; import { TemplateExecutionEntity } from '../entities/template-execution.entity'; import { InjectRepository } from '@nestjs/typeorm'; import { Repository } from 'typeorm'; +import { ApiCommonResponses } from '../decorators/api-common-responses.decorator'; -/** - * 模板控制器 - * 提供模板相关的API接口,支持混合式架构的动态模板管理 - */ +@ApiTags('AI模板系统') @Controller('templates') +@ApiCommonResponses() export class TemplateController { constructor( private readonly templateFactory: N8nTemplateFactoryService, @@ -35,13 +49,29 @@ export class TemplateController { private readonly executionRepository: Repository, ) {} - /** - * 执行模板 - 通过模板ID - * @param templateId 模板ID - * @param body 请求体,包含imageUrl - * @returns 执行结果 - */ @Post(':templateId/execute') + @ApiOperation({ + summary: '执行模板生成', + description: '根据模板ID执行AI生成任务,支持图片和视频生成', + }) + @ApiParam({ name: 'templateId', description: '模板ID', example: 1 }) + @ApiBody({ type: TemplateExecuteDto }) + @ApiResponse({ + status: 200, + description: '执行成功', + type: TemplateExecuteResponseDto, + }) + @ApiResponse({ + status: 400, + description: '参数错误', + schema: { + example: { + code: 400, + message: 'imageUrl is required', + data: null + } + } + }) async executeTemplateById( @Param('templateId', ParseIntPipe) templateId: number, @Body() body: { imageUrl: string }, @@ -76,13 +106,18 @@ export class TemplateController { } } - /** - * 执行模板 - 通过模板代码 - * @param code 模板代码 - * @param body 请求体,包含imageUrl - * @returns 执行结果 - */ @Post('code/:code/execute') + @ApiOperation({ + summary: '通过代码执行模板', + description: '根据模板代码执行AI生成任务,支持图片和视频生成', + }) + @ApiParam({ name: 'code', description: '模板代码', example: 'character_figurine_v1' }) + @ApiBody({ type: TemplateExecuteDto }) + @ApiResponse({ + status: 200, + description: '执行成功', + type: TemplateExecuteResponseDto, + }) async executeTemplateByCode( @Param('code') code: string, @Body() body: { imageUrl: string }, @@ -116,13 +151,30 @@ export class TemplateController { } } - /** - * 批量执行模板 - * @param templateId 模板ID - * @param body 包含多个imageUrl的数组 - * @returns 批量执行结果 - */ @Post(':templateId/batch-execute') + @ApiOperation({ + summary: '批量执行模板', + description: '批量执行模板生成任务,支持多张图片同时处理', + }) + @ApiParam({ name: 'templateId', description: '模板ID', example: 1 }) + @ApiBody({ type: BatchExecuteDto }) + @ApiResponse({ + status: 200, + description: '批量执行成功', + schema: { + example: { + success: true, + data: { + templateId: 1, + totalCount: 2, + results: [ + { inputUrl: 'image1.jpg', outputUrl: 'output1.jpg' }, + { inputUrl: 'image2.jpg', outputUrl: 'output2.jpg' } + ] + } + } + } + }) async batchExecuteTemplate( @Param('templateId', ParseIntPipe) templateId: number, @Body() body: { imageUrls: string[] }, @@ -161,11 +213,16 @@ export class TemplateController { } } - /** - * 获取所有模板列表 - * @returns 模板配置列表 - */ @Get() + @ApiOperation({ + summary: '获取所有模板列表', + description: '获取所有可用的AI生成模板,支持按类型筛选', + }) + @ApiResponse({ + status: 200, + description: '获取成功', + type: [TemplateListDto], + }) async getAllTemplates() { try { const templates = await this.templateFactory.getAllTemplates(); @@ -197,11 +254,16 @@ export class TemplateController { } } - /** - * 获取图片类型模板 - * @returns 图片模板列表 - */ @Get('image') + @ApiOperation({ + summary: '获取图片模板列表', + description: '获取所有图片类型的AI生成模板', + }) + @ApiResponse({ + status: 200, + description: '获取成功', + type: [TemplateListDto], + }) async getImageTemplates() { try { const templates = await this.templateFactory.getImageTemplates(); @@ -217,11 +279,16 @@ export class TemplateController { } } - /** - * 获取视频类型模板 - * @returns 视频模板列表 - */ @Get('video') + @ApiOperation({ + summary: '获取视频模板列表', + description: '获取所有视频类型的AI生成模板', + }) + @ApiResponse({ + status: 200, + description: '获取成功', + type: [TemplateListDto], + }) async getVideoTemplates() { try { const templates = await this.templateFactory.getVideoTemplates(); @@ -237,13 +304,26 @@ export class TemplateController { } } - /** - * 根据用户偏好推荐模板 - * @param tags 用户偏好标签,逗号分隔 - * @param limit 推荐数量 - * @returns 推荐模板列表 - */ @Get('recommend') + @ApiOperation({ + summary: '推荐模板', + description: '根据用户偏好标签推荐适合的模板', + }) + @ApiQuery({ name: 'tags', required: false, description: '用户偏好标签,逗号分隔', example: '人物,手办' }) + @ApiQuery({ name: 'limit', required: false, description: '推荐数量', example: 5 }) + @ApiResponse({ + status: 200, + description: '推荐成功', + schema: { + example: { + success: true, + data: { + userTags: ['人物', '手办'], + recommendedTemplates: [] + } + } + } + }) async recommendTemplates( @Query('tags') tags?: string, @Query('limit') limit: number = 5, @@ -270,12 +350,21 @@ export class TemplateController { } } - /** - * 获取特定模板详情 - * @param templateId 模板ID - * @returns 模板详细信息 - */ @Get(':templateId') + @ApiOperation({ + summary: '获取模板详情', + description: '根据模板ID获取详细信息', + }) + @ApiParam({ name: 'templateId', description: '模板ID', example: 1 }) + @ApiResponse({ + status: 200, + description: '获取成功', + type: TemplateListDto, + }) + @ApiResponse({ + status: 404, + description: '模板不存在', + }) async getTemplateById(@Param('templateId', ParseIntPipe) templateId: number) { try { const template = await this.templateFactory.createTemplate(templateId); @@ -411,12 +500,30 @@ export class TemplateController { } } - /** - * 创建新模板 - * @param createTemplateDto 创建模板的数据传输对象 - * @returns 创建的模板信息 - */ @Post() + @ApiOperation({ + summary: '创建新模板', + description: '创建一个新的AI生成模板', + }) + @ApiBody({ type: CreateTemplateDto }) + @ApiResponse({ + status: 200, + description: '创建成功', + schema: { + example: { + success: true, + data: { + id: 1, + code: 'new_template_v1', + name: '新模板' + } + } + } + }) + @ApiResponse({ + status: 409, + description: '模板代码已存在', + }) async createTemplate(@Body() createTemplateDto: CreateTemplateDto) { try { const existingTemplate = await this.templateRepository.findOne({ @@ -448,13 +555,26 @@ export class TemplateController { } } - /** - * 更新模板 - * @param templateId 模板ID - * @param updateTemplateDto 更新模板的数据传输对象 - * @returns 更新后的模板信息 - */ @Put(':templateId') + @ApiOperation({ + summary: '更新模板', + description: '更新指定模板的配置信息', + }) + @ApiParam({ name: 'templateId', description: '模板ID', example: 1 }) + @ApiBody({ type: UpdateTemplateDto }) + @ApiResponse({ + status: 200, + description: '更新成功', + type: TemplateListDto, + }) + @ApiResponse({ + status: 404, + description: '模板不存在', + }) + @ApiResponse({ + status: 409, + description: '模板代码已存在', + }) async updateTemplate( @Param('templateId', ParseIntPipe) templateId: number, @Body() updateTemplateDto: UpdateTemplateDto, diff --git a/src/decorators/api-common-responses.decorator.ts b/src/decorators/api-common-responses.decorator.ts new file mode 100644 index 0000000..1ca3d55 --- /dev/null +++ b/src/decorators/api-common-responses.decorator.ts @@ -0,0 +1,18 @@ +import { applyDecorators } from '@nestjs/common'; +import { ApiResponse } from '@nestjs/swagger'; +import { CommonErrorResponses } from '../dto/error-response.dto'; + +export function ApiCommonResponses() { + return applyDecorators( + ApiResponse(CommonErrorResponses.BadRequest), + ApiResponse(CommonErrorResponses.Unauthorized), + ApiResponse(CommonErrorResponses.InternalServerError), + ); +} + +export function ApiAuthResponses() { + return applyDecorators( + ApiResponse(CommonErrorResponses.Unauthorized), + ApiResponse(CommonErrorResponses.Forbidden), + ); +} \ No newline at end of file diff --git a/src/dto/common-response.dto.ts b/src/dto/common-response.dto.ts new file mode 100644 index 0000000..224f517 --- /dev/null +++ b/src/dto/common-response.dto.ts @@ -0,0 +1,43 @@ +import { ApiProperty, ApiHideProperty } from '@nestjs/swagger'; + +export class CommonResponseDto { + @ApiProperty({ description: '响应状态码', example: 200 }) + code: number; + + @ApiProperty({ description: '响应消息', example: 'success' }) + message: string; + + @ApiHideProperty() + data: any; + + @ApiProperty({ description: '时间戳', example: 1703001000000 }) + timestamp: number; + + @ApiProperty({ description: '追踪ID', example: 'trace-uuid-123' }) + traceId: string; +} + +export class PaginationDto { + @ApiProperty({ description: '页码', example: 1, minimum: 1 }) + page: number; + + @ApiProperty({ description: '每页数量', example: 10, minimum: 1, maximum: 100 }) + limit: number; +} + +export class PaginationResponseDto { + @ApiHideProperty() + items: any[]; + + @ApiProperty({ description: '总数量', example: 100 }) + total: number; + + @ApiProperty({ description: '当前页码', example: 1 }) + page: number; + + @ApiProperty({ description: '每页数量', example: 10 }) + limit: number; + + @ApiProperty({ description: '总页数', example: 10 }) + totalPages: number; +} \ No newline at end of file diff --git a/src/dto/error-response.dto.ts b/src/dto/error-response.dto.ts new file mode 100644 index 0000000..6c78654 --- /dev/null +++ b/src/dto/error-response.dto.ts @@ -0,0 +1,53 @@ +import { ApiProperty, ApiHideProperty } from '@nestjs/swagger'; + +export class ErrorResponseDto { + @ApiProperty({ description: '错误状态码', example: 400 }) + code: number; + + @ApiProperty({ description: '错误消息', example: '请求参数错误' }) + message: string; + + @ApiHideProperty() + data: null; + + @ApiProperty({ description: '时间戳', example: 1703001000000 }) + timestamp: number; + + @ApiProperty({ description: '追踪ID', example: 'trace-uuid-123' }) + traceId: string; + + @ApiProperty({ + description: '详细错误信息', + required: false, + example: ['字段验证失败'], + }) + details?: string[]; +} + +export const CommonErrorResponses = { + BadRequest: { + status: 400, + description: '请求参数错误', + type: ErrorResponseDto, + }, + Unauthorized: { + status: 401, + description: '未授权访问', + type: ErrorResponseDto, + }, + Forbidden: { + status: 403, + description: '禁止访问', + type: ErrorResponseDto, + }, + NotFound: { + status: 404, + description: '资源不存在', + type: ErrorResponseDto, + }, + InternalServerError: { + status: 500, + description: '服务器内部错误', + type: ErrorResponseDto, + }, +}; \ No newline at end of file diff --git a/src/dto/template.dto.ts b/src/dto/template.dto.ts index 5e7774a..d48d026 100644 --- a/src/dto/template.dto.ts +++ b/src/dto/template.dto.ts @@ -8,151 +8,267 @@ import { Min, Max, } from 'class-validator'; +import { ApiProperty } from '@nestjs/swagger'; import { TemplateType } from '../entities/n8n-template.entity'; export class CreateTemplateDto { + @ApiProperty({ description: '模板代码', example: 'character_figurine_v1' }) @IsString() code: string; + @ApiProperty({ description: '模板名称', example: '人物手办' }) @IsString() name: string; + @ApiProperty({ description: '模板描述', example: '将人物照片制作成精细的角色手办模型' }) @IsString() description: string; + @ApiProperty({ description: '积分消耗', example: 28, minimum: 0 }) @IsNumber() @Min(0) creditCost: number; + @ApiProperty({ description: '版本号', example: '1.0.0' }) @IsString() version: string; + @ApiProperty({ description: '输入示例URL', required: false, example: 'https://example.com/input.jpg' }) @IsString() @IsOptional() inputExampleUrl?: string; + @ApiProperty({ description: '输出示例URL', required: false, example: 'https://example.com/output.jpg' }) @IsString() @IsOptional() outputExampleUrl?: string; + @ApiProperty({ description: '标签数组', required: false, example: ['人物', '手办', '模型'] }) @IsArray() @IsOptional() tags?: string[]; + @ApiProperty({ description: '模板类型', enum: TemplateType, example: 'image' }) @IsEnum(TemplateType) templateType: TemplateType; + @ApiProperty({ description: '模板类名', example: 'CharacterFigurineTemplate' }) @IsString() templateClass: string; + @ApiProperty({ description: '图片模型', required: false, example: 'flux-dev' }) @IsString() @IsOptional() imageModel?: string; + @ApiProperty({ description: '图片提示词模板', required: false }) @IsString() @IsOptional() imagePrompt?: string; + @ApiProperty({ description: '视频模型', required: false, example: 'runway-gen3' }) @IsString() @IsOptional() videoModel?: string; + @ApiProperty({ description: '视频提示词模板', required: false }) @IsString() @IsOptional() videoPrompt?: string; + @ApiProperty({ description: '视频时长(秒)', required: false, example: 10, minimum: 1, maximum: 300 }) @IsNumber() @IsOptional() @Min(1) @Max(300) duration?: number; + @ApiProperty({ description: '宽高比', required: false, example: '16:9' }) @IsString() @IsOptional() aspectRatio?: string; + @ApiProperty({ description: '是否启用', required: false, example: true }) @IsBoolean() @IsOptional() isActive?: boolean; + @ApiProperty({ description: '排序权重', required: false, example: 100 }) @IsNumber() @IsOptional() sortOrder?: number; } export class UpdateTemplateDto { + @ApiProperty({ description: '模板代码', required: false, example: 'character_figurine_v1' }) @IsString() @IsOptional() code?: string; + @ApiProperty({ description: '模板名称', required: false, example: '人物手办' }) @IsString() @IsOptional() name?: string; + @ApiProperty({ description: '模板描述', required: false, example: '将人物照片制作成精细的角色手办模型' }) @IsString() @IsOptional() description?: string; + @ApiProperty({ description: '积分消耗', required: false, example: 28, minimum: 0 }) @IsNumber() @Min(0) @IsOptional() creditCost?: number; + @ApiProperty({ description: '版本号', required: false, example: '1.0.1' }) @IsString() @IsOptional() version?: string; + @ApiProperty({ description: '输入示例URL', required: false, example: 'https://example.com/input.jpg' }) @IsString() @IsOptional() inputExampleUrl?: string; + @ApiProperty({ description: '输出示例URL', required: false, example: 'https://example.com/output.jpg' }) @IsString() @IsOptional() outputExampleUrl?: string; + @ApiProperty({ description: '标签数组', required: false, example: ['人物', '手办', '模型'] }) @IsArray() @IsOptional() tags?: string[]; + @ApiProperty({ description: '模板类型', enum: TemplateType, required: false }) @IsEnum(TemplateType) @IsOptional() templateType?: TemplateType; + @ApiProperty({ description: '模板类名', required: false, example: 'CharacterFigurineTemplate' }) @IsString() @IsOptional() templateClass?: string; + @ApiProperty({ description: '图片模型', required: false, example: 'flux-dev' }) @IsString() @IsOptional() imageModel?: string; + @ApiProperty({ description: '图片提示词模板', required: false }) @IsString() @IsOptional() imagePrompt?: string; + @ApiProperty({ description: '视频模型', required: false, example: 'runway-gen3' }) @IsString() @IsOptional() videoModel?: string; + @ApiProperty({ description: '视频提示词模板', required: false }) @IsString() @IsOptional() videoPrompt?: string; + @ApiProperty({ description: '视频时长(秒)', required: false, example: 10, minimum: 1, maximum: 300 }) @IsNumber() @IsOptional() @Min(1) @Max(300) duration?: number; + @ApiProperty({ description: '宽高比', required: false, example: '16:9' }) @IsString() @IsOptional() aspectRatio?: string; + @ApiProperty({ description: '是否启用', required: false, example: true }) @IsBoolean() @IsOptional() isActive?: boolean; + @ApiProperty({ description: '排序权重', required: false, example: 100 }) @IsNumber() @IsOptional() sortOrder?: number; } + +export class TemplateExecuteDto { + @ApiProperty({ + description: '输入图片URL', + example: 'https://cdn.example.com/upload/image.jpg' + }) + @IsString() + imageUrl: string; +} + +export class TemplateExecuteResponseDto { + @ApiProperty({ description: '执行状态', example: true }) + success: boolean; + + @ApiProperty({ description: '生成结果URL(图片模板)', required: false }) + imageUrl?: string; + + @ApiProperty({ description: '生成结果URL(视频模板)', required: false }) + videoUrl?: string; + + @ApiProperty({ description: '缩略图URL', required: false }) + thumbnailUrl?: string; + + @ApiProperty({ description: '任务ID', example: 'req_1704067200_abc123' }) + taskId: string; + + @ApiProperty({ description: '执行耗时(毫秒)', example: 5000 }) + executionTime: number; + + @ApiProperty({ description: '消耗积分', example: 28 }) + creditCost: number; +} + +export class TemplateListDto { + @ApiProperty({ description: '模板ID', example: 1 }) + id: number; + + @ApiProperty({ description: '模板代码', example: 'character_figurine_v1' }) + code: string; + + @ApiProperty({ description: '模板名称', example: '人物手办' }) + name: string; + + @ApiProperty({ description: '模板描述', example: '将人物照片制作成精细的角色手办模型' }) + description: string; + + @ApiProperty({ enum: TemplateType, description: '模板类型', example: 'video' }) + templateType: TemplateType; + + @ApiProperty({ description: '积分消耗', example: 28 }) + creditCost: number; + + @ApiProperty({ description: '版本号', example: '1.0.0' }) + version: string; + + @ApiProperty({ description: '输入示例URL', required: false }) + inputExampleUrl?: string; + + @ApiProperty({ description: '输出示例URL', required: false }) + outputExampleUrl?: string; + + @ApiProperty({ type: [String], description: '标签数组', example: ['人物', '手办', '模型'] }) + tags: string[]; + + @ApiProperty({ description: '是否启用', example: true }) + isActive: boolean; + + @ApiProperty({ description: '创建时间', example: '2024-01-01T00:00:00Z' }) + createdAt: Date; +} + +export class BatchExecuteDto { + @ApiProperty({ + description: '输入图片URL数组', + example: ['https://cdn.example.com/upload/image1.jpg', 'https://cdn.example.com/upload/image2.jpg'] + }) + @IsArray() + imageUrls: string[]; +} diff --git a/src/generate-swagger-json.ts b/src/generate-swagger-json.ts new file mode 100644 index 0000000..e6e8083 --- /dev/null +++ b/src/generate-swagger-json.ts @@ -0,0 +1,43 @@ +import { NestFactory } from '@nestjs/core'; +import { SwaggerModule, DocumentBuilder } from '@nestjs/swagger'; +import { AppModule } from './app.module'; +import * as fs from 'fs'; + +async function generateSwaggerJson() { + const app = await NestFactory.create(AppModule, { logger: false }); + + const config = new DocumentBuilder() + .setTitle('多平台小程序统一后台API') + .setDescription('支持微信、支付宝、百度、字节跳动等多平台的统一后台服务') + .setVersion('1.0.0') + .addBearerAuth( + { + type: 'http', + scheme: 'bearer', + bearerFormat: 'JWT', + name: 'JWT', + description: 'Enter JWT token', + in: 'header', + }, + 'JWT-auth', + ) + .addTag('用户管理', '用户注册、登录、信息管理') + .addTag('平台适配', '各平台特定接口和数据同步') + .addTag('AI模板系统', 'AI图片/视频生成模板管理') + .addTag('积分系统', '积分获取、消耗、查询管理') + .addTag('扩展服务', '预留的扩展功能接口') + .build(); + + const document = SwaggerModule.createDocument(app as any, config); + + fs.writeFileSync('./swagger.json', JSON.stringify(document, null, 2)); + fs.writeFileSync('./docs/api-spec.json', JSON.stringify(document, null, 2)); + + console.log('Swagger JSON文档已生成:'); + console.log('- ./swagger.json'); + console.log('- ./docs/api-spec.json'); + + await app.close(); +} + +generateSwaggerJson().catch(console.error); \ No newline at end of file diff --git a/src/main.ts b/src/main.ts index 4583331..dd2e010 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1,25 +1,47 @@ import { NestFactory } from '@nestjs/core'; +import { ValidationPipe } from '@nestjs/common'; import { AppModule } from './app.module'; +import { setupSwagger } from './config/swagger.config'; async function bootstrap() { const app = await NestFactory.create(AppModule); + // 启用全局验证管道 + app.useGlobalPipes(new ValidationPipe({ + whitelist: true, + forbidNonWhitelisted: true, + transform: true, + })); + + // 设置Swagger文档(在全局前缀之前) + try { + setupSwagger(app); + console.log('✅ Swagger setup completed successfully'); + } catch (error) { + console.error('❌ Swagger setup failed:', error.message); + } + + // 设置API前缀(排除docs路径) + app.setGlobalPrefix('api/v1', { + exclude: ['docs', 'docs/(.*)'] + }); + // 启用 CORS 支持多平台访问 app.enableCors({ - origin: true, + origin: process.env.NODE_ENV === 'production' + ? ['https://example.com'] + : true, methods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'], allowedHeaders: ['Content-Type', 'Authorization', 'X-Requested-With'], credentials: true, }); - // 设置全局前缀 - app.setGlobalPrefix(''); - - const port = process.env.PORT ?? 3000; + const port = process.env.PORT ?? 3003; await app.listen(port); console.log(`🚀 多平台小程序后台服务启动成功!`); console.log(`📡 服务地址: http://localhost:${port}`); + console.log(`📖 API文档地址: http://localhost:${port}/docs`); console.log(`📋 模板管理 API: http://localhost:${port}/api/v1/templates`); } bootstrap(); diff --git a/src/platform/controllers/unified-user.controller.ts b/src/platform/controllers/unified-user.controller.ts index e4d783e..a89c865 100644 --- a/src/platform/controllers/unified-user.controller.ts +++ b/src/platform/controllers/unified-user.controller.ts @@ -24,16 +24,37 @@ import { import { PlatformAuthGuard } from '../guards/platform-auth.guard'; import { PlatformType } from '../../entities/platform-user.entity'; -@ApiTags('统一用户管理') -@Controller('api/v1/users') +@ApiTags('用户管理') +@Controller('users') export class UnifiedUserController { constructor(private readonly unifiedUserService: UnifiedUserService) {} @Post('login') - @ApiOperation({ summary: '统一登录接口' }) - @ApiResponse({ status: 200, description: '登录成功' }) + @ApiOperation({ + summary: '多平台统一登录', + description: '支持微信、支付宝、百度、字节跳动等8大平台的统一登录接口', + }) + @ApiResponse({ + status: 200, + description: '登录成功', + schema: { + example: { + code: 200, + message: '登录成功', + data: { + token: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...', + refreshToken: 'refresh_token_string', + userInfo: { + id: 'user-uuid', + nickname: '用户昵称', + avatarUrl: 'https://example.com/avatar.jpg' + } + } + } + } + }) @ApiResponse({ status: 400, description: '请求参数错误' }) - @ApiResponse({ status: 401, description: '授权失败' }) + @ApiResponse({ status: 401, description: '平台授权失败' }) async login(@Body() loginDto: PlatformLoginDto) { const result = await this.unifiedUserService.login( loginDto.platform, @@ -47,8 +68,24 @@ export class UnifiedUserController { } @Post('register') - @ApiOperation({ summary: '统一注册接口' }) - @ApiResponse({ status: 200, description: '注册成功' }) + @ApiOperation({ + summary: '多平台统一注册', + description: '支持多平台用户注册,自动创建统一用户身份', + }) + @ApiResponse({ + status: 200, + description: '注册成功', + schema: { + example: { + code: 200, + message: '注册成功', + data: { + userId: 'user-uuid', + unifiedUserId: 'unified-user-123' + } + } + } + }) async register(@Body() registerDto: PlatformLoginDto) { const result = await this.unifiedUserService.register( registerDto.platform, @@ -63,9 +100,31 @@ export class UnifiedUserController { @Get('profile') @UseGuards(PlatformAuthGuard) - @ApiBearerAuth() - @ApiOperation({ summary: '获取用户信息' }) - @ApiResponse({ status: 200, description: '获取成功' }) + @ApiBearerAuth('JWT-auth') + @ApiOperation({ + summary: '获取用户档案', + description: '获取当前登录用户的详细信息和平台绑定状态', + }) + @ApiResponse({ + status: 200, + description: '获取成功', + schema: { + example: { + code: 200, + message: '获取成功', + data: { + id: 'user-uuid', + unifiedUserId: 'unified-user-123', + nickname: '用户昵称', + avatarUrl: 'https://example.com/avatar.jpg', + phone: '13800138000', + email: 'user@example.com', + platformUsers: [] + } + } + } + }) + @ApiResponse({ status: 401, description: '未授权访问' }) async getProfile(@Request() req) { const userInfo = await this.unifiedUserService.getUserInfo(req.user.userId); return { @@ -77,9 +136,22 @@ export class UnifiedUserController { @Put('profile') @UseGuards(PlatformAuthGuard) - @ApiBearerAuth() - @ApiOperation({ summary: '更新用户信息' }) - @ApiResponse({ status: 200, description: '更新成功' }) + @ApiBearerAuth('JWT-auth') + @ApiOperation({ + summary: '更新用户信息', + description: '更新当前用户的基本信息(昵称、头像等)', + }) + @ApiResponse({ + status: 200, + description: '更新成功', + schema: { + example: { + code: 200, + message: '更新成功' + } + } + }) + @ApiResponse({ status: 401, description: '未授权访问' }) async updateProfile(@Request() req, @Body() updateDto: UserInfoUpdateDto) { await this.unifiedUserService.updateUserInfo( req.user.platform, @@ -94,9 +166,23 @@ export class UnifiedUserController { @Post('bind-platform') @UseGuards(PlatformAuthGuard) - @ApiBearerAuth() - @ApiOperation({ summary: '绑定平台账号' }) - @ApiResponse({ status: 200, description: '绑定成功' }) + @ApiBearerAuth('JWT-auth') + @ApiOperation({ + summary: '绑定平台账号', + description: '将其他平台账号绑定到当前统一用户身份', + }) + @ApiResponse({ + status: 200, + description: '绑定成功', + schema: { + example: { + code: 200, + message: '绑定成功' + } + } + }) + @ApiResponse({ status: 401, description: '未授权访问' }) + @ApiResponse({ status: 409, description: '平台账号已绑定其他用户' }) async bindPlatform(@Request() req, @Body() bindDto: PlatformBindDto) { await this.unifiedUserService.bindPlatform( req.user.userId, @@ -111,9 +197,23 @@ export class UnifiedUserController { @Delete('unbind-platform/:platform') @UseGuards(PlatformAuthGuard) - @ApiBearerAuth() - @ApiOperation({ summary: '解绑平台账号' }) - @ApiResponse({ status: 200, description: '解绑成功' }) + @ApiBearerAuth('JWT-auth') + @ApiOperation({ + summary: '解绑平台账号', + description: '解除指定平台账号与当前用户的绑定关系', + }) + @ApiResponse({ + status: 200, + description: '解绑成功', + schema: { + example: { + code: 200, + message: '解绑成功' + } + } + }) + @ApiResponse({ status: 401, description: '未授权访问' }) + @ApiResponse({ status: 404, description: '平台绑定不存在' }) async unbindPlatform( @Request() req, @Param('platform') platform: PlatformType, @@ -126,8 +226,32 @@ export class UnifiedUserController { } @Get('platforms') - @ApiOperation({ summary: '获取支持的平台列表' }) - @ApiResponse({ status: 200, description: '获取成功' }) + @ApiOperation({ + summary: '获取支持的平台列表', + description: '获取系统支持的所有平台类型和相关信息', + }) + @ApiResponse({ + status: 200, + description: '获取成功', + schema: { + example: { + code: 200, + message: '获取成功', + data: [ + { + type: 'wechat', + name: '微信小程序', + supported: true + }, + { + type: 'alipay', + name: '支付宝小程序', + supported: true + } + ] + } + } + }) async getSupportedPlatforms() { const platforms = this.unifiedUserService.getSupportedPlatforms(); return { diff --git a/swagger.json b/swagger.json new file mode 100644 index 0000000..7d6c640 --- /dev/null +++ b/swagger.json @@ -0,0 +1,1972 @@ +{ + "openapi": "3.0.0", + "paths": { + "/api/v1/templates": { + "get": { + "operationId": "AppController_getTemplates", + "parameters": [], + "responses": { + "200": { + "description": "" + } + }, + "tags": [ + "App" + ] + }, + "post": { + "operationId": "AppController_executeTemplate", + "parameters": [], + "responses": { + "201": { + "description": "" + } + }, + "tags": [ + "App" + ] + } + }, + "/api/v1/templates/{templateCode}": { + "get": { + "operationId": "AppController_getTemplate", + "parameters": [ + { + "name": "templateCode", + "required": true, + "in": "path", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "" + } + }, + "tags": [ + "App" + ] + } + }, + "/api/v1/templates/callback": { + "post": { + "operationId": "AppController_callback", + "parameters": [], + "responses": { + "201": { + "description": "" + } + }, + "tags": [ + "App" + ] + } + }, + "/templates/{templateId}/execute": { + "post": { + "description": "根据模板ID执行AI生成任务,支持图片和视频生成", + "operationId": "TemplateController_executeTemplateById", + "parameters": [ + { + "name": "templateId", + "required": true, + "in": "path", + "description": "模板ID", + "schema": { + "example": 1, + "type": "number" + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TemplateExecuteDto" + } + } + } + }, + "responses": { + "200": { + "description": "执行成功", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TemplateExecuteResponseDto" + } + } + } + }, + "400": { + "description": "参数错误", + "content": { + "application/json": { + "schema": { + "example": { + "code": 400, + "message": "imageUrl is required", + "data": null + } + } + } + } + }, + "401": { + "description": "未授权访问", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponseDto" + } + } + } + }, + "500": { + "description": "服务器内部错误", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponseDto" + } + } + } + } + }, + "summary": "执行模板生成", + "tags": [ + "AI模板系统" + ] + } + }, + "/templates/code/{code}/execute": { + "post": { + "description": "根据模板代码执行AI生成任务,支持图片和视频生成", + "operationId": "TemplateController_executeTemplateByCode", + "parameters": [ + { + "name": "code", + "required": true, + "in": "path", + "description": "模板代码", + "schema": { + "example": "character_figurine_v1", + "type": "string" + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TemplateExecuteDto" + } + } + } + }, + "responses": { + "200": { + "description": "执行成功", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TemplateExecuteResponseDto" + } + } + } + }, + "400": { + "description": "请求参数错误", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponseDto" + } + } + } + }, + "401": { + "description": "未授权访问", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponseDto" + } + } + } + }, + "500": { + "description": "服务器内部错误", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponseDto" + } + } + } + } + }, + "summary": "通过代码执行模板", + "tags": [ + "AI模板系统" + ] + } + }, + "/templates/{templateId}/batch-execute": { + "post": { + "description": "批量执行模板生成任务,支持多张图片同时处理", + "operationId": "TemplateController_batchExecuteTemplate", + "parameters": [ + { + "name": "templateId", + "required": true, + "in": "path", + "description": "模板ID", + "schema": { + "example": 1, + "type": "number" + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BatchExecuteDto" + } + } + } + }, + "responses": { + "200": { + "description": "批量执行成功", + "content": { + "application/json": { + "schema": { + "example": { + "success": true, + "data": { + "templateId": 1, + "totalCount": 2, + "results": [ + { + "inputUrl": "image1.jpg", + "outputUrl": "output1.jpg" + }, + { + "inputUrl": "image2.jpg", + "outputUrl": "output2.jpg" + } + ] + } + } + } + } + } + }, + "400": { + "description": "请求参数错误", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponseDto" + } + } + } + }, + "401": { + "description": "未授权访问", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponseDto" + } + } + } + }, + "500": { + "description": "服务器内部错误", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponseDto" + } + } + } + } + }, + "summary": "批量执行模板", + "tags": [ + "AI模板系统" + ] + } + }, + "/templates": { + "get": { + "description": "获取所有可用的AI生成模板,支持按类型筛选", + "operationId": "TemplateController_getAllTemplates", + "parameters": [], + "responses": { + "200": { + "description": "获取成功", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/TemplateListDto" + } + } + } + } + }, + "400": { + "description": "请求参数错误", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponseDto" + } + } + } + }, + "401": { + "description": "未授权访问", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponseDto" + } + } + } + }, + "500": { + "description": "服务器内部错误", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponseDto" + } + } + } + } + }, + "summary": "获取所有模板列表", + "tags": [ + "AI模板系统" + ] + }, + "post": { + "description": "创建一个新的AI生成模板", + "operationId": "TemplateController_createTemplate", + "parameters": [], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateTemplateDto" + } + } + } + }, + "responses": { + "200": { + "description": "创建成功", + "content": { + "application/json": { + "schema": { + "example": { + "success": true, + "data": { + "id": 1, + "code": "new_template_v1", + "name": "新模板" + } + } + } + } + } + }, + "400": { + "description": "请求参数错误", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponseDto" + } + } + } + }, + "401": { + "description": "未授权访问", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponseDto" + } + } + } + }, + "409": { + "description": "模板代码已存在" + }, + "500": { + "description": "服务器内部错误", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponseDto" + } + } + } + } + }, + "summary": "创建新模板", + "tags": [ + "AI模板系统" + ] + } + }, + "/templates/image": { + "get": { + "description": "获取所有图片类型的AI生成模板", + "operationId": "TemplateController_getImageTemplates", + "parameters": [], + "responses": { + "200": { + "description": "获取成功", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/TemplateListDto" + } + } + } + } + }, + "400": { + "description": "请求参数错误", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponseDto" + } + } + } + }, + "401": { + "description": "未授权访问", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponseDto" + } + } + } + }, + "500": { + "description": "服务器内部错误", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponseDto" + } + } + } + } + }, + "summary": "获取图片模板列表", + "tags": [ + "AI模板系统" + ] + } + }, + "/templates/video": { + "get": { + "description": "获取所有视频类型的AI生成模板", + "operationId": "TemplateController_getVideoTemplates", + "parameters": [], + "responses": { + "200": { + "description": "获取成功", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/TemplateListDto" + } + } + } + } + }, + "400": { + "description": "请求参数错误", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponseDto" + } + } + } + }, + "401": { + "description": "未授权访问", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponseDto" + } + } + } + }, + "500": { + "description": "服务器内部错误", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponseDto" + } + } + } + } + }, + "summary": "获取视频模板列表", + "tags": [ + "AI模板系统" + ] + } + }, + "/templates/recommend": { + "get": { + "description": "根据用户偏好标签推荐适合的模板", + "operationId": "TemplateController_recommendTemplates", + "parameters": [ + { + "name": "tags", + "required": false, + "in": "query", + "description": "用户偏好标签,逗号分隔", + "schema": { + "example": "人物,手办", + "type": "string" + } + }, + { + "name": "limit", + "required": false, + "in": "query", + "description": "推荐数量", + "schema": { + "example": 5, + "type": "number" + } + } + ], + "responses": { + "200": { + "description": "推荐成功", + "content": { + "application/json": { + "schema": { + "example": { + "success": true, + "data": { + "userTags": [ + "人物", + "手办" + ], + "recommendedTemplates": [] + } + } + } + } + } + }, + "400": { + "description": "请求参数错误", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponseDto" + } + } + } + }, + "401": { + "description": "未授权访问", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponseDto" + } + } + } + }, + "500": { + "description": "服务器内部错误", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponseDto" + } + } + } + } + }, + "summary": "推荐模板", + "tags": [ + "AI模板系统" + ] + } + }, + "/templates/{templateId}": { + "get": { + "description": "根据模板ID获取详细信息", + "operationId": "TemplateController_getTemplateById", + "parameters": [ + { + "name": "templateId", + "required": true, + "in": "path", + "description": "模板ID", + "schema": { + "example": 1, + "type": "number" + } + } + ], + "responses": { + "200": { + "description": "获取成功", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TemplateListDto" + } + } + } + }, + "400": { + "description": "请求参数错误", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponseDto" + } + } + } + }, + "401": { + "description": "未授权访问", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponseDto" + } + } + } + }, + "404": { + "description": "模板不存在" + }, + "500": { + "description": "服务器内部错误", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponseDto" + } + } + } + } + }, + "summary": "获取模板详情", + "tags": [ + "AI模板系统" + ] + }, + "put": { + "description": "更新指定模板的配置信息", + "operationId": "TemplateController_updateTemplate", + "parameters": [ + { + "name": "templateId", + "required": true, + "in": "path", + "description": "模板ID", + "schema": { + "example": 1, + "type": "number" + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UpdateTemplateDto" + } + } + } + }, + "responses": { + "200": { + "description": "更新成功", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TemplateListDto" + } + } + } + }, + "400": { + "description": "请求参数错误", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponseDto" + } + } + } + }, + "401": { + "description": "未授权访问", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponseDto" + } + } + } + }, + "404": { + "description": "模板不存在" + }, + "409": { + "description": "模板代码已存在" + }, + "500": { + "description": "服务器内部错误", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponseDto" + } + } + } + } + }, + "summary": "更新模板", + "tags": [ + "AI模板系统" + ] + }, + "delete": { + "operationId": "TemplateController_deleteTemplate", + "parameters": [ + { + "name": "templateId", + "required": true, + "in": "path", + "schema": { + "type": "number" + } + } + ], + "responses": { + "200": { + "description": "" + }, + "400": { + "description": "请求参数错误", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponseDto" + } + } + } + }, + "401": { + "description": "未授权访问", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponseDto" + } + } + } + }, + "500": { + "description": "服务器内部错误", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponseDto" + } + } + } + } + }, + "tags": [ + "AI模板系统" + ] + } + }, + "/templates/execution/{taskId}/progress": { + "get": { + "operationId": "TemplateController_getExecutionProgress", + "parameters": [ + { + "name": "taskId", + "required": true, + "in": "path", + "schema": { + "type": "number" + } + } + ], + "responses": { + "200": { + "description": "" + }, + "400": { + "description": "请求参数错误", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponseDto" + } + } + } + }, + "401": { + "description": "未授权访问", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponseDto" + } + } + } + }, + "500": { + "description": "服务器内部错误", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponseDto" + } + } + } + } + }, + "tags": [ + "AI模板系统" + ] + } + }, + "/templates/executions/user/{userId}": { + "get": { + "operationId": "TemplateController_getUserExecutions", + "parameters": [ + { + "name": "userId", + "required": true, + "in": "path", + "schema": { + "type": "string" + } + }, + { + "name": "status", + "required": true, + "in": "query", + "schema": { + "type": "string" + } + }, + { + "name": "limit", + "required": true, + "in": "query", + "schema": { + "type": "number" + } + } + ], + "responses": { + "200": { + "description": "" + }, + "400": { + "description": "请求参数错误", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponseDto" + } + } + } + }, + "401": { + "description": "未授权访问", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponseDto" + } + } + } + }, + "500": { + "description": "服务器内部错误", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponseDto" + } + } + } + } + }, + "tags": [ + "AI模板系统" + ] + } + }, + "/templates/admin/{templateId}": { + "get": { + "operationId": "TemplateController_getTemplateForAdmin", + "parameters": [ + { + "name": "templateId", + "required": true, + "in": "path", + "schema": { + "type": "number" + } + } + ], + "responses": { + "200": { + "description": "" + }, + "400": { + "description": "请求参数错误", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponseDto" + } + } + } + }, + "401": { + "description": "未授权访问", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponseDto" + } + } + } + }, + "500": { + "description": "服务器内部错误", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponseDto" + } + } + } + } + }, + "tags": [ + "AI模板系统" + ] + } + }, + "/templates/admin": { + "get": { + "operationId": "TemplateController_getAllTemplatesForAdmin", + "parameters": [ + { + "name": "page", + "required": true, + "in": "query", + "schema": { + "type": "number" + } + }, + { + "name": "limit", + "required": true, + "in": "query", + "schema": { + "type": "number" + } + }, + { + "name": "type", + "required": true, + "in": "query", + "schema": { + "type": "string" + } + }, + { + "name": "isActive", + "required": true, + "in": "query", + "schema": { + "type": "boolean" + } + } + ], + "responses": { + "200": { + "description": "" + }, + "400": { + "description": "请求参数错误", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponseDto" + } + } + } + }, + "401": { + "description": "未授权访问", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponseDto" + } + } + } + }, + "500": { + "description": "服务器内部错误", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponseDto" + } + } + } + } + }, + "tags": [ + "AI模板系统" + ] + } + }, + "/users/login": { + "post": { + "description": "支持微信、支付宝、百度、字节跳动等8大平台的统一登录接口", + "operationId": "UnifiedUserController_login", + "parameters": [], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PlatformLoginDto" + } + } + } + }, + "responses": { + "200": { + "description": "登录成功", + "content": { + "application/json": { + "schema": { + "example": { + "code": 200, + "message": "登录成功", + "data": { + "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...", + "refreshToken": "refresh_token_string", + "userInfo": { + "id": "user-uuid", + "nickname": "用户昵称", + "avatarUrl": "https://example.com/avatar.jpg" + } + } + } + } + } + } + }, + "400": { + "description": "请求参数错误" + }, + "401": { + "description": "平台授权失败" + } + }, + "summary": "多平台统一登录", + "tags": [ + "用户管理" + ] + } + }, + "/users/register": { + "post": { + "description": "支持多平台用户注册,自动创建统一用户身份", + "operationId": "UnifiedUserController_register", + "parameters": [], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PlatformLoginDto" + } + } + } + }, + "responses": { + "200": { + "description": "注册成功", + "content": { + "application/json": { + "schema": { + "example": { + "code": 200, + "message": "注册成功", + "data": { + "userId": "user-uuid", + "unifiedUserId": "unified-user-123" + } + } + } + } + } + } + }, + "summary": "多平台统一注册", + "tags": [ + "用户管理" + ] + } + }, + "/users/profile": { + "get": { + "description": "获取当前登录用户的详细信息和平台绑定状态", + "operationId": "UnifiedUserController_getProfile", + "parameters": [], + "responses": { + "200": { + "description": "获取成功", + "content": { + "application/json": { + "schema": { + "example": { + "code": 200, + "message": "获取成功", + "data": { + "id": "user-uuid", + "unifiedUserId": "unified-user-123", + "nickname": "用户昵称", + "avatarUrl": "https://example.com/avatar.jpg", + "phone": "13800138000", + "email": "user@example.com", + "platformUsers": [] + } + } + } + } + } + }, + "401": { + "description": "未授权访问" + } + }, + "security": [ + { + "JWT-auth": [] + } + ], + "summary": "获取用户档案", + "tags": [ + "用户管理" + ] + }, + "put": { + "description": "更新当前用户的基本信息(昵称、头像等)", + "operationId": "UnifiedUserController_updateProfile", + "parameters": [], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UserInfoUpdateDto" + } + } + } + }, + "responses": { + "200": { + "description": "更新成功", + "content": { + "application/json": { + "schema": { + "example": { + "code": 200, + "message": "更新成功" + } + } + } + } + }, + "401": { + "description": "未授权访问" + } + }, + "security": [ + { + "JWT-auth": [] + } + ], + "summary": "更新用户信息", + "tags": [ + "用户管理" + ] + } + }, + "/users/bind-platform": { + "post": { + "description": "将其他平台账号绑定到当前统一用户身份", + "operationId": "UnifiedUserController_bindPlatform", + "parameters": [], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PlatformBindDto" + } + } + } + }, + "responses": { + "200": { + "description": "绑定成功", + "content": { + "application/json": { + "schema": { + "example": { + "code": 200, + "message": "绑定成功" + } + } + } + } + }, + "401": { + "description": "未授权访问" + }, + "409": { + "description": "平台账号已绑定其他用户" + } + }, + "security": [ + { + "JWT-auth": [] + } + ], + "summary": "绑定平台账号", + "tags": [ + "用户管理" + ] + } + }, + "/users/unbind-platform/{platform}": { + "delete": { + "description": "解除指定平台账号与当前用户的绑定关系", + "operationId": "UnifiedUserController_unbindPlatform", + "parameters": [ + { + "name": "platform", + "required": true, + "in": "path", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "解绑成功", + "content": { + "application/json": { + "schema": { + "example": { + "code": 200, + "message": "解绑成功" + } + } + } + } + }, + "401": { + "description": "未授权访问" + }, + "404": { + "description": "平台绑定不存在" + } + }, + "security": [ + { + "JWT-auth": [] + } + ], + "summary": "解绑平台账号", + "tags": [ + "用户管理" + ] + } + }, + "/users/platforms": { + "get": { + "description": "获取系统支持的所有平台类型和相关信息", + "operationId": "UnifiedUserController_getSupportedPlatforms", + "parameters": [], + "responses": { + "200": { + "description": "获取成功", + "content": { + "application/json": { + "schema": { + "example": { + "code": 200, + "message": "获取成功", + "data": [ + { + "type": "wechat", + "name": "微信小程序", + "supported": true + }, + { + "type": "alipay", + "name": "支付宝小程序", + "supported": true + } + ] + } + } + } + } + } + }, + "summary": "获取支持的平台列表", + "tags": [ + "用户管理" + ] + } + } + }, + "info": { + "title": "多平台小程序统一后台API", + "description": "支持微信、支付宝、百度、字节跳动等多平台的统一后台服务", + "version": "1.0.0", + "contact": {} + }, + "tags": [ + { + "name": "用户管理", + "description": "用户注册、登录、信息管理" + }, + { + "name": "平台适配", + "description": "各平台特定接口和数据同步" + }, + { + "name": "AI模板系统", + "description": "AI图片/视频生成模板管理" + }, + { + "name": "积分系统", + "description": "积分获取、消耗、查询管理" + }, + { + "name": "扩展服务", + "description": "预留的扩展功能接口" + } + ], + "servers": [], + "components": { + "securitySchemes": { + "JWT-auth": { + "scheme": "bearer", + "bearerFormat": "JWT", + "type": "http", + "name": "JWT", + "description": "Enter JWT token", + "in": "header" + } + }, + "schemas": { + "ErrorResponseDto": { + "type": "object", + "properties": { + "code": { + "type": "number", + "description": "错误状态码", + "example": 400 + }, + "message": { + "type": "string", + "description": "错误消息", + "example": "请求参数错误" + }, + "timestamp": { + "type": "number", + "description": "时间戳", + "example": 1703001000000 + }, + "traceId": { + "type": "string", + "description": "追踪ID", + "example": "trace-uuid-123" + }, + "details": { + "description": "详细错误信息", + "example": [ + "字段验证失败" + ], + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "code", + "message", + "timestamp", + "traceId" + ] + }, + "TemplateExecuteDto": { + "type": "object", + "properties": { + "imageUrl": { + "type": "string", + "description": "输入图片URL", + "example": "https://cdn.example.com/upload/image.jpg" + } + }, + "required": [ + "imageUrl" + ] + }, + "TemplateExecuteResponseDto": { + "type": "object", + "properties": { + "success": { + "type": "boolean", + "description": "执行状态", + "example": true + }, + "imageUrl": { + "type": "string", + "description": "生成结果URL(图片模板)" + }, + "videoUrl": { + "type": "string", + "description": "生成结果URL(视频模板)" + }, + "thumbnailUrl": { + "type": "string", + "description": "缩略图URL" + }, + "taskId": { + "type": "string", + "description": "任务ID", + "example": "req_1704067200_abc123" + }, + "executionTime": { + "type": "number", + "description": "执行耗时(毫秒)", + "example": 5000 + }, + "creditCost": { + "type": "number", + "description": "消耗积分", + "example": 28 + } + }, + "required": [ + "success", + "taskId", + "executionTime", + "creditCost" + ] + }, + "BatchExecuteDto": { + "type": "object", + "properties": { + "imageUrls": { + "description": "输入图片URL数组", + "example": [ + "https://cdn.example.com/upload/image1.jpg", + "https://cdn.example.com/upload/image2.jpg" + ], + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "imageUrls" + ] + }, + "TemplateListDto": { + "type": "object", + "properties": { + "id": { + "type": "number", + "description": "模板ID", + "example": 1 + }, + "code": { + "type": "string", + "description": "模板代码", + "example": "character_figurine_v1" + }, + "name": { + "type": "string", + "description": "模板名称", + "example": "人物手办" + }, + "description": { + "type": "string", + "description": "模板描述", + "example": "将人物照片制作成精细的角色手办模型" + }, + "templateType": { + "type": "string", + "enum": [ + "image", + "video" + ], + "description": "模板类型", + "example": "video" + }, + "creditCost": { + "type": "number", + "description": "积分消耗", + "example": 28 + }, + "version": { + "type": "string", + "description": "版本号", + "example": "1.0.0" + }, + "inputExampleUrl": { + "type": "string", + "description": "输入示例URL" + }, + "outputExampleUrl": { + "type": "string", + "description": "输出示例URL" + }, + "tags": { + "description": "标签数组", + "example": [ + "人物", + "手办", + "模型" + ], + "type": "array", + "items": { + "type": "string" + } + }, + "isActive": { + "type": "boolean", + "description": "是否启用", + "example": true + }, + "createdAt": { + "format": "date-time", + "type": "string", + "description": "创建时间", + "example": "2024-01-01T00:00:00Z" + } + }, + "required": [ + "id", + "code", + "name", + "description", + "templateType", + "creditCost", + "version", + "tags", + "isActive", + "createdAt" + ] + }, + "CreateTemplateDto": { + "type": "object", + "properties": { + "code": { + "type": "string", + "description": "模板代码", + "example": "character_figurine_v1" + }, + "name": { + "type": "string", + "description": "模板名称", + "example": "人物手办" + }, + "description": { + "type": "string", + "description": "模板描述", + "example": "将人物照片制作成精细的角色手办模型" + }, + "creditCost": { + "type": "number", + "description": "积分消耗", + "example": 28, + "minimum": 0 + }, + "version": { + "type": "string", + "description": "版本号", + "example": "1.0.0" + }, + "inputExampleUrl": { + "type": "string", + "description": "输入示例URL", + "example": "https://example.com/input.jpg" + }, + "outputExampleUrl": { + "type": "string", + "description": "输出示例URL", + "example": "https://example.com/output.jpg" + }, + "tags": { + "description": "标签数组", + "example": [ + "人物", + "手办", + "模型" + ], + "type": "array", + "items": { + "type": "string" + } + }, + "templateType": { + "type": "string", + "description": "模板类型", + "enum": [ + "image", + "video" + ], + "example": "image" + }, + "templateClass": { + "type": "string", + "description": "模板类名", + "example": "CharacterFigurineTemplate" + }, + "imageModel": { + "type": "string", + "description": "图片模型", + "example": "flux-dev" + }, + "imagePrompt": { + "type": "string", + "description": "图片提示词模板" + }, + "videoModel": { + "type": "string", + "description": "视频模型", + "example": "runway-gen3" + }, + "videoPrompt": { + "type": "string", + "description": "视频提示词模板" + }, + "duration": { + "type": "number", + "description": "视频时长(秒)", + "example": 10, + "minimum": 1, + "maximum": 300 + }, + "aspectRatio": { + "type": "string", + "description": "宽高比", + "example": "16:9" + }, + "isActive": { + "type": "boolean", + "description": "是否启用", + "example": true + }, + "sortOrder": { + "type": "number", + "description": "排序权重", + "example": 100 + } + }, + "required": [ + "code", + "name", + "description", + "creditCost", + "version", + "templateType", + "templateClass" + ] + }, + "UpdateTemplateDto": { + "type": "object", + "properties": { + "code": { + "type": "string", + "description": "模板代码", + "example": "character_figurine_v1" + }, + "name": { + "type": "string", + "description": "模板名称", + "example": "人物手办" + }, + "description": { + "type": "string", + "description": "模板描述", + "example": "将人物照片制作成精细的角色手办模型" + }, + "creditCost": { + "type": "number", + "description": "积分消耗", + "example": 28, + "minimum": 0 + }, + "version": { + "type": "string", + "description": "版本号", + "example": "1.0.1" + }, + "inputExampleUrl": { + "type": "string", + "description": "输入示例URL", + "example": "https://example.com/input.jpg" + }, + "outputExampleUrl": { + "type": "string", + "description": "输出示例URL", + "example": "https://example.com/output.jpg" + }, + "tags": { + "description": "标签数组", + "example": [ + "人物", + "手办", + "模型" + ], + "type": "array", + "items": { + "type": "string" + } + }, + "templateType": { + "type": "string", + "description": "模板类型", + "enum": [ + "image", + "video" + ] + }, + "templateClass": { + "type": "string", + "description": "模板类名", + "example": "CharacterFigurineTemplate" + }, + "imageModel": { + "type": "string", + "description": "图片模型", + "example": "flux-dev" + }, + "imagePrompt": { + "type": "string", + "description": "图片提示词模板" + }, + "videoModel": { + "type": "string", + "description": "视频模型", + "example": "runway-gen3" + }, + "videoPrompt": { + "type": "string", + "description": "视频提示词模板" + }, + "duration": { + "type": "number", + "description": "视频时长(秒)", + "example": 10, + "minimum": 1, + "maximum": 300 + }, + "aspectRatio": { + "type": "string", + "description": "宽高比", + "example": "16:9" + }, + "isActive": { + "type": "boolean", + "description": "是否启用", + "example": true + }, + "sortOrder": { + "type": "number", + "description": "排序权重", + "example": 100 + } + } + }, + "PlatformType": { + "type": "string", + "enum": [ + "wechat", + "alipay", + "baidu", + "bytedance", + "jd", + "qq", + "feishu", + "kuaishou", + "h5", + "rn" + ], + "description": "平台类型" + }, + "PlatformLoginDto": { + "type": "object", + "properties": { + "platform": { + "description": "平台类型", + "example": "wechat", + "allOf": [ + { + "$ref": "#/components/schemas/PlatformType" + } + ] + }, + "code": { + "type": "string", + "description": "平台授权码", + "example": "081234567890abcdef" + }, + "encryptedData": { + "type": "string", + "description": "加密用户数据(微信小程序)" + }, + "iv": { + "type": "string", + "description": "加密向量(微信小程序)" + }, + "userInfo": { + "type": "object", + "description": "用户基础信息" + }, + "anonymousCode": { + "type": "string", + "description": "匿名授权码(抖音小程序)" + } + }, + "required": [ + "platform", + "code" + ] + }, + "UserInfoUpdateDto": { + "type": "object", + "properties": { + "nickname": { + "type": "string", + "description": "用户昵称" + }, + "avatarUrl": { + "type": "string", + "description": "头像URL" + }, + "phone": { + "type": "string", + "description": "手机号码" + }, + "email": { + "type": "string", + "description": "电子邮箱" + } + } + }, + "PlatformBindDto": { + "type": "object", + "properties": { + "platform": { + "type": "string", + "description": "平台类型", + "enum": [ + "wechat", + "alipay", + "baidu", + "bytedance", + "jd", + "qq", + "feishu", + "kuaishou", + "h5", + "rn" + ] + }, + "code": { + "type": "string", + "description": "平台授权码" + }, + "encryptedData": { + "type": "string", + "description": "加密用户数据(微信小程序)" + }, + "iv": { + "type": "string", + "description": "加密向量(微信小程序)" + }, + "userInfo": { + "type": "object", + "description": "用户基础信息" + } + }, + "required": [ + "platform", + "code" + ] + } + } + } +} \ No newline at end of file