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