From ebe6cdc7f188a2c60692bd20f36e4bc3dd82128c Mon Sep 17 00:00:00 2001 From: Huarch Date: Tue, 21 Jul 2026 12:35:36 +0800 Subject: [PATCH] fix: improve mobile workbench controls --- app/layout.tsx | 7 ++- features/map/core/components/notice.tsx | 6 +- .../components/workbench-top-bar-menus.tsx | 20 +++---- .../components/workbench-top-bar-styles.ts | 7 +++ .../components/workbench-top-bar.tsx | 22 ++++---- features/workbench/map-workbench-page.tsx | 56 ++++++++----------- features/workbench/map/camera.test.ts | 2 +- features/workbench/map/camera.ts | 2 +- tests/browser/agent-panel-resize.e2e.ts | 31 +++++++++- tests/browser/map-notice-position.e2e.ts | 19 +++++++ tests/browser/workbench-top-bar-mobile.e2e.ts | 34 +++++++++++ 11 files changed, 144 insertions(+), 62 deletions(-) create mode 100644 features/workbench/components/workbench-top-bar-styles.ts create mode 100644 tests/browser/map-notice-position.e2e.ts create mode 100644 tests/browser/workbench-top-bar-mobile.e2e.ts diff --git a/app/layout.tsx b/app/layout.tsx index 1446548..74495db 100644 --- a/app/layout.tsx +++ b/app/layout.tsx @@ -1,4 +1,4 @@ -import type { Metadata } from "next"; +import type { Metadata, Viewport } from "next"; import { MapToaster } from "@/features/map/core/components/notice"; import "katex/dist/katex.min.css"; import "streamdown/styles.css"; @@ -9,6 +9,11 @@ export const metadata: Metadata = { description: "Agent 编排型沉浸式排水管网业务工作台" }; +export const viewport: Viewport = { + width: "device-width", + initialScale: 1 +}; + export default function RootLayout({ children }: Readonly<{ diff --git a/features/map/core/components/notice.tsx b/features/map/core/components/notice.tsx index 3fbb543..75490b6 100644 --- a/features/map/core/components/notice.tsx +++ b/features/map/core/components/notice.tsx @@ -31,7 +31,7 @@ type SonnerPosition = NonNullable["position"]>; const DEFAULT_POSITION: MapNoticePosition = "top-center"; const positionClassNames: Record = { - "top-center": "top-[84px]", + "top-center": "!left-1/2 !right-auto top-[84px] [translate:-50%_0]", "top-right": "top-[84px] right-[72px]", "bottom-left": "bottom-12 left-4", "bottom-right": "bottom-12 right-4" @@ -120,7 +120,7 @@ export function showMapNotice(options: MapNoticeOptions) { MAP_ICON_CELL_RADIUS_CLASS_NAME ) }, - className: cn("!fixed !z-[60]", positionClassNames[position]) + className: cn("!fixed !z-[60] !w-[min(420px,calc(100vw-24px))]", positionClassNames[position]) } ); } @@ -232,7 +232,7 @@ function MapNoticeFrame({ tone, children }: { tone: MapNoticeTone; children: Rea
= { active: "运行中", @@ -50,11 +55,6 @@ const menuSurfaceClassName = cn( ); const menuReadableRowClassName = "surface-well focus:bg-blue-50 focus:text-slate-950"; -const headerControlButtonClassName = - "inline-flex h-8 items-center gap-2 rounded-full border border-transparent bg-transparent text-sm font-semibold text-slate-700 transition-colors hover:bg-white/70 hover:text-blue-700 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-blue-600/20 focus-visible:ring-offset-2 data-[state=open]:bg-white/90 data-[state=open]:text-blue-700"; -const headerControlIconClassName = - "grid h-5 w-5 shrink-0 place-items-center rounded-full bg-slate-100/80 text-slate-500 transition-colors group-hover:bg-blue-50 group-hover:text-blue-700 group-data-[state=open]:bg-blue-50 group-data-[state=open]:text-blue-700"; - export function ScenarioMenu({ open, onOpenChange, @@ -87,8 +87,8 @@ export function ScenarioMenu({ - 场景 · {activeScenarioName} -
-
+
@@ -144,7 +144,7 @@ export function WorkbenchTopBar({ className={cn("group px-2 active:scale-95", headerControlButtonClassName, devPanelOpen && "bg-blue-50/80 text-blue-700")} > - Dev + Dev
: null}
@@ -209,7 +209,7 @@ function TaskTickerToggle({ >
- + {!agent.mobileOpen ? ( + + ) : null} {!agent.mobileOpen ? (
@@ -1111,36 +1119,16 @@ function getScheduledConditionIdFromAlertId(alertId: string) { } function MobileAgentToggle({ - open, personaState, statusLabel, streaming, - onOpen, - onClose + onOpen }: { - open: boolean; personaState: ComponentProps["state"]; statusLabel: string; streaming: boolean; onOpen: () => void; - onClose: () => void; }) { - if (open) { - return ( -
- -
- ); - } - return (