import { Popover } from "antd"; import { Switch } from "@/components/ui/base/switch"; import { CircleUserRound, LogIn, Moon, Sun } from "lucide-react"; import { useEffect, useState } from "react"; import { Link } from "react-router"; import { AppChangelogButton } from "@/components/layout/app-changelog-modal"; import { IdentityProviderBadge } from "@/components/layout/identity-provider-badge"; import { useWalletBalance } from "@/hooks/use-wallet-balance"; import { cn } from "@/lib/utils"; import { useThemeStore } from "@/stores/use-theme-store"; import { useUserStore, type LocalUser } from "@/stores/use-user-store"; /** 顶部栏头像账户菜单:只承载账户信息、版本和显示偏好;管理与退出入口统一放在侧栏。 */ export function WorkspaceAccountMenu() { const theme = useThemeStore((state) => state.theme); const setTheme = useThemeStore((state) => state.setTheme); const user = useUserStore((state) => state.user); const hydrated = useUserStore((state) => state.hydrated); const creditsEnabled = useUserStore((state) => state.features.creditsEnabled); const { availableMicrocredits } = useWalletBalance(user?.id, creditsEnabled); const [menuOpen, setMenuOpen] = useState(false); const balance = availableMicrocredits === null ? "--" : (availableMicrocredits / 1_000_000).toLocaleString("zh-CN", { maximumFractionDigits: 2 }); if (!hydrated) { return ; } return user ? ( {user.displayName || user.username} {creditsEnabled ? 可用 {balance} 积分 : null} {theme === "dark" ? : } 深色模式 setTheme(checked ? "dark" : "light")} aria-label="深色模式" /> )} > ) : ( ); } function UserAvatar({ user, className }: { user: LocalUser; className?: string }) { const [failed, setFailed] = useState(false); const avatarUrl = /^https?:\/\//i.test(user.avatarUrl || "") ? user.avatarUrl : ""; useEffect(() => setFailed(false), [avatarUrl]); // 结构保持 button > span > svg:占位图标自动复用顶栏图标按钮的 18px/1.8 描边与配色合同;默认不套圆角容器,hover 由按钮背景反馈。 return ( {avatarUrl && !failed ? ( setFailed(true)} /> ) : ( )} ); }