1
0

NoticeIcon.tsx 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. import { BellOutlined } from '@ant-design/icons';
  2. import { Badge, Spin, Tabs } from 'antd';
  3. import classNames from 'classnames';
  4. import useMergedState from 'rc-util/es/hooks/useMergedState';
  5. import React from 'react';
  6. import HeaderDropdown from '../HeaderDropdown';
  7. import styles from './index.less';
  8. import type { NoticeIconTabProps } from './NoticeList';
  9. import NoticeList from './NoticeList';
  10. const { TabPane } = Tabs;
  11. export type NoticeIconProps = {
  12. count?: number;
  13. bell?: React.ReactNode;
  14. className?: string;
  15. loading?: boolean;
  16. onClear?: (tabName: string, tabKey: string) => void;
  17. onItemClick?: (item: API.NoticeIconItem, tabProps: NoticeIconTabProps) => void;
  18. onViewMore?: (tabProps: NoticeIconTabProps, e: MouseEvent) => void;
  19. onTabChange?: (tabTile: string) => void;
  20. style?: React.CSSProperties;
  21. onPopupVisibleChange?: (visible: boolean) => void;
  22. popupVisible?: boolean;
  23. clearText?: string;
  24. viewMoreText?: string;
  25. clearClose?: boolean;
  26. emptyImage?: string;
  27. children?: React.ReactElement<NoticeIconTabProps>[];
  28. };
  29. const NoticeIcon: React.FC<NoticeIconProps> & {
  30. Tab: typeof NoticeList;
  31. } = (props) => {
  32. const getNotificationBox = (): React.ReactNode => {
  33. const {
  34. children,
  35. loading,
  36. onClear,
  37. onTabChange,
  38. onItemClick,
  39. onViewMore,
  40. clearText,
  41. viewMoreText,
  42. } = props;
  43. if (!children) {
  44. return null;
  45. }
  46. const panes: React.ReactNode[] = [];
  47. React.Children.forEach(children, (child: React.ReactElement<NoticeIconTabProps>): void => {
  48. if (!child) {
  49. return;
  50. }
  51. const { list, title, count, tabKey, showClear, showViewMore } = child.props;
  52. const len = list && list.length ? list.length : 0;
  53. const msgCount = count || count === 0 ? count : len;
  54. const tabTitle: string = msgCount > 0 ? `${title} (${msgCount})` : title;
  55. panes.push(
  56. <TabPane tab={tabTitle} key={tabKey}>
  57. <NoticeList
  58. clearText={clearText}
  59. viewMoreText={viewMoreText}
  60. list={list}
  61. tabKey={tabKey}
  62. onClear={(): void => onClear && onClear(title, tabKey)}
  63. onClick={(item): void => onItemClick && onItemClick(item, child.props)}
  64. onViewMore={(event): void => onViewMore && onViewMore(child.props, event)}
  65. showClear={showClear}
  66. showViewMore={showViewMore}
  67. title={title}
  68. />
  69. </TabPane>,
  70. );
  71. });
  72. return (
  73. <>
  74. <Spin spinning={loading} delay={300}>
  75. <Tabs className={styles.tabs} onChange={onTabChange}>
  76. {panes}
  77. </Tabs>
  78. </Spin>
  79. </>
  80. );
  81. };
  82. const { className, count, bell } = props;
  83. const [visible, setVisible] = useMergedState<boolean>(false, {
  84. value: props.popupVisible,
  85. onChange: props.onPopupVisibleChange,
  86. });
  87. const noticeButtonClass = classNames(className, styles.noticeButton);
  88. const notificationBox = getNotificationBox();
  89. const NoticeBellIcon = bell || <BellOutlined className={styles.icon} />;
  90. const trigger = (
  91. <span className={classNames(noticeButtonClass, { opened: visible })}>
  92. <Badge count={count} style={{ boxShadow: 'none' }} className={styles.badge}>
  93. {NoticeBellIcon}
  94. </Badge>
  95. </span>
  96. );
  97. if (!notificationBox) {
  98. return trigger;
  99. }
  100. return (
  101. <HeaderDropdown
  102. placement="bottomRight"
  103. overlay={notificationBox}
  104. overlayClassName={styles.popover}
  105. trigger={['click']}
  106. visible={visible}
  107. onVisibleChange={setVisible}
  108. >
  109. {trigger}
  110. </HeaderDropdown>
  111. );
  112. };
  113. NoticeIcon.defaultProps = {
  114. emptyImage: 'https://gw.alipayobjects.com/zos/rmsportal/wAhyIChODzsoKIOBHcBk.svg',
  115. };
  116. NoticeIcon.Tab = NoticeList;
  117. export default NoticeIcon;