feat: 去 React Router 化 + 实现三种窗口类型的页面调度体系

移除 react-router-dom 依赖,将导航从 URL 路由切换为事件总线驱动,
  新增 Modal / Drawer / FloatingPanel 三种窗口类型支持。

  架构变更:
  - 删除 src/router/(唯一路由 /* → HomePage,无实际用途)
  - App.tsx 移除 HashRouter,直接渲染 Layout > HomePage
  - Layout 从 useLocation + Outlet 改为 children prop
  - NavBar 移除 useNavigate,所有页面导航改为 emit(OPEN_PAGE)
  - NavAction 精简:'navigate'|'spa' 合并为 'page'

  新增组件:
  - FloatingPanel:纯手写非模态浮动面板(可拖拽、无遮罩、多面板共存、
    暗色主题适配、边界约束),对应 QT 非模态窗口的 Web 映射
    Modal(居中模态)| Drawer(侧滑)| FloatingPanel(浮动可拖拽)
  - 8 个页面占位组件(compliance-assets/account/vip/recharge/
    billing/orders/projects/quota),各显示导航栏名称作为占位

  配置扩展:
  - NavItemConfig 新增 modalType?: 'modal' | 'drawer' | 'floating'
  - nav-config 所有 page 项补齐 modalType(支付类→modal,浏览类→floating)
  - event-bus 新增 OPEN_PAGE 事件,payload 携带 {target, modalType, label}
  - 卸载 react-router-dom@^7.16.0(连带移除 4 个包)

  设计原则:
  - 页面组件不感知窗口类型(内容与容器分离),切换窗口类型只需改配置
  - Modal/Drawer 单实例(模态含义=独占注意力),Floating 多实例共存
  - 主页面始终挂载不卸载,所有子页面为叠加层(对应 QT 多窗口模型)
This commit is contained in:
2026-06-08 16:33:47 +08:00
parent 0f137b21fa
commit ada915f298
22 changed files with 631 additions and 242 deletions

View File

@@ -46,10 +46,10 @@ export function SettingsPage({ open, onClose }: SettingsPageProps) {
>
<div className="flex flex-col gap-4 p-4">
<ThemeSetting />
<StoragePathSetting edition={edition} />
<SystemInfoSetting />
<PasswordSetting />
<UpdateSetting />
<StoragePathSetting edition={edition} />
<PasswordSetting />
</div>
</Modal>
);

View File

@@ -46,14 +46,14 @@ export function SystemInfoSetting() {
];
return (
<Card size="small" title="系统信息" className="rounded-md!">
<Card size="small" title="系统信息(开发显示信息)" className="rounded-md!">
<div className="flex flex-col gap-2">
{infoItems.map((item) => (
<div key={item.label} className="flex items-center gap-2">
<span style={{ color: 'var(--color-primary, #4F46E5)', fontSize: 14 }}>
{item.icon}
</span>
<Text type="secondary" className="text-sm min-w-[64px]">
<Text type="secondary" className="text-sm min-w-16">
{item.label}
</Text>
<Tag color={item.color}>{item.value}</Tag>