fix(core): 测试清单 行4-15 — 记住我7天/工作台布局/商品创建选择弹窗/上传图持久化/清空筛选

- 记住我7天:勾选才持久化token+预填用户名,7天过期强制重登(localStorage vs sessionStorage)
- 工作台:最近项目进度/状态列对齐、快捷&提示卡片圆角边框、余额按钮金额左对齐
- 商品创建成功改为复用弹窗,选择 继续创建/去新建项目;主图随创建上传持久化
- 商品卡显示真实主图、点视频进详情视频项目tab
- 商品库/视频项目补 清空筛选 按钮

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
zyc
2026-06-16 14:13:52 +08:00
co-authored by Claude Opus 4.8
parent b2288a2652
commit 57018fb101
10 changed files with 290 additions and 72 deletions
+37 -4
View File
@@ -461,7 +461,8 @@ export function ImageWorkbenchPage({
modelConfigs,
onBack,
navigate,
onGenerate
onGenerate,
onResume
}: {
mode: WorkMode;
products: Product[];
@@ -470,6 +471,7 @@ export function ImageWorkbenchPage({
onBack: () => void;
navigate?: (page: Page) => void;
onGenerate: (payload: { prompt: string; mode?: "image" | "model" | "cover"; count?: number }) => Promise<{ assets: Asset[] } | null>;
onResume?: (mode: "image" | "model" | "cover", ids: string[]) => Promise<{ assets: Asset[] } | null>;
}) {
const meta = MODE_META[mode];
const [productId, setProductId] = useState(products[0]?.id || "");
@@ -532,6 +534,37 @@ export function ImageWorkbenchPage({
}
}
/* 跨刷新恢复:读本地残留(由 App.generateImages 落盘),先回显已出的图,
再对还在跑的任务继续轮询——刷新页面不再丢"生成中"与已出结果。 */
useEffect(() => {
let cancelled = false;
try {
const raw = localStorage.getItem(`airshelf:imgwb:${mode}`);
if (!raw) return;
const saved = JSON.parse(raw) as { pending?: string[]; results?: Asset[]; ts?: number };
if (saved.ts && Date.now() - saved.ts > 60 * 60 * 1000) return; // 1 小时前的残留不恢复
if (saved.results && saved.results.length) setResults(saved.results);
const pending = saved.pending || [];
if (pending.length && onResume) {
setGenerating(true);
onResume(mode, pending)
.then((res) => {
if (!cancelled && res?.assets) setResults(res.assets);
})
.finally(() => {
if (!cancelled) setGenerating(false);
});
}
} catch {
/* 残留解析失败则忽略,按初始态渲染 */
}
return () => {
cancelled = true;
};
// 仅在挂载/切换 mode 时恢复一次
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [mode]);
const hasResults = !!(results && results.length > 0);
/* ── 共享:生成结果网格(§4.18 .gen-card · 三 mode 统一渲染真图)── */
@@ -1002,15 +1035,15 @@ export function ImageWorkbenchPage({
</div>
<div className="gen-card">{renderResultGrid()}</div>
<div className="gen-card-actions">
<button className="btn btn-sm" type="button">
<button className="btn btn-sm" type="button" disabled={generating} onClick={() => runGenerate()}>
<RefreshCw size={13} />
重跑
</button>
<button className="btn btn-sm" type="button">
<button className="btn btn-sm" type="button" onClick={() => navigate?.("library")}>
<Check size={13} />
采用并入资产库
</button>
<button className="btn btn-sm btn-ghost" type="button" title="更多">
<button className="btn btn-sm btn-ghost" type="button" title="下载全部" onClick={() => results?.forEach((asset, i) => { const u = asset.files?.[0]?.preview_url; if (u) downloadImage(u, `${meta.title}-${i + 1}.png`); })}>
<MoreHorizontal size={13} />
</button>
</div>