Просмотр исходного кода

feat: add count prop for NoticeIconTab component (#2862)

* feat: add count prop for NoticeIconTab component.(ant-design-pro#2216)
prop count is not required.

* feat: unread notice message demo
Anyuxuan 7 лет назад
Родитель
Сommit
3fffc83d70

+ 1 - 0
mock/user.js

@@ -36,6 +36,7 @@ export default {
       },
     ],
     notifyCount: 12,
+    unreadCount: 11,
     country: 'China',
     geographic: {
       province: {

+ 28 - 1
src/components/GlobalHeader/RightContent.js

@@ -40,6 +40,28 @@ export default class GlobalHeaderRight extends PureComponent {
     return groupBy(newNotices, 'type');
   }
 
+  getUnreadData = noticeData => {
+    const unreadMsg = {};
+    Object.entries(noticeData).forEach(([key, value]) => {
+      if (!unreadMsg[key]) {
+        unreadMsg[key] = 0;
+      }
+      if (Array.isArray(value)) {
+        unreadMsg[key] = value.filter(item => !item.read).length;
+      }
+    });
+    return unreadMsg;
+  };
+
+  changeReadState = clickedItem => {
+    const { id } = clickedItem;
+    const { dispatch } = this.props;
+    dispatch({
+      type: 'global/changeNoticeReadState',
+      payload: id,
+    });
+  };
+
   render() {
     const {
       currentUser,
@@ -71,6 +93,7 @@ export default class GlobalHeaderRight extends PureComponent {
       </Menu>
     );
     const noticeData = this.getNoticeData();
+    const unreadMsg = this.getUnreadData(noticeData);
     let className = styles.right;
     if (theme === 'dark') {
       className = `${styles.right}  ${styles.dark}`;
@@ -104,9 +127,10 @@ export default class GlobalHeaderRight extends PureComponent {
         </Tooltip>
         <NoticeIcon
           className={styles.action}
-          count={currentUser.notifyCount}
+          count={currentUser.unreadCount}
           onItemClick={(item, tabProps) => {
             console.log(item, tabProps); // eslint-disable-line
+            this.changeReadState(item, tabProps);
           }}
           locale={{
             emptyText: formatMessage({ id: 'component.noticeIcon.empty' }),
@@ -119,6 +143,7 @@ export default class GlobalHeaderRight extends PureComponent {
           clearClose
         >
           <NoticeIcon.Tab
+            count={unreadMsg.notification}
             list={noticeData.notification}
             title={formatMessage({ id: 'component.globalHeader.notification' })}
             name="notification"
@@ -126,6 +151,7 @@ export default class GlobalHeaderRight extends PureComponent {
             emptyImage="https://gw.alipayobjects.com/zos/rmsportal/wAhyIChODzsoKIOBHcBk.svg"
           />
           <NoticeIcon.Tab
+            count={unreadMsg.message}
             list={noticeData.message}
             title={formatMessage({ id: 'component.globalHeader.message' })}
             name="message"
@@ -133,6 +159,7 @@ export default class GlobalHeaderRight extends PureComponent {
             emptyImage="https://gw.alipayobjects.com/zos/rmsportal/sAuJeJzSKbUmHfBQRzmZ.svg"
           />
           <NoticeIcon.Tab
+            count={unreadMsg.event}
             list={noticeData.event}
             title={formatMessage({ id: 'component.globalHeader.event' })}
             name="event"

+ 1 - 0
src/components/NoticeIcon/NoticeIconTab.d.ts

@@ -10,6 +10,7 @@ export interface INoticeIconData {
 
 export interface INoticeIconTabProps {
   list?: INoticeIconData[];
+  count?: number;
   title?: string;
   name?: string;
   emptyText?: React.ReactNode;

+ 12 - 12
src/components/NoticeIcon/index.js

@@ -33,13 +33,13 @@ export default class NoticeIcon extends PureComponent {
     }
   };
 
-  onClear = (name) => {
+  onClear = name => {
     const { onClear, clearClose } = this.props;
-    onClear(name)
+    onClear(name);
     if (clearClose) {
       this.popover.click();
     }
-  }
+  };
 
   onTabChange = tabType => {
     const { onTabChange } = this.props;
@@ -52,18 +52,18 @@ export default class NoticeIcon extends PureComponent {
       return null;
     }
     const panes = React.Children.map(children, child => {
-      const title =
-        child.props.list && child.props.list.length > 0
-          ? `${child.props.title} (${child.props.list.length})`
-          : child.props.title;
+      const { list, title, name, count } = child.props;
+      const len = list && list.length ? list.length : 0;
+      const msgCount = count || count === 0 ? count : len;
+      const tabTitle = msgCount > 0 ? `${title} (${msgCount})` : title;
       return (
-        <TabPane tab={title} key={child.props.name}>
+        <TabPane tab={tabTitle} key={name}>
           <List
             {...child.props}
-            data={child.props.list}
+            data={list}
             onClick={item => this.onItemClick(item, child.props)}
-            onClear={() => this.onClear(child.props.name)}
-            title={child.props.title}
+            onClear={() => this.onClear(name)}
+            title={title}
             locale={locale}
           />
         </TabPane>
@@ -107,7 +107,7 @@ export default class NoticeIcon extends PureComponent {
         popupAlign={popupAlign}
         onVisibleChange={onPopupVisibleChange}
         {...popoverProps}
-        ref={node => { this.popover = ReactDOM.findDOMNode(node)}} // eslint-disable-line
+        ref={node => (this.popover = ReactDOM.findDOMNode(node))} // eslint-disable-line
       >
         {trigger}
       </Popover>

+ 37 - 3
src/models/global.js

@@ -9,15 +9,21 @@ export default {
   },
 
   effects: {
-    *fetchNotices(_, { call, put }) {
+    *fetchNotices(_, { call, put, select }) {
       const data = yield call(queryNotices);
       yield put({
         type: 'saveNotices',
         payload: data,
       });
+      const unreadCount = yield select(
+        state => state.global.notices.filter(item => !item.read).length
+      );
       yield put({
         type: 'user/changeNotifyCount',
-        payload: data.length,
+        payload: {
+          totalCount: data.length,
+          unreadCount,
+        },
       });
     },
     *clearNotices({ payload }, { put, select }) {
@@ -26,9 +32,37 @@ export default {
         payload,
       });
       const count = yield select(state => state.global.notices.length);
+      const unreadCount = yield select(
+        state => state.global.notices.filter(item => !item.read).length
+      );
       yield put({
         type: 'user/changeNotifyCount',
-        payload: count,
+        payload: {
+          totalCount: count,
+          unreadCount,
+        },
+      });
+    },
+    *changeNoticeReadState({ payload }, { put, select }) {
+      const notices = yield select(state =>
+        state.global.notices.map(item => {
+          const notice = { ...item };
+          if (notice.id === payload) {
+            notice.read = true;
+          }
+          return notice;
+        })
+      );
+      yield put({
+        type: 'saveNotices',
+        payload: notices,
+      });
+      yield put({
+        type: 'user/changeNotifyCount',
+        payload: {
+          totalCount: notices.length,
+          unreadCount: notices.filter(item => !item.read).length,
+        },
       });
     },
   },

+ 2 - 1
src/models/user.js

@@ -43,7 +43,8 @@ export default {
         ...state,
         currentUser: {
           ...state.currentUser,
-          notifyCount: action.payload,
+          notifyCount: action.payload.totalCount,
+          unreadCount: action.payload.unreadCount,
         },
       };
     },