superxuu
feat: link user info modal with payment flow for VIP renewal
951cee4
'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)}
/>
</>
);
}