动态菜单和动态路由的 antd pro

index.js 5.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. import React, { PureComponent } from 'react';
  2. import { Menu, Icon, Spin, Tag, Dropdown, Avatar, Divider, Tooltip } from 'antd';
  3. import moment from 'moment';
  4. import groupBy from 'lodash/groupBy';
  5. import Debounce from 'lodash-decorators/debounce';
  6. import { Link } from 'dva/router';
  7. import NoticeIcon from '../NoticeIcon';
  8. import HeaderSearch from '../HeaderSearch';
  9. import styles from './index.less';
  10. export default class GlobalHeader extends PureComponent {
  11. componentWillUnmount() {
  12. this.triggerResizeEvent.cancel();
  13. }
  14. getNoticeData() {
  15. const { notices = [] } = this.props;
  16. if (notices.length === 0) {
  17. return {};
  18. }
  19. const newNotices = notices.map(notice => {
  20. const newNotice = { ...notice };
  21. if (newNotice.datetime) {
  22. newNotice.datetime = moment(notice.datetime).fromNow();
  23. }
  24. // transform id to item key
  25. if (newNotice.id) {
  26. newNotice.key = newNotice.id;
  27. }
  28. if (newNotice.extra && newNotice.status) {
  29. const color = {
  30. todo: '',
  31. processing: 'blue',
  32. urgent: 'red',
  33. doing: 'gold',
  34. }[newNotice.status];
  35. newNotice.extra = (
  36. <Tag color={color} style={{ marginRight: 0 }}>
  37. {newNotice.extra}
  38. </Tag>
  39. );
  40. }
  41. return newNotice;
  42. });
  43. return groupBy(newNotices, 'type');
  44. }
  45. toggle = () => {
  46. const { collapsed, onCollapse } = this.props;
  47. onCollapse(!collapsed);
  48. this.triggerResizeEvent();
  49. };
  50. /* eslint-disable*/
  51. @Debounce(600)
  52. triggerResizeEvent() {
  53. const event = document.createEvent('HTMLEvents');
  54. event.initEvent('resize', true, false);
  55. window.dispatchEvent(event);
  56. }
  57. render() {
  58. const {
  59. currentUser = {},
  60. collapsed,
  61. fetchingNotices,
  62. isMobile,
  63. logo,
  64. onNoticeVisibleChange,
  65. onMenuClick,
  66. onNoticeClear,
  67. } = this.props;
  68. const menu = (
  69. <Menu className={styles.menu} selectedKeys={[]} onClick={onMenuClick}>
  70. <Menu.Item disabled>
  71. <Icon type="user" />个人中心
  72. </Menu.Item>
  73. <Menu.Item disabled>
  74. <Icon type="setting" />设置
  75. </Menu.Item>
  76. <Menu.Item key="triggerError">
  77. <Icon type="close-circle" />触发报错
  78. </Menu.Item>
  79. <Menu.Divider />
  80. <Menu.Item key="logout">
  81. <Icon type="logout" />退出登录
  82. </Menu.Item>
  83. </Menu>
  84. );
  85. const noticeData = this.getNoticeData();
  86. return (
  87. <div className={styles.header}>
  88. {isMobile && [
  89. <Link to="/" className={styles.logo} key="logo">
  90. <img src={logo} alt="logo" width="32" />
  91. </Link>,
  92. <Divider type="vertical" key="line" />,
  93. ]}
  94. <Icon
  95. className={styles.trigger}
  96. type={collapsed ? 'menu-unfold' : 'menu-fold'}
  97. onClick={this.toggle}
  98. />
  99. <div className={styles.right}>
  100. <HeaderSearch
  101. className={`${styles.action} ${styles.search}`}
  102. placeholder="站内搜索"
  103. dataSource={['搜索提示一', '搜索提示二', '搜索提示三']}
  104. onSearch={value => {
  105. console.log('input', value); // eslint-disable-line
  106. }}
  107. onPressEnter={value => {
  108. console.log('enter', value); // eslint-disable-line
  109. }}
  110. />
  111. <Tooltip title="使用文档">
  112. <a
  113. target="_blank"
  114. href="http://pro.ant.design/docs/getting-started"
  115. rel="noopener noreferrer"
  116. className={styles.action}
  117. >
  118. <Icon type="question-circle-o" />
  119. </a>
  120. </Tooltip>
  121. <NoticeIcon
  122. className={styles.action}
  123. count={currentUser.notifyCount}
  124. onItemClick={(item, tabProps) => {
  125. console.log(item, tabProps); // eslint-disable-line
  126. }}
  127. onClear={onNoticeClear}
  128. onPopupVisibleChange={onNoticeVisibleChange}
  129. loading={fetchingNotices}
  130. popupAlign={{ offset: [20, -16] }}
  131. >
  132. <NoticeIcon.Tab
  133. list={noticeData['通知']}
  134. title="通知"
  135. emptyText="你已查看所有通知"
  136. emptyImage="https://gw.alipayobjects.com/zos/rmsportal/wAhyIChODzsoKIOBHcBk.svg"
  137. />
  138. <NoticeIcon.Tab
  139. list={noticeData['消息']}
  140. title="消息"
  141. emptyText="您已读完所有消息"
  142. emptyImage="https://gw.alipayobjects.com/zos/rmsportal/sAuJeJzSKbUmHfBQRzmZ.svg"
  143. />
  144. <NoticeIcon.Tab
  145. list={noticeData['待办']}
  146. title="待办"
  147. emptyText="你已完成所有待办"
  148. emptyImage="https://gw.alipayobjects.com/zos/rmsportal/HsIsxMZiWKrNUavQUXqx.svg"
  149. />
  150. </NoticeIcon>
  151. {currentUser.name ? (
  152. <Dropdown overlay={menu}>
  153. <span className={`${styles.action} ${styles.account}`}>
  154. <Avatar size="small" className={styles.avatar} src={currentUser.avatar} />
  155. <span className={styles.name}>{currentUser.name}</span>
  156. </span>
  157. </Dropdown>
  158. ) : (
  159. <Spin size="small" style={{ marginLeft: 8 }} />
  160. )}
  161. </div>
  162. </div>
  163. );
  164. }
  165. }