global.ts 3.46 KB
Newer Older
1 2
import { Reducer } from 'redux';
import { Subscription } from 'dva';
ι™ˆεΈ…'s avatar
ι™ˆεΈ… committed
3 4 5

import { Effect } from './connect.d';
import { NoticeIconData } from '@/components/NoticeIcon';
6
import { queryNotices } from '@/services/user';
何乐's avatar
何乐 committed
7

8
export interface NoticeItem extends NoticeIconData {
何乐's avatar
何乐 committed
9 10
  id: string;
  type: string;
11
  status: string;
何乐's avatar
何乐 committed
12
}
13

14 15
export interface GlobalModelState {
  collapsed: boolean;
何乐's avatar
何乐 committed
16
  notices: NoticeItem[];
17 18 19 20 21 22 23 24 25
}

export interface GlobalModelType {
  namespace: 'global';
  state: GlobalModelState;
  effects: {
    fetchNotices: Effect;
    clearNotices: Effect;
    changeNoticeReadState: Effect;
duanledexianxianxian's avatar
sync  
duanledexianxianxian committed
26
    checkUserLoginStatus: Effect;
27 28
  };
  reducers: {
何乐's avatar
何乐 committed
29 30 31
    changeLayoutCollapsed: Reducer<GlobalModelState>;
    saveNotices: Reducer<GlobalModelState>;
    saveClearedNotices: Reducer<GlobalModelState>;
32 33 34 35 36
  };
  subscriptions: { setup: Subscription };
}

const GlobalModel: GlobalModelType = {
37 38 39 40 41 42 43 44
  namespace: 'global',

  state: {
    collapsed: false,
    notices: [],
  },

  effects: {
45
    *fetchNotices(_, { call, put, select }) {
46 47 48
      const data = yield call(queryNotices);
      yield put({
        type: 'saveNotices',
Yu's avatar
Yu committed
49
        payload: data,
50
      });
何乐's avatar
何乐 committed
51 52
      const unreadCount: number = yield select(
        state => state.global.notices.filter(item => !item.read).length,
53
      );
Xiaoming Liu's avatar
Xiaoming Liu committed
54 55
      yield put({
        type: 'user/changeNotifyCount',
56 57 58 59
        payload: {
          totalCount: data.length,
          unreadCount,
        },
Xiaoming Liu's avatar
Xiaoming Liu committed
60
      });
61
    },
afc163's avatar
afc163 committed
62
    *clearNotices({ payload }, { put, select }) {
63 64 65 66
      yield put({
        type: 'saveClearedNotices',
        payload,
      });
何乐's avatar
何乐 committed
67 68 69
      const count: number = yield select(state => state.global.notices.length);
      const unreadCount: number = yield select(
        state => state.global.notices.filter(item => !item.read).length,
70
      );
afc163's avatar
afc163 committed
71 72
      yield put({
        type: 'user/changeNotifyCount',
73 74 75 76 77 78 79
        payload: {
          totalCount: count,
          unreadCount,
        },
      });
    },
    *changeNoticeReadState({ payload }, { put, select }) {
何乐's avatar
何乐 committed
80
      const notices: NoticeItem[] = yield select(state =>
81 82 83 84 85 86
        state.global.notices.map(item => {
          const notice = { ...item };
          if (notice.id === payload) {
            notice.read = true;
          }
          return notice;
何乐's avatar
何乐 committed
87
        }),
88
      );
89

90 91 92 93
      yield put({
        type: 'saveNotices',
        payload: notices,
      });
94

95 96 97 98 99 100
      yield put({
        type: 'user/changeNotifyCount',
        payload: {
          totalCount: notices.length,
          unreadCount: notices.filter(item => !item.read).length,
        },
afc163's avatar
afc163 committed
101 102
      });
    },
103 104 105
  },

  reducers: {
106
    changeLayoutCollapsed(state = { notices: [], collapsed: true }, { payload }): GlobalModelState {
107 108 109 110 111
      return {
        ...state,
        collapsed: payload,
      };
    },
112
    saveNotices(state, { payload }): GlobalModelState {
113
      return {
ι™ˆεΈ…'s avatar
ι™ˆεΈ… committed
114
        collapsed: false,
115 116 117 118
        ...state,
        notices: payload,
      };
    },
119
    saveClearedNotices(state = { notices: [], collapsed: true }, { payload }): GlobalModelState {
120
      return {
ι™ˆεΈ…'s avatar
ι™ˆεΈ… committed
121
        collapsed: false,
122
        ...state,
123
        notices: state.notices.filter((item): boolean => item.type !== payload),
124 125 126
      };
    },
  },
afc163's avatar
afc163 committed
127 128

  subscriptions: {
129
    setup({ history }): void {
afc163's avatar
afc163 committed
130
      // Subscribe history(url) change, trigger `load` action if pathname is `/`
131
      history.listen(({ pathname, search }): void => {
132 133
        if (typeof (window as any).ga !== 'undefined') {
          (window as any).ga('send', 'pageview', pathname + search);
afc163's avatar
afc163 committed
134 135 136 137
        }
      });
    },
  },
138
};
139 140

export default GlobalModel;