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: { Menus: storage("lacal").getItem("menus").val || [] },
OrgId: storage("lacal").getItem("webOrgId").val || "",
baseConfig: storage("lacal").getItem("baseConfig").val || {},
userId: (storage("lacal").getItem("webUserInfo").val || {}).ID || "",
user: storage("lacal").getItem("webUserInfo").val || {},
Tenant: storage("lacal").getItem("Tenant").val,
Notifications: [],
screenLocked: false, // 是否锁屏
flatMenus: storage("lacal").getItem("flatMenus").val || [],
currActivatedTab: null, // 用于面包屑导航,同步于 model app
currActivatedMenu: null, // 当前选中的菜单项,同步于 model app
roles: storage("lacal").getItem("roles").val || [],
rolePerm: storage("lacal").getItem("rolePerm").val || {},
userType: storage("lacal").getItem("UserType").val || 0,
},
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/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 {
if (localStorage.getItem("webOrgId") == '00300000-0000-0000-0000-000000000000') {
dispatch(routerRedux.replace('/grouphome'))
}else{
dispatch(routerRedux.replace('/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("webUserInfo", ret.User);
storage("lacal").setItem("DataRule", ret.DataRule || []);
storage("lacal").setItem("OrgRule", ret.OrgRule || []);
storage("lacal").setItem("departmentId", ret.User.DEPARTMENT_ID);
storage("lacal").setItem("MineType", ret.User.MineType);
storage("lacal").setItem("UserType", ret.UserType);
storage("lacal").setItem("baseConfig", ret.BaseConfig);
storage("lacal").setItem("roles", ret.Roles || []);
storage("lacal").setItem("rolePerm", ret.Nav_RolePerm || {});
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;
const safeFlatMenus = flatMenus.map(m => ({ ID: m.ID, NAME: m.NAME, CODE: m.CODE, MENU_LEVEL: m.MENU_LEVEL, idLevels: m.idLevels, nameLevels: m.nameLevels, menuLevels: m.menuLevels, Nav_MenuForm: m.Nav_MenuForm, IS_RESIDENT: m.IS_RESIDENT, ICON: m.ICON, IS_BACKEND: m.IS_BACKEND, MineType: m.MineType }));
const pruneMenus = (arr) => arr.map(it => ({ Node: { ID: it.Node.ID, NAME: it.Node.NAME, CODE: it.Node.CODE, MENU_LEVEL: it.Node.MENU_LEVEL, MineType: it.Node.MineType, Nav_MenuForm: it.Node.Nav_MenuForm, IS_RESIDENT: it.Node.IS_RESIDENT, ICON: it.Node.ICON, IS_BACKEND: it.Node.IS_BACKEND }, Children: (it.Children && it.Children.length) ? pruneMenus(it.Children) : [] }));
const safeMenus = pruneMenus(copyMenus);
storage("lacal").setItem("menus", safeMenus);
storage("lacal").setItem("flatMenus", safeFlatMenus);
const currentMineType = localStorage.getItem("currentMineType");
if (currentMineType) {
storage("lacal").setItem("currentMineType", currentMineType);
var filterObj = function (item) {
if (item.Node.MineType && item.Node.MineType.indexOf("_" + currentMineType + "_") > -1) {
if (item.Children.length !== 0) {
item.Children = item.Children.filter(function (child) {
if (child.Children.length !== 0) {
return filterObj(child);
} else {
if (child.Node.MineType) {
return child.Node.MineType.indexOf("_" + currentMineType + "_") > -1
}
}
});
if (item.Children.length > 0) {
return true;
}
} else {
if (item.Node.MineType) {
return item.Node.MineType.indexOf("_" + currentMineType + "_") > -1;
}
return;
}
return true;
}
};
var filter = ret.Menus.filter(function (item) {
return filterObj(item);
});
ret.Menus = filter;
}
// 存储 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,
currentMineType: currentMineType,
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, put }) {
const { OrgId } = yield select((state) => state.login);
if (!OrgId) {
const webOrgId = storage("lacal").getItem("webOrgId").val || storage("lacal").getItem("Orgid").val;
const userInfo = storage("lacal").getItem("webUserInfo").val;
const flatMenus = storage("lacal").getItem("flatMenus").val;
const menus = storage("lacal").getItem("menus").val;
const enums = storage("lacal").getItem("enums").val;
const baseConfig = storage("lacal").getItem("baseConfig").val;
const roles = storage("lacal").getItem("roles").val;
const rolePerm = storage("lacal").getItem("rolePerm").val;
if (webOrgId) {
const payload = { OrgId: webOrgId };
if (userInfo) {
payload.user = userInfo;
payload.userId = userInfo.ID;
}
if (flatMenus) {
payload.flatMenus = flatMenus;
}
if (baseConfig) {
payload.baseConfig = baseConfig;
}
if (menus) {
const tmpFlatMenus = [];
recurseMenu(menus, undefined, tmpFlatMenus);
payload.loginInfo = { Menus: menus };
payload.flatMenus = payload.flatMenus && payload.flatMenus.length ? payload.flatMenus : tmpFlatMenus;
}
if (roles) {
payload.roles = roles;
}
if (rolePerm) {
payload.rolePerm = rolePerm;
}
yield put({ type: "save", payload });
if (enums) {
yield put({ type: "app/save", payload: { enums } });
}
onSuccess instanceof Function && onSuccess();
} else {
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 };
},
},
};