auto-save 2026-05-12 16:44 (~4)
This commit is contained in:
@@ -76,6 +76,13 @@
|
||||
"message": "auto-save 2026-05-12 16:33 (~1)",
|
||||
"hash": "37bf7c9",
|
||||
"files_changed": 1
|
||||
},
|
||||
{
|
||||
"ts": "2026-05-12T16:39:03+08:00",
|
||||
"type": "commit",
|
||||
"message": "auto-save 2026-05-12 16:38 (~1)",
|
||||
"hash": "1b95cb2",
|
||||
"files_changed": 1
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
============================================================ */
|
||||
|
||||
:root {
|
||||
color-scheme: light;
|
||||
/* ---- Light · 暖白底 ---- */
|
||||
--bg-canvas-1: #f6f4ed;
|
||||
--bg-canvas-2: #ece6d8;
|
||||
@@ -59,6 +60,7 @@
|
||||
}
|
||||
|
||||
.dark {
|
||||
color-scheme: dark;
|
||||
/* ---- Dark · 深蓝紫 ---- */
|
||||
--bg-canvas-1: #0a0d1c;
|
||||
--bg-canvas-2: #14172e;
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
import { useCallback, useEffect, useMemo, useRef, useState } from "react"
|
||||
import {
|
||||
ReactFlow, Background, BackgroundVariant, Controls, MiniMap,
|
||||
useNodesState, useEdgesState,
|
||||
type Node, type Edge,
|
||||
} from "@xyflow/react"
|
||||
import { Toaster, toast } from "sonner"
|
||||
@@ -137,19 +138,29 @@ export default function Home() {
|
||||
onToggleFrame: handleToggleFrame,
|
||||
}), [job, submitting, selectedFrames, handleSubmit, handleUpload, handleToggleFrame])
|
||||
|
||||
const nodes: Node[] = useMemo(
|
||||
() => LAYOUT.map((n) => ({
|
||||
// 用 useNodesState 让 ReactFlow 自己管位置(避免轮询时重置 drag)
|
||||
const [nodes, setNodes, onNodesChange] = useNodesState<Node>(
|
||||
LAYOUT.map((n) => ({
|
||||
id: n.id,
|
||||
type: n.type,
|
||||
position: { x: n.x, y: n.y },
|
||||
data: nodeData,
|
||||
draggable: true,
|
||||
})),
|
||||
[nodeData],
|
||||
)
|
||||
const [edges, setEdges, onEdgesChange] = useEdgesState<Edge>(
|
||||
EDGES_RAW.map(([from, to], i) => ({
|
||||
id: `e${i}`, source: from, target: to, animated: false, type: "default",
|
||||
})),
|
||||
)
|
||||
|
||||
// 边状态:source 节点 done 时 animated
|
||||
const edges: Edge[] = useMemo(() => {
|
||||
// Job 数据变化时只更新节点 data 不动 position
|
||||
useEffect(() => {
|
||||
setNodes((prev) => prev.map((n) => ({ ...n, data: nodeData })))
|
||||
}, [nodeData, setNodes])
|
||||
|
||||
// 边的 animated 状态跟 Job 进度联动
|
||||
useEffect(() => {
|
||||
const doneOf: Record<string, boolean> = {
|
||||
input: !!job,
|
||||
download: !!job?.video_url,
|
||||
@@ -158,14 +169,8 @@ export default function Home() {
|
||||
asr: !!job && job.transcript.length > 0,
|
||||
translate: !!job && (job.transcript.some((s) => s.zh) ?? false),
|
||||
}
|
||||
return EDGES_RAW.map(([from, to], i) => ({
|
||||
id: `e${i}`,
|
||||
source: from,
|
||||
target: to,
|
||||
animated: !!doneOf[from],
|
||||
type: "default",
|
||||
}))
|
||||
}, [job])
|
||||
setEdges((prev) => prev.map((e) => ({ ...e, animated: !!doneOf[e.source] })))
|
||||
}, [job, setEdges])
|
||||
|
||||
return (
|
||||
<>
|
||||
@@ -197,6 +202,8 @@ export default function Home() {
|
||||
<ReactFlow
|
||||
nodes={nodes}
|
||||
edges={edges}
|
||||
onNodesChange={onNodesChange}
|
||||
onEdgesChange={onEdgesChange}
|
||||
nodeTypes={NODE_TYPES}
|
||||
fitView
|
||||
fitViewOptions={{ padding: 0.12 }}
|
||||
|
||||
@@ -74,7 +74,7 @@ export function InputNode({ data, selected }: NodeProps<{ data: NodeData }> | an
|
||||
onChange={(e) => setUrl(e.target.value)}
|
||||
placeholder="粘贴 TikTok 链接"
|
||||
disabled={isLocked}
|
||||
className="w-full text-[12px] px-2.5 py-2 rounded-md bg-white/40 dark:bg-white/[0.04] border border-black/10 dark:border-white/10 outline-none placeholder:text-[var(--text-faint)] focus:ring-2 focus:ring-[var(--ring)] disabled:opacity-40"
|
||||
className="w-full text-[12px] px-2.5 py-2 rounded-md bg-white/60 dark:bg-black/40 border border-black/10 dark:border-white/10 outline-none text-[var(--text-strong)] placeholder:text-[var(--text-faint)] focus:ring-2 focus:ring-[var(--ring)] disabled:opacity-40"
|
||||
/>
|
||||
<div className="mt-2 flex gap-1.5">
|
||||
<button
|
||||
|
||||
Reference in New Issue
Block a user