mirror of
https://github.com/basketikun/infinite-canvas.git
synced 2026-08-06 09:24:24 +08:00
feat(canvas): 添加视频节点支持功能
- 在后端添加 AI 视频相关接口处理函数 - 扩展前端画布组件支持视频节点类型 - 实现视频上传、生成和播放功能 - 更新画布数据结构文档以包含视频节点 - 添加视频节点的操作工具栏和配置面板 - 集成视频存储和检索服务 - 优化视频节点的渲染和交互体验
This commit is contained in:
@@ -12,7 +12,7 @@ import { fetchAssetLibrary, type AssetLibraryItem } from "@/services/api/assets"
|
||||
|
||||
export type AssetPickerTab = "my-assets" | "library";
|
||||
|
||||
export type InsertAssetPayload = { kind: "text"; content: string; title: string } | { kind: "image"; dataUrl: string; title: string; storageKey?: string };
|
||||
export type InsertAssetPayload = { kind: "text"; content: string; title: string } | { kind: "image"; dataUrl: string; title: string; storageKey?: string } | { kind: "video"; url: string; title: string; storageKey?: string };
|
||||
|
||||
type Props = {
|
||||
open: boolean;
|
||||
@@ -48,6 +48,7 @@ const kindOptions = [
|
||||
{ label: "全部", value: "all" },
|
||||
{ label: "文本", value: "text" },
|
||||
{ label: "图片", value: "image" },
|
||||
{ label: "视频", value: "video" },
|
||||
];
|
||||
|
||||
function LibraryTab({ onInsert }: { onInsert: (payload: InsertAssetPayload) => void }) {
|
||||
@@ -157,7 +158,7 @@ function PickerCard({ title, kind, cover, loading, onClick }: { title: string; k
|
||||
<div className="p-2.5">
|
||||
<div className="flex items-center justify-between gap-2">
|
||||
<span className="line-clamp-1 text-xs font-medium text-stone-800 dark:text-stone-200">{title}</span>
|
||||
<Tag className="m-0 shrink-0 text-[10px]">{kind === "image" ? "图片" : "文本"}</Tag>
|
||||
<Tag className="m-0 shrink-0 text-[10px]">{kind === "image" ? "图片" : kind === "video" ? "视频" : "文本"}</Tag>
|
||||
</div>
|
||||
</div>
|
||||
{loading && (
|
||||
@@ -190,7 +191,7 @@ function MyAssetsTab({ onInsert }: { onInsert: (payload: InsertAssetPayload) =>
|
||||
const filtered = useMemo(() => {
|
||||
const query = keyword.trim().toLowerCase();
|
||||
return assets
|
||||
.filter((a) => a.kind === "text" || a.kind === "image")
|
||||
.filter((a) => a.kind === "text" || a.kind === "image" || a.kind === "video")
|
||||
.filter((a) => kindFilter === "all" || a.kind === kindFilter)
|
||||
.filter((a) => !query || [a.title, ...(a.tags || [])].join(" ").toLowerCase().includes(query));
|
||||
}, [assets, keyword, kindFilter]);
|
||||
@@ -206,7 +207,7 @@ function MyAssetsTab({ onInsert }: { onInsert: (payload: InsertAssetPayload) =>
|
||||
if (asset.kind === "text") {
|
||||
onInsert({ kind: "text", content: asset.data.content, title: asset.title });
|
||||
} else {
|
||||
onInsert({ kind: "image", dataUrl: asset.data.dataUrl, storageKey: asset.data.storageKey, title: asset.title });
|
||||
onInsert(asset.kind === "video" ? { kind: "video", url: asset.data.url, storageKey: asset.data.storageKey, title: asset.title } : { kind: "image", dataUrl: asset.data.dataUrl, storageKey: asset.data.storageKey, title: asset.title });
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user