Files
bw-mini-app-server/src/controllers/template.controller.ts
imeepos cf6844ad6e refactor: 移除模板迁移API接口,改为migrations阶段处理
- 删除 template-migration.service.ts 文件
- 移除控制器中的迁移相关API接口 (/migrate, /sync, /admin/migration-report)
- 清理文档中的迁移服务相关内容
- 添加 data-source.ts 配置文件用于运行数据库迁移
- 模板迁移功能完全通过数据库migration脚本处理
2025-09-04 15:36:26 +08:00

282 lines
7.1 KiB
TypeScript
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.
import {
Controller,
Get,
Post,
Param,
Body,
ParseIntPipe,
Query,
HttpException,
HttpStatus
} from '@nestjs/common';
import { N8nTemplateFactoryService } from '../services/n8n-template-factory.service';
/**
* 模板控制器
* 提供模板相关的API接口支持混合式架构的动态模板管理
*/
@Controller('templates')
export class TemplateController {
constructor(
private readonly templateFactory: N8nTemplateFactoryService
) {}
/**
* 执行模板 - 通过模板ID
* @param templateId 模板ID
* @param body 请求体包含imageUrl
* @returns 执行结果
*/
@Post(':templateId/execute')
async executeTemplateById(
@Param('templateId', ParseIntPipe) templateId: number,
@Body() body: { imageUrl: string }
) {
try {
const { imageUrl } = body;
if (!imageUrl) {
throw new HttpException('imageUrl is required', HttpStatus.BAD_REQUEST);
}
// 通过工厂服务创建模板实例并执行
const template = await this.templateFactory.createTemplate(templateId);
const result = await template.execute(imageUrl);
return {
success: true,
data: {
templateId,
templateCode: template.code,
templateName: template.name,
inputUrl: imageUrl,
outputUrl: result,
creditCost: template.creditCost
}
};
} catch (error) {
throw new HttpException(
error.message || 'Template execution failed',
HttpStatus.INTERNAL_SERVER_ERROR
);
}
}
/**
* 执行模板 - 通过模板代码
* @param code 模板代码
* @param body 请求体包含imageUrl
* @returns 执行结果
*/
@Post('code/:code/execute')
async executeTemplateByCode(
@Param('code') code: string,
@Body() body: { imageUrl: string }
) {
try {
const { imageUrl } = body;
if (!imageUrl) {
throw new HttpException('imageUrl is required', HttpStatus.BAD_REQUEST);
}
// 通过模板代码创建实例并执行
const template = await this.templateFactory.createTemplateByCode(code);
const result = await template.execute(imageUrl);
return {
success: true,
data: {
templateCode: template.code,
templateName: template.name,
inputUrl: imageUrl,
outputUrl: result,
creditCost: template.creditCost
}
};
} catch (error) {
throw new HttpException(
error.message || 'Template execution failed',
HttpStatus.INTERNAL_SERVER_ERROR
);
}
}
/**
* 批量执行模板
* @param templateId 模板ID
* @param body 包含多个imageUrl的数组
* @returns 批量执行结果
*/
@Post(':templateId/batch-execute')
async batchExecuteTemplate(
@Param('templateId', ParseIntPipe) templateId: number,
@Body() body: { imageUrls: string[] }
) {
try {
const { imageUrls } = body;
if (!imageUrls || !Array.isArray(imageUrls) || imageUrls.length === 0) {
throw new HttpException('imageUrls array is required', HttpStatus.BAD_REQUEST);
}
const results = await this.templateFactory.batchExecute(templateId, imageUrls);
return {
success: true,
data: {
templateId,
totalCount: imageUrls.length,
results: imageUrls.map((inputUrl, index) => ({
inputUrl,
outputUrl: results[index]
}))
}
};
} catch (error) {
throw new HttpException(
error.message || 'Batch execution failed',
HttpStatus.INTERNAL_SERVER_ERROR
);
}
}
/**
* 获取所有模板列表
* @returns 模板配置列表
*/
@Get()
async getAllTemplates() {
try {
const templates = await this.templateFactory.getAllTemplates();
return {
success: true,
data: templates.map(template => ({
id: template.id,
code: template.code,
name: template.name,
description: template.description,
creditCost: template.creditCost,
version: template.version,
templateType: template.templateType,
templateClass: template.templateClass,
tags: template.tags,
inputExample: template.inputExampleUrl,
outputExample: template.outputExampleUrl,
sortOrder: template.sortOrder,
isActive: template.isActive,
createdAt: template.createdAt,
updatedAt: template.updatedAt
}))
};
} catch (error) {
throw new HttpException(
error.message || 'Failed to fetch templates',
HttpStatus.INTERNAL_SERVER_ERROR
);
}
}
/**
* 获取图片类型模板
* @returns 图片模板列表
*/
@Get('image')
async getImageTemplates() {
try {
const templates = await this.templateFactory.getImageTemplates();
return {
success: true,
data: templates
};
} catch (error) {
throw new HttpException(
error.message || 'Failed to fetch image templates',
HttpStatus.INTERNAL_SERVER_ERROR
);
}
}
/**
* 获取视频类型模板
* @returns 视频模板列表
*/
@Get('video')
async getVideoTemplates() {
try {
const templates = await this.templateFactory.getVideoTemplates();
return {
success: true,
data: templates
};
} catch (error) {
throw new HttpException(
error.message || 'Failed to fetch video templates',
HttpStatus.INTERNAL_SERVER_ERROR
);
}
}
/**
* 根据用户偏好推荐模板
* @param tags 用户偏好标签,逗号分隔
* @param limit 推荐数量
* @returns 推荐模板列表
*/
@Get('recommend')
async recommendTemplates(
@Query('tags') tags?: string,
@Query('limit') limit: number = 5
) {
try {
const userTags = tags ? tags.split(',').map(tag => tag.trim()) : [];
const templates = await this.templateFactory.recommendTemplates(userTags, limit);
return {
success: true,
data: {
userTags,
recommendedTemplates: templates
}
};
} catch (error) {
throw new HttpException(
error.message || 'Failed to recommend templates',
HttpStatus.INTERNAL_SERVER_ERROR
);
}
}
/**
* 获取特定模板详情
* @param templateId 模板ID
* @returns 模板详细信息
*/
@Get(':templateId')
async getTemplateById(@Param('templateId', ParseIntPipe) templateId: number) {
try {
const template = await this.templateFactory.createTemplate(templateId);
return {
success: true,
data: {
id: templateId,
code: template.code,
name: template.name,
description: template.description,
creditCost: template.creditCost,
version: template.version,
tags: template.tags,
inputExample: template.input,
outputExample: template.output
}
};
} catch (error) {
throw new HttpException(
error.message || 'Template not found',
HttpStatus.NOT_FOUND
);
}
}
}