优化 AI 设计任务失败提示

问题:客户端直接展示 policy_blocked 等内部错误码。

实现:统一转换为中文设计语言提示,并补充策略拦截场景回归测试。
This commit is contained in:
2026-08-05 16:28:39 +08:00
parent 3cc2182ffd
commit 2a3c9850d1
2 changed files with 33 additions and 1 deletions

View File

@@ -37,6 +37,19 @@ import type {
} from '../../../shared/image-workspace'; } from '../../../shared/image-workspace';
const ACTIVE_TASK_STATUSES = new Set<DesignTaskStatus>(['queued', 'running']); const ACTIVE_TASK_STATUSES = new Set<DesignTaskStatus>(['queued', 'running']);
const TASK_FAILURE_MESSAGES: Record<string, string> = {
policy_blocked: '内容可能涉及版权或安全风险,请调整设计后重试',
budget_denied: '当前设计点不足,无法开始生成',
quote_expired: '生成方案已过期,请重新确认',
asset_rejected: '生成结果未通过媒体检查,请调整设计后重试',
dependency_unavailable: '生成服务暂时不可用,请稍后重试',
submission_unknown: '正在确认生成请求状态,请稍后查看',
submission_not_accepted: '生成请求未被服务接受,请重新确认后再试',
generation_failed: '生成未完成,请调整设计或稍后重试',
result_persist_failed: '生成结果保存失败,请稍后重试',
cancelled: '生成任务已取消',
expired: '生成任务已过期,请重新确认',
};
const CONFIRMATION_UNAVAILABLE_MESSAGE = ( const CONFIRMATION_UNAVAILABLE_MESSAGE = (
'当前没有可确认的生成报价,请先让设计 Agent 完成方案与报价。' '当前没有可确认的生成报价,请先让设计 Agent 完成方案与报价。'
); );
@@ -61,6 +74,10 @@ function taskStatusLabel(status: DesignTaskStatus): string {
return '失败'; return '失败';
} }
function taskFailureMessage(code: string): string {
return TASK_FAILURE_MESSAGES[code] ?? '生成未完成,请稍后重试';
}
function mediumLabel(medium: 'image' | 'video'): string { function mediumLabel(medium: 'image' | 'video'): string {
return medium === 'video' ? '视频' : '图片'; return medium === 'video' ? '视频' : '图片';
} }
@@ -153,7 +170,7 @@ function TaskCard({ task }: { task: DesignGenerationTask }) {
</p> </p>
{task.failureCode ? ( {task.failureCode ? (
<p role="alert" className="mt-2 rounded-lg bg-destructive/10 px-2 py-1.5 text-[11px] font-semibold text-destructive"> <p role="alert" className="mt-2 rounded-lg bg-destructive/10 px-2 py-1.5 text-[11px] font-semibold text-destructive">
{task.failureCode} {taskFailureMessage(task.failureCode)}
</p> </p>
) : null} ) : null}
</div> </div>

View File

@@ -482,6 +482,21 @@ describe('ImageCanvas Workspace-first design experience', () => {
expect(confirmImageWorkspaceGenerationMock).not.toHaveBeenCalled(); expect(confirmImageWorkspaceGenerationMock).not.toHaveBeenCalled();
}); });
it('renders policy-blocked generation tasks with a user-facing design message', async () => {
fetchImageWorkspaceTasksMock.mockResolvedValue([{
...taskFixture,
status: 'failed',
failureCode: 'policy_blocked',
resultAssets: [],
}]);
render(<MemoryRouter><ImageCanvas /></MemoryRouter>);
const alert = await screen.findByRole('alert');
expect(alert).toHaveTextContent('内容可能涉及版权或安全风险,请调整设计后重试');
expect(alert).not.toHaveTextContent('policy_blocked');
});
it('renders a new task pushed by the design event stream without repeated polling', async () => { it('renders a new task pushed by the design event stream without repeated polling', async () => {
const queuedTask = { const queuedTask = {
...taskFixture, ...taskFixture,