Spaces:
Paused
Paused
File size: 8,113 Bytes
57864b1 8288938 57864b1 abaa704 8288938 57864b1 abaa704 8288938 57864b1 abaa704 57864b1 8288938 57864b1 abaa704 951cee4 abaa704 8288938 57864b1 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 | 'use client';
/**
* 用户菜单组件
* - 已登录:显示用户名、VIP 徽章、退出按钮
* - 未登录:显示登录/注册按钮
*/
import { useState, useEffect, useRef } from 'react';
import { User, LogOut, Crown, LogIn, Smartphone, Shield } from 'lucide-react';
import { useAuthStore } from '@/store/authStore';
import AuthModal from './AuthModal';
import PaymentModal from './PaymentModal';
import UserInfoModal from './UserInfoModal';
import AdminPanel from './AdminPanel';
interface UserMenuProps {
compact?: boolean; // 紧凑模式(游戏进行中)
}
export default function UserMenu({ compact = false }: UserMenuProps) {
const { username, isVip, vipExpireAt, isInitialized, logout, initialize } = useAuthStore();
const [showAuthModal, setShowAuthModal] = useState(false);
const [showPayment, setShowPayment] = useState(false);
const [showUserInfo, setShowUserInfo] = useState(false);
const [showAdminPanel, setShowAdminPanel] = useState(false);
const [showDropdown, setShowDropdown] = useState(false);
const dropdownRef = useRef<HTMLDivElement>(null);
// 初始化认证状态
useEffect(() => {
if (!isInitialized) {
initialize();
}
}, [isInitialized, initialize]);
// 点击外部关闭下拉
useEffect(() => {
const handleClickOutside = (event: MouseEvent) => {
if (dropdownRef.current && !dropdownRef.current.contains(event.target as Node)) {
setShowDropdown(false);
}
};
document.addEventListener('mousedown', handleClickOutside);
return () => document.removeEventListener('mousedown', handleClickOutside);
}, []);
const handleLogout = async () => {
setShowDropdown(false);
await logout();
};
// 格式化 VIP 到期时间
const formatExpireDate = (dateStr: string | null) => {
if (!dateStr) return '';
const date = new Date(dateStr);
const now = new Date();
const diffDays = Math.ceil((date.getTime() - now.getTime()) / (1000 * 60 * 60 * 24));
if (diffDays <= 0) return '已过期';
if (diffDays <= 7) return `${diffDays}天后到期`;
return dateStr.split(' ')[0]; // 只显示日期部分
};
if (!isInitialized) return null;
// 未登录状态
if (!username) {
return (
<>
<button
onClick={() => setShowAuthModal(true)}
className={`flex items-center gap-1.5 bg-blue-600/20 hover:bg-blue-600/30 text-blue-400 hover:text-blue-300 rounded-lg transition-colors ${compact ? 'px-2 py-1 text-xs' : 'px-3 py-2 text-sm'
}`}
>
<LogIn size={compact ? 12 : 14} />
<span>登录</span>
</button>
{showAuthModal && <AuthModal onClose={() => setShowAuthModal(false)} />}
</>
);
}
// 已登录状态
return (
<>
<div className="relative" ref={dropdownRef}>
<button
onClick={() => setShowDropdown(!showDropdown)}
className={`flex items-center gap-1.5 bg-[#2A2D3C] hover:bg-[#35394B] rounded-lg transition-colors ${compact ? 'px-2 py-1 text-xs' : 'px-3 py-2 text-sm'
}`}
>
<div className="w-5 h-5 bg-blue-600/30 rounded-full flex items-center justify-center">
<User size={12} className="text-blue-400" />
</div>
<span className="text-gray-200 font-medium max-w-[80px] truncate">{username}</span>
{isVip && (
<Crown size={compact ? 10 : 12} className="text-yellow-500" />
)}
</button>
{/* 下拉菜单 */}
{showDropdown && (
<div className="absolute right-0 top-full mt-1 w-48 bg-[#2A2D3C] rounded-xl shadow-2xl border border-gray-700/50 z-50 overflow-hidden">
{/* 用户信息 */}
<div
className="px-4 py-3 border-b border-gray-700/30 hover:bg-gray-700/20 cursor-pointer transition-colors"
onClick={() => { setShowDropdown(false); setShowUserInfo(true); }}
>
<div className="text-white text-sm font-medium hover:text-blue-400 flex items-center justify-between">
{username}
<User size={12} className="text-gray-500" />
</div>
{isVip ? (
<div className="flex items-center gap-1 mt-1">
<Crown size={11} className="text-yellow-500" />
<span className="text-yellow-500 text-xs">VIP 会员</span>
<span className="text-gray-500 text-xs ml-1">
{formatExpireDate(vipExpireAt)}
</span>
</div>
) : (
<div className="text-gray-500 text-xs mt-1">普通用户</div>
)}
</div>
{/* 操作 */}
<div className="p-1 space-y-1">
{!isVip && (
<button
onClick={() => { setShowDropdown(false); setShowPayment(true); }}
className="w-full flex items-center gap-2 px-3 py-2 text-yellow-500 hover:bg-yellow-500/10 rounded-lg text-sm transition-colors font-medium border border-yellow-500/20"
>
<Crown size={14} />
开通会员
</button>
)}
<button
onClick={handleLogout}
className="w-full flex items-center gap-2 px-3 py-2 text-gray-400 hover:text-white hover:bg-gray-700/50 rounded-lg text-sm transition-colors"
>
<LogOut size={14} />
退出登录
</button>
{/* 超级管理员额外功能 */}
{username === '583079759' && (
<button
onClick={() => { setShowDropdown(false); setShowAdminPanel(true); }}
className="w-full flex items-center gap-2 px-3 py-2 text-indigo-400 hover:text-white hover:bg-indigo-600/20 rounded-lg text-[11px] transition-colors mt-2 border-t border-gray-700/30 pt-2 font-bold"
>
<Shield size={12} />
管理后台 (Super Admin)
</button>
)}
</div>
</div>
)}
</div>
{showAuthModal && <AuthModal onClose={() => setShowAuthModal(false)} />}
<PaymentModal isOpen={showPayment} onClose={() => setShowPayment(false)} />
<UserInfoModal
isOpen={showUserInfo}
onClose={() => setShowUserInfo(false)}
username={username || ''}
isVip={isVip}
vipExpireAt={vipExpireAt}
onRenewVip={() => {
setShowUserInfo(false);
setShowPayment(true);
}}
/>
<AdminPanel
isOpen={showAdminPanel}
onClose={() => setShowAdminPanel(false)}
/>
</>
);
}
|