refactor: 移除executeTemplateByCode接口的后端图片审核功能
- 简化执行流程,直接执行模板跳过后端审核 - 支持前端传递auditTaskId参数用于审核追踪 - 移除UnifiedContentService依赖和相关审核逻辑 - 删除handleAuditComplete和startTemplateExecution方法 - 更新API文档说明前端审核职责 - 修改测试用例适配新的执行流程 - 保持数据库字段兼容性,auditTaskId改为前端传入 变更影响: - executeTemplateByCode接口不再执行后端图片审核 - 执行记录状态直接设为PROCESSING - 前端需要在调用接口前完成图片审核
This commit is contained in:
parent
6ef0fe5bb1
commit
fe0aa0a9c5
|
|
@ -190,28 +190,23 @@ describe('TemplateController', () => {
|
||||||
);
|
);
|
||||||
mockTemplate.execute.mockResolvedValue('task123');
|
mockTemplate.execute.mockResolvedValue('task123');
|
||||||
|
|
||||||
unifiedContentService.auditImage.mockResolvedValue({
|
|
||||||
taskId: 'audit123',
|
|
||||||
status: AuditStatus.COMPLETED,
|
|
||||||
conclusion: AuditConclusion.PASS,
|
|
||||||
confidence: 99,
|
|
||||||
details: [],
|
|
||||||
riskLevel: RiskLevel.LOW,
|
|
||||||
suggestion: AuditSuggestion.PASS,
|
|
||||||
timestamp: new Date(),
|
|
||||||
} as any);
|
|
||||||
|
|
||||||
const result = await controller.executeTemplateByCode(
|
const result = await controller.executeTemplateByCode(
|
||||||
'test_template_v1',
|
'test_template_v1',
|
||||||
{ imageUrl: 'http://example.com/input.jpg' },
|
{ imageUrl: 'http://example.com/input.jpg', auditTaskId: 'audit123' },
|
||||||
mockRequest,
|
mockRequest,
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(result.code).toBe(200);
|
expect(result.code).toBe(200);
|
||||||
expect(result.data?.executionId).toBe(1);
|
expect(result.data?.executionId).toBe(1);
|
||||||
expect(result.data?.taskId).toBe('task123');
|
expect(result.data?.taskId).toBe('task123');
|
||||||
|
expect(result.data?.auditTaskId).toBe('audit123');
|
||||||
expect(result.data?.status).toBe('processing');
|
expect(result.data?.status).toBe('processing');
|
||||||
expect(unifiedContentService.auditImage).toHaveBeenCalled();
|
expect(templateFactory.createTemplateByCode).toHaveBeenCalledWith(
|
||||||
|
'test_template_v1',
|
||||||
|
);
|
||||||
|
expect(mockTemplate.execute).toHaveBeenCalledWith(
|
||||||
|
'http://example.com/input.jpg',
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should throw error when template not found', async () => {
|
it('should throw error when template not found', async () => {
|
||||||
|
|
@ -228,37 +223,24 @@ describe('TemplateController', () => {
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should throw error when image audit fails', async () => {
|
it('should execute template without audit when auditTaskId is not provided', async () => {
|
||||||
templateFactory.getTemplateByCode.mockResolvedValue(mockTemplate as any);
|
templateFactory.getTemplateByCode.mockResolvedValue(mockTemplate as any);
|
||||||
|
templateFactory.createTemplateByCode.mockResolvedValue(
|
||||||
// Reset the mock to ensure it returns the correct audit failure response
|
mockTemplate as any,
|
||||||
unifiedContentService.auditImage.mockResolvedValue({
|
|
||||||
taskId: 'audit123',
|
|
||||||
status: AuditStatus.COMPLETED,
|
|
||||||
conclusion: AuditConclusion.REJECT,
|
|
||||||
confidence: 95,
|
|
||||||
details: [
|
|
||||||
{
|
|
||||||
type: 'inappropriate_content',
|
|
||||||
label: 'blocked',
|
|
||||||
confidence: 95,
|
|
||||||
description: '包含不当内容',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
riskLevel: RiskLevel.HIGH,
|
|
||||||
suggestion: AuditSuggestion.BLOCK,
|
|
||||||
timestamp: new Date(),
|
|
||||||
} as any);
|
|
||||||
|
|
||||||
await expect(
|
|
||||||
controller.executeTemplateByCode(
|
|
||||||
'test_template_v1',
|
|
||||||
{ imageUrl: 'http://example.com/input.jpg' },
|
|
||||||
mockRequest,
|
|
||||||
),
|
|
||||||
).rejects.toThrow(
|
|
||||||
new HttpException('图片审核未通过: 包含不当内容', HttpStatus.FORBIDDEN),
|
|
||||||
);
|
);
|
||||||
|
mockTemplate.execute.mockResolvedValue('task123');
|
||||||
|
|
||||||
|
const result = await controller.executeTemplateByCode(
|
||||||
|
'test_template_v1',
|
||||||
|
{ imageUrl: 'http://example.com/input.jpg' },
|
||||||
|
mockRequest,
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(result.code).toBe(200);
|
||||||
|
expect(result.data?.executionId).toBe(1);
|
||||||
|
expect(result.data?.taskId).toBe('task123');
|
||||||
|
expect(result.data?.auditTaskId).toBeNull();
|
||||||
|
expect(result.data?.status).toBe('processing');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should throw error when user has too many tasks', async () => {
|
it('should throw error when user has too many tasks', async () => {
|
||||||
|
|
@ -278,7 +260,7 @@ describe('TemplateController', () => {
|
||||||
),
|
),
|
||||||
).rejects.toThrow(
|
).rejects.toThrow(
|
||||||
new HttpException(
|
new HttpException(
|
||||||
'有4个任务正在进行中,请稍后再试',
|
'当前账号有4个任务正在进行中,且距开始时间不足5分钟,请稍后再试',
|
||||||
HttpStatus.TOO_MANY_REQUESTS,
|
HttpStatus.TOO_MANY_REQUESTS,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -119,14 +119,16 @@ export class TemplateController {
|
||||||
@ApiOperation({
|
@ApiOperation({
|
||||||
summary: '通过代码执行模板',
|
summary: '通过代码执行模板',
|
||||||
description: `
|
description: `
|
||||||
根据模板代码执行AI生成任务,支持同步和异步两种审核模式:
|
根据模板代码执行AI生成任务,直接执行模板无需后端审核。
|
||||||
- 同步模式:立即返回审核结果,若通过则开始执行,返回 executionId 和 taskId
|
|
||||||
- 异步模式:返回 executionId 和 auditTaskId,等待审核回调完成后开始执行
|
|
||||||
|
|
||||||
ID说明:
|
参数说明:
|
||||||
|
- imageUrl: 输入图片URL(必需)
|
||||||
|
- auditTaskId: 前端审核任务ID(可选),用于追踪审核记录
|
||||||
|
|
||||||
|
返回ID说明:
|
||||||
- executionId: 数据库执行记录主键,用于查询执行状态
|
- executionId: 数据库执行记录主键,用于查询执行状态
|
||||||
- taskId: 外部服务(N8N)任务ID,同步模式时返回
|
- taskId: 外部服务(N8N)任务ID,用于追踪模板执行状态
|
||||||
- auditTaskId: 审核服务任务ID,异步模式时返回
|
- auditTaskId: 前端传入的审核任务ID
|
||||||
`,
|
`,
|
||||||
})
|
})
|
||||||
@ApiParam({
|
@ApiParam({
|
||||||
|
|
@ -144,35 +146,11 @@ export class TemplateController {
|
||||||
message: '模板执行已启动',
|
message: '模板执行已启动',
|
||||||
data: {
|
data: {
|
||||||
executionId: 123,
|
executionId: 123,
|
||||||
taskId: 'n8n_task_456', // 同步模式
|
taskId: 'n8n_task_456',
|
||||||
status: 'processing'
|
auditTaskId: 'audit_task_789',
|
||||||
}
|
status: 'processing',
|
||||||
}
|
message: '模板执行已启动',
|
||||||
}
|
},
|
||||||
})
|
|
||||||
@SwaggerApiResponse({
|
|
||||||
status: 200,
|
|
||||||
description: '异步审核模式',
|
|
||||||
schema: {
|
|
||||||
example: {
|
|
||||||
code: 200,
|
|
||||||
message: '模板执行已提交,正在进行图片审核',
|
|
||||||
data: {
|
|
||||||
executionId: 124,
|
|
||||||
auditTaskId: 'audit_task_789', // 异步模式
|
|
||||||
status: 'pending_audit'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
@SwaggerApiResponse({
|
|
||||||
status: 403,
|
|
||||||
description: '图片审核未通过',
|
|
||||||
schema: {
|
|
||||||
example: {
|
|
||||||
code: 403,
|
|
||||||
message: '图片审核未通过: 包含不当内容',
|
|
||||||
data: null,
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
@ -590,10 +568,10 @@ export class TemplateController {
|
||||||
outputUrl: null,
|
outputUrl: null,
|
||||||
errorMessage: null,
|
errorMessage: null,
|
||||||
createdAt: '2025-01-01T00:00:00Z',
|
createdAt: '2025-01-01T00:00:00Z',
|
||||||
updatedAt: '2025-01-01T00:05:00Z'
|
updatedAt: '2025-01-01T00:05:00Z',
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
@SwaggerApiResponse({
|
@SwaggerApiResponse({
|
||||||
status: 404,
|
status: 404,
|
||||||
|
|
@ -881,7 +859,6 @@ export class TemplateController {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 更新执行状态
|
* 更新执行状态
|
||||||
*/
|
*/
|
||||||
|
|
@ -899,7 +876,10 @@ export class TemplateController {
|
||||||
updateData.errorMessage = errorMessage;
|
updateData.errorMessage = errorMessage;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (status === ExecutionStatus.FAILED || status === ExecutionStatus.AUDIT_FAILED) {
|
if (
|
||||||
|
status === ExecutionStatus.FAILED ||
|
||||||
|
status === ExecutionStatus.AUDIT_FAILED
|
||||||
|
) {
|
||||||
updateData.completedAt = new Date();
|
updateData.completedAt = new Date();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -284,6 +284,15 @@ export class TemplateExecuteDto {
|
||||||
})
|
})
|
||||||
@IsString()
|
@IsString()
|
||||||
imageUrl: string;
|
imageUrl: string;
|
||||||
|
|
||||||
|
@ApiProperty({
|
||||||
|
description: '审核任务ID(可选)',
|
||||||
|
required: false,
|
||||||
|
example: 'audit_task_12345',
|
||||||
|
})
|
||||||
|
@IsString()
|
||||||
|
@IsOptional()
|
||||||
|
auditTaskId?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class TemplateExecuteResponseDto {
|
export class TemplateExecuteResponseDto {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue