NoticeIcon.tsx 3.7 KB

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