From e60177c1778d42ca5e1b5834baae6076cfec18f2 Mon Sep 17 00:00:00 2001 From: Your Name Date: Sun, 5 Apr 2026 03:00:29 +0800 Subject: [PATCH] Polish video canvas surface consistency --- app/canvas/[id]/page.tsx | 32 +++++----- components/canvas/CanvasWorkspace.tsx | 10 +-- components/canvas/nodes/ImageNode.tsx | 78 ++++++++++++------------ components/canvas/nodes/VideoNode.tsx | 26 ++++---- components/canvas/nodes/WorkflowNode.tsx | 49 +++++++-------- 5 files changed, 98 insertions(+), 97 deletions(-) diff --git a/app/canvas/[id]/page.tsx b/app/canvas/[id]/page.tsx index 4ffda8086..b4374c7c6 100644 --- a/app/canvas/[id]/page.tsx +++ b/app/canvas/[id]/page.tsx @@ -419,19 +419,19 @@ const AGENT_RESULT_MODE_LABELS: Record = sku_replacement: "SKU 替换", }; const VIDEO_CANVAS_PANEL_CLASS = - "pointer-events-auto overflow-hidden rounded-[28px] border border-border/60 bg-background shadow-2xl"; + "pointer-events-auto overflow-hidden rounded-[28px] border border-slate-200 bg-white text-foreground shadow-[0_20px_50px_-28px_rgba(15,23,42,0.24)] dark:border-zinc-800 dark:bg-zinc-950"; const VIDEO_CANVAS_PANEL_BADGE_CLASS = - "border-border/60 bg-background text-foreground/75"; + "border-slate-200 bg-white text-foreground/75 dark:border-zinc-800 dark:bg-zinc-950"; const VIDEO_CANVAS_SUBSECTION_CLASS = - "rounded-2xl border border-border/60 bg-background p-3"; + "rounded-2xl border border-slate-200 bg-white p-3 dark:border-zinc-800 dark:bg-zinc-950"; const VIDEO_CANVAS_TOOLBAR_CLASS = - "flex items-center gap-1.5 rounded-[28px] border border-border/60 bg-background px-2.5 py-1.5 shadow-2xl"; + "flex items-center gap-1.5 rounded-[28px] border border-slate-200 bg-white px-2.5 py-1.5 shadow-[0_18px_40px_-24px_rgba(15,23,42,0.24)] dark:border-zinc-800 dark:bg-zinc-950"; const VIDEO_CANVAS_TOOLBAR_BUTTON_CLASS = - "h-9 w-9 rounded-xl border border-transparent text-foreground/75 hover:border-border/60 hover:bg-background hover:text-foreground"; + "h-9 w-9 rounded-xl border border-transparent text-foreground/75 hover:border-slate-200 hover:bg-slate-50 hover:text-foreground dark:hover:border-zinc-800 dark:hover:bg-zinc-900"; const VIDEO_CANVAS_TOOLBAR_ACTIVE_BUTTON_CLASS = - "border-border/60 bg-background text-foreground shadow-sm hover:bg-background"; + "border-slate-200 bg-white text-foreground shadow-sm hover:bg-slate-50 dark:border-zinc-800 dark:bg-zinc-950 dark:hover:bg-zinc-900"; const VIDEO_CANVAS_COMPACT_CONTROLS_CLASS = - "rounded-full border border-border/60 bg-background px-2 py-1 shadow-sm"; + "rounded-full border border-slate-200 bg-white px-2 py-1 shadow-sm dark:border-zinc-800 dark:bg-zinc-950"; function buildScopedCanvasChatId(projectId: string, scope: "agent-mode") { const normalized = String(projectId || "").trim().toLowerCase().replace(/-/g, ""); @@ -7095,8 +7095,8 @@ export default function CanvasEditorPage({ params }: PageProps) {
{selectedVideoWorkflowDefinition.label} - - 参考 APP 里这个节点后面通常会接这些分支,点击后会自动放到右侧并连线。 + + 常用下游分支会放在这里,点击后自动放到右侧并连线。
@@ -7110,7 +7110,7 @@ export default function CanvasEditorPage({ params }: PageProps) { key={`${selectedVideoWorkflowDefinition.type}-${item.type}`} size="sm" variant="secondary" - className="rounded-full border border-border/60 bg-background hover:bg-background" + className="rounded-full border border-slate-200 bg-white hover:bg-slate-50 dark:border-zinc-800 dark:bg-zinc-950 dark:hover:bg-zinc-900" onClick={() => handleAddWorkflowNode(item.type)} > {item.label} @@ -7126,7 +7126,7 @@ export default function CanvasEditorPage({ params }: PageProps) {
工作流执行 - + {selectedWorkflowActionHint}
@@ -7200,7 +7200,7 @@ export default function CanvasEditorPage({ params }: PageProps) {
上游提示
-
+
{selectedWorkflowPrompt.trim() ? selectedWorkflowPrompt : "当前还没有抽取到可执行提示词,先在上游接入脚本、分镜或参考素材。"} @@ -7217,7 +7217,7 @@ export default function CanvasEditorPage({ params }: PageProps) { {selectedWorkflowLinkedAgentProject.title || selectedWorkflowLinkedAgentProject.id}
- 再次点击下方按钮会把当前视频画布上下文同步进去,并直接打开该项目。 + 再点下方按钮会同步当前视频画布上下文,并直接打开该项目。
) : null} @@ -7245,7 +7245,7 @@ export default function CanvasEditorPage({ params }: PageProps) { variant="secondary" onClick={() => void handleOpenSelectedWorkflowInAgent()} disabled={isAnyWorkflowExecutionRunning} - className="w-full rounded-2xl border border-border/60 bg-background hover:bg-background" + className="w-full rounded-2xl border border-slate-200 bg-white hover:bg-slate-50 dark:border-zinc-800 dark:bg-zinc-950 dark:hover:bg-zinc-900" > {isSelectedWorkflowAgentRunning ? ( <> @@ -7267,7 +7267,7 @@ export default function CanvasEditorPage({ params }: PageProps) { variant="secondary" onClick={() => void handleCreateSelectedAgentResultBranches()} disabled={isAnyWorkflowExecutionRunning} - className="w-full rounded-2xl border border-border/60 bg-background hover:bg-background" + className="w-full rounded-2xl border border-slate-200 bg-white hover:bg-slate-50 dark:border-zinc-800 dark:bg-zinc-950 dark:hover:bg-zinc-900" > {isSelectedWorkflowBranchRunning ? ( <> @@ -7286,7 +7286,7 @@ export default function CanvasEditorPage({ params }: PageProps) { variant="secondary" onClick={() => void handleRunStoryboardBatch()} disabled={isAnyWorkflowExecutionRunning} - className="w-full rounded-2xl border border-border/60 bg-background hover:bg-background" + className="w-full rounded-2xl border border-slate-200 bg-white hover:bg-slate-50 dark:border-zinc-800 dark:bg-zinc-950 dark:hover:bg-zinc-900" > {isSelectedWorkflowBatchRunning ? ( <> diff --git a/components/canvas/CanvasWorkspace.tsx b/components/canvas/CanvasWorkspace.tsx index 0f4b2f624..76a68ad2a 100644 --- a/components/canvas/CanvasWorkspace.tsx +++ b/components/canvas/CanvasWorkspace.tsx @@ -66,10 +66,10 @@ export function CanvasWorkspace({ const WORKFLOW_HANDLE_SIZE = 16; const isWorkflowCanvas = workspaceVariant === "video"; const overlayPanelClassName = isWorkflowCanvas - ? "rounded-full border border-border/60 bg-background px-3 py-1.5 text-xs text-muted-foreground shadow-sm" + ? "rounded-full border border-slate-200 bg-white px-3 py-1.5 text-xs text-muted-foreground shadow-sm dark:border-zinc-800 dark:bg-zinc-950" : "bg-background/80 backdrop-blur-sm rounded-md px-2 py-1 text-xs text-muted-foreground"; const zoomOverlayClassName = isWorkflowCanvas - ? "absolute bottom-4 right-4 rounded-full border border-border/60 bg-background shadow-sm" + ? "absolute bottom-4 right-4 rounded-full border border-slate-200 bg-white shadow-sm dark:border-zinc-800 dark:bg-zinc-950" : "absolute bottom-4 right-4 bg-background/80 backdrop-blur-sm rounded-lg flex items-center gap-1 px-1 py-1 shadow-sm border border-border/50"; type SnapGuideLines = { @@ -1325,7 +1325,7 @@ export function CanvasWorkspace({ className={cn( "px-4 py-2 text-sm text-primary shadow-sm", isWorkflowCanvas - ? "rounded-full border border-primary/20 bg-background" + ? "rounded-full border border-primary/20 bg-white dark:bg-zinc-950" : "rounded-md bg-background/90" )} > @@ -1525,8 +1525,8 @@ export function CanvasWorkspace({ {showEmptyState && nodes.length === 0 && (
{isWorkflowCanvas ? ( -
-
+
+

{workspaceLabel}还是空的

diff --git a/components/canvas/nodes/ImageNode.tsx b/components/canvas/nodes/ImageNode.tsx index 67463c75c..dba88113c 100644 --- a/components/canvas/nodes/ImageNode.tsx +++ b/components/canvas/nodes/ImageNode.tsx @@ -2630,7 +2630,7 @@ export function ImageNode({ node, isSelected }: ImageNodeProps) {
{ @@ -2661,7 +2661,7 @@ export function ImageNode({ node, isSelected }: ImageNodeProps) { clipPath: `inset(0 ${100 - compareSplitPercent}% 0 0)`, }} > -
+
{displayTitle} -
+
{`${displayTitle}-原图`}
-
+
新图
-
+
原图
@@ -2722,7 +2722,7 @@ export function ImageNode({ node, isSelected }: ImageNodeProps) { src={displayImageSrc} alt={displayTitle} className={cn( - "w-full h-full object-contain bg-muted/30", + "h-full w-full object-contain bg-slate-50 dark:bg-zinc-900", boxCutoutMode ? "cursor-crosshair" : isThisNodePicking ? "cursor-crosshair" : "cursor-pointer" )} draggable={false} @@ -2870,19 +2870,19 @@ export function ImageNode({ node, isSelected }: ImageNodeProps) { )}
) : data.status === 'generating' ? ( -
- - - {detailProgressLabel || "生成中..."} - -
+
+ + + {detailProgressLabel || "生成中..."} + +
) : data.status === 'failed' ? ( -
+
生成失败
) : ( -
+
点击上传图片 {/* 隐藏的文件输入 */} @@ -2906,7 +2906,7 @@ export function ImageNode({ node, isSelected }: ImageNodeProps) { {/* 处理中遮罩 */} {isProcessing && ( -
+
处理中... @@ -3000,14 +3000,14 @@ export function ImageNode({ node, isSelected }: ImageNodeProps) { {/* 提示词显示 */} {data.prompt && isHovered && !isProcessing && ( -
+

{data.prompt}

)} {data.note && !isSelected && (
@@ -3019,7 +3019,7 @@ export function ImageNode({ node, isSelected }: ImageNodeProps) { type="button" onClick={() => setSnapshotDialogOpen(true)} className={cn( - "absolute left-2 inline-flex items-center gap-1 rounded-full bg-black/70 px-2 py-1 text-[11px] text-white shadow-sm transition-colors hover:bg-black/80", + "absolute left-2 inline-flex items-center gap-1 rounded-full bg-slate-950 px-2 py-1 text-[11px] text-white shadow-sm transition-colors hover:bg-black", data.note && !isSelected ? "top-10" : "top-2" )} title={`执行快照:${agentExecutionSnapshotId}`} @@ -3102,7 +3102,7 @@ export function ImageNode({ node, isSelected }: ImageNodeProps) {
handleAction('enhance')} > HD @@ -3147,7 +3147,7 @@ export function ImageNode({ node, isSelected }: ImageNodeProps) { @@ -3260,7 +3260,7 @@ export function ImageNode({ node, isSelected }: ImageNodeProps) { variant="ghost" size="icon" disabled={isProcessing} - className="h-10 w-10 rounded-xl text-slate-700 hover:bg-slate-100 hover:text-slate-900 dark:text-slate-100 dark:hover:bg-white/10" + className="h-10 w-10 rounded-xl text-slate-700 hover:bg-slate-100 hover:text-slate-900 dark:text-slate-100 dark:hover:bg-zinc-800" onClick={handleDownload} > @@ -3273,7 +3273,7 @@ export function ImageNode({ node, isSelected }: ImageNodeProps) { {isSelected && !isMultiSelected && data.src && boxCutoutMode && typeof document !== "undefined" && createPortal(
event.stopPropagation()} onClick={(event) => event.stopPropagation()} > -
+
{boxCutoutHintText}
@@ -3312,7 +3312,7 @@ export function ImageNode({ node, isSelected }: ImageNodeProps) { {/* 底部控制栏 */} -
+
{/* 进度条 */} {isPlaying ? ( @@ -203,7 +203,7 @@ export function VideoNode({ node, isSelected }: VideoNodeProps) {
) : data.status === 'generating' ? ( -
+
生成中... {data.progress && ( @@ -227,12 +227,12 @@ export function VideoNode({ node, isSelected }: VideoNodeProps) { )}
) : data.status === 'failed' ? ( -
+
生成失败
) : ( -