fix(web): humanize generation failure messages
This commit is contained in:
@@ -4,8 +4,41 @@ import { Alert, Button, Card, Form, Input, Select, Space, Typography, message }
|
||||
import { useMutation, useQuery } from '@tanstack/react-query';
|
||||
import { createGenerationTask, getGenerationResults, getGenerationTask } from '@/api/generation';
|
||||
import { getAssetLibraries } from '@/api/assets';
|
||||
import { getProject } from '@/api/projects';
|
||||
import { useAuthStore } from '@/store/authStore';
|
||||
|
||||
const humanizeGenerationStatus = (status: string) => {
|
||||
const labels: Record<string, string> = {
|
||||
pending: '排队中',
|
||||
running: '生成中',
|
||||
completed: '生成完成',
|
||||
failed: '生成失败',
|
||||
cancelled: '已取消',
|
||||
};
|
||||
return labels[status] || status;
|
||||
};
|
||||
|
||||
const humanizeGenerationError = (errorMessage?: string | null) => {
|
||||
const raw = (errorMessage || '').trim();
|
||||
if (!raw) {
|
||||
return '生成失败了,但系统没有返回具体原因。请重新发起一次;如果还失败,把项目和素材库发给小虾排查。';
|
||||
}
|
||||
const lower = raw.toLowerCase();
|
||||
if (lower.includes('ffmpeg') || lower.includes('ffprobe') || lower.includes('invalid data') || lower.includes('moov atom')) {
|
||||
return '视频素材格式无法被系统识别。请换一个常见 MP4/H.264 文件,或先用剪映/播放器重新导出后再上传。';
|
||||
}
|
||||
if (lower.includes('oss') || lower.includes('bucket') || lower.includes('accesskey') || lower.includes('storage')) {
|
||||
return '素材存储服务暂时异常,系统没能读取或保存文件。请稍后重试;如果持续失败,让小虾检查 OSS 配置。';
|
||||
}
|
||||
if (lower.includes('not found') || lower.includes('no such file')) {
|
||||
return '系统找不到要生成的视频素材。请确认素材已经上传并导入完成,再重新生成。';
|
||||
}
|
||||
if (lower.includes('permission') || lower.includes('forbidden') || lower.includes('unauthorized')) {
|
||||
return '当前账号没有这个项目或素材库的操作权限。请回到工作空间确认登录账号和权限。';
|
||||
}
|
||||
return `生成失败:${raw}`;
|
||||
};
|
||||
|
||||
const ProjectGeneration: React.FC = () => {
|
||||
const { id } = useParams<{ id: string }>();
|
||||
const location = useLocation();
|
||||
@@ -13,16 +46,33 @@ const ProjectGeneration: React.FC = () => {
|
||||
const projectId = id || '';
|
||||
const routedWorkspaceId = (location.state as { workspaceId?: string } | null)?.workspaceId || '';
|
||||
const storedWorkspaceId = projectId ? sessionStorage.getItem(`project-workspace:${projectId}`) || '' : '';
|
||||
const workspaceId = routedWorkspaceId || storedWorkspaceId;
|
||||
const [resolvedWorkspaceId, setResolvedWorkspaceId] = useState<string>(routedWorkspaceId || storedWorkspaceId);
|
||||
const workspaceId = routedWorkspaceId || storedWorkspaceId || resolvedWorkspaceId;
|
||||
const [taskId, setTaskId] = useState('');
|
||||
const [form] = Form.useForm();
|
||||
|
||||
useEffect(() => {
|
||||
if (projectId && routedWorkspaceId) {
|
||||
sessionStorage.setItem(`project-workspace:${projectId}`, routedWorkspaceId);
|
||||
setResolvedWorkspaceId(routedWorkspaceId);
|
||||
}
|
||||
}, [projectId, routedWorkspaceId]);
|
||||
|
||||
const projectQuery = useQuery({
|
||||
queryKey: ['project', projectId],
|
||||
queryFn: () => getProject(projectId),
|
||||
enabled: !!projectId && !workspaceId,
|
||||
retry: false,
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
const projectWorkspaceId = projectQuery.data?.workspace_id;
|
||||
if (projectId && projectWorkspaceId) {
|
||||
sessionStorage.setItem(`project-workspace:${projectId}`, projectWorkspaceId);
|
||||
setResolvedWorkspaceId(projectWorkspaceId);
|
||||
}
|
||||
}, [projectId, projectQuery.data?.workspace_id]);
|
||||
|
||||
const librariesQuery = useQuery({
|
||||
queryKey: ['generation-libraries', projectId],
|
||||
queryFn: () => getAssetLibraries(projectId),
|
||||
@@ -51,7 +101,7 @@ const ProjectGeneration: React.FC = () => {
|
||||
setTaskId(task.id);
|
||||
message.success('生成任务已创建');
|
||||
},
|
||||
onError: (error: any) => message.error(error.response?.data?.detail || '创建生成任务失败'),
|
||||
onError: (error: any) => message.error(humanizeGenerationError(error.response?.data?.detail || '创建生成任务失败')),
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
@@ -70,6 +120,10 @@ const ProjectGeneration: React.FC = () => {
|
||||
[librariesQuery.data]
|
||||
);
|
||||
|
||||
const failedReason = taskQuery.data?.status === 'failed'
|
||||
? humanizeGenerationError(taskQuery.data.error_message)
|
||||
: '';
|
||||
|
||||
return (
|
||||
<div style={{ padding: 24 }}>
|
||||
<Card title="项目生成任务">
|
||||
@@ -127,8 +181,12 @@ const ProjectGeneration: React.FC = () => {
|
||||
<Alert
|
||||
style={{ marginTop: 16 }}
|
||||
type={taskQuery.data.status === 'failed' ? 'error' : taskQuery.data.status === 'completed' ? 'success' : 'info'}
|
||||
message={`任务状态:${taskQuery.data.status}`}
|
||||
description={`进度:${taskQuery.data.progress}% / 结果数:${taskQuery.data.result_count}${taskQuery.data.error_message ? ` / 错误:${taskQuery.data.error_message}` : ''}`}
|
||||
message={`任务状态:${humanizeGenerationStatus(taskQuery.data.status)}`}
|
||||
description={
|
||||
taskQuery.data.status === 'failed'
|
||||
? failedReason
|
||||
: `进度:${taskQuery.data.progress}% / 结果数:${taskQuery.data.result_count}`
|
||||
}
|
||||
/>
|
||||
)}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user