import { useState, useEffect } from 'react'
import { Layout, Badge, Avatar, Dropdown, Space, Popover, List, Tabs, Button, Empty, Typography } from 'antd'
import { useNavigate } from 'react-router-dom'
import {
MenuFoldOutlined,
MenuUnfoldOutlined,
BellOutlined,
QuestionCircleOutlined,
FileTextOutlined,
CustomerServiceOutlined,
UserOutlined,
CheckOutlined,
ProjectOutlined,
TeamOutlined,
NotificationOutlined,
} from '@ant-design/icons'
import useUserStore from '@/stores/userStore'
import { getNotifications, getUnreadCount, markAsRead, markAllAsRead } from '@/api/notification'
import Toast from '@/components/Toast/Toast'
import headerMenuData from '../../data/headerMenuData.json'
import './AppHeader.css'
const { Header } = Layout
const { Text } = Typography
// 图标映射
const iconMap = {
QuestionCircleOutlined: ,
FileTextOutlined: ,
CustomerServiceOutlined: ,
}
function AppHeader({ collapsed, onToggle }) {
const navigate = useNavigate()
const { user, logout } = useUserStore()
// 用户下拉菜单
const userMenuItems = [
{
key: 'profile',
label: '个人中心',
},
{
key: 'settings',
label: '账户设置',
},
{
type: 'divider',
},
{
key: 'logout',
label: '退出登录',
},
]
const [notifications, setNotifications] = useState([])
const [unreadCount, setUnreadCount] = useState(0)
const [loading, setLoading] = useState(false)
const [popoverVisible, setPopoverVisible] = useState(false)
useEffect(() => {
if (user) {
fetchUnreadCount()
// 每 2 分钟轮询一次
const timer = setInterval(fetchUnreadCount, 120000)
return () => clearInterval(timer)
}
}, [user])
const fetchUnreadCount = async () => {
try {
const res = await getUnreadCount()
setUnreadCount(res.data.unread_count)
} catch (error) {
console.error('Fetch unread count error:', error)
}
}
const fetchNotifications = async () => {
setLoading(true)
try {
const res = await getNotifications({ page: 1, page_size: 5 })
setNotifications(res.data || [])
} catch (error) {
console.error('Fetch notifications error:', error)
} finally {
setLoading(false)
}
}
const handleMarkRead = async (id) => {
try {
await markAsRead(id)
setNotifications(notifications.map(n => n.id === id ? { ...n, is_read: 1 } : n))
fetchUnreadCount()
} catch (error) {
console.error('Mark read error:', error)
}
}
const handleMarkAllRead = async () => {
try {
await markAllAsRead()
setNotifications(notifications.map(n => ({ ...n, is_read: 1 })))
setUnreadCount(0)
Toast.success('操作成功', '所有通知已标记为已读')
} catch (error) {
console.error('Mark all read error:', error)
}
}
const handleNotificationClick = (n) => {
if (n.is_read === 0) {
handleMarkRead(n.id)
}
if (n.link) {
navigate(n.link)
setPopoverVisible(false)
}
}
const getCategoryIcon = (category) => {
switch (category) {
case 'project': return
case 'collaboration': return
default: return
}
}
const notificationContent = (
消息通知
{unreadCount > 0 && (
)}
}}
renderItem={(item) => (
handleNotificationClick(item)}
>
}
title={{item.title}}
description={
{item.content}
{new Date(item.created_at).toLocaleString('zh-CN')}
}
/>
)}
/>
)
const handleUserMenuClick = ({ key }) => {
if (key === 'logout') {
logout()
Toast.success('退出成功', '您已安全退出')
navigate('/login')
} else if (key === 'profile') {
navigate('/profile')
} else if (key === 'settings') {
Toast.info('开发中', '账户设置功能正在开发中')
}
}
const handleHeaderMenuClick = (key) => {
console.log('Header menu clicked:', key)
if (key === 'support') {
Toast.info('开发中', '支持功能正在开发中')
}
}
return (
{/* 左侧:Logo + 折叠按钮 */}
{/* Logo 区域 */}
NEX Docus
{/* 折叠按钮 */}
{collapsed ? : }
{/* 右侧:功能按钮 + 用户信息 */}
{/* 功能图标 */}
{/* 动态渲染 header 菜单 */}
{headerMenuData.map((item) => (
handleHeaderMenuClick(item.key)}
>
{iconMap[item.icon]}
{item.label}
))}
{/* 消息中心 */}
{
setPopoverVisible(visible)
if (visible) {
fetchNotifications()
}
}}
placement="bottomRight"
overlayClassName="header-notification-popover"
>
消息
{/* 用户下拉菜单 */}
} />
{user?.nickname || user?.username || 'User'}
)
}
export default AppHeader