style: refine realtime canvas dialog ui
This commit is contained in:
parent
153efc8f96
commit
080328fbeb
@ -612,75 +612,89 @@ export function RealtimeCanvasDialog({
|
||||
|
||||
return (
|
||||
<Dialog open={open} onOpenChange={onOpenChange}>
|
||||
<DialogContent className="h-[88vh] w-[95vw] max-w-[1400px] overflow-hidden rounded-2xl border border-zinc-200 bg-[#f6f7f8] p-0">
|
||||
<DialogHeader className="border-b border-zinc-200 px-5 py-3">
|
||||
<div className="flex items-center justify-between gap-3">
|
||||
<DialogContent className="h-[90vh] w-[96vw] max-w-[1540px] overflow-hidden rounded-[24px] border border-zinc-200/80 bg-[#f2f3f5] p-0 shadow-2xl">
|
||||
<DialogHeader className="border-b border-zinc-200/80 bg-white/70 px-6 py-4 backdrop-blur">
|
||||
<div className="flex items-start justify-between gap-4">
|
||||
<div>
|
||||
<DialogTitle className="text-[17px] font-semibold text-zinc-900">实时画布</DialogTitle>
|
||||
<DialogDescription className="text-[12px] text-zinc-500">
|
||||
左侧画草图,右侧实时预览,底部输入提示词后持续渲染
|
||||
<DialogTitle className="text-[24px] font-semibold tracking-tight text-zinc-900">
|
||||
实时画布
|
||||
</DialogTitle>
|
||||
<DialogDescription className="mt-1 text-[13px] text-zinc-500">
|
||||
左侧绘制草图,右侧实时渲染,整体风格与无限画布保持一致
|
||||
</DialogDescription>
|
||||
<div className="mt-2 text-[12px] text-zinc-500">{statusMessage}</div>
|
||||
</div>
|
||||
<div className="flex items-center gap-2">
|
||||
<span
|
||||
className={cn(
|
||||
"inline-flex items-center rounded-full px-2.5 py-1 text-[11px] font-medium",
|
||||
"inline-flex h-9 items-center gap-1.5 rounded-full px-3 text-[12px] font-medium",
|
||||
statusBadge.className
|
||||
)}
|
||||
>
|
||||
{status === "error" ? <WifiOff className="mr-1 h-3.5 w-3.5" /> : <Wifi className="mr-1 h-3.5 w-3.5" />}
|
||||
{status === "error" ? <WifiOff className="h-3.5 w-3.5" /> : <Wifi className="h-3.5 w-3.5" />}
|
||||
{statusBadge.label}
|
||||
</span>
|
||||
<Button type="button" variant="outline" size="sm" onClick={forceReconnect}>
|
||||
<RefreshCw className="mr-1 h-3.5 w-3.5" />
|
||||
<Button
|
||||
type="button"
|
||||
variant="outline"
|
||||
size="sm"
|
||||
onClick={forceReconnect}
|
||||
className="h-9 rounded-xl border-zinc-300 bg-white px-3"
|
||||
>
|
||||
<RefreshCw className="mr-1.5 h-3.5 w-3.5" />
|
||||
重连
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
<div className="mt-1 text-[11px] text-zinc-500">{statusMessage}</div>
|
||||
</DialogHeader>
|
||||
|
||||
<div className="flex min-h-0 flex-1 flex-col">
|
||||
<div className="grid min-h-0 flex-1 grid-cols-2 gap-3 px-4 py-3">
|
||||
<div className="flex min-h-0 flex-col rounded-xl border border-zinc-200 bg-white/85">
|
||||
<div className="flex items-center justify-between border-b border-zinc-200 px-3 py-2">
|
||||
<span className="text-[12px] font-medium text-zinc-700">草图画布</span>
|
||||
<div className="flex min-h-0 flex-1 flex-col px-5 pb-5 pt-4">
|
||||
<div className="grid min-h-0 flex-1 grid-cols-2 gap-4">
|
||||
<div className="flex min-h-0 flex-col overflow-hidden rounded-2xl border border-zinc-200 bg-white/95 shadow-sm">
|
||||
<div className="flex h-12 items-center justify-between border-b border-zinc-200 px-4">
|
||||
<span className="text-[15px] font-medium text-zinc-800">草图画布</span>
|
||||
<div className="flex items-center gap-1.5">
|
||||
<Button
|
||||
type="button"
|
||||
size="icon"
|
||||
variant={brushMode === "brush" ? "default" : "outline"}
|
||||
className="h-7 w-7"
|
||||
className="h-8 w-8 rounded-lg"
|
||||
onClick={() => setBrushMode("brush")}
|
||||
>
|
||||
<Paintbrush className="h-3.5 w-3.5" />
|
||||
<Paintbrush className="h-4 w-4" />
|
||||
</Button>
|
||||
<Button
|
||||
type="button"
|
||||
size="icon"
|
||||
variant={brushMode === "eraser" ? "default" : "outline"}
|
||||
className="h-7 w-7"
|
||||
className="h-8 w-8 rounded-lg"
|
||||
onClick={() => setBrushMode("eraser")}
|
||||
>
|
||||
<Eraser className="h-3.5 w-3.5" />
|
||||
<Eraser className="h-4 w-4" />
|
||||
</Button>
|
||||
<Button type="button" size="icon" variant="outline" className="h-7 w-7" onClick={clearSketch}>
|
||||
<Trash2 className="h-3.5 w-3.5" />
|
||||
<Button
|
||||
type="button"
|
||||
size="icon"
|
||||
variant="outline"
|
||||
className="h-8 w-8 rounded-lg"
|
||||
onClick={clearSketch}
|
||||
>
|
||||
<Trash2 className="h-4 w-4" />
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
<div ref={canvasWrapRef} className="min-h-0 flex-1 bg-[#d8d8db] p-2">
|
||||
<div ref={canvasWrapRef} className="min-h-0 flex-1 bg-[#d0d1d4] p-3">
|
||||
<canvas
|
||||
ref={canvasRef}
|
||||
className="h-full w-full touch-none rounded-md border border-zinc-300 bg-[#d8d8db]"
|
||||
className="h-full w-full touch-none rounded-xl border border-zinc-300/80 bg-[#d0d1d4]"
|
||||
onPointerDown={handlePointerDown}
|
||||
onPointerMove={handlePointerMove}
|
||||
onPointerUp={handlePointerUp}
|
||||
onPointerCancel={handlePointerUp}
|
||||
/>
|
||||
</div>
|
||||
<div className="flex items-center gap-2 border-t border-zinc-200 px-3 py-2">
|
||||
<Label htmlFor="rt-brush-size" className="text-[11px] text-zinc-500">
|
||||
<div className="flex h-12 items-center gap-3 border-t border-zinc-200 px-4">
|
||||
<Label htmlFor="rt-brush-size" className="text-[12px] font-medium text-zinc-500">
|
||||
画笔粗细
|
||||
</Label>
|
||||
<input
|
||||
@ -691,60 +705,72 @@ export function RealtimeCanvasDialog({
|
||||
step={1}
|
||||
value={brushSize}
|
||||
onChange={(event) => setBrushSize(Number(event.target.value))}
|
||||
className="h-2 w-32 accent-zinc-800"
|
||||
className="h-2 w-40 accent-zinc-800"
|
||||
/>
|
||||
<span className="text-[11px] text-zinc-500">{brushSize}px</span>
|
||||
<span className="text-[12px] text-zinc-500">{brushSize}px</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex min-h-0 flex-col rounded-xl border border-zinc-200 bg-white/85">
|
||||
<div className="flex items-center justify-between border-b border-zinc-200 px-3 py-2">
|
||||
<span className="text-[12px] font-medium text-zinc-700">实时预览</span>
|
||||
<Button type="button" variant="outline" size="sm" onClick={() => scheduleFlush(true)}>
|
||||
<Sparkles className="mr-1 h-3.5 w-3.5" />
|
||||
<div className="flex min-h-0 flex-col overflow-hidden rounded-2xl border border-zinc-200 bg-white/95 shadow-sm">
|
||||
<div className="flex h-12 items-center justify-between border-b border-zinc-200 px-4">
|
||||
<span className="text-[15px] font-medium text-zinc-800">实时预览</span>
|
||||
<Button
|
||||
type="button"
|
||||
variant="outline"
|
||||
size="sm"
|
||||
className="h-8 rounded-lg border-zinc-300 bg-white px-3 text-[12px]"
|
||||
onClick={() => scheduleFlush(true)}
|
||||
>
|
||||
<Sparkles className="mr-1.5 h-3.5 w-3.5" />
|
||||
刷新
|
||||
</Button>
|
||||
</div>
|
||||
<div className="relative min-h-0 flex-1 overflow-hidden rounded-b-xl bg-[#d2d3d6]">
|
||||
{previewUrl ? (
|
||||
<img src={previewUrl} alt="实时预览" className="h-full w-full object-contain" />
|
||||
) : (
|
||||
<div className="flex h-full items-center justify-center text-[12px] text-zinc-500">
|
||||
{status === "connecting" ? (
|
||||
<span className="inline-flex items-center">
|
||||
<Loader2 className="mr-1.5 h-3.5 w-3.5 animate-spin" />
|
||||
正在等待首帧...
|
||||
</span>
|
||||
) : (
|
||||
<span>开始绘制后将显示实时预览</span>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
<div className="relative min-h-0 flex-1 overflow-hidden bg-[#d0d1d4] p-3">
|
||||
<div className="h-full w-full overflow-hidden rounded-xl border border-zinc-300/80 bg-[#d0d1d4]">
|
||||
{previewUrl ? (
|
||||
<img src={previewUrl} alt="实时预览" className="h-full w-full object-contain" />
|
||||
) : (
|
||||
<div className="flex h-full items-center justify-center text-[13px] text-zinc-500">
|
||||
{status === "connecting" ? (
|
||||
<span className="inline-flex items-center rounded-full bg-white/70 px-3 py-1.5">
|
||||
<Loader2 className="mr-2 h-3.5 w-3.5 animate-spin" />
|
||||
正在等待首帧...
|
||||
</span>
|
||||
) : (
|
||||
<span>开始绘制后将显示实时预览</span>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="border-t border-zinc-200 bg-white/90 px-4 py-3">
|
||||
<div className="mt-4 rounded-2xl border border-zinc-200 bg-white/95 p-3 shadow-sm">
|
||||
<div className="flex items-center gap-2">
|
||||
<Input
|
||||
value={prompt}
|
||||
onChange={(event) => setPrompt(event.target.value)}
|
||||
onBlur={() => scheduleFlush(true)}
|
||||
placeholder="输入提示词,例如:将草图渲染为高端工业设计风格..."
|
||||
className="h-10 flex-1 rounded-xl border-zinc-300 bg-white"
|
||||
className="h-11 flex-1 rounded-xl border-zinc-300 bg-white text-[15px]"
|
||||
/>
|
||||
<Button
|
||||
type="button"
|
||||
className="h-10 rounded-xl"
|
||||
className="h-11 rounded-xl px-5"
|
||||
disabled={!previewUrl || isApplying}
|
||||
onClick={uploadPreviewToCanvas}
|
||||
>
|
||||
{isApplying ? <Loader2 className="mr-1.5 h-4 w-4 animate-spin" /> : <Send className="mr-1.5 h-4 w-4" />}
|
||||
{isApplying ? (
|
||||
<Loader2 className="mr-1.5 h-4 w-4 animate-spin" />
|
||||
) : (
|
||||
<Send className="mr-1.5 h-4 w-4" />
|
||||
)}
|
||||
发送到画布
|
||||
</Button>
|
||||
</div>
|
||||
<div className="mt-2 text-[11px] text-zinc-500">
|
||||
提示:绘制过程会自动触发实时渲染。当前发送节流 {adaptiveThrottleMs}ms。
|
||||
<div className="mt-2 text-[12px] text-zinc-500">
|
||||
绘制会自动触发实时渲染,当前节流间隔 {adaptiveThrottleMs}ms。
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user