refactor: organize supply frontend structure

This commit is contained in:
2026-07-22 18:16:43 +08:00
parent 699a0bced4
commit b9bc9c3d39
96 changed files with 917 additions and 745 deletions
@@ -0,0 +1,118 @@
import { AgentCollapsedRail, AgentCommandPanel, AgentPersona } from "@/features/agent";
import {
MAP_CONTROL_SURFACE_CLASS_NAME,
MAP_MAJOR_PANEL_RADIUS_CLASS_NAME
} from "@/features/map/core";
import { cn } from "@/shared/ui/cn";
import type { ComponentProps } from "react";
import { WORKBENCH_LAYOUT, getWorkbenchViewportLayout } from "../layout/workbench-layout";
import { useAgentPanelResize } from "../hooks/use-agent-panel-resize";
type AgentPanelProps = Omit<ComponentProps<typeof AgentCommandPanel>, "collapsing" | "onCollapse">;
type WorkbenchAgentPanelsProps = {
panelProps: AgentPanelProps;
panelOpen: boolean;
panelCollapsing: boolean;
mobileOpen: boolean;
mobilePanelCollapsing: boolean;
personaState: ComponentProps<typeof AgentPersona>["state"];
statusLabel: string;
viewportWidth: number;
onCollapsePanel: () => void;
onCloseMobilePanel: () => void;
onExpandPanel: () => void;
onOpenMobilePanel: () => void;
};
export function WorkbenchAgentPanels({
panelProps,
panelOpen,
panelCollapsing,
mobileOpen,
mobilePanelCollapsing,
personaState,
statusLabel,
viewportWidth,
onCollapsePanel,
onCloseMobilePanel,
onExpandPanel,
onOpenMobilePanel
}: WorkbenchAgentPanelsProps) {
const resize = useAgentPanelResize(viewportWidth);
const defaultWidth = getWorkbenchViewportLayout(viewportWidth).agentWidth;
return (
<>
<div
ref={resize.panelRef}
className="pointer-events-none absolute bottom-4 left-3 top-24 z-20 hidden w-[var(--workbench-agent-width)] max-w-[50vw] 2xl:w-[var(--workbench-agent-width-wide)] lg:block"
style={resize.width === null ? undefined : { width: resize.width }}
>
{panelOpen ? (
<>
<AgentCommandPanel
{...panelProps}
collapsing={panelCollapsing}
onCollapse={onCollapsePanel}
/>
<div
aria-label="调整 Agent 面板宽度"
aria-orientation="vertical"
aria-valuemax={Math.round(viewportWidth * WORKBENCH_LAYOUT.maxAgentViewportRatio)}
aria-valuemin={defaultWidth}
aria-valuenow={Math.round(resize.width ?? defaultWidth)}
className={cn(
"group pointer-events-auto absolute -right-3 top-4 bottom-4 z-10 flex w-6 cursor-ew-resize touch-none items-center justify-center outline-hidden",
resize.resizing && "[&>span]:bg-blue-500 [&>span]:opacity-100"
)}
role="separator"
tabIndex={0}
title="拖拽调整 Agent 面板宽度"
onKeyDown={resize.handleKeyDown}
onPointerDown={resize.handlePointerDown}
>
<span className="h-14 w-1 rounded-full bg-slate-500/60 opacity-50 shadow-xs transition-[height,background-color,opacity] group-hover:h-20 group-hover:bg-blue-500 group-hover:opacity-100 group-focus-visible:h-20 group-focus-visible:bg-blue-500 group-focus-visible:opacity-100" />
</div>
</>
) : (
<AgentCollapsedRail
personaState={personaState}
statusLabel={statusLabel}
onExpand={onExpandPanel}
/>
)}
</div>
<div className="absolute bottom-20 left-3 right-3 z-30 lg:hidden">
{mobileOpen ? (
<div className="h-[calc(100dvh-8.5rem)] min-h-[420px]">
<AgentCommandPanel
{...panelProps}
collapsing={mobilePanelCollapsing}
onCollapse={onCloseMobilePanel}
/>
</div>
) : null}
</div>
{!mobileOpen ? (
<div className="absolute bottom-20 left-3 z-30 lg:hidden">
<button
type="button"
aria-label="打开 Agent 面板"
title="打开 Agent 面板"
onClick={onOpenMobilePanel}
className={cn(
"grid h-12 w-12 place-items-center text-violet-700",
MAP_MAJOR_PANEL_RADIUS_CLASS_NAME,
MAP_CONTROL_SURFACE_CLASS_NAME
)}
>
<AgentPersona className="pointer-events-none h-10 w-10" state={personaState} />
</button>
</div>
) : null}
</>
);
}