diff --git a/components/angle-edit-dialog.tsx b/components/angle-edit-dialog.tsx index 78d8aba..f0a1eba 100644 --- a/components/angle-edit-dialog.tsx +++ b/components/angle-edit-dialog.tsx @@ -6,15 +6,15 @@ import { DialogContent, DialogHeader, DialogTitle, - DialogDescription, } from "@/components/ui/dialog"; import { Button } from "@/components/ui/button"; import { Slider } from "@/components/ui/slider"; import { Label } from "@/components/ui/label"; -import { Loader2, Download, Check, RotateCcw, Move3D, Sparkles } from "lucide-react"; +import { Loader2, Download, Check, RotateCcw, Move3D, Sparkles, X } from "lucide-react"; import { toast } from "sonner"; import { QwenCameraWidget, type CameraState } from "./qwen-camera-widget"; import { cn } from "@/lib/utils"; +import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"; interface AngleEditDialogProps { open: boolean; @@ -62,26 +62,39 @@ export function AngleEditDialog({ elevation: 0, distance: 5, }); + // 预览 Tab 状态:如果生成了结果,默认显示结果;否则显示原图 + const [activeTab, setActiveTab] = useState<"original" | "result">("original"); // 当对话框关闭时重置状态 useEffect(() => { if (!open) { setResultUrl(null); setIsProcessing(false); + setActiveTab("original"); } }, [open]); + // 当生成结果时,自动切换到结果 Tab + useEffect(() => { + if (resultUrl) { + setActiveTab("result"); + } + }, [resultUrl]); + // 处理相机状态变化 const handleCameraStateChange = useCallback((state: CameraState) => { setCameraState(state); // 角度变化时清除之前的结果 - setResultUrl(null); - }, []); + if (!isProcessing) { + setResultUrl(null); + } + }, [isProcessing]); // 生成新视角 const handleGenerate = useCallback(async () => { setIsProcessing(true); setResultUrl(null); + setActiveTab("result"); // 切换到结果 Tab 显示加载状态 try { const response = await fetch("/api/angle-edit", { @@ -107,6 +120,7 @@ export function AngleEditDialog({ } catch (error) { console.error("角度编辑失败:", error); toast.error(error instanceof Error ? error.message : "生成失败,请重试"); + setActiveTab("original"); // 失败后切回原图 } finally { setIsProcessing(false); } @@ -151,45 +165,40 @@ export function AngleEditDialog({ distance: 5, }); setLoraScale(0.9); + setActiveTab("original"); }, []); return ( - - -
-
-
- -
-
- 多角度编辑 - - 拖拽 3D 控制器中的彩色手柄调整相机角度,AI 将生成对应视角的图像 - -
+ + {/* 紧凑标题栏 */} +
+
+
+
+ 3D 视角编辑器
- + +
-
-
- {/* 左侧:3D 控制器 (占 5 列) */} -
-
- -
+
+ {/* 左侧:3D 控制区 (固定宽度 320px) */} +
+
+ - {/* LoRA 强度控制 */} -
+
- - + + {(loraScale * 100).toFixed(0)}%
@@ -199,113 +208,29 @@ export function AngleEditDialog({ min={0.5} max={1.0} step={0.05} - className="py-2" + className="py-1" /> -

- 强度越高角度变化越明显,越低则保留更多原图特征。建议 85-95%。 -

+ +
- - {/* 右侧:图片预览 (占 7 列) */} -
-
- {/* 原图 */} -
-
- 原图 -
- 原图 -
- - {/* 结果图 */} -
-
-
- 生成结果 -
- {resultUrl && ( - - 完成 - - )} -
- -
- {isProcessing ? ( -
-
-
-
- -
-
-
-

正在生成新视角...

-

预计需要 10-30 秒

-
-
- ) : resultUrl ? ( - 生成结果 - ) : ( -
-
- -
-

准备就绪

-

拖拽左侧彩色手柄调整角度后点击生成

-
- )} -
-
-
-
-
-
- - {/* 底部操作栏 */} -
- - -
- {resultUrl ? ( - <> - - - - ) : ( + + {/* 生成按钮区 */} +
- )} +
+
+ + {/* 右侧:预览区 (自适应) */} +
+ setActiveTab(v as any)} className="flex-1 flex flex-col"> +
+ + 原图 + + 生成结果 + {resultUrl && } + + + + {resultUrl && ( +
+ + +
+ )} +
+ +
+ {/* 原图 Tab */} + +
+ 原图 +
+
+ + {/* 结果 Tab */} + +
+ {isProcessing ? ( +
+
+
+
+ +
+
+

正在渲染新视角...

+
+ ) : resultUrl ? ( + 生成结果 + ) : ( +
+ +

暂无结果

+
+ )} +
+ +
+
@@ -328,3 +322,4 @@ export function AngleEditDialog({ } export default AngleEditDialog; + diff --git a/components/qwen-camera-widget.tsx b/components/qwen-camera-widget.tsx index cfe2e02..72fd1bd 100644 --- a/components/qwen-camera-widget.tsx +++ b/components/qwen-camera-widget.tsx @@ -546,9 +546,9 @@ export function QwenCameraWidget({ }; return ( -
+
{/* 3D 画布 */} -
+
{/* 提示词浮层 */} -
+
{generatePrompt(state)}
{/* 控制面板 */} -
-
-
- +
+
+
+ -
- - {Math.round(state.azimuth)}° - -
+ + {Math.round(state.azimuth)}° +
-
- +
+ -
- - {Math.round(state.elevation)}° - -
+ + {Math.round(state.elevation)}° +
-
- +
+ -
- - {state.distance.toFixed(1)} - -
+ + {state.distance.toFixed(1)} +
- -
);