| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125 |
- 'use client'
- import { useEffect, useRef, useState } from 'react'
- import { BellIcon as BellIconOutline } from '@heroicons/react/24/outline'
- import { BellIcon as BellIconSolid } from '@heroicons/react/24/solid'
- import useSWR from 'swr'
- import classNames from '@/utils/classnames'
- import { useAppContext } from '@/context/app-context'
- import { fetchUnreadCount } from '@/service/notifications'
- import NotificationPanel from './notification-panel'
- type NotificationsNavProps = {
- className?: string
- }
- const NotificationsNav = ({ className }: NotificationsNavProps) => {
- const [isOpen, setIsOpen] = useState(false)
- const panelRef = useRef<HTMLDivElement>(null)
- const buttonRef = useRef<HTMLDivElement>(null)
- const { userProfile } = useAppContext()
- // 调试:输出当前用户信息
- useEffect(() => {
- if (userProfile?.id) {
- console.log('[NOTIFY] Current user:', {
- id: userProfile.id,
- name: userProfile.name,
- email: userProfile.email,
- })
- }
- }, [userProfile])
- // 获取未读通知数量
- const { data: unreadData, mutate: mutateUnreadCount } = useSWR(
- '/datasets/notifications/unread-count',
- fetchUnreadCount,
- {
- refreshInterval: 30000, // 每30秒刷新一次
- onSuccess: (data) => {
- console.log('[NOTIFY] Unread count data:', data)
- },
- onError: (error) => {
- console.error('[NOTIFY] Failed to fetch unread count:', error)
- },
- },
- )
- const unreadCount = unreadData?.unread_count || 0
- // 点击外部关闭面板
- useEffect(() => {
- const handleClickOutside = (event: MouseEvent) => {
- if (
- panelRef.current
- && !panelRef.current.contains(event.target as Node)
- && buttonRef.current
- && !buttonRef.current.contains(event.target as Node)
- )
- setIsOpen(false)
- }
- if (isOpen) {
- document.addEventListener('mousedown', handleClickOutside)
- return () => {
- document.removeEventListener('mousedown', handleClickOutside)
- }
- }
- }, [isOpen])
- const handleToggle = () => {
- setIsOpen(!isOpen)
- }
- const handleNotificationRead = () => {
- // 重新获取未读数量
- mutateUnreadCount()
- }
- return (
- <div className="relative">
- <div
- ref={buttonRef}
- onClick={handleToggle}
- className={classNames(
- className,
- 'group cursor-pointer',
- )}
- >
- <div
- className={classNames(
- 'system-sm-medium relative flex h-8 w-8 flex-row items-center justify-center rounded-xl border border-transparent p-1.5',
- isOpen && 'border-components-main-nav-nav-button-border bg-components-main-nav-nav-button-bg-active text-components-main-nav-nav-button-text shadow-md',
- !isOpen && 'text-text-tertiary hover:bg-state-base-hover hover:text-text-secondary',
- )}
- >
- {/* 未读数量徽章 */}
- {unreadCount > 0 && (
- <div className="absolute right-[-4px] top-[-4px] flex h-5 min-w-[20px] items-center justify-center rounded-full bg-util-colors-red-red-600 px-1 text-[11px] font-semibold text-white">
- {unreadCount > 99 ? '99+' : unreadCount}
- </div>
- )}
- {/* 铃铛图标 */}
- {isOpen
- ? <BellIconSolid className="h-4 w-4" />
- : <BellIconOutline className="h-4 w-4" />}
- </div>
- </div>
- {/* 通知面板 */}
- {isOpen && (
- <div
- ref={panelRef}
- className="absolute right-0 top-[calc(100%+8px)] z-[1200]"
- >
- <NotificationPanel
- onClose={() => setIsOpen(false)}
- onNotificationRead={handleNotificationRead}
- />
- </div>
- )}
- </div>
- )
- }
- export default NotificationsNav
|