refactor(canvas): derive toolbar offsets from panel geometry
This commit is contained in:
parent
93e5493993
commit
f2b752dd7d
@ -79,6 +79,10 @@ const SIZE_PRESETS = [
|
||||
{ label: "9:16", value: "9:16", width: 1024, height: 1820 },
|
||||
];
|
||||
|
||||
const FLOATING_PANEL_WIDTH = 460;
|
||||
const FLOATING_PANEL_INSET = 16;
|
||||
const FLOATING_UI_GAP = 16;
|
||||
|
||||
export default function CanvasEditorPage({ params }: PageProps) {
|
||||
// 使用 useParams 确保客户端导航时能正确获取更新的 id
|
||||
const routeParams = useParams();
|
||||
@ -124,6 +128,7 @@ export default function CanvasEditorPage({ params }: PageProps) {
|
||||
const [isPanelOpen, setIsPanelOpen] = useState(true);
|
||||
// 面板模式: 'chat' 聊天面板, 'fileList' 文件列表
|
||||
const [panelMode, setPanelMode] = useState<'chat' | 'fileList'>('chat');
|
||||
const [viewportWidth, setViewportWidth] = useState(0);
|
||||
|
||||
const { data: siteSettingsData } = useSWR<{
|
||||
siteName?: string;
|
||||
@ -145,6 +150,13 @@ export default function CanvasEditorPage({ params }: PageProps) {
|
||||
? nodes.find(n => n.id === selectedNodeIds[0] && n.type === 'image')
|
||||
: null;
|
||||
|
||||
const resolvedPanelWidth = viewportWidth > 0
|
||||
? Math.min(FLOATING_PANEL_WIDTH, Math.max(viewportWidth - FLOATING_PANEL_INSET, 0))
|
||||
: FLOATING_PANEL_WIDTH;
|
||||
const panelOcclusionRight = isPanelOpen ? resolvedPanelWidth + FLOATING_PANEL_INSET : 0;
|
||||
const floatingToolbarOffset = isPanelOpen ? -(panelOcclusionRight / 2) : 0;
|
||||
const compactControlsRight = isPanelOpen ? panelOcclusionRight + FLOATING_UI_GAP : FLOATING_UI_GAP;
|
||||
|
||||
// 加载画布数据
|
||||
useEffect(() => {
|
||||
console.log('[Canvas] Loading project:', id);
|
||||
@ -179,6 +191,13 @@ export default function CanvasEditorPage({ params }: PageProps) {
|
||||
loadProject();
|
||||
}, [id]); // 只依赖 id,使用 getState() 直接调用 store actions
|
||||
|
||||
useEffect(() => {
|
||||
const updateViewportWidth = () => setViewportWidth(window.innerWidth);
|
||||
updateViewportWidth();
|
||||
window.addEventListener("resize", updateViewportWidth);
|
||||
return () => window.removeEventListener("resize", updateViewportWidth);
|
||||
}, []);
|
||||
|
||||
const persistCanvasState = useCallback(
|
||||
async (reason: "autosave" | "delete" | "beforeunload") => {
|
||||
const canvasData = getCanvasState();
|
||||
@ -561,7 +580,7 @@ export default function CanvasEditorPage({ params }: PageProps) {
|
||||
|
||||
{/* 1. Canvas Layer (Full Screen) - 使用 key 强制在 id 变化时重新挂载 */}
|
||||
<div className="absolute inset-0 z-0" key={`workspace-${id}`}>
|
||||
<CanvasWorkspace occlusionRight={isPanelOpen ? 476 : 0} />
|
||||
<CanvasWorkspace occlusionRight={panelOcclusionRight} />
|
||||
</div>
|
||||
|
||||
{/* Brand Entry (Top Left) */}
|
||||
@ -641,7 +660,7 @@ export default function CanvasEditorPage({ params }: PageProps) {
|
||||
|
||||
{/* 3. Floating Actions (Top Right) */}
|
||||
{!isPanelOpen && (
|
||||
<div className="absolute top-4 right-4 z-20">
|
||||
<div className="absolute z-20" style={{ top: FLOATING_PANEL_INSET, right: FLOATING_PANEL_INSET }}>
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<Button
|
||||
@ -660,9 +679,16 @@ export default function CanvasEditorPage({ params }: PageProps) {
|
||||
|
||||
{/* 4. Floating Sidebar (Right) */}
|
||||
<div className={cn(
|
||||
"absolute top-4 right-4 bottom-4 z-10 w-[460px] max-w-[calc(100vw-1rem)] transition-all duration-300 ease-in-out",
|
||||
"absolute z-10 transition-all duration-300 ease-in-out",
|
||||
isPanelOpen ? "translate-x-0 opacity-100" : "translate-x-[120%] opacity-0 pointer-events-none"
|
||||
)}>
|
||||
)}
|
||||
style={{
|
||||
top: FLOATING_PANEL_INSET,
|
||||
right: FLOATING_PANEL_INSET,
|
||||
bottom: FLOATING_PANEL_INSET,
|
||||
width: FLOATING_PANEL_WIDTH,
|
||||
maxWidth: `calc(100vw - ${FLOATING_PANEL_INSET}px)`,
|
||||
}}>
|
||||
<div className="h-full w-full rounded-2xl border bg-white dark:bg-zinc-950 shadow-2xl overflow-hidden flex flex-col">
|
||||
{panelMode === 'chat' ? (
|
||||
// AI 对话内容 - 使用 key 强制在 id 变化时重新挂载
|
||||
@ -687,9 +713,7 @@ export default function CanvasEditorPage({ params }: PageProps) {
|
||||
<div className="absolute bottom-5 left-1/2 z-20 -translate-x-1/2">
|
||||
<div
|
||||
className="flex items-center gap-1 rounded-[24px] border bg-background/88 px-2.5 py-1.5 shadow-2xl backdrop-blur-md"
|
||||
style={{
|
||||
marginLeft: isPanelOpen ? "-238px" : "0px",
|
||||
}}
|
||||
style={{ marginLeft: `${floatingToolbarOffset}px` }}
|
||||
>
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
@ -797,7 +821,7 @@ export default function CanvasEditorPage({ params }: PageProps) {
|
||||
{/* 6. Bottom Right Compact Controls */}
|
||||
<div
|
||||
className="absolute bottom-5 z-20"
|
||||
style={{ right: isPanelOpen ? "492px" : "16px" }}
|
||||
style={{ right: `${compactControlsRight}px` }}
|
||||
>
|
||||
<div className="flex items-center gap-1 rounded-2xl border bg-background/88 px-2 py-1.5 shadow-xl backdrop-blur-md">
|
||||
<Tooltip>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user