375 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			375 lines
		
	
	
		
			12 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("MineType", ret.User.MineType);
 | 
						||
        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;
 | 
						||
 | 
						||
        const currentMineType = localStorage.getItem("currentMineType");
 | 
						||
        if (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,
 | 
						||
            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 };
 | 
						||
    },
 | 
						||
  },
 | 
						||
};
 |