feat(canvas): 视频节点 - 接入 Vidstack 播放器并收敛任务查询范围
This commit is contained in:
@@ -3,6 +3,7 @@ import { Button, Image, Modal } from "antd";
|
||||
import { TaskDetailItem, taskStatusText } from "./canvas-project-feedback";
|
||||
import type { GenerationTask, TaskLog } from "@/services/api/task-center";
|
||||
import { CanvasNodeType, type CanvasNodeData } from "@/types/canvas";
|
||||
import { VideoPlayer } from "@/components/video-player";
|
||||
|
||||
type CanvasProjectStatusDialogsProps = {
|
||||
theme: { node: { stroke: string; panel: string; muted: string; fill: string } };
|
||||
@@ -48,7 +49,7 @@ export function CanvasProjectStatusDialogs({ theme, task, taskLogs, taskLoading,
|
||||
</Modal>
|
||||
|
||||
<Modal title="视频预览" open={Boolean(previewNode?.metadata?.content && previewNode.type === CanvasNodeType.Video)} centered onCancel={onClosePreview} footer={null} width="min(1200px, calc(100vw - 32px))" styles={{ body: { padding: 0, display: "flex", justifyContent: "center", alignItems: "center", maxHeight: "84vh", overflow: "hidden", background: "#090909" } }}>
|
||||
{previewNode?.metadata?.content && previewNode.type === CanvasNodeType.Video ? <video src={previewNode.metadata.content} controls className="max-h-[84vh] max-w-full bg-black object-contain" /> : null}
|
||||
{previewNode?.metadata?.content && previewNode.type === CanvasNodeType.Video ? <VideoPlayer src={previewNode.metadata.content} mimeType={previewNode.metadata.mimeType} title={previewNode.title || "视频预览"} className="max-h-[84vh] max-w-full bg-black" /> : null}
|
||||
</Modal>
|
||||
|
||||
{previewNode?.metadata?.content && previewNode.type === CanvasNodeType.Image ? (
|
||||
|
||||
@@ -140,15 +140,26 @@ export function useCanvasGenerationBatches({ projectId, projectLoaded, nodes, no
|
||||
});
|
||||
}, [projectId, setNodes]);
|
||||
|
||||
// 调度只补齐后台返回的用户级活跃任务空位,最终并发仍由后端原子校验。
|
||||
// 仅查询当前画布的活跃任务来安排批次,跨画布并发仍由后端创建任务时原子校验。
|
||||
const scheduleWaitingItems = useCallback(async () => {
|
||||
if (!projectLoaded || schedulingRef.current) return;
|
||||
schedulingRef.current = true;
|
||||
try {
|
||||
const tasks = await listGenerationTasks(100).catch(() => null);
|
||||
const currentNodes = nodesRef.current;
|
||||
// 没有当前画布的等待项时无需查询任务中心,避免空画布持续轮询。
|
||||
const hasWaitingItems = currentNodes.some((sourceNode) =>
|
||||
(sourceNode.metadata?.generationBatches || []).some((batch) =>
|
||||
batch.projectId === projectId &&
|
||||
batch.status !== "completed" &&
|
||||
batch.status !== "cancelled" &&
|
||||
batch.items.some((item) => item.status === "waiting"),
|
||||
),
|
||||
);
|
||||
if (!hasWaitingItems) return;
|
||||
|
||||
const tasks = await listGenerationTasks(100, { projectId, activeOnly: true }).catch(() => null);
|
||||
if (!tasks) return;
|
||||
const activeTaskCount = tasks.filter((task) => task.status === "queued" || task.status === "running").length;
|
||||
const currentNodes = nodesRef.current;
|
||||
const nodeById = new Map(currentNodes.map((node) => [node.id, node]));
|
||||
const pendingReservations = [...controllersRef.current.keys()].filter((key) => {
|
||||
const [, itemId] = key.split(":");
|
||||
|
||||
@@ -165,7 +165,7 @@ export function useCanvasGeneration({ projectId, domainProjectId, projectLoaded,
|
||||
const taskIds = Array.from(new Set(recoveryNodes.map((node) => node.metadata?.taskId).filter((id): id is string => Boolean(id))));
|
||||
const tasks = (await Promise.all(taskIds.map((id) => queryGenerationTask(id).catch(() => undefined)))).filter((task): task is GenerationTask => Boolean(task));
|
||||
if (recoveryNodes.some((node) => !node.metadata?.taskId)) {
|
||||
const recentTasks = await listGenerationTasks(30).catch(() => []);
|
||||
const recentTasks = await listGenerationTasks(30, { projectId }).catch(() => []);
|
||||
tasks.push(...recentTasks.filter((task) => !tasks.some((item) => item.id === task.id)));
|
||||
}
|
||||
const projectTasks = tasks.filter((task) => task.projectId === projectId && (task.type.startsWith("canvas_") || task.type === "agent_storyboard_rows"));
|
||||
|
||||
Reference in New Issue
Block a user