auto-save 2026-05-14 00:48 (+4, ~3)

This commit is contained in:
2026-05-14 00:48:59 +08:00
parent 042efdc376
commit e8a653e524
7 changed files with 673 additions and 4 deletions

View File

@@ -46,6 +46,8 @@ export interface NodeData {
onOpenStoryboard?: (frameIdx: number) => void // 打开分镜头编排专属面板
onOpenWorkbench?: (frameIdx?: number) => void // 展开顶部分镜编排内嵌面板
onCopyImage?: (ref: ImageRef) => void // 复制图片到全局剪贴板(粘贴到分镜头编排插槽)
pinnedNodes?: Set<string> // 已钉住的节点 id 集合 — 钉住后位置 + 尺寸锁定
onToggleNodePin?: (id: string) => void
}
/* ---- 状态映射工具 ---- */
@@ -234,6 +236,8 @@ export function InputNode({ data, selected }: NodeProps<{ data: NodeData }> | an
subtitle={isDownloading ? "STEP 1 · 下载中" : hasVideo ? "STEP 1 · 视频就绪" : "STEP 1"}
selected={selected}
hasTarget={false}
pinned={d.pinnedNodes?.has("input")}
onTogglePin={() => d.onToggleNodePin?.("input")}
>
{/* URL + 上传入口 — 一直显示(即使已有视频,也可以继续加新的) */}
<>
@@ -499,6 +503,8 @@ export function KeyframeNode({ data, selected }: any) {
title="镜头拆解 · 元素提取"
subtitle={`STEP 2 · ${frames.length ? `${d.selectedFrames.size}/${frames.length} 入编排` : "等待抽取"}`}
selected={selected}
pinned={d.pinnedNodes?.has("keyframe")}
onTogglePin={() => d.onToggleNodePin?.("keyframe")}
>
{frames.length > 0 ? (() => {
const cleanedCount = frames.filter((x) => x.cleaned_url).length
@@ -726,6 +732,8 @@ export function ASRNode({ data, selected }: any) {
title="声音文案 · ASR"
subtitle="STEP 3 · 可选文案轨"
selected={selected}
pinned={d.pinnedNodes?.has("asr")}
onTogglePin={() => d.onToggleNodePin?.("asr")}
>
<div className="text-[11.5px] text-[var(--text-soft)]">
Gemini 2.5 ·
@@ -767,6 +775,8 @@ export function TranslateNode({ data, selected }: any) {
title="翻译理解 · Translate"
subtitle="STEP 4 · EN → ZH"
selected={selected}
pinned={d.pinnedNodes?.has("translate")}
onTogglePin={() => d.onToggleNodePin?.("translate")}
>
<div className="text-[11.5px] text-[var(--text-soft)]">
· ·
@@ -785,7 +795,8 @@ export function TranslateNode({ data, selected }: any) {
/* ============================================================
7. RewriteNode (placeholder)
============================================================ */
export function RewriteNode({ selected }: any) {
export function RewriteNode({ data, selected }: any) {
const d: NodeData = data
return (
<NodeShell
type="ai" status="pending"
@@ -793,6 +804,8 @@ export function RewriteNode({ selected }: any) {
title="产品文案 · Rewrite"
subtitle="STEP 5 · 接 SKG 卖点"
selected={selected}
pinned={d.pinnedNodes?.has("rewrite")}
onTogglePin={() => d.onToggleNodePin?.("rewrite")}
>
<textarea
placeholder="粘贴 SKG 产品信息 / 关键卖点(可作为视频脚本和镜头动作参考)"
@@ -929,6 +942,8 @@ export function StoryboardNode({ data, selected }: any) {
title="元素改造 · Storyboard"
subtitle={`STEP 6 · 参考元素 → SKG 画面${storyboardCount > 0 ? ` · ${storyboardCount} 分镜` : ""}`}
selected={selected}
pinned={d.pinnedNodes?.has("storyboard")}
onTogglePin={() => d.onToggleNodePin?.("storyboard")}
>
<div className="text-[11.5px] leading-relaxed text-[var(--text-soft)]">
/ / / SKG
@@ -1103,6 +1118,8 @@ export function VideoGenNode({ data, selected }: any) {
title="生成视频 · Video Gen"
subtitle={`STEP 7 · 首帧 + 动作 prompt${videos.length > 0 ? ` · ${videos.length} 个视频任务` : ""}`}
selected={selected}
pinned={d.pinnedNodes?.has("videogen")}
onTogglePin={() => d.onToggleNodePin?.("videogen")}
>
<div className="grid grid-cols-3 gap-1.5 text-[10.5px]">
{["Seedance", "Kling", "Veo 3"].map((m) => (
@@ -1124,7 +1141,8 @@ export function VideoGenNode({ data, selected }: any) {
/* ============================================================
10. ComposeNode (placeholder)
============================================================ */
export function ComposeNode({ selected }: any) {
export function ComposeNode({ data, selected }: any) {
const d: NodeData = data
return (
<NodeShell
type="output" status="pending"
@@ -1133,6 +1151,8 @@ export function ComposeNode({ selected }: any) {
subtitle="STEP 8 · ffmpeg + 字幕"
selected={selected}
hasSource={false}
pinned={d.pinnedNodes?.has("compose")}
onTogglePin={() => d.onToggleNodePin?.("compose")}
>
<div className="text-[11.5px] text-[var(--text-soft)] leading-relaxed">
+ / TTS<br /> mp4