fix: 优化 compact 对话框、画布节点标签、删图重置及比例弹窗

- compact 模式尺寸调整,生成按钮不再溢出框外
- 生成时自动进入 compact 状态,idle 时恢复
- 删除所有样图后重置为新对话状态(清除画布、恢复标题)
- 去掉 drag handle 模式标签,原图右上角统一高级黑 tag
- 作品图不再显示重复标识
- 比例弹窗宽度自适应内容,添加 hover/active 交互样式
- 套图模式默认三种各一张
- 设置弹窗点击外部可关闭
- 历史记录删除按钮样式优化

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
2026-06-12 12:37:32 +08:00
parent 863f1f075e
commit e88edbe165
2 changed files with 120 additions and 70 deletions
+28 -19
View File
@@ -981,9 +981,9 @@ const cloneSetCountOptions: Array<{
];
const cloneSetCountKeys = cloneSetCountOptions.map((option) => option.key);
const defaultCloneSetCounts: Record<CloneSetCountKey, number> = {
selling: 3,
selling: 1,
white: 1,
scene: 3,
scene: 1,
};
const minCloneSetTotal = 1;
const maxCloneSetTotal = 16;
@@ -1674,9 +1674,9 @@ function ProductClonePage(_props: ProductClonePageProps = {}) {
const [selectedScenes, setSelectedScenes] = useState<string[]>([]);
useEffect(() => {
if (status === "done") {
if (status === "done" || status === "generating") {
setIsCommandComposerCompact(true);
} else if (status === "generating" || status === "idle") {
} else if (status === "idle") {
setIsCommandComposerCompact(false);
}
}, [status]);
@@ -2623,6 +2623,12 @@ function ProductClonePage(_props: ProductClonePageProps = {}) {
if (next.length === 0) {
setStatus("idle");
setResults([]);
setCanvasNodes([]);
setIsCommandComposerCompact(false);
setPreviewOffset({ x: 0, y: 0 });
previewOffsetRef.current = { x: 0, y: 0 };
setPreviewZoom(1);
setActiveHistoryRecordId(null);
}
return next;
});
@@ -3013,7 +3019,7 @@ function ProductClonePage(_props: ProductClonePageProps = {}) {
const composer = commandComposerWrapRef.current;
if (composer?.contains(target)) return;
if (composerMenu && composerMenu !== "settings") setComposerMenu(null);
if (composerMenu) setComposerMenu(null);
if (status === "done" && !isCommandComposerCompact) setIsCommandComposerCompact(true);
};
@@ -3629,6 +3635,7 @@ function ProductClonePage(_props: ProductClonePageProps = {}) {
setDetailRequirement("");
setSelectedDetailModules(defaultDetailModuleIds);
setDetailStatus("idle");
setIsCommandComposerCompact(false);
};
const activeToolMeta = sideTools.find((tool) => tool.key === activeTool);
@@ -4655,25 +4662,27 @@ function ProductClonePage(_props: ProductClonePageProps = {}) {
}
}}
>
<span className="clone-ai-node-label">{node.mode === "set" ? "套图" : node.mode === "detail" ? "详情图" : node.mode === "model" ? "模特图" : node.mode === "hot" ? "爆款图" : node.mode}</span>
</div>
{node.sourceImage ? (
<button
type="button"
className="clone-ai-main-result"
onClick={() => openProductSetPreview({ src: node.sourceImage!, label: "原图素材" })}
>
<img src={node.sourceImage} alt="原图素材" />
<span></span>
</button>
<div className="clone-ai-main-result-wrap">
<button
type="button"
className="clone-ai-main-result"
onClick={() => openProductSetPreview({ src: node.sourceImage!, label: "原图素材" })}
>
<img src={node.sourceImage} alt="原图素材" />
<span className="clone-ai-img-tag"></span>
</button>
</div>
) : null}
<div className="clone-ai-flow-arrow" aria-hidden="true" />
<div className="clone-ai-result-grid result-reveal">
{node.results.map((card) => (
<button key={card.id} type="button" style={{ aspectRatio: parseRatioToAspectCss(ratio) }} onClick={() => openProductSetPreview(card)}>
<img src={card.src} alt={card.label} />
<span>{card.label}</span>
</button>
{node.results.map((card, cardIndex) => (
<div key={card.id} className="clone-ai-result-item">
<button type="button" style={{ aspectRatio: parseRatioToAspectCss(ratio) }} onClick={() => openProductSetPreview(card)}>
<img src={card.src} alt={card.label} />
</button>
</div>
))}
</div>
</article>