bw-mini-app-server/docs/swagger-api-documentation.md

1028 lines
26 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Swagger API 文档配置指南
## 1. Swagger 基础配置
### 1.1 安装依赖
```bash
pnpm add @nestjs/swagger swagger-ui-express
pnpm add -D @types/swagger-ui-express
```
### 1.2 基础配置文件
```typescript
// src/config/swagger.config.ts
import { DocumentBuilder, SwaggerModule } from '@nestjs/swagger';
import { INestApplication } from '@nestjs/common';
export function setupSwagger(app: INestApplication): void {
const config = new DocumentBuilder()
.setTitle('多平台小程序统一后台API')
.setDescription(`
## 功能特性
- 🔐 统一用户认证 (微信/支付宝/百度/字节跳动等)
- 🔄 平台数据同步 (数据库异步处理)
- 🧩 可扩展架构 (支持后续添加支付、推送等功能)
- 📊 灵活数据存储 (MySQL + JSON)
## 认证方式
使用JWT Bearer Token进行API认证
## AI模板系统
- 🎨 动态模板管理 (数据库配置 + 代码执行)
- 🚀 N8n工作流集成 (图片/视频生成)
- 📊 使用统计分析 (性能监控 + 用户行为)
- 🎛️ 运营管理后台 (A/B测试 + 个性化推荐)
## 响应格式
所有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('🧩 扩展服务', '预留的扩展功能接口')
.addTag('📊 数据统计', '业务数据统计和分析')
.addServer('http://localhost:3000', '开发环境')
.addServer('https://api-dev.example.com', '测试环境')
.addServer('https://api.example.com', '生产环境')
.build();
const document = SwaggerModule.createDocument(app, config, {
operationIdFactory: (controllerKey: string, methodKey: string) => methodKey,
});
SwaggerModule.setup('api/docs', app, 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',
],
customCssUrl: [
'https://cdnjs.cloudflare.com/ajax/libs/swagger-ui/4.15.5/swagger-ui.min.css',
],
});
}
```
## 2. 通用DTO定义
### 2.1 统一响应格式
```typescript
// src/dto/common-response.dto.ts
import { ApiProperty } from '@nestjs/swagger';
export class CommonResponseDto<T = any> {
@ApiProperty({ description: '响应状态码', example: 200 })
code: number;
@ApiProperty({ description: '响应消息', example: 'success' })
message: string;
@ApiProperty({ description: '响应数据' })
data: T;
@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<T = any> {
@ApiProperty({ description: '数据列表' })
items: T[];
@ApiProperty({ description: '总数量', example: 100 })
total: number;
@ApiProperty({ description: '当前页码', example: 1 })
page: number;
@ApiProperty({ description: '每页数量', example: 10 })
limit: number;
@ApiProperty({ description: '总页数', example: 10 })
totalPages: number;
}
```
### 2.2 平台枚举定义
```typescript
// src/dto/platform.dto.ts
import { ApiProperty } from '@nestjs/swagger';
export enum PlatformType {
WECHAT = 'wechat',
ALIPAY = 'alipay',
BAIDU = 'baidu',
BYTEDANCE = 'bytedance',
JD = 'jd',
QQ = 'qq',
FEISHU = 'feishu',
KUAISHOU = 'kuaishou',
H5 = 'h5',
RN = 'rn'
}
export const PlatformDescriptions = {
[PlatformType.WECHAT]: '微信小程序',
[PlatformType.ALIPAY]: '支付宝小程序',
[PlatformType.BAIDU]: '百度智能小程序',
[PlatformType.BYTEDANCE]: '字节跳动小程序',
[PlatformType.JD]: '京东小程序',
[PlatformType.QQ]: 'QQ小程序',
[PlatformType.FEISHU]: '飞书小程序',
[PlatformType.KUAISHOU]: '快手小程序',
[PlatformType.H5]: 'H5应用',
[PlatformType.RN]: 'React Native应用',
};
```
## 3. 用户管理API文档
### 3.1 用户登录DTO
```typescript
// src/dto/user.dto.ts
import { ApiProperty } from '@nestjs/swagger';
import { IsString, IsEnum, IsOptional, IsObject } from 'class-validator';
import { PlatformType } from './platform.dto';
export class UserLoginDto {
@ApiProperty({
description: '平台类型',
enum: PlatformType,
example: PlatformType.WECHAT,
enumName: 'PlatformType',
})
@IsEnum(PlatformType)
platform: PlatformType;
@ApiProperty({
description: '平台授权码/临时登录凭证',
example: '081234567890abcdef',
minLength: 1,
maxLength: 200,
})
@IsString()
code: string;
@ApiProperty({
description: '加密用户数据 (微信小程序专用)',
required: false,
example: 'encrypted_user_data_string',
})
@IsOptional()
@IsString()
encryptedData?: string;
@ApiProperty({
description: '加密向量 (微信小程序专用)',
required: false,
example: 'iv_string',
})
@IsOptional()
@IsString()
iv?: string;
@ApiProperty({
description: '额外的平台特定数据',
required: false,
type: 'object',
example: { sessionKey: 'session_key_value' },
})
@IsOptional()
@IsObject()
extra?: Record<string, any>;
}
export class UserInfoDto {
@ApiProperty({ description: '用户ID', example: 'user-uuid-123' })
id: string;
@ApiProperty({ description: '统一用户ID', example: 'unified-user-123' })
unifiedUserId: string;
@ApiProperty({ description: '用户昵称', example: '张三' })
nickname: string;
@ApiProperty({
description: '头像URL',
example: 'https://example.com/avatar.jpg'
})
avatarUrl: string;
@ApiProperty({
description: '手机号',
example: '13800138000',
required: false
})
phone?: string;
@ApiProperty({
description: '邮箱',
example: 'user@example.com',
required: false
})
email?: string;
@ApiProperty({ description: '用户状态', example: 1 })
status: number;
@ApiProperty({ description: '创建时间', example: '2023-12-01T10:00:00Z' })
createdAt: Date;
@ApiProperty({ description: '更新时间', example: '2023-12-01T10:00:00Z' })
updatedAt: Date;
}
export class UserLoginResponseDto {
@ApiProperty({
description: 'JWT访问令牌',
example: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...',
})
token: string;
@ApiProperty({
description: '刷新令牌',
example: 'refresh_token_string_here',
})
refreshToken: string;
@ApiProperty({
description: '用户信息',
type: UserInfoDto,
})
userInfo: UserInfoDto;
@ApiProperty({
description: '平台特定数据',
type: 'object',
required: false,
example: { openid: 'wx_openid_123' },
})
platformSpecific?: Record<string, any>;
}
```
## 4. 扩展服务API文档
### 4.1 扩展数据相关DTO
```typescript
// src/dto/extension.dto.ts
import { ApiProperty } from '@nestjs/swagger';
import { IsString, IsEnum, IsOptional, IsObject } from 'class-validator';
import { PlatformType } from './platform.dto';
export class CreateExtensionDataDto {
@ApiProperty({
description: '用户ID',
example: 'user-uuid-123',
})
@IsString()
userId: string;
@ApiProperty({
description: '平台类型',
enum: PlatformType,
example: PlatformType.WECHAT,
})
@IsEnum(PlatformType)
platform: PlatformType;
@ApiProperty({
description: '数据类型',
example: 'custom',
maxLength: 50,
})
@IsString()
dataType: string;
@ApiProperty({
description: '外部引用ID',
required: false,
example: 'ref-123456',
maxLength: 100,
})
@IsOptional()
@IsString()
referenceId?: string;
@ApiProperty({
description: '扩展数据内容',
type: 'object',
example: {
customField1: 'value1',
customField2: 'value2',
settings: { enabled: true }
},
})
@IsObject()
data: Record<string, any>;
@ApiProperty({
description: '元数据',
required: false,
type: 'object',
example: { source: 'api', version: '1.0' },
})
@IsOptional()
@IsObject()
metadata?: Record<string, any>;
}
export class ExtensionDataResponseDto {
@ApiProperty({ description: '扩展数据ID', example: 'ext-uuid-123' })
id: string;
@ApiProperty({ description: '用户ID', example: 'user-uuid-123' })
userId: string;
@ApiProperty({
description: '平台类型',
enum: PlatformType,
example: PlatformType.WECHAT,
})
platform: PlatformType;
@ApiProperty({ description: '数据类型', example: 'custom' })
dataType: string;
@ApiProperty({ description: '外部引用ID', example: 'ref-123456' })
referenceId: string;
@ApiProperty({
description: '扩展数据内容',
type: 'object',
})
data: Record<string, any>;
@ApiProperty({
description: '元数据',
type: 'object',
})
metadata: Record<string, any>;
@ApiProperty({ description: '状态', example: 'active' })
status: string;
@ApiProperty({ description: '创建时间', example: '2023-12-01T10:00:00Z' })
createdAt: Date;
@ApiProperty({ description: '更新时间', example: '2023-12-01T10:00:00Z' })
updatedAt: Date;
}
```
## 5. 错误响应文档
### 5.1 通用错误响应
```typescript
// src/dto/error-response.dto.ts
import { ApiProperty } from '@nestjs/swagger';
export class ErrorResponseDto {
@ApiProperty({ description: '错误状态码', example: 400 })
code: number;
@ApiProperty({ description: '错误消息', example: '请求参数错误' })
message: string;
@ApiProperty({ description: '错误数据', example: null })
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,
},
};
```
## 6. 装饰器使用示例
### 6.1 Controller装饰器
```typescript
// src/decorators/api-common-responses.decorator.ts
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),
);
}
```
### 6.2 使用示例
```typescript
// src/controllers/user.controller.ts
import { Controller, Post, Body, Get, UseGuards } from '@nestjs/common';
import {
ApiTags,
ApiOperation,
ApiResponse,
ApiBearerAuth,
} from '@nestjs/swagger';
import { ApiCommonResponses, ApiAuthResponses } from '../decorators/api-common-responses.decorator';
@ApiTags('🔐 用户管理')
@Controller('users')
@ApiCommonResponses()
export class UserController {
@Post('login')
@ApiOperation({
summary: '用户登录',
description: '支持多平台用户登录返回JWT令牌和用户信息',
})
@ApiResponse({
status: 200,
description: '登录成功',
type: UserLoginResponseDto,
})
async login(@Body() loginDto: UserLoginDto) {
return this.userService.login(loginDto);
}
@Get('profile')
@UseGuards(JwtAuthGuard)
@ApiBearerAuth('JWT-auth')
@ApiAuthResponses()
@ApiOperation({
summary: '获取用户信息',
description: '获取当前登录用户的详细信息',
})
@ApiResponse({
status: 200,
description: '获取成功',
type: UserInfoDto,
})
async getProfile(@CurrentUser() user: any) {
return this.userService.getProfile(user.id);
}
}
```
## 7. AI模板管理 API
### 7.1 模板数据传输对象
```typescript
// src/dto/template.dto.ts
import { ApiProperty } from '@nestjs/swagger';
import { IsString, IsNumber, IsEnum, IsOptional, IsArray, IsBoolean } from 'class-validator';
export enum TemplateType {
IMAGE = 'image',
VIDEO = 'video'
}
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 TemplateExecuteDto {
@ApiProperty({
description: '输入图片URL',
example: 'https://cdn.roasmax.cn/upload/3d590851eb584e92aa415a964e93260e.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 TemplateStatsDto {
@ApiProperty({ description: '总模板数', example: 8 })
total: number;
@ApiProperty({ description: '启用模板数', example: 8 })
enabled: number;
@ApiProperty({ description: '图片模板数', example: 3 })
imageTemplates: number;
@ApiProperty({ description: '视频模板数', example: 5 })
videoTemplates: number;
}
```
### 7.2 模板管理控制器
```typescript
// src/controllers/template.controller.ts
import {
Controller, Get, Post, Param, Body, Query, UseGuards, ParseIntPipe
} from '@nestjs/common';
import {
ApiTags,
ApiOperation,
ApiResponse,
ApiBearerAuth,
ApiParam,
ApiQuery
} from '@nestjs/swagger';
import { JwtAuthGuard } from '../guards/jwt-auth.guard';
import { CurrentUser } from '../decorators/current-user.decorator';
import { ApiCommonResponses, ApiAuthResponses } from '../decorators/api-common-responses.decorator';
import { N8nTemplateFactoryService } from '../services/n8n-template-factory.service';
import { TemplateListDto, TemplateExecuteDto, TemplateExecuteResponseDto, TemplateStatsDto } from '../dto/template.dto';
@ApiTags('🎨 AI模板系统')
@Controller('templates')
@ApiCommonResponses()
export class TemplateController {
constructor(
private readonly templateFactory: N8nTemplateFactoryService,
) {}
@Get()
@ApiOperation({
summary: '获取所有模板列表',
description: '获取所有可用的AI生成模板支持按类型筛选'
})
@ApiQuery({
name: 'type',
required: false,
enum: ['image', 'video'],
description: '模板类型筛选'
})
@ApiResponse({
status: 200,
description: '获取成功',
type: [TemplateListDto]
})
async getTemplates(@Query('type') type?: 'image' | 'video') {
if (type === 'image') {
return this.templateFactory.getTemplatesByType('image');
} else if (type === 'video') {
return this.templateFactory.getTemplatesByType('video');
}
return this.templateFactory.getAllTemplates();
}
@Get('stats')
@ApiOperation({
summary: '获取模板统计信息',
description: '获取模板总数、类型分布等统计信息'
})
@ApiResponse({
status: 200,
description: '获取成功',
type: TemplateStatsDto
})
async getTemplateStats() {
const allTemplates = await this.templateFactory.getAllTemplates();
const imageTemplates = allTemplates.filter(t => t.templateType === 'image');
const videoTemplates = allTemplates.filter(t => t.templateType === 'video');
return {
total: allTemplates.length,
enabled: allTemplates.filter(t => t.isActive).length,
imageTemplates: imageTemplates.length,
videoTemplates: videoTemplates.length,
};
}
@Get(':templateId')
@ApiOperation({
summary: '获取模板详情',
description: '根据模板ID获取详细信息'
})
@ApiParam({
name: 'templateId',
description: '模板ID',
example: 1
})
@ApiResponse({
status: 200,
description: '获取成功',
type: TemplateListDto
})
async getTemplateById(@Param('templateId', ParseIntPipe) templateId: number) {
return this.templateFactory.getTemplateById(templateId);
}
@Get('code/:templateCode')
@ApiOperation({
summary: '通过代码获取模板详情',
description: '根据模板代码获取详细信息'
})
@ApiParam({
name: 'templateCode',
description: '模板代码',
example: 'character_figurine_v1'
})
@ApiResponse({
status: 200,
description: '获取成功',
type: TemplateListDto
})
async getTemplateByCode(@Param('templateCode') templateCode: string) {
return this.templateFactory.getTemplateByCode(templateCode);
}
@Post(':templateId/execute')
@UseGuards(JwtAuthGuard)
@ApiBearerAuth('JWT-auth')
@ApiAuthResponses()
@ApiOperation({
summary: '执行模板生成',
description: '根据模板ID执行AI生成任务支持图片和视频生成'
})
@ApiParam({
name: 'templateId',
description: '模板ID',
example: 1
})
@ApiResponse({
status: 200,
description: '执行成功',
type: TemplateExecuteResponseDto
})
@ApiResponse({
status: 400,
description: '参数错误',
schema: {
example: {
code: 400,
message: '输入图片URL不能为空',
data: null
}
}
})
@ApiResponse({
status: 402,
description: '积分不足',
schema: {
example: {
code: 402,
message: '积分不足,当前余额: 10需要: 28',
data: null
}
}
})
async executeTemplate(
@Param('templateId', ParseIntPipe) templateId: number,
@Body() executeDto: TemplateExecuteDto,
@CurrentUser() user: any
) {
const startTime = Date.now();
// 获取模板配置
const templateConfig = await this.templateFactory.getTemplateById(templateId);
// 创建动态模板实例并执行
let template;
if (templateConfig.templateType === 'image') {
template = await this.templateFactory.createImageTemplate(templateId);
} else {
template = await this.templateFactory.createVideoTemplate(templateId);
}
const result = await template.execute(executeDto.imageUrl);
const executionTime = Date.now() - startTime;
return {
success: true,
imageUrl: templateConfig.templateType === 'image' ? result : undefined,
videoUrl: templateConfig.templateType === 'video' ? result : undefined,
taskId: `req_${Date.now()}_${Math.random().toString(36).substr(2, 6)}`,
executionTime,
creditCost: templateConfig.creditCost
};
}
@Post('code/:templateCode/execute')
@UseGuards(JwtAuthGuard)
@ApiBearerAuth('JWT-auth')
@ApiAuthResponses()
@ApiOperation({
summary: '通过代码执行模板',
description: '根据模板代码执行AI生成任务支持图片和视频生成'
})
@ApiParam({
name: 'templateCode',
description: '模板代码',
example: 'character_figurine_v1'
})
@ApiResponse({
status: 200,
description: '执行成功',
type: TemplateExecuteResponseDto
})
async executeTemplateByCode(
@Param('templateCode') templateCode: string,
@Body() executeDto: TemplateExecuteDto,
@CurrentUser() user: any
) {
const startTime = Date.now();
// 创建动态模板实例并执行
const template = await this.templateFactory.createTemplateByCode(templateCode);
const result = await template.execute(executeDto.imageUrl);
const executionTime = Date.now() - startTime;
return {
success: true,
imageUrl: template.templateType === 'image' ? result : undefined,
videoUrl: template.templateType === 'video' ? result : undefined,
taskId: `req_${Date.now()}_${Math.random().toString(36).substr(2, 6)}`,
executionTime,
creditCost: template.creditCost
};
}
}
```
### 7.3 API使用示例
#### 获取所有模板
```bash
curl -X GET "http://localhost:3000/api/templates" \
-H "accept: application/json"
```
响应示例:
```json
{
"code": 200,
"message": "success",
"data": [
{
"id": 1,
"code": "character_figurine_v1",
"name": "人物手办",
"description": "将人物照片制作成精细的角色手办模型,展示在收藏家房间中,并生成抚摸手办的视频",
"templateType": "video",
"creditCost": 28,
"version": "1.0.0",
"inputExampleUrl": "https://cdn.roasmax.cn/upload/3d590851eb584e92aa415a964e93260e.jpg",
"outputExampleUrl": "https://file.302.ai/gpt/imgs/20250828/2283106b31faf2066e1a72d955f65bca.jpg",
"tags": ["人物", "手办", "模型", "收藏", "PVC", "角色模型", "视频生成"],
"isActive": true,
"createdAt": "2024-01-01T00:00:00Z"
}
]
}
```
#### 执行模板生成
```bash
curl -X POST "http://localhost:3000/api/templates/1/execute" \
-H "accept: application/json" \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"imageUrl": "https://cdn.roasmax.cn/upload/3d590851eb584e92aa415a964e93260e.jpg"
}'
```
响应示例:
```json
{
"code": 200,
"message": "success",
"data": {
"success": true,
"videoUrl": "https://n8n.bowongai.com/files/generated_video_abc123.mp4",
"taskId": "req_1704067200_abc123",
"executionTime": 5000,
"creditCost": 28
}
}
```
### 7.4 错误处理
```typescript
// 常见错误响应
export const TemplateApiErrors = {
TEMPLATE_NOT_FOUND: {
code: 404,
message: '模板不存在',
data: null
},
INSUFFICIENT_CREDITS: {
code: 402,
message: '积分不足',
data: { required: 28, current: 10 }
},
INVALID_IMAGE_URL: {
code: 400,
message: '无效的图片URL',
data: null
},
TEMPLATE_EXECUTION_FAILED: {
code: 500,
message: 'AI生成失败请稍后重试',
data: null
},
TEMPLATE_DISABLED: {
code: 403,
message: '模板已禁用',
data: null
}
};
```
## 8. 环境配置
### 8.1 开发环境配置
```typescript
// src/main.ts
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,
}));
// API前缀
app.setGlobalPrefix('api/v1');
// CORS配置
app.enableCors({
origin: process.env.NODE_ENV === 'production'
? ['https://example.com']
: true,
credentials: true,
});
// 仅在非生产环境启用Swagger
if (process.env.NODE_ENV !== 'production') {
setupSwagger(app);
}
const port = process.env.PORT || 3000;
await app.listen(port);
console.log('🚀 应用启动成功!');
console.log(`📖 API文档地址: http://localhost:${port}/api/docs`);
}
bootstrap();
```
## 9. 访问API文档
启动应用后访问以下地址查看API文档
- **开发环境**: http://localhost:3000/api/docs
- **JSON格式**: http://localhost:3000/api/docs-json
- **YAML格式**: http://localhost:3000/api/docs-yaml
API文档包含
- 📋 完整的接口列表和参数说明
- 🔐 JWT认证测试功能
- 📝 请求/响应示例
- 🧪 在线接口测试功能
- 📊 数据模型定义
- 🎨 AI模板系统接口 (支持图片/视频生成)
- 💾 动态模板配置管理
- 📈 模板使用统计和监控