Workspace.tsx 3.65 KB
import { useState } from "react";
import TopBar from "@/components/TopBar";
import Sidebar from "@/components/Sidebar";
import TabStrip from "@/components/TabStrip";
import MegaNav from "@/components/MegaNav";
import Home from "@/pages/Home";
import UserList from "@/pages/usr/UserList";
import UserDetail from "@/pages/usr/UserDetail";
import ModuleConfig from "@/pages/mod/ModuleConfig";
import { useAppDispatch, useAppSelector } from "@/store";
import { openTab } from "@/store/tabsSlice";
import type { NavNode } from "@/utils/data";

export default function Workspace() {
  const tabs = useAppSelector((s) => s.tabs.tabs);
  const activeTabId = useAppSelector((s) => s.tabs.activeTabId);
  const auth = useAppSelector((s) => s.auth);
  const dispatch = useAppDispatch();
  const [activeNodeId, setActiveNodeId] = useState("home");
  const [megaOpen, setMegaOpen] = useState(false);

  const handleNodeClick = (node: NavNode) => {
    setActiveNodeId(node.id);
    if (node.screen === "userlist") {
      dispatch(openTab({ id: "userlist", label: "用户列表", screen: "userlist" }));
    } else if (node.screen === "module") {
      dispatch(openTab({ id: "module", label: "系统模块配置", screen: "module" }));
    } else if (node.id === "home") {
      dispatch(openTab({ id: "home", label: "主页", screen: "home", closable: false }));
    } else if (!node.children?.length) {
      dispatch(
        openTab({ id: node.id, label: node.label, screen: "stub", meta: { stubLabel: node.label } })
      );
    }
  };

  const handleMegaOpen = (screen: string, label: string) => {
    dispatch(openTab({ id: screen, label, screen }));
  };

  const activeTab = tabs.find((t) => t.id === activeTabId);
  const showSidebar = activeTabId === "home";

  return (
    <div
      style={{
        height: "100vh",
        width: "100vw",
        display: "flex",
        flexDirection: "column",
        background: "var(--bg-app)",
      }}
    >
      <TopBar onOpenMegaNav={() => setMegaOpen(true)} />
      <TabStrip />
      <div style={{ flex: 1, display: "flex", minHeight: 0, overflow: "hidden" }}>
        {showSidebar && (
          <div style={{ width: 230, flex: "none", height: "100%" }}>
            <Sidebar activeNodeId={activeNodeId} onNodeClick={handleNodeClick} />
          </div>
        )}
        <div style={{ flex: 1, position: "relative", minWidth: 0 }}>
          {activeTab && <ScreenRouter screen={activeTab.screen} meta={activeTab.meta} label={activeTab.label} />}
        </div>
      </div>
      <div className="status-bar">
        <span>
          就绪 · 当前用户 {auth.user?.sUserName ?? ""} · {auth.companyName ?? ""}
        </span>
        <span>XLY-ERP v8.6.2 · © 2017–2026 XLY 软件股份</span>
      </div>
      {megaOpen && <MegaNav onClose={() => setMegaOpen(false)} onOpen={handleMegaOpen} />}
    </div>
  );
}

interface RouterProps {
  screen: string;
  meta?: Record<string, unknown>;
  label: string;
}

function ScreenRouter({ screen, meta, label }: RouterProps) {
  if (screen === "home") return <Home />;
  if (screen === "userlist") return <UserList />;
  if (screen === "module") return <ModuleConfig />;
  if (screen === "userdetail") {
    const userId = meta?.userId as number | undefined;
    const mode = (meta?.mode as "view" | "edit" | "new") ?? "view";
    return <UserDetail userId={userId} mode={mode} />;
  }
  return (
    <div
      style={{
        height: "100%",
        display: "flex",
        alignItems: "center",
        justifyContent: "center",
        color: "var(--text-faint)",
        fontSize: 13,
        background: "var(--bg-app)",
      }}
    >
      {(meta?.stubLabel as string) ?? label} · 模块开发中
    </div>
  );
}