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(
, 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 }; }, }, };