feat(web-platform): release V0.9.3 全模块界面重构
web-platform-ci / TypeScript, lint, unit, build (push) Has been cancelled
web-platform-ci / Playwright E2E (push) Has been cancelled

This commit is contained in:
2026-09-08 17:57:57 +08:00
parent 831d0b95bb
commit 13e35be98b
124 changed files with 5182 additions and 2141 deletions
+20 -83
View File
@@ -1,88 +1,25 @@
import { CirclePause, CirclePlay, Mouse, MousePointer2 } from 'lucide-react';
import type { InteractionMode, ViewerSelection } from '../../viewer/MuJoCoViewer';
import { Badge, Kbd } from '../../components/ui';
const labels: Record<InteractionMode, string> = {
select: '选择',
joint: '关节拖动',
force: '外力施加',
};
const primaryGestures: Record<InteractionMode, string> = {
select: '左键旋转',
joint: '左键拖动关节',
force: '左键拖动施力',
};
export function ViewportHUD({
paused,
mode,
selection,
ready,
mapEditing = false,
}: {
paused: boolean;
mode: InteractionMode;
selection: ViewerSelection | null;
ready: boolean;
mapEditing?: boolean;
}) {
if (!ready) return null;
import { CirclePause, CirclePlay } from 'lucide-react';
import { useAppStore } from '../../stores/useAppStore';
import { Badge } from '../../components/ui';
import { StoreStatusBar } from './StatusBar';
export function ViewportHUD() {
const paused = useAppStore((state) => state.paused);
const ready = useAppStore((state) => Boolean(state.snapshot));
return (
<>
<div
aria-label="视口状态"
className="pointer-events-none absolute left-3 top-3 z-10 flex max-w-[70%] flex-wrap items-center gap-1.5"
>
<Badge tone={paused ? 'neutral' : 'success'}>
{paused ? <CirclePause className="h-3 w-3" /> : <CirclePlay className="h-3 w-3" />}
{paused ? '已暂停' : '仿真中'}
</Badge>
<Badge tone="accent">
<MousePointer2 className="h-3 w-3" />
{labels[mode]}
</Badge>
{selection && (
<Badge title={`body ${selection.bodyId} · geom ${selection.geomId}`}>
{selection.bodyName}
</Badge>
)}
</div>
<div
aria-label="视口操作提示"
className="pointer-events-none absolute bottom-14 left-1/2 z-10 hidden -translate-x-1/2 items-center gap-2 whitespace-nowrap rounded-full border border-border-strong bg-panel/85 px-3 py-1.5 text-[10px] text-text-secondary shadow-xl backdrop-blur lg:flex"
>
<Mouse aria-hidden="true" className="h-3 w-3 text-text-secondary" />
<span>{primaryGestures[mode]}</span>
<span aria-hidden="true" className="text-border-strong">
·
</span>
<span>右键平移</span>
<span aria-hidden="true" className="text-border-strong">
·
</span>
<span>滚轮缩放</span>
{mapEditing && mode === 'select' ? (
<>
<span aria-hidden="true" className="text-border-strong">
·
</span>
<Kbd>W</Kbd>
<Kbd>E</Kbd>
<Kbd>R</Kbd>
<span>变换</span>
<Kbd>F</Kbd>
<span>聚焦</span>
</>
<div
aria-label="视口状态"
className="flex flex-wrap items-center gap-2 rounded-lg border border-border bg-panel/90 px-2 py-1 text-xs shadow-sm"
>
<Badge tone={!ready || paused ? 'neutral' : 'success'}>
{!ready || paused ? (
<CirclePause className="h-3.5 w-3.5" />
) : (
mode !== 'select' && (
<>
<span aria-hidden="true" className="text-border-strong">
·
</span>
<Kbd>1</Kbd>
<span>旋转视角</span>
</>
)
<CirclePlay className="h-3.5 w-3.5" />
)}
</div>
</>
{!ready ? '待导入' : paused ? '已暂停' : '仿真中'}
</Badge>
<StoreStatusBar />
</div>
);
}