resolve: 解决template.controller.ts合并冲突

- 保留内容审核功能(403状态码响应)
- 保留任务限制检查功能(429状态码响应)
- 合并两个版本的executeTemplateByCode方法
- 确保UnifiedContentService正确注入
This commit is contained in:
imeepos 2025-09-05 14:53:54 +08:00
commit da5db8c5b6
1 changed files with 100 additions and 30 deletions

View File

@ -34,7 +34,11 @@ import {
TemplateListDto, TemplateListDto,
BatchExecuteDto, BatchExecuteDto,
} from '../dto/template.dto'; } from '../dto/template.dto';
import { TemplateExecutionEntity, ExecutionStatus, ExecutionType } from '../entities/template-execution.entity'; import {
TemplateExecutionEntity,
ExecutionStatus,
ExecutionType,
} from '../entities/template-execution.entity';
import { InjectRepository } from '@nestjs/typeorm'; import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm'; import { Repository } from 'typeorm';
import { ApiCommonResponses } from '../decorators/api-common-responses.decorator'; import { ApiCommonResponses } from '../decorators/api-common-responses.decorator';
@ -54,7 +58,7 @@ export class TemplateController {
@InjectRepository(TemplateExecutionEntity) @InjectRepository(TemplateExecutionEntity)
private readonly executionRepository: Repository<TemplateExecutionEntity>, private readonly executionRepository: Repository<TemplateExecutionEntity>,
private readonly unifiedContentService: UnifiedContentService, private readonly unifiedContentService: UnifiedContentService,
) { } ) {}
@Post(':templateId/execute') @Post(':templateId/execute')
@ApiOperation({ @ApiOperation({
@ -141,10 +145,22 @@ export class TemplateController {
}, },
}, },
}) })
@SwaggerApiResponse({
status: 429,
description: '任务数量限制',
schema: {
example: {
code: 429,
message:
'当前账号有3个任务正在进行中且距开始时间不足5分钟请稍后再试',
data: null,
},
},
})
async executeTemplateByCode( async executeTemplateByCode(
@Param('code') code: string, @Param('code') code: string,
@Body() body: { imageUrl: string }, @Body() body: { imageUrl: string },
@Request() req @Request() req,
): Promise<ApiResponse<number>> { ): Promise<ApiResponse<number>> {
try { try {
const { imageUrl } = body; const { imageUrl } = body;
@ -153,13 +169,17 @@ export class TemplateController {
throw new HttpException('imageUrl is required', HttpStatus.BAD_REQUEST); throw new HttpException('imageUrl is required', HttpStatus.BAD_REQUEST);
} }
const userId = req.user.userId;
// 检查用户当前的任务限制
await this.checkUserTaskLimit(userId);
// 首先获取模板配置以确定模板类型 // 首先获取模板配置以确定模板类型
const templateConfig = await this.templateFactory.getTemplateByCode(code); const templateConfig = await this.templateFactory.getTemplateByCode(code);
if (!templateConfig) { if (!templateConfig) {
throw new HttpException('Template not found', HttpStatus.NOT_FOUND); throw new HttpException('Template not found', HttpStatus.NOT_FOUND);
} }
const userId = req.user.userId;
const platform = req.user.platform; const platform = req.user.platform;
// 1. 先进行图片内容审核 // 1. 先进行图片内容审核
@ -197,7 +217,10 @@ export class TemplateController {
templateId: templateConfig.id, templateId: templateConfig.id,
userId, userId,
platform: req.user.platform, platform: req.user.platform,
type: templateConfig.templateType === TemplateType.VIDEO ? ExecutionType.VIDEO : ExecutionType.IMAGE, type:
templateConfig.templateType === TemplateType.VIDEO
? ExecutionType.VIDEO
: ExecutionType.IMAGE,
prompt: '', // 可以从请求参数中获取,如果有的话 prompt: '', // 可以从请求参数中获取,如果有的话
inputImageUrl: imageUrl, inputImageUrl: imageUrl,
taskId: taskId, // 保存外部系统返回的任务ID用于回调匹配 taskId: taskId, // 保存外部系统返回的任务ID用于回调匹配
@ -212,7 +235,7 @@ export class TemplateController {
// 返回任务id (执行记录的ID) 以及审核信息 // 返回任务id (执行记录的ID) 以及审核信息
return ResponseUtil.success(savedExecution.id, '模板执行已启动'); return ResponseUtil.success(savedExecution.id, '模板执行已启动');
} catch (error) { } catch (error) {
console.error(error) console.error(error);
throw new HttpException( throw new HttpException(
error.message || 'Template execution failed', error.message || 'Template execution failed',
error instanceof HttpException ? error.getStatus() : HttpStatus.INTERNAL_SERVER_ERROR, error instanceof HttpException ? error.getStatus() : HttpStatus.INTERNAL_SERVER_ERROR,
@ -220,6 +243,48 @@ export class TemplateController {
} }
} }
/**
*
* @param userId ID
* @throws HttpException
*/
private async checkUserTaskLimit(userId: string): Promise<void> {
// 查询用户当前进行中的任务
const processingTasks = await this.executionRepository.find({
where: {
userId,
status: ExecutionStatus.PROCESSING,
},
order: {
startedAt: 'ASC',
},
});
// 如果当前没有进行中的任务,允许执行
if (processingTasks.length === 0) {
return;
}
// 如果当前进行中任务数量已达到3个需要检查时间限制
if (processingTasks.length >= 3) {
const now = new Date();
const fiveMinutesAgo = new Date(now.getTime() - 5 * 60 * 1000);
// 检查是否有任务在5分钟内开始
const recentTasks = processingTasks.filter(
(task) =>
task.startedAt && task.startedAt.getTime() > fiveMinutesAgo.getTime(),
);
if (recentTasks.length > 3) {
throw new HttpException(
`${recentTasks.length}个任务正在进行中,请稍后再试`,
HttpStatus.TOO_MANY_REQUESTS,
);
}
}
}
@Post(':templateId/batch-execute') @Post(':templateId/batch-execute')
@ApiOperation({ @ApiOperation({
summary: '批量执行模板', summary: '批量执行模板',
@ -474,7 +539,9 @@ export class TemplateController {
* @returns * @returns
*/ */
@Get('execution/:taskId/progress') @Get('execution/:taskId/progress')
async getExecutionProgress(@Param('taskId', ParseIntPipe) taskId: number): Promise<ApiResponse<any>> { async getExecutionProgress(
@Param('taskId', ParseIntPipe) taskId: number,
): Promise<ApiResponse<any>> {
try { try {
const execution = await this.executionRepository.findOne({ const execution = await this.executionRepository.findOne({
where: { id: taskId }, where: { id: taskId },
@ -488,27 +555,30 @@ export class TemplateController {
); );
} }
return ResponseUtil.success({ return ResponseUtil.success(
taskId: execution.id, {
templateId: execution.templateId, taskId: execution.id,
templateName: execution.template?.name, templateId: execution.templateId,
userId: execution.userId, templateName: execution.template?.name,
platform: execution.platform, userId: execution.userId,
type: execution.type, platform: execution.platform,
status: execution.status, type: execution.type,
progress: execution.progress, status: execution.status,
inputImageUrl: execution.inputImageUrl, progress: execution.progress,
outputUrl: execution.outputUrl, inputImageUrl: execution.inputImageUrl,
thumbnailUrl: execution.thumbnailUrl, outputUrl: execution.outputUrl,
errorMessage: execution.errorMessage, thumbnailUrl: execution.thumbnailUrl,
creditCost: execution.creditCost, errorMessage: execution.errorMessage,
startedAt: execution.startedAt, creditCost: execution.creditCost,
completedAt: execution.completedAt, startedAt: execution.startedAt,
executionDuration: execution.executionDuration, completedAt: execution.completedAt,
createdAt: execution.createdAt, executionDuration: execution.executionDuration,
updatedAt: execution.updatedAt, createdAt: execution.createdAt,
executionResult: execution.executionResult updatedAt: execution.updatedAt,
}, '获取执行进度成功'); executionResult: execution.executionResult,
},
'获取执行进度成功',
);
} catch (error) { } catch (error) {
if (error instanceof HttpException) { if (error instanceof HttpException) {
throw error; throw error;