增加复制粘贴交互

This commit is contained in:
andy committed 2026-09-30 13:22:53 +08:00
1 parent 4195525dc7
commit deb9cc5bcf
14 files changed
+1144 -31

No files matched your search

+23 -4
View File
@@ -1,6 +1,6 @@
"use client";
import { useEffect, useMemo, useRef, useState, type PointerEvent as ReactPointerEvent, type KeyboardEvent as ReactKeyboardEvent } from "react";
import { useEffect, useMemo, useRef, useState, type ClipboardEvent as ReactClipboardEvent, type PointerEvent as ReactPointerEvent, type KeyboardEvent as ReactKeyboardEvent } from "react";
import { BoxSelect, Brush, Check, Hand, ImageIcon, Loader2, MapPin, Maximize2, Minimize2, Redo2, ScanLine, Trash2, Undo2, Upload, X, ZoomIn, ZoomOut } from "lucide-react";
import clsx from "clsx";
import { materialPreviewUrl } from "@/lib/client/asset-urls";
@@ -37,6 +37,7 @@ export function SeedreamWorkspace({
onSelectSource,
onToggleSource,
onUpload,
onPasteImage,
onInsertAnnotation
}: {
mode: Exclude<SeedreamCreationMode, "basic">;
@@ -49,6 +50,7 @@ export function SeedreamWorkspace({
onSelectSource: (material: PromptMaterial) => void;
onToggleSource: (material: PromptMaterial) => void;
onUpload: (files: FileList | null) => void;
onPasteImage?: (event: ReactClipboardEvent<HTMLElement>) => void;
onInsertAnnotation: (token: string) => void;
}) {
const [tool, setTool] = useState<AnnotationTool>("box");
@@ -324,7 +326,15 @@ export function SeedreamWorkspace({
const currentImageIndex = sourceIndexByKey.get(sourceKey) || 1;
return (
<section ref={workspaceRef} className={clsx("seedream-workspace", mode === "interactive" ? "interactive" : "layers")} aria-label={mode === "interactive" ? "Seedream 交互编辑" : "Seedream 图层拆分"}>
<section
ref={workspaceRef}
className={clsx("seedream-workspace", mode === "interactive" ? "interactive" : "layers")}
aria-label={mode === "interactive" ? "Seedream 交互编辑" : "Seedream 图层拆分"}
onPaste={(event) => {
if (event.target instanceof HTMLElement && event.target.closest("input, textarea, [contenteditable]")) return;
onPasteImage?.(event);
}}
>
<header className="seedream-workspace-head">
<div>
<strong>{mode === "interactive" ? "精准编辑画布" : "指定拆分区域"}</strong>
@@ -334,10 +344,19 @@ export function SeedreamWorkspace({
</header>
{!source ? (
<div className="seedream-source-empty">
<div
className="seedream-source-empty"
tabIndex={0}
aria-label="图片画布:可粘贴截图或复制的图片"
onPointerDown={(event) => {
if (event.target instanceof Element && event.target.closest("label, button, input")) return;
event.currentTarget.focus({ preventScroll: true });
}}
>
<span className="seedream-source-empty-icon" aria-hidden="true"><ImageIcon size={24} /></span>
<strong>{sources.length ? "选择参与生成的图片" : "先上传一张图片"}</strong>
<span>{mode === "interactive" ? "可以选择多张图片进行跨图定位编辑" : "模板效果预览图不会自动参与拆分"}</span>
<span>支持 Ctrl+V / ⌘+V 粘贴图片或图片下载地址,链接确认后导入</span>
<label className="button primary">
{uploading ? <Loader2 className="spin" size={16} /> : <Upload size={16} />}
上传图片
@@ -428,7 +447,7 @@ export function SeedreamWorkspace({
</div>
</div>
<div className="seedream-canvas-note">
<span>滚轮缩放 · 空格 / 中键拖动 · 放大后可继续标注 · 适应画布恢复全图</span>
<span>滚轮缩放 · 空格 / 中键拖动 · 放大后可继续标注 · 适应画布恢复全图 · Ctrl+V / ⌘+V 粘贴图片或图片地址</span>
{mode === "interactive"
? "蓝色涂鸦会在提交时自动合成到对应输入图;框选和点选会转换成官方坐标标签。"
: "蓝色涂鸦会合成到待拆图片;框选会转换为 <bbox> 坐标,不会修改原始素材。"}