|
@@ -1,4 +1,7 @@
|
|
|
-import Vue from 'vue';
|
|
|
|
|
|
|
+/**
|
|
|
|
|
+ * 路由配置(对齐 EOM)
|
|
|
|
|
+ */
|
|
|
|
|
+import Vue from 'vue';
|
|
|
import NProgress from 'nprogress';
|
|
import NProgress from 'nprogress';
|
|
|
import VueRouter from 'vue-router';
|
|
import VueRouter from 'vue-router';
|
|
|
import {
|
|
import {
|
|
@@ -10,78 +13,102 @@ import {
|
|
|
isHomeAliasPath,
|
|
isHomeAliasPath,
|
|
|
} from '@/config/setting';
|
|
} from '@/config/setting';
|
|
|
import store from '@/store';
|
|
import store from '@/store';
|
|
|
-import { getToken, setToken, getCurrentUser, removeToken } from '@/utils/token-util';
|
|
|
|
|
|
|
+import { getToken, setToken, getCurrentUser } from '@/utils/token-util';
|
|
|
import { routes, getMenuRoutes } from './routes';
|
|
import { routes, getMenuRoutes } from './routes';
|
|
|
import { changeRole } from '@/api/layout';
|
|
import { changeRole } from '@/api/layout';
|
|
|
import { rewriteLegacyHrMenus } from '@/utils/menu-rewrite';
|
|
import { rewriteLegacyHrMenus } from '@/utils/menu-rewrite';
|
|
|
|
|
|
|
|
Vue.use(VueRouter);
|
|
Vue.use(VueRouter);
|
|
|
|
|
|
|
|
-// 与 EOM 一致:
|
|
|
|
|
-// - WT 内浏览器路径:/page-hr/xxxx(同 page-eos/home/index)
|
|
|
|
|
-// - 独立运行:/hr/xxxx(同 /eos/,对应 publicPath)
|
|
|
|
|
-const routerOptions = {
|
|
|
|
|
- base: window.__POWERED_BY_QIANKUN__
|
|
|
|
|
- ? `/page-${SYSTEM_NAME}/`
|
|
|
|
|
- : `/${SYSTEM_NAME}/`,
|
|
|
|
|
- routes,
|
|
|
|
|
- mode: 'history',
|
|
|
|
|
- scrollBehavior() {
|
|
|
|
|
- return { y: 0 };
|
|
|
|
|
- },
|
|
|
|
|
-};
|
|
|
|
|
|
|
+/** 运行时计算 base,避免模块加载时 __POWERED_BY_QIANKUN__ 尚未注入 */
|
|
|
|
|
+export function getAppRouterBase() {
|
|
|
|
|
+ const pageBase = `/page-${SYSTEM_NAME}/`;
|
|
|
|
|
+ const shortBase = `/${SYSTEM_NAME}/`;
|
|
|
|
|
+ if (window.__POWERED_BY_QIANKUN__) {
|
|
|
|
|
+ return pageBase;
|
|
|
|
|
+ }
|
|
|
|
|
+ try {
|
|
|
|
|
+ const path = window.location?.pathname || '';
|
|
|
|
|
+ if (path === `/page-${SYSTEM_NAME}` || path.startsWith(pageBase)) {
|
|
|
|
|
+ return pageBase;
|
|
|
|
|
+ }
|
|
|
|
|
+ } catch (e) {
|
|
|
|
|
+ /* ignore */
|
|
|
|
|
+ }
|
|
|
|
|
+ return shortBase;
|
|
|
|
|
+}
|
|
|
|
|
|
|
|
function createRouter() {
|
|
function createRouter() {
|
|
|
- return new VueRouter(routerOptions);
|
|
|
|
|
|
|
+ return new VueRouter({
|
|
|
|
|
+ base: getAppRouterBase(),
|
|
|
|
|
+ routes,
|
|
|
|
|
+ mode: 'history',
|
|
|
|
|
+ scrollBehavior() {
|
|
|
|
|
+ return { y: 0 };
|
|
|
|
|
+ },
|
|
|
|
|
+ });
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
const router = createRouter();
|
|
const router = createRouter();
|
|
|
|
|
|
|
|
-/** 动态路由是否已挂到当前 matcher(用标记,避免 getRoutes 长度比较死循环) */
|
|
|
|
|
|
|
+/** 动态路由是否已挂到当前 matcher */
|
|
|
let dynamicRoutesReady = false;
|
|
let dynamicRoutesReady = false;
|
|
|
|
|
|
|
|
-/** 重新登录 / 切角色前清空动态路由,避免重复注册导致白屏 */
|
|
|
|
|
|
|
+/** 重新登录 / 切角色前清空动态路由 */
|
|
|
export function resetRouter() {
|
|
export function resetRouter() {
|
|
|
const newRouter = createRouter();
|
|
const newRouter = createRouter();
|
|
|
router.matcher = newRouter.matcher;
|
|
router.matcher = newRouter.matcher;
|
|
|
|
|
+ // 同步 options.base,避免后续跳转仍用旧 base
|
|
|
|
|
+ router.options.base = newRouter.options.base;
|
|
|
dynamicRoutesReady = false;
|
|
dynamicRoutesReady = false;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+/** 乾坤下把本系统菜单写回门户,防止被主应用默认/首个系统菜单覆盖 */
|
|
|
|
|
+function syncMenusToPortal(menus) {
|
|
|
|
|
+ if (!window.__POWERED_BY_QIANKUN__ || !menus?.length) return;
|
|
|
|
|
+ try {
|
|
|
|
|
+ Vue.prototype.$portalStore?.commit('user/setMenus', menus);
|
|
|
|
|
+ } catch (e) {
|
|
|
|
|
+ console.warn('[page-hr] syncMenusToPortal failed', e);
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
function registerMenuRoutes(menus, homePath, authoritiesRouter = []) {
|
|
function registerMenuRoutes(menus, homePath, authoritiesRouter = []) {
|
|
|
- resetRouter();
|
|
|
|
|
const nextMenus = rewriteLegacyHrMenus(menus || []);
|
|
const nextMenus = rewriteLegacyHrMenus(menus || []);
|
|
|
const nextAuth = rewriteLegacyHrMenus(authoritiesRouter || []);
|
|
const nextAuth = rewriteLegacyHrMenus(authoritiesRouter || []);
|
|
|
store.commit('user/setMenus', nextMenus);
|
|
store.commit('user/setMenus', nextMenus);
|
|
|
store.commit('user/setAuthoritiesRouter', nextAuth);
|
|
store.commit('user/setAuthoritiesRouter', nextAuth);
|
|
|
- router.addRoute(
|
|
|
|
|
- getMenuRoutes(
|
|
|
|
|
- [...nextMenus, ...nextAuth],
|
|
|
|
|
- homePath || HOME_PATH || '/home/index',
|
|
|
|
|
- ),
|
|
|
|
|
- );
|
|
|
|
|
|
|
+ // 接口拉到的菜单注册时同步写回门户
|
|
|
|
|
+ syncMenusToPortal(nextMenus);
|
|
|
|
|
+ // 与 EOM 一致:有菜单才注册
|
|
|
|
|
+ if (nextMenus.length || nextAuth.length) {
|
|
|
|
|
+ router.addRoute(
|
|
|
|
|
+ getMenuRoutes(
|
|
|
|
|
+ [...nextMenus, ...nextAuth],
|
|
|
|
|
+ homePath || HOME_PATH || '/home/index',
|
|
|
|
|
+ ),
|
|
|
|
|
+ );
|
|
|
|
|
+ }
|
|
|
dynamicRoutesReady = true;
|
|
dynamicRoutesReady = true;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/** 供登录页等外部主动注册动态路由 */
|
|
/** 供登录页等外部主动注册动态路由 */
|
|
|
export function setupDynamicRoutes(menus, homePath, authoritiesRouter = []) {
|
|
export function setupDynamicRoutes(menus, homePath, authoritiesRouter = []) {
|
|
|
|
|
+ resetRouter();
|
|
|
registerMenuRoutes(menus, homePath, authoritiesRouter);
|
|
registerMenuRoutes(menus, homePath, authoritiesRouter);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+/**
|
|
|
|
|
+ * 路由守卫(对齐 EOM:fetch 后 next({ ...to }),不强制改写地址栏)
|
|
|
|
|
+ */
|
|
|
router.beforeEach((to, from, next) => {
|
|
router.beforeEach((to, from, next) => {
|
|
|
if (!from.path.includes(REDIRECT_PATH)) {
|
|
if (!from.path.includes(REDIRECT_PATH)) {
|
|
|
NProgress.start();
|
|
NProgress.start();
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- const homePath = HOME_PATH || '/home/index';
|
|
|
|
|
-
|
|
|
|
|
if (getToken()) {
|
|
if (getToken()) {
|
|
|
- // 已登录访问登录页:直接进首页,避免停在空白态
|
|
|
|
|
- if (to.path === '/login') {
|
|
|
|
|
- next({ path: homePath, replace: true });
|
|
|
|
|
- return;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // 旧首页别名统一跳到 /home/index,避免再开「首页」可关闭页签
|
|
|
|
|
|
|
+ // 旧首页别名统一到 HOME_PATH
|
|
|
|
|
+ const homePath = HOME_PATH || '/home/index';
|
|
|
if (isHomeAliasPath(to.path) && to.path !== homePath) {
|
|
if (isHomeAliasPath(to.path) && to.path !== homePath) {
|
|
|
next({
|
|
next({
|
|
|
path: homePath,
|
|
path: homePath,
|
|
@@ -92,49 +119,51 @@ router.beforeEach((to, from, next) => {
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ // 还未注册动态路由则先获取(与 EOM:menus == null)
|
|
|
if (store.state.user.menus == null) {
|
|
if (store.state.user.menus == null) {
|
|
|
store
|
|
store
|
|
|
.dispatch('user/fetchUserInfo')
|
|
.dispatch('user/fetchUserInfo')
|
|
|
.then(({ menus, homePath: menuHome, authoritiesRouter }) => {
|
|
.then(({ menus, homePath: menuHome, authoritiesRouter }) => {
|
|
|
- registerMenuRoutes(
|
|
|
|
|
- menus || [],
|
|
|
|
|
- menuHome || homePath,
|
|
|
|
|
- authoritiesRouter || [],
|
|
|
|
|
- );
|
|
|
|
|
- // 根路径必须落到首页,否则只有布局、子路由空白
|
|
|
|
|
- const targetPath =
|
|
|
|
|
- to.path === LAYOUT_PATH || to.path === '/'
|
|
|
|
|
- ? homePath
|
|
|
|
|
- : to.fullPath;
|
|
|
|
|
- next({ path: targetPath, replace: true });
|
|
|
|
|
|
|
+ // 与 EOM:有菜单才 addRoute;无菜单也 next,避免卡死
|
|
|
|
|
+ if (menus?.length || authoritiesRouter?.length) {
|
|
|
|
|
+ registerMenuRoutes(
|
|
|
|
|
+ menus || [],
|
|
|
|
|
+ menuHome || homePath,
|
|
|
|
|
+ authoritiesRouter || [],
|
|
|
|
|
+ );
|
|
|
|
|
+ } else {
|
|
|
|
|
+ // 乾坤下接口暂无 /page-hr:沿用门户侧栏做路由,但不回写,
|
|
|
|
|
+ // 避免把主应用已错误覆盖的「第一个系统菜单」再次固化
|
|
|
|
|
+ const portalMenus =
|
|
|
|
|
+ Vue.prototype.$portalStore?.state?.user?.menus;
|
|
|
|
|
+ if (window.__POWERED_BY_QIANKUN__ && portalMenus?.length) {
|
|
|
|
|
+ store.commit(
|
|
|
|
|
+ 'user/setMenus',
|
|
|
|
|
+ rewriteLegacyHrMenus(portalMenus),
|
|
|
|
|
+ );
|
|
|
|
|
+ dynamicRoutesReady = true;
|
|
|
|
|
+ } else {
|
|
|
|
|
+ store.commit('user/setMenus', []);
|
|
|
|
|
+ dynamicRoutesReady = true;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ next({ ...to, replace: true });
|
|
|
})
|
|
})
|
|
|
.catch((e) => {
|
|
.catch((e) => {
|
|
|
console.error(e);
|
|
console.error(e);
|
|
|
- removeToken();
|
|
|
|
|
- store.commit('user/setMenus', null);
|
|
|
|
|
- store.commit('user/setAuthoritiesRouter', []);
|
|
|
|
|
- resetRouter();
|
|
|
|
|
- next({ path: '/login', replace: true });
|
|
|
|
|
|
|
+ next();
|
|
|
});
|
|
});
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- // 有菜单但动态路由未就绪时补注册(热更新 / reset 后)
|
|
|
|
|
- if (!dynamicRoutesReady) {
|
|
|
|
|
|
|
+ // 有菜单但动态路由未就绪时补注册
|
|
|
|
|
+ if (!dynamicRoutesReady && store.state.user.menus?.length) {
|
|
|
registerMenuRoutes(
|
|
registerMenuRoutes(
|
|
|
store.state.user.menus,
|
|
store.state.user.menus,
|
|
|
homePath,
|
|
homePath,
|
|
|
store.state.user.authoritiesRouter || [],
|
|
store.state.user.authoritiesRouter || [],
|
|
|
);
|
|
);
|
|
|
- const targetPath =
|
|
|
|
|
- to.path === LAYOUT_PATH || to.path === '/' ? homePath : to.fullPath;
|
|
|
|
|
- next({ path: targetPath, replace: true });
|
|
|
|
|
- return;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // 动态路由已就绪时,访问 / 仍强制进首页
|
|
|
|
|
- if (to.path === LAYOUT_PATH || to.path === '/') {
|
|
|
|
|
- next({ path: homePath, replace: true });
|
|
|
|
|
|
|
+ next({ ...to, replace: true });
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -164,6 +193,7 @@ router.afterEach((to) => {
|
|
|
router.roleChange = async ({ menus, homePath, authoritiesRouter }) => {
|
|
router.roleChange = async ({ menus, homePath, authoritiesRouter }) => {
|
|
|
const currentUser = getCurrentUser();
|
|
const currentUser = getCurrentUser();
|
|
|
if (menus?.length) {
|
|
if (menus?.length) {
|
|
|
|
|
+ resetRouter();
|
|
|
registerMenuRoutes(menus, homePath, authoritiesRouter);
|
|
registerMenuRoutes(menus, homePath, authoritiesRouter);
|
|
|
const target = HOME_PATH || menus[0].redirect || menus[0].path;
|
|
const target = HOME_PATH || menus[0].redirect || menus[0].path;
|
|
|
if (router.currentRoute.path !== target) {
|
|
if (router.currentRoute.path !== target) {
|