import { history } from 'umi'; import { userLogin, retrieveUserInfo, retrieveUserInfoAuthorityMenu, userLogout, retrieveUserAuthorityMenu, } from '@/services/user'; import type { Effect, Reducer, ConnectProps } from 'umi'; import handleRedirect from '@/utils/handleRedirect'; import handleGetRootSubmenuKeys from '@/utils/handleGetRootSubmenuKeys'; import handleGetEachDatumFromNestedDataByKey from '@/utils/handleGetEachDatumFromNestedDataByKey'; import handleGetIndexValidMenuItemByPath from '@/utils/handleGetIndexValidMenuItemByPath'; import { notification } from 'antd'; /** * 全局用户数据 * @description isLogin 是否登录过 * @description data 用户信息 * @description menu 菜单数据 * @description authority 权限数组 * @description loginBtnLoading 按钮loading状态 * @description rootSubmenuKeys 子菜单的父级菜单key * @description layoutWrapperLoading 布局外层容器loading状态 * @description indexAllMenuItemById 通过id索引索引菜单项的映射 * @description indexAllMenuItemByPath 通过path索引所有菜单项的映射 * @description indexValidMenuItemByPath 通过path索引有效菜单项的映射 */ export type UserModelState = { isLogin: boolean; data: API.UserInfo; menu: API.MenuData; authority: string[]; loginBtnLoading: boolean; rootSubmenuKeys: React.Key[]; layoutWrapperLoading: boolean; indexAllMenuItemById: IndexAllMenuItemByKey<'id'>; indexValidMenuItemByPath: IndexValidMenuItemByPath; indexAllMenuItemByPath: IndexAllMenuItemByKey<'path'>; } export type UserConnectedProps = { user: UserModelState; } & ConnectProps; type UserModelType = { namespace: 'user'; state: UserModelState; effects: { login: Effect; logout: Effect; resetLoginStatus: Effect; getUserInfoAuthorityMenu: Effect; }; reducers: { save: Reducer; }; } /** * 请求顺序 * @description 并发 | 继发 */ type ReqOrder = 'concurrent' | 'relay'; const UserModel: UserModelType = { namespace: 'user', state: { data: {}, authority: [], isLogin: false, rootSubmenuKeys: [], loginBtnLoading: false, layoutWrapperLoading: true, menu: [ ], indexAllMenuItemById: { }, indexAllMenuItemByPath: { }, indexValidMenuItemByPath: { }, }, effects: { //登录 *login({ payload }, { call, put, select }) { // 检查当前是否已经在登录状态 const { isLogin } = yield select((state) => state.user); if (isLogin) { return { code: 1, message: '您已经登录' }; } // 检查是否有payload,防止自动触发 if (!payload) { return { code: 1, message: '登录参数无效' }; } yield put({ type: 'save', payload: { loginBtnLoading: true, }, }); try { const res: API.LoginResponse = yield call(userLogin, payload); console.log('res', res); if (res.code === 200) { localStorage.setItem('Authorization', res.data.accessToken); yield put({ type: 'getUserInfoAuthorityMenu', payload: { type: 'concurrent', }, }); return res; } else { yield put({ type: 'save', payload: { loginBtnLoading: false, }, }); return { code: res.code, message: res.message }; } } catch (error) { yield put({ type: 'save', payload: { loginBtnLoading: false, }, }); return { code: 1, message: error?.message || '登录失败,请稍后重试' }; } }, //获取用户信息和权限以及菜单 *getUserInfoAuthorityMenu({ payload }, { call, put }) { // const { type }: { type: ReqOrder } = payload; // // 如果当前在登录页面,且不是通过登录操作触发,则不执行后续操作 // if (window.location.pathname === '/user/login' && type !== 'concurrent') { // yield put({ // type: 'save', // payload: { // layoutWrapperLoading: false, // isLogin: false // 确保在登录页面时重置登录状态 // }, // }); // return false; // } let userInfoRes: API.UserInfoResponse = { data: {}, code: 0, message: '', }; // let userAuthorityRes: API.UserAuthorityResponse = { // data: { // authority: [], // }, // code: 0, // message: '', // }; let menuRes: API.MenuDataResponse = { data: [], code: 0, message: '', }; // //用户在登录页登录完成之后执行 // if (type === 'concurrent') { // const res: API.UserInfoAuthMenuResponse = yield call(retrieveUserInfoAuthorityMenu); // console.log('res', res); // userInfoRes = res[0] as API.UserInfoResponse; // // userAuthorityRes = res[1] as API.UserAuthorityResponse; // menuRes = res[1] as API.MenuDataResponse; // } else { // //其他情形首先查询用户的登录状态, 未登录则不继续操作 // try { // userInfoRes = yield call(retrieveUserInfo); // } catch (error) { // //接口报错了, 比如返回了401 // yield put({ // type: 'save', // payload: { // layoutWrapperLoading: false, // }, // }); // // 只有在非登录页面时才执行重定向 // if (window.location.pathname !== '/user/login') { // yield put({ // type: 'resetLoginStatus', // }); // } // return false; // } // const res: API.UserAuthMenuResponse = yield call(retrieveUserAuthorityMenu); // // userAuthorityRes = res[0] as API.UserAuthorityResponse; // menuRes = res[0] as API.MenuDataResponse; // } // console.log('userInfoRes', userInfoRes); menuRes.data = [ { path: '/', redirect: '', name: '', children: [ { path: '/test/index', redirect: '', name: '测试', component: "@/pages/test/index", }, { path: '/Invoicing/index', redirect: '', name: '开票管理', component: "@/pages/Invoicing/index", }, { path: '/DigitalElectronics/index', redirect: '', name: '开票管理', component: "@/pages/DigitalElectronics/index", }, { path: '/redReversal/index', redirect: '', name: '红冲管理', component: "@/pages/redReversal/index", }, { path: '/InvoiceInquiry/index', redirect: '', name: '开票查询', component: "@/pages/InvoiceInquiry/index", }, { path: '/InvoiceSearch/index', redirect: '', name: '开票查询', component: "@/pages/InvoiceSearch/index", }, { path: '/serverpartAssets/index', redirect: '', name: '服务区资产管理', component: "@/pages/serverpartAssets/index", }, { path: '/operationReport/index', redirect: '', name: '运营报表', component: "@/pages/operationReport/index", }, { path: '/operationReport/routineInspection', redirect: '', name: '日常巡检记录表', component: "@/pages/operationReport/routineInspection", }, { path: '/operationReport/onSiteInspection', redirect: '', name: '现场巡检记录表', component: "@/pages/operationReport/onSiteInspection", }, { path: '/operationReport/securityIssueList', redirect: '', name: '安全问题记录表', component: "@/pages/operationReport/securityIssueList", }, { path: '/operationReport/rectificationStatus', redirect: '', name: '整改情况追踪表', component: "@/pages/operationReport/rectificationStatus", }, { path: '/RentCalculation/index', redirect: '', name: '租金测算', component: "@/pages/RentCalculation/index", }, { path: '/rentComparison/index', redirect: '', name: '租金对比', component: "@/pages/rentComparison/index", }, { path: '/realEstate/index', redirect: '', name: '不动产管理', component: "@/pages/realEstate/index", }, ] } ] // menuRes.data = [ // { // path: '/standard/index', // redirect: '', // name: '生成标准页面', // component: "@/pages/standard/index", // }, // { // path: '/examine', // redirect: '', // name: '走动式管理', // children: [ // { // path: '/examine/index', // name: '考评分类管理', // component: "@/pages/examine/index", // }, // { // path: '/examine/question', // name: '考核问题管理', // component: "@/pages/examine/question", // }, // { // path: '/examine/modal', // name: '考核模版管理', // component: "@/pages/examine/modal", // }, // { // path: '/examine/record', // name: '考核记录管理', // component: "@/pages/examine/record", // } // ] // }, // ] let indexAllMenuItemByPath: any = [] let indexValidMenuItemByPath: any = [] if (menuRes.data && menuRes.data.length > 0) { indexAllMenuItemByPath = handleGetEachDatumFromNestedDataByKey(menuRes.data, 'path'); indexValidMenuItemByPath = handleGetIndexValidMenuItemByPath(menuRes.data); } //在登录完获取菜单数据之后做是否需要重定向的操作 yield call( handleRedirect, window.location.pathname === '/cloudMenu/user/login', indexAllMenuItemByPath, indexValidMenuItemByPath, ); yield put({ type: 'save', payload: { isLogin: true, menu: menuRes.data, data: userInfoRes.data, loginBtnLoading: false, indexAllMenuItemByPath, indexValidMenuItemByPath, layoutWrapperLoading: false, // authority: userAuthorityRes.data.authority, authority: [ '/test/index', '/cloudMenu/test/index', "/Invoicing/index", "/DigitalElectronics/index", "/InvoiceInquiry/index", "/redReversal/index", "/InvoiceSearch/index", "/serverpartAssets/index", "/operationReport/index", "/operationReport/routineInspection", "/operationReport/onSiteInspection", "/operationReport/securityIssueList", "/operationReport/rectificationStatus", "/RentCalculation/index", "/rentComparison/index", "/realEstate/index", // '/examine/index', // '/examine/modal', // '/examine/question', // '/examine/record', ], rootSubmenuKeys: handleGetRootSubmenuKeys(menuRes.data), indexAllMenuItemById: handleGetEachDatumFromNestedDataByKey(menuRes.data, 'id'), }, }); //为保证所有语句都return, 因此这里加一句这个 return true; }, //登出 * logout({ payload }, { call, put }) { const res: API.LogoutResponse = yield call(userLogout, payload); console.log('res', res) if (res.code === 200) { yield put({ type: 'resetLoginStatus', }); } }, //重置登录状态 * resetLoginStatus(_, { put }) { localStorage.removeItem('Authorization'); yield put({ type: 'save', payload: { isLogin: false, loginBtnLoading: false, }, }); //当前页面不是登录页时,才进行重定向 if (window.location.pathname !== '/user/login') { // 只获取路径部分,不包含查询参数,避免redirect参数累积 let redirectValue = window.location.pathname; // 检查是否有base路径重复问题 if (redirectValue.startsWith('/') && redirectValue.indexOf('/', 1) !== -1) { const firstSlashAfterRoot = redirectValue.indexOf('/', 1); const possiblePrefix = redirectValue.substring(0, firstSlashAfterRoot); // 检查是否有重复的路径前缀 if (redirectValue.indexOf(possiblePrefix, firstSlashAfterRoot) === firstSlashAfterRoot) { redirectValue = redirectValue.substring(firstSlashAfterRoot); } } // history.push(`/user/login?redirect=${encodeURIComponent(redirectValue)}`); } }, }, reducers: { save(state, action) { return { ...state, ...action.payload, }; }, }, }; export default UserModel;