import { Reducer } from 'redux'; import { Effect } from './connect.d'; import { Subscription } from 'dva'; import { routerRedux } from 'dva/router'; import store from '@/utils/store'; import { getPageQuery } from '@/utils'; import { setAuthority } from '@/utils/authority'; import { reloadAuthorized } from '@/utils/Authorized'; import { NoticeIconData } from '@/components/NoticeIcon'; import { queryNotices } from '@/services/user'; import { login, logout } from '@/services/global'; export interface NoticeItem extends NoticeIconData { id: string; type: string; status: string; } export interface GlobalModelState { collapsed: boolean; notices: NoticeItem[]; } export interface GlobalModelType { namespace: 'global'; state: GlobalModelState; effects: { fetchNotices: Effect; clearNotices: Effect; changeNoticeReadState: Effect; login: Effect; }; reducers: { changeLayoutCollapsed: Reducer; saveNotices: Reducer; saveClearedNotices: Reducer; changeLoginStatus: Reducer; }; subscriptions: { setup: Subscription }; } const GlobalModel: GlobalModelType = { namespace: 'global', state: { collapsed: false, notices: [], }, effects: { *login({ payload }, { call, put }) { const { code, data } = yield call(login, payload); if (code === 'sys.success') { yield put({ type: 'changeLoginStatus', payload: {}, }); reloadAuthorized(); const { token, userId } = data; store.set('token', token); store.set('userId', userId); const urlParams = new URL(window.location.href); const params = getPageQuery(); // 是否需要重定向 let { redirect } = params; if (redirect) { const redirectUrlParams = new URL(redirect); // origin相同 if (redirectUrlParams.origin === urlParams.origin) { redirect = redirect.substr(urlParams.origin.length); if (redirect.match(/^\/.*#/)) { redirect = redirect.substr(redirect.indexOf('#') + 1); } } else { window.location.href = redirect; return; } } // else { // redirect = config.homePage; // } yield put(routerRedux.replace(redirect || '/')); } }, *fetchNotices(_, { call, put, select }) { const data = yield call(queryNotices); yield put({ type: 'saveNotices', payload: data, }); const unreadCount: number = yield select( state => state.global.notices.filter(item => !item.read).length, ); yield put({ type: 'user/changeNotifyCount', payload: { totalCount: data.length, unreadCount, }, }); }, *clearNotices({ payload }, { put, select }) { yield put({ type: 'saveClearedNotices', payload, }); const count: number = yield select(state => state.global.notices.length); const unreadCount: number = yield select( state => state.global.notices.filter(item => !item.read).length, ); yield put({ type: 'user/changeNotifyCount', payload: { totalCount: count, unreadCount, }, }); }, *changeNoticeReadState({ payload }, { put, select }) { const notices: NoticeItem[] = 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, }, }); }, }, reducers: { changeLoginStatus(state, { payload }) { setAuthority('user'); return { ...state, }; }, changeLayoutCollapsed(state = { notices: [], collapsed: true }, { payload }): GlobalModelState { return { ...state, collapsed: payload, }; }, saveNotices(state, { payload }): GlobalModelState { return { collapsed: false, ...state, notices: payload, }; }, saveClearedNotices(state = { notices: [], collapsed: true }, { payload }): GlobalModelState { return { collapsed: false, ...state, notices: state.notices.filter((item): boolean => item.type !== payload), }; }, }, subscriptions: { setup({ history }): void { // Subscribe history(url) change, trigger `load` action if pathname is `/` history.listen(({ pathname, search }): void => { if (typeof (window as any).ga !== 'undefined') { (window as any).ga('send', 'pageview', pathname + search); } }); }, }, }; export default GlobalModel;