feat: 添加图片内容审核功能到模板执行流程

- 集成统一内容审核服务到模板控制器
- 在模板执行前进行图片内容审核
- 审核未通过时返回403错误和详细原因
- 添加内容审核模块和相关服务
- 创建内容审核日志表迁移文件
This commit is contained in:
imeepos
2025-09-05 14:48:49 +08:00
parent 1e31514f11
commit 00bf807b31
19 changed files with 2393 additions and 6 deletions

View File

@@ -40,6 +40,8 @@ import { Repository } from 'typeorm';
import { ApiCommonResponses } from '../decorators/api-common-responses.decorator';
import { PlatformAuthGuard } from 'src/platform/guards/platform-auth.guard';
import { ResponseUtil, ApiResponse } from '../utils/response.util';
import { UnifiedContentService } from '../content-moderation/services/unified-content.service';
import { AuditConclusion } from '../content-moderation/interfaces/content-moderation.interface';
@ApiTags('AI模板系统')
@Controller('templates')
@@ -51,6 +53,7 @@ export class TemplateController {
private readonly templateRepository: Repository<N8nTemplateEntity>,
@InjectRepository(TemplateExecutionEntity)
private readonly executionRepository: Repository<TemplateExecutionEntity>,
private readonly unifiedContentService: UnifiedContentService,
) { }
@Post(':templateId/execute')
@@ -114,7 +117,7 @@ export class TemplateController {
@UseGuards(PlatformAuthGuard)
@ApiOperation({
summary: '通过代码执行模板',
description: '根据模板代码执行AI生成任务支持图片和视频生成',
description: '根据模板代码执行AI生成任务支持图片和视频生成。执行前会进行图片内容审核。',
})
@ApiParam({
name: 'code',
@@ -127,6 +130,17 @@ export class TemplateController {
description: '执行成功',
type: TemplateExecuteResponseDto,
})
@SwaggerApiResponse({
status: 403,
description: '图片审核未通过',
schema: {
example: {
code: 403,
message: '图片审核未通过: 包含不当内容',
data: null,
},
},
})
async executeTemplateByCode(
@Param('code') code: string,
@Body() body: { imageUrl: string },
@@ -144,13 +158,41 @@ export class TemplateController {
if (!templateConfig) {
throw new HttpException('Template not found', HttpStatus.NOT_FOUND);
}
const userId = req.user.userId;
const platform = req.user.platform;
// 通过模板代码创建实例并执行
// 1. 先进行图片内容审核
const auditResult = await this.unifiedContentService.auditImage(
platform,
{
imageUrl,
userId,
businessType: 'template_execution',
extraData: {
templateId: templateConfig.id,
templateCode: code,
},
}
);
// 2. 检查审核结果
if (auditResult.conclusion !== AuditConclusion.PASS) {
const failureReason = auditResult.details.length > 0
? auditResult.details.map(d => d.description).join(', ')
: '包含不当内容';
throw new HttpException(
`图片审核未通过: ${failureReason}`,
HttpStatus.FORBIDDEN,
);
}
// 3. 审核通过,执行模板
const template = await this.templateFactory.createTemplateByCode(code);
const taskId = await template.execute(imageUrl);
// 将任务保存到 TemplateExecutionEntity
const userId = req.user.userId;
// 4. 将任务保存到 TemplateExecutionEntity
const execution = this.executionRepository.create({
templateId: templateConfig.id,
userId,
@@ -167,13 +209,13 @@ export class TemplateController {
const savedExecution = await this.executionRepository.save(execution);
// 返回任务id (执行记录的ID)
// 返回任务id (执行记录的ID) 以及审核信息
return ResponseUtil.success(savedExecution.id, '模板执行已启动');
} catch (error) {
console.error(error)
throw new HttpException(
error.message || 'Template execution failed',
HttpStatus.INTERNAL_SERVER_ERROR,
error instanceof HttpException ? error.getStatus() : HttpStatus.INTERNAL_SERVER_ERROR,
);
}
}