import { BellOutlined } from '@ant-design/icons'; import { Badge, Col, Empty, List, Row, Tag } from 'antd'; import Link from 'antd/lib/typography/Link'; import VirtualList from 'rc-virtual-list'; import { useEffect, useRef, useState } from 'react'; import ReactDOM from 'react-dom'; import { useIntl, useRequest } from 'umi'; import styles from './index.less'; type Notification = { id: number; type: 1 | 2 | 21 | 3 | 4 | 20 | 22 | 25 | 10 | 24 | 23 | 26; title: string; content: string; state: 1 | 2; link?: string; }; const NotificationCenter = () => { const { formatMessage } = useIntl(); const typemap = { 1: { title: formatMessage({ id: 'public.notification.states.1', defaultMessage: '申请完成' }), color: 'blue', option: formatMessage({ id: 'public.notification.options.view', defaultMessage: '查看' }), }, 2: { title: formatMessage({ id: 'public.notification.states.2', defaultMessage: '待审批' }), color: 'red', option: formatMessage({ id: 'public.notification.options.do', defaultMessage: '去处理' }), }, 21: { title: formatMessage({ id: 'public.notification.states.21', defaultMessage: '待审批' }), color: 'red', option: formatMessage({ id: 'public.notification.options.do', defaultMessage: '去处理' }), }, 4: { title: formatMessage({ id: 'public.notification.states.3', defaultMessage: '代理审批人审批', }), color: 'orange', option: formatMessage({ id: 'public.notification.options.view', defaultMessage: '查看' }), }, 3: { title: formatMessage({ id: 'public.notification.states.4', defaultMessage: '代理审批人设置', }), color: 'red', option: '', }, 20: { title: formatMessage({ id: 'public.notification.states.20', defaultMessage: '申请单停滞' }), color: 'red', option: formatMessage({ id: 'public.notification.options.do', defaultMessage: '去处理' }), }, 22: { title: formatMessage({ id: 'public.notification.states.22', defaultMessage: '创建人权限转移', }), color: 'red', option: formatMessage({ id: 'public.notification.options.do', defaultMessage: '去处理' }), }, 25: { title: formatMessage({ id: 'public.notification.states.25', defaultMessage: '管理员离职' }), color: 'red', option: formatMessage({ id: 'public.notification.options.do', defaultMessage: '去处理' }), }, 10: { title: formatMessage({ id: 'public.notification.states.10', defaultMessage: '权限解绑' }), color: 'red', option: formatMessage({ id: 'public.notification.options.view', defaultMessage: '查看' }), }, 24: { title: formatMessage({ id: 'public.notification.states.24', defaultMessage: '审批流异常' }), color: 'red', option: formatMessage({ id: 'public.notification.options.do', defaultMessage: '去处理' }), }, 23: { title: formatMessage({ id: 'public.notification.states.23', defaultMessage: '权限即将到期' }), color: 'orange', option: formatMessage({ id: 'public.notification.options.do', defaultMessage: '去处理' }), }, 26: { title: formatMessage({ id: 'public.notification.states.26', defaultMessage: '权限预警' }), color: 'orange', option: formatMessage({ id: 'public.notification.options.view', defaultMessage: '查看' }), }, }; const [notifications, setNotifications] = useState([]); const [visible, setVisible] = useState(false); const hideTimeout = useRef | null>(); const [disabledIds, setDisabledIds] = useState([]); const [page, setPage] = useState(1); const ContainerHeight = 286; const { data: TotalData, run: totalRun } = useRequest( () => ({ url: '/goapi/user/message', method: 'POST', data: { condition: { state: 1, }, pagination: { page: 1, size: 10, }, }, }), { pollingInterval: 3000, }, ); const { data, loading, run } = useRequest( ({ page: currentPage } = { page: 1 }) => ({ url: '/goapi/user/message', method: 'POST', data: { condition: { state: 1, }, pagination: { page: currentPage, size: 10, }, }, }), { manual: false, onSuccess: (res) => { const { list } = res; if (list.length > 0) { setNotifications([...notifications, ...list]); } }, }, ); const { run: doneRun } = useRequest( (ids) => ({ url: '/goapi/user/message/clear', method: 'POST', data: { ids, state: 2, }, }), { manual: true, }, ); const { run: allDoneRun, loading: allLoading } = useRequest( (ids) => ({ url: '/goapi/user/message/clear', method: 'POST', data: { ids, all: true, state: 2, }, }), { manual: true, }, ); const onScroll = (e: React.UIEvent) => { if (e.currentTarget.scrollHeight - e.currentTarget.scrollTop === ContainerHeight) { run({ page: page + 1 }).then((d) => { if (d?.list?.length > 0) { setPage(page + 1); } }); } }; const handleMouseEnter = () => { if (hideTimeout.current) { clearTimeout(hideTimeout.current); } setVisible(true); }; const handleMouseLeave = () => { hideTimeout.current = setTimeout(() => { setVisible(false); }, 100); // 延迟100ms隐藏 }; const totalNumber = TotalData?.pagination?.total || 0; const showNumber = data?.pagination?.total || 0; useEffect(() => { if (totalNumber !== showNumber) { setNotifications([]); run(); } // eslint-disable-next-line react-hooks/exhaustive-deps }, [totalNumber, showNumber]); const menu = ( {formatMessage({ id: 'public.notification.title', defaultMessage: '通知' })} ( {TotalData?.pagination?.total || 0}) } bordered loading={loading || allLoading} footer={
{ if (notifications?.length > 0) { await allDoneRun([]); setNotifications([]); run(); totalRun(); } }} > {formatMessage({ id: 'public.notification.read.all', defaultMessage: '全部已读' })}
} > {notifications?.length > 0 ? ( {(item) => ( {typemap[item.type]?.title}} description={
{item.content}
} />
)}
) : ( )}
); return (
handleMouseLeave()} onClick={() => handleMouseEnter()} > {ReactDOM.createPortal(
handleMouseEnter()} onMouseLeave={() => handleMouseLeave()} className={`${styles['notification-center-menu']} ${ visible && styles['notification-center-menu-show'] }`} > {menu}
, document.body, )}
); }; export default NotificationCenter;