TopBar.tsx 3.2 KB
import {
  AppstoreOutlined,
  HomeOutlined,
  SearchOutlined,
  BellOutlined,
  BankOutlined,
  DownOutlined,
} from "@ant-design/icons";
import { Dropdown } from "antd";
import { useAppDispatch, useAppSelector } from "@/store";
import { logout } from "@/store/authSlice";
import { resetTabs, setActiveTab } from "@/store/tabsSlice";
import { useNavigate } from "react-router-dom";

interface Props {
  onOpenMegaNav: () => void;
}

export default function TopBar({ onOpenMegaNav }: Props) {
  const auth = useAppSelector((s) => s.auth);
  const dispatch = useAppDispatch();
  const navigate = useNavigate();

  const onLogout = () => {
    dispatch(logout());
    dispatch(resetTabs());
    navigate("/login", { replace: true });
  };

  const goHome = () => {
    dispatch(setActiveTab("home"));
  };

  return (
    <div className="top-bar">
      <button className="top-btn" onClick={onOpenMegaNav} title="全部导航">
        <AppstoreOutlined /> 全部导航
      </button>
      <button className="top-btn" onClick={goHome} title="主页">
        <HomeOutlined /> 主页
      </button>
      <div
        style={{
          flex: 1,
          minWidth: 0,
          display: "flex",
          alignItems: "center",
          gap: 8,
          paddingLeft: 12,
          overflow: "hidden",
        }}
      >
        <Brand />
        <span
          style={{
            color: "#fff",
            fontSize: 13,
            fontWeight: 500,
            letterSpacing: 1,
            whiteSpace: "nowrap",
            flex: "none",
          }}
        >
          XLY-ERP
        </span>
        <span
          style={{
            color: "var(--text-on-dark-muted)",
            fontSize: 11,
            whiteSpace: "nowrap",
            overflow: "hidden",
            textOverflow: "ellipsis",
            minWidth: 0,
          }}
        >
          · {auth.companyName ?? ""}
        </span>
      </div>
      <button className="top-btn">
        <SearchOutlined />
      </button>
      <button className="top-btn">
        <span style={{ position: "relative", display: "inline-flex" }}>
          <BellOutlined />
          <span
            style={{
              position: "absolute",
              top: -2,
              right: -3,
              width: 6,
              height: 6,
              background: "var(--danger)",
              borderRadius: 3,
            }}
          />
        </span>
      </button>
      <Dropdown
        menu={{ items: [{ key: "logout", label: "登出", onClick: onLogout }] }}
        placement="bottomRight"
      >
        <button className="top-btn">
          <BankOutlined /> {auth.user?.sUserName ?? "用户"}({auth.user?.sUserType ?? ""})
          <DownOutlined style={{ fontSize: 10, marginLeft: 2 }} />
        </button>
      </Dropdown>
    </div>
  );
}

function Brand() {
  return (
    <svg width="22" height="22" viewBox="0 0 22 22" fill="none" style={{ flex: "none" }}>
      <rect x="2" y="2" width="10" height="10" stroke="rgba(255,255,255,0.95)" strokeWidth="1.5" />
      <rect x="6" y="6" width="10" height="10" stroke="rgba(255,255,255,0.85)" strokeWidth="1.5" />
      <rect x="10" y="10" width="10" height="10" stroke="rgba(255,255,255,0.7)" strokeWidth="1.5" />
    </svg>
  );
}