fix: 全站页面保活机制、登录拦截优化、UI修复与功能完善

- 移除未登录全页面拦截,改为浏览自由 + 功能使用时弹窗
- 修复PageTransition退出动画卡死导致黑屏的bug
- CanvasPage添加加载中状态避免首次访问黑屏假死
- 全站7个工具页添加页面保活机制,切页后台任务不中断
- 修复未登录时401误触发"用户已在别处登录"弹窗
- 删除MorePage模板板块、微信登录、EcommerceTemplates/SizeTemplate路由
- 剧本评分接入DashScope qwen3.7-max直连API
- 电商视频生成重构为3阶段可视管线(策划→生成图片→生成视频)
- 电商视频保活增强:异步函数直接写localStorage避免卸载丢失
- Workbench侧边栏移除mode过滤,三模式共用同一对话列表
- 首页更新轮播图/背景视频、按钮跳转修正、文案优化
- AppShell顶栏新增网站备案信息按钮
- 多个页面的terminate/cancel按钮覆盖、单镜头重试、批量保存下载

Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
2026-06-03 01:39:06 +08:00
parent 8f57e08004
commit 468d1d27dd
35 changed files with 1263 additions and 441 deletions
@@ -22,6 +22,7 @@ import type { WebImageWorkbenchTool, WebViewKey } from "../../types";
import { aiGenerationClient } from "../../api/aiGenerationClient";
import { uploadAssetWithProgress } from "../../api/uploadWithProgress";
import { waitForTask } from "../../api/taskSubscription";
import { saveToolTaskState, loadToolTaskState, clearToolTaskState } from "../workbench/toolKeepalive";
import { addToolResultToAssetLibrary, saveToolResultToLocal } from "../workbench/toolResultActions";
import { CheckCircleOutlined, InfoCircleOutlined } from "@ant-design/icons";
@@ -85,12 +86,32 @@ function CharacterMixPage({
};
}, [checkImage, characterPreview]);
const keepaliveRestoredRef = useRef(false);
// Keep-alive: restore saved task on mount
useEffect(() => {
if (keepaliveRestoredRef.current) return;
keepaliveRestoredRef.current = true;
const saved = loadToolTaskState("charactermix");
if (!saved || saved.resultUrl) return;
setIsCreating(true);
abortRef.current = false;
void pollTaskUntilDone(saved.taskId).then((result) => {
setResultUrl(result);
setNotice(result ? "角色迁移完成" : "已取消");
setIsCreating(false);
setProgress(0);
if (result) {
saveToolTaskState("charactermix", { taskId: saved.taskId, resultUrl: result, status: "完成", progress: 100 });
} else {
clearToolTaskState("charactermix");
}
});
}, []);
useEffect(() => {
return () => {
abortRef.current = true;
if (taskIdRef.current) {
aiGenerationClient.cancelTask(taskIdRef.current).catch(() => {});
}
};
}, []);
@@ -100,6 +121,7 @@ function CharacterMixPage({
aiGenerationClient.cancelTask(taskIdRef.current).catch(() => {});
taskIdRef.current = null;
}
clearToolTaskState("charactermix");
}, []);
const pollTaskUntilDone = useCallback(async (taskId: string): Promise<string | null> => {
@@ -153,10 +175,16 @@ function CharacterMixPage({
muted: !watermark,
});
taskIdRef.current = taskId;
saveToolTaskState("charactermix", { taskId, status: "running", progress: 0 });
const result = await pollTaskUntilDone(taskId);
setResultUrl(result);
setNotice(result ? "角色迁移完成" : "已取消");
if (result) {
saveToolTaskState("charactermix", { taskId, resultUrl: result, status: "完成", progress: 100 });
} else {
clearToolTaskState("charactermix");
}
} catch (error) {
setNotice(error instanceof Error ? error.message : "任务创建失败,请稍后重试。");
} finally {