mh-sms-web/src/models/login.js
2024-02-02 10:46:11 +08:00

339 lines
11 KiB
JavaScript
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 * 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 };
},
},
};