mh-sms-web/src/models/login.js

339 lines
11 KiB
JavaScript
Raw Normal View History

2024-01-22 09:18:38 +08:00
import * as appService from "../services/login";
import { routerRedux } from "dva/router";
import { initFilter } from "../utils/common";
import storage from "../utils/storage";
import { history as globalHistory } from "../utils/history";
import { cloneDeep } from "lodash";
import ReactDOM from "react-dom";
import { Spin } from "antd";
import config from "../config";
function recurseMenu(menus, parentMenu = {}, flatMenus = []) {
menus.forEach((menu) => {
const { Node: Menu, Children: ChildMenus } = menu;
menu.Menu = Menu;
menu.ChildMenus = ChildMenus;
Menu.idLevels = (parentMenu.idLevels || []).concat(Menu.ID);
Menu.nameLevels = (parentMenu.nameLevels || []).concat(Menu.NAME);
Menu.menuLevels = (parentMenu.menuLevels || []).concat(Menu.MENU_LEVEL);
Menu.childMenuLevels = (parentMenu.childMenuLevels || []).concat([
ChildMenus,
]);
flatMenus.push(Menu);
ChildMenus && ChildMenus.length && recurseMenu(ChildMenus, Menu, flatMenus);
});
}
// 当前正在请求的数量
let requestCount = 0;
// 显示loading
function showLoading() {
const spinStyle = {
position: "fixed",
width: "100vw",
height: "100vh",
justifyContent: "center",
alignItems: "center",
display: "flex",
top: 0,
left: 0,
background: "rgba(229, 229, 229, 0.5)",
zIndex: 1000,
};
if (requestCount === 0) {
var dom = document.createElement("div");
dom.setAttribute("id", "loading");
document.body.appendChild(dom);
ReactDOM.render(
<div style={spinStyle}>
<Spin tip="加载中..." size="large" />
</div>,
dom
);
}
requestCount++;
}
// 隐藏loading
function hideLoading() {
requestCount--;
if (requestCount === 0) {
document.body.removeChild(document.getElementById("loading"));
}
}
export default {
namespace: "login",
state: {
loginInfo: {},
OrgId: "",
baseConfig: {},
userId: "",
user: {},
Tenant: storage("lacal").getItem("Tenant").val,
Notifications: [],
screenLocked: false, // 是否锁屏
flatMenus: [],
currActivatedTab: null, // 用于面包屑导航,同步于 model app
currActivatedMenu: null, // 当前选中的菜单项,同步于 model app
},
subscriptions: {
setup({ dispatch, history }) {
history.listen((params) => {
const toLogin = function () {
let tm;
showLoading();
tm = setTimeout(() => {
localStorage.removeItem("accessToken");
dispatch(routerRedux.push("/login"));
hideLoading();
}, 10000);
const { username, password } =
storage("lacal").getItem("loginUserVerify").val;
const webOrgId = storage("lacal").getItem("webOrgId").val;
dispatch({
type: "toLogin",
payload: {
Parameter1: username,
Parameter2: password,
Parameter4: webOrgId,
Parameter5: storage("lacal").getItem("formConfigVersion").val,
Parameter7: true,
},
}).then((validRes) => {
if (validRes) {
dispatch({
type: "getOrg",
payload: {
Sort: "CODE",
Order: 0,
Parameter10: window.location.host,
Parameter11: "0",
},
});
dispatch({
type: "refreshToken",
});
dispatch({
type: "app/getCurrVer",
});
dispatch({
type: "app/getAllEnum",
}).then((e) => {
clearTimeout(tm);
hideLoading();
});
}
});
};
const { pathname } = params;
if (pathname !== "/login") {
/**
* 当前页不在登录页并且 local 不存在 token
* 那么直接跳转登录页
*/
if (!storage("lacal").getItem("accessToken").val) {
dispatch(routerRedux.push("/login"));
return;
}
/**
* 当前页不在登录页并且 local 存在 token
* 如果不存在 OrgId则说明还未登录此时调用登录接口
*/
dispatch({
type: "checkLoginStatus",
onFail: () => toLogin(),
});
} else {
/**
* 当前页在登录页并且 local 存在 token
* 则直接跳转到首页首页调用的接口会验证此 token 是否过期
* 如果 local token 真的过期那么还是会自动跳转到登录页
* 如果 local token 没过期则正常停留在主页
*/
if (storage("lacal").getItem("accessToken").val) {
if (window.navigator.userAgent.indexOf("Windows") < 1) {
window.location.replace(config.guideH5Host);
// dispatch(routerRedux.push("/HomeMobileNew"));
} else {
dispatch(routerRedux.push("/home"));
}
// 新开 tab 页面,直接从 login 路径进来,则需要重新检查一下是否登录,未登录则执行登录获取到菜单以及必要数据
dispatch({
type: "checkLoginStatus",
onFail: () => toLogin(),
});
}
}
});
},
},
effects: {
// 获取组织列表
*getOrg({ payload }, { call, put }) {
const ret = yield call(appService.getOrg, payload);
if (ret) {
const { Tenant = "", Data = [] } = ret;
storage("lacal").setItem("Tenant", Tenant);
storage("lacal").setItem("RootOrgId", Data[0]?.Node?.ID || "");
yield put({ type: "save", payload: { Tenant } });
}
return ret;
},
// 获取 Token
*getToken({ payload }, { call }) {
return yield call(appService.getToken, payload);
},
// 刷新 Token以保持登录状态
*refreshToken({ payload }, { call, put, select }) {
// 锁屏状态下不更新
const { screenLocked } = yield select((state) => state.login);
if (screenLocked) return;
// 存在 payload 则只更新 payload 中的 token
if (payload) {
const { access_token, refreshToken, expiresIn } = payload;
storage("lacal").setItem("accessToken", access_token);
storage("lacal").setItem("refreshToken", refreshToken);
storage("lacal").setItem("expiresIn", expiresIn);
storage("lacal").setItem("refreshTimestamp", new Date().getTime());
return;
}
// 如果刷新的时候已经是过期之后的时间了,则不再继续刷新 token
const nowTimestamp = new Date().getTime();
const refreshTimestamp = storage("lacal").getItem("refreshTimestamp").val;
const expiresIn = storage("lacal").getItem("expiresIn").val;
// 登陆过期
if (
refreshTimestamp &&
refreshTimestamp + expiresIn * 1000 <= nowTimestamp
) {
console.log("过期了");
localStorage.removeItem("accessToken");
globalHistory.push({ pathname: "/login" });
return;
}
// 接口刷新 token
const RefreshToken = storage("lacal").getItem("refreshToken").val;
const ret = yield call(appService.getToken, {
RefreshToken,
grant_type: 2,
});
if (ret && !ret.error) {
const { access_token, refreshToken, expiresIn } = ret;
storage("lacal").setItem("accessToken", access_token);
storage("lacal").setItem("refreshToken", refreshToken);
storage("lacal").setItem("expiresIn", expiresIn);
storage("lacal").setItem("refreshTimestamp", new Date().getTime());
}
},
// 登录、获取信息
*toLogin({ payload, loginPayload }, { call, put, select }) {
const ret = yield call(appService.getLoginInfo, payload);
if (ret) {
if (loginPayload) {
const {
accessToken,
refreshToken,
expiresIn,
username,
password,
userid,
} = loginPayload;
storage("lacal").setItem("accessToken", accessToken); // access_token存入localStorage
storage("lacal").setItem("refreshToken", refreshToken);
storage("lacal").setItem("expiresIn", expiresIn);
storage("lacal").setItem("refreshTimestamp", new Date().getTime());
storage("lacal").setItem("userid", userid);
storage("lacal").setItem("loginUserVerify", { username, password }); // 登录凭证存入localStorage
}
storage("lacal").setItem("webOrgId", ret.User.ORG_ID);
storage("lacal").setItem("DataRule", ret.DataRule || []);
storage("lacal").setItem("OrgRule", ret.OrgRule || []);
storage("lacal").setItem("departmentId", ret.User.DEPARTMENT_ID);
storage("lacal").setItem("UserType", ret.UserType);
const localStorage = window.localStorage;
ret.FormConfigVersion &&
storage("lacal").setItem("formConfigVersion", ret.FormConfigVersion);
// 拍平 Menus
const flatMenus = [];
const copyMenus = cloneDeep(ret.Menus);
recurseMenu(copyMenus, undefined, flatMenus);
ret.Menus = copyMenus;
// 存储 model state
yield put({
type: "save",
payload: {
loginInfo: ret,
OrgId: ret.User.ORG_ID,
OrgCode: ret.User.Nav_Org ? ret.User.Nav_Org.CODE : "",
baseConfig: ret.BaseConfig,
userType: ret.UserType,
roles: ret.Roles,
rolePerm: ret.Nav_RolePerm,
userId: ret.User.ID,
user: ret.User,
flatMenus,
},
});
// 不是很清楚为什么这里要清除这个 requestKey
// const localStorage = window.localStorage
if (localStorage) {
for (let i = 0; i < localStorage.length; i++) {
const key = localStorage.key(i);
if (key.indexOf("_requestKey") > -1) {
localStorage.removeItem(key);
}
}
}
// 获取消息提醒
const getNoticesParams = initFilter(
ret.User.ORG_ID,
"",
"CREATE_TIME",
1,
1,
ret.User.ID
);
yield put({ type: "getNotices", payload: getNoticesParams });
}
return ret;
},
// 验证登录状态
*checkLoginStatus({ onSuccess, onFail }, { select }) {
const { OrgId } = yield select((state) => state.login);
if (!OrgId) {
onFail instanceof Function && onFail();
} else {
onSuccess instanceof Function && onSuccess();
}
},
// 获取消息通知
*getNotices({ payload }, { call, put }) {
const ret = yield call(appService.getNotices, payload);
yield put({
type: "save",
payload: {
Notifications: ret,
},
});
return ret;
},
// 获取告警日志
*getAlarmLog({ payload }, { call }) {
return yield call(appService.getAlarmLog, payload);
},
// 修改密码
*modifyPassword({ payload }, { call }) {
return yield call(appService.modifyPassword, payload);
},
},
reducers: {
save(state, action) {
return { ...state, ...action.payload };
},
},
};