From 25bde02b43bd779588eca1c585c50dcb2a70a667 Mon Sep 17 00:00:00 2001 From: JIANG Date: Tue, 10 Feb 2026 17:11:04 +0800 Subject: [PATCH] =?UTF-8?q?=E4=B8=BA=E7=99=BB=E5=BD=95=E5=90=8E=E7=9A=84?= =?UTF-8?q?=E9=A1=B5=E9=9D=A2=E6=96=B0=E5=A2=9E=E5=88=87=E6=8D=A2=E9=A1=B9?= =?UTF-8?q?=E7=9B=AE=E5=BC=B9=E7=AA=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/header/index.tsx | 171 ++++++++++++++++++--- src/components/project/ProjectSelector.tsx | 22 ++- 2 files changed, 170 insertions(+), 23 deletions(-) diff --git a/src/components/header/index.tsx b/src/components/header/index.tsx index e54f9ca..5a17771 100644 --- a/src/components/header/index.tsx +++ b/src/components/header/index.tsx @@ -3,15 +3,25 @@ import { ColorModeContext } from "@contexts/color-mode"; import DarkModeOutlined from "@mui/icons-material/DarkModeOutlined"; import LightModeOutlined from "@mui/icons-material/LightModeOutlined"; +import Logout from "@mui/icons-material/Logout"; +import SwapHoriz from "@mui/icons-material/SwapHoriz"; import AppBar from "@mui/material/AppBar"; import Avatar from "@mui/material/Avatar"; +import ButtonBase from "@mui/material/ButtonBase"; +import Divider from "@mui/material/Divider"; import IconButton from "@mui/material/IconButton"; +import ListItemIcon from "@mui/material/ListItemIcon"; +import ListItemText from "@mui/material/ListItemText"; +import Menu from "@mui/material/Menu"; +import MenuItem from "@mui/material/MenuItem"; import Stack from "@mui/material/Stack"; import Toolbar from "@mui/material/Toolbar"; import Typography from "@mui/material/Typography"; -import { useGetIdentity } from "@refinedev/core"; +import { useGetIdentity, useLogout } from "@refinedev/core"; import { HamburgerMenu, RefineThemedLayoutHeaderProps } from "@refinedev/mui"; -import React, { useContext } from "react"; +import React, { useContext, useState } from "react"; +import { ProjectSelector } from "@components/project/ProjectSelector"; +import { setMapWorkspace, setNetworkName } from "@config/config"; type IUser = { id: number; @@ -23,9 +33,35 @@ export const Header: React.FC = ({ sticky = true, }) => { const { mode, setMode } = useContext(ColorModeContext); + const { mutate: logout } = useLogout(); + const [anchorEl, setAnchorEl] = useState(null); + const [showProjectSelector, setShowProjectSelector] = useState(false); + const open = Boolean(anchorEl); const { data: user } = useGetIdentity(); + const handleMenuOpen = (event: React.MouseEvent) => { + setAnchorEl(event.currentTarget); + }; + + const handleMenuClose = () => { + setAnchorEl(null); + }; + + const handleSwitchProjectClick = () => { + handleMenuClose(); + setShowProjectSelector(true); + }; + + const handleProjectSelect = (workspace: string, networkName: string) => { + setMapWorkspace(workspace); + setNetworkName(networkName); + localStorage.setItem("NEXT_PUBLIC_MAP_WORKSPACE", workspace); + localStorage.setItem("NEXT_PUBLIC_NETWORK_NAME", networkName); + setShowProjectSelector(false); + window.location.reload(); + }; + return ( @@ -52,27 +88,118 @@ export const Header: React.FC = ({ {(user?.avatar || user?.name) && ( - - {user?.name && ( - + + - {user?.name} - - )} - - + {user?.name && ( + + {user?.name} + + )} + + + + + + + + + 切换项目 + + + logout()}> + + + + 登出 + + + setShowProjectSelector(false)} + /> + )} diff --git a/src/components/project/ProjectSelector.tsx b/src/components/project/ProjectSelector.tsx index 7537cb2..03c951f 100644 --- a/src/components/project/ProjectSelector.tsx +++ b/src/components/project/ProjectSelector.tsx @@ -12,12 +12,15 @@ import { Box, Typography, Fade, + IconButton, } from "@mui/material"; +import CloseIcon from "@mui/icons-material/Close"; import { useState } from "react"; interface ProjectSelectorProps { open: boolean; onSelect: (workspace: string, networkName: string) => void; + onClose?: () => void; } const PROJECTS = [ @@ -29,6 +32,7 @@ const PROJECTS = [ export const ProjectSelector: React.FC = ({ open, onSelect, + onClose, }) => { const [workspace, setWorkspace] = useState(PROJECTS[0].workspace); const [networkName, setNetworkName] = useState(PROJECTS[0].networkName); @@ -41,7 +45,8 @@ export const ProjectSelector: React.FC = ({ return ( = ({ minWidth: 400, background: "rgba(255, 255, 255, 0.95)", backdropFilter: "blur(10px)", + position: "relative", } } }} slots={{ transition: Fade }} transitionDuration={500} > + {onClose && ( + theme.palette.grey[500], + }} + > + + + )}