<template>
  <div id="app" v-loading="loading" style="min-height: 100vh">
    <transition name="fade" mode="out-in">
      <router-view v-if="!loading" :menu-list="menuList" :page-right="pageRight"></router-view>
    </transition>
  </div>
</template>

<script>
import Vue from 'vue';
import errorMsg from '@/common/js/error.js';
import { getRequest, postRequest } from '@/api/api.js';
import router from '@/router';
const whiteRoute = ['/login', '/loginMore'];
let toPath = '';
let fromPath = '';
router.beforeEach((to, from, next) => {
  toPath = to.path;
  fromPath = from.path;
  // 如果从登录页登页面进来后，刷新一下页面，重新获取权限相关的数据
  if (!sessionStorage.getItem('hbReload')) {
    if (whiteRoute.includes(fromPath)) {
      sessionStorage.setItem('hbReload', 1);
      setTimeout(() => {
        location.reload();
      }, 50);
    }
  } else {
    sessionStorage.removeItem('hbReload');
  }
  next();
});

export default {
  name: 'App',
  data() {
    return {
      loading: true,
      menuList: [],
      pageRight: []
    };
  },
  created() {
    this.getUserInfo().then(() => {
      // 如果是登录页登页面，就不获取权限数据
      if (whiteRoute.includes(toPath) || whiteRoute.includes(fromPath)) {
        this.loading = false;
      } else {
        Promise.all([this.getRight(), this.getMenuList()]).finally(() => {
          setTimeout(() => (this.loading = false), 200);
        });
      }
    });
  },
  methods: {
    getUserInfo() {
      return postRequest('/haoban-manage3-web/get-login-info', {}).then(resp => {
        const { errorCode, result } = resp.data || {};
        if (errorCode != 1) {
          errorMsg.errorMsg(resp.data);
          return;
        }
        sessionStorage.setItem('userInfos', JSON.stringify(result));
        if (result.enterpriseId) {
          Vue.axios.defaults.headers.common['enterpriseId'] = result.enterpriseId;
        }
      });
    },
    getMenuList() {
      return getRequest('/haoban-manage3-web/get-haoban-menu', {}).then(res => {
        const { errorCode, result } = res.data || [];
        if (errorCode != 1) {
          errorMsg.errorMsg(res.data);
          return;
        }
        if (!Array.isArray(result)) return;
        this.menuList = result;
        this.setIndexRoute(result);
      });
    },
    getRight() {
      return getRequest('/haoban-manage3-web/get-haoban-right', {}).then(resp => {
        const { errorCode, result } = resp.data || {};
        if (errorCode != 1) {
          errorMsg.errorMsg(resp.data);
          return;
        }
        this.pageRight = this.getPageRight(result.menu);
        this.checkButtonRight(result.button);
        this.checkPageRight(this.pageRight, menu => consoleButtonCode(menu, result.button));
        // 打印当前页面需要权限控制的按钮数据
        function consoleButtonCode(menu, buttonList) {
          if (menu && menu.menuCode) {
            console.log(buttonList.filter(el => el.parentCode == menu.menuCode));
          }
        }
      });
    },
    /**
     * @description 给页面权限数据添加正则字段，页面访问权限校验时使用正则字段校验url
     * @param {Array} menu 页面权限数据
     * @return {Array} 新的页面权限数据，已经添加了正则字段并且过滤掉menuUrl为空的数据
     */
    getPageRight(menu) {
      return menu
        .filter(el => typeof el.menuUrl == 'string' && el.menuUrl.length > 0)
        .map(el => {
          let { menuUrl } = el;
          let menuUrlReg = menuUrl;
          let pathConfigReg = /(:.*)(\/?)/;
          const pathRegStr = '([\\d\\w]+[\\-]*[\\d\\w]*)';
          while (pathConfigReg.test(menuUrlReg)) {
            menuUrlReg = menuUrlReg.replace(pathConfigReg, `${pathRegStr}$2`);
          }
          pathConfigReg = /(\/\*)(\/?)/;
          while (pathConfigReg.test(menuUrlReg)) {
            menuUrlReg = menuUrlReg.replace(pathConfigReg, `${pathRegStr}$2`);
          }
          el.regexp = new RegExp(`^\/${menuUrlReg}\$`);
          return el;
        });
    },
    /**
     * @description 校验按钮权限
     */
    checkButtonRight(rightList) {
      // 按钮权限校验
      Vue.prototype.$getButtonLimit = code => {
        const btn = rightList.find(el => el.menuCode == code) || {};
        return btn.hasRight == 1;
      };
    },
    /**
     * @description 校验页面访问权限
     * @param {Array} rightList 所有需要权限控制的页面路径，hasRight为1时才有访问权限
     */
    checkPageRight(rightList, consoleButtonCode) {
      // 页面访问权限校验
      const menu = rightList.find(el => el.regexp.test(toPath));
      // 页面第一次打开后，校验权限的beforeEach还没有创建，所以需要手动校验一下页面权限
      if (menu && menu.hasRight == 0) {
        // 切换商户后，如果当前页面无访问权限，就回首页
        // 如果地址栏中输入无权访问的路径，就到403
        const hbReloadPath = sessionStorage.getItem('hbReloadPath') || '';
        if (menu.menuUrl == hbReloadPath.substr(1)) {
          this.$router.push('/index');
          sessionStorage.removeItem('hbReloadPath');
        } else {
          this.$router.push({ path: '/403' });
        }
      }
      consoleButtonCode(menu);
      router.beforeEach((to, from, next) => {
        const menu = rightList.find(el => el.regexp.test(to.path));
        consoleButtonCode(menu);
        if (menu && menu.hasRight == 0) {
          return next({ path: '/403' });
        }
        next();
      });
    },
    /**
     * @description 设置/index路径重定向的路径，实现默认打开第一个有权限的页面
     * @param {Array} menuList 菜单权限树数据
     */
    setIndexRoute(menuList) {
      let path = '';
      const routes = [{ path: '*', redirect: '/404' }];
      menuList.some(first => {
        if (first.hasRight && first.isShow && Array.isArray(first.childList)) {
          first.childList.some(second => {
            if (second.hasRight && second.isShow && Array.isArray(second.childList)) {
              second.childList.some(third => {
                if (third.hasRight && third.isShow) {
                  path = third.menuUrl;
                }
                return third.hasRight && third.isShow;
              });
            }
            return path;
          });
        }
        return path;
      });
      if (path) {
        routes.push({ path: '/index', redirect: '/' + path });
      }
      this.$router.addRoutes(routes);
    }
  }
};
</script>
<style>
.svg-iconfont {
  width: 1em;
  height: 1em;
  vertical-align: -0.15em;
  fill: currentColor;
  overflow: hidden;
}
</style>
