cloudMenu/src/models/user.ts
ylj20011123 fc695d48d3 update
2025-12-15 18:31:12 +08:00

455 lines
14 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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<UserModelState>;
};
}
/**
* 请求顺序
* @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;