mirror of
https://gitee.com/yiming_chang/vue-pure-admin.git
synced 2024-11-29 17:57:37 +08:00
parent
d49b23e8f9
commit
9d0c3f305d
3
.env
3
.env
@ -1,2 +1,5 @@
|
|||||||
# 平台本地运行端口号
|
# 平台本地运行端口号
|
||||||
VITE_PORT = 8848
|
VITE_PORT = 8848
|
||||||
|
|
||||||
|
# 是否隐藏首页 隐藏 true 不隐藏 false (勿删除,VITE_HIDE_HOME只需在.env文件配置)
|
||||||
|
VITE_HIDE_HOME = false
|
||||||
|
@ -6,6 +6,7 @@ const warpperEnv = (envConf: Recordable): ViteEnv => {
|
|||||||
VITE_PUBLIC_PATH: "",
|
VITE_PUBLIC_PATH: "",
|
||||||
VITE_ROUTER_HISTORY: "",
|
VITE_ROUTER_HISTORY: "",
|
||||||
VITE_CDN: false,
|
VITE_CDN: false,
|
||||||
|
VITE_HIDE_HOME: "false",
|
||||||
VITE_COMPRESSION: "none"
|
VITE_COMPRESSION: "none"
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -12,7 +12,6 @@ const include = [
|
|||||||
"axios",
|
"axios",
|
||||||
"pinia",
|
"pinia",
|
||||||
"swiper",
|
"swiper",
|
||||||
"echarts",
|
|
||||||
"intro.js",
|
"intro.js",
|
||||||
"vue-i18n",
|
"vue-i18n",
|
||||||
"js-cookie",
|
"js-cookie",
|
||||||
|
@ -135,7 +135,7 @@
|
|||||||
"terser": "^5.17.1",
|
"terser": "^5.17.1",
|
||||||
"typescript": "^5.0.4",
|
"typescript": "^5.0.4",
|
||||||
"unplugin-vue-define-options": "1.1.6",
|
"unplugin-vue-define-options": "1.1.6",
|
||||||
"vite": "^4.3.4",
|
"vite": "^4.3.5",
|
||||||
"vite-plugin-cdn-import": "^0.3.5",
|
"vite-plugin-cdn-import": "^0.3.5",
|
||||||
"vite-plugin-compression": "^0.5.1",
|
"vite-plugin-compression": "^0.5.1",
|
||||||
"vite-plugin-mock": "^2.9.6",
|
"vite-plugin-mock": "^2.9.6",
|
||||||
|
6754
pnpm-lock.yaml
6754
pnpm-lock.yaml
File diff suppressed because it is too large
Load Diff
@ -1,5 +1,6 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { isEqual } from "@pureadmin/utils";
|
import { isEqual } from "@pureadmin/utils";
|
||||||
|
import { routerArrays } from "@/layout/types";
|
||||||
import { transformI18n } from "@/plugins/i18n";
|
import { transformI18n } from "@/plugins/i18n";
|
||||||
import { ref, watch, onMounted, toRaw } from "vue";
|
import { ref, watch, onMounted, toRaw } from "vue";
|
||||||
import { getParentPaths, findRouteByPath } from "@/router/utils";
|
import { getParentPaths, findRouteByPath } from "@/router/utils";
|
||||||
@ -10,14 +11,9 @@ const route = useRoute();
|
|||||||
const levelList = ref([]);
|
const levelList = ref([]);
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const routes: any = router.options.routes;
|
const routes: any = router.options.routes;
|
||||||
|
const { VITE_HIDE_HOME } = import.meta.env;
|
||||||
const multiTags: any = useMultiTagsStoreHook().multiTags;
|
const multiTags: any = useMultiTagsStoreHook().multiTags;
|
||||||
|
|
||||||
const isDashboard = (route: RouteLocationMatched): boolean | string => {
|
|
||||||
const name = route && (route.name as string);
|
|
||||||
if (!name) return false;
|
|
||||||
return name.trim().toLocaleLowerCase() === "Welcome".toLocaleLowerCase();
|
|
||||||
};
|
|
||||||
|
|
||||||
const getBreadcrumb = (): void => {
|
const getBreadcrumb = (): void => {
|
||||||
// 当前路由信息
|
// 当前路由信息
|
||||||
let currentRoute;
|
let currentRoute;
|
||||||
@ -35,7 +31,7 @@ const getBreadcrumb = (): void => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
currentRoute = findRouteByPath(router.currentRoute.value.path, multiTags);
|
currentRoute = findRouteByPath(router.currentRoute.value.path, routes);
|
||||||
}
|
}
|
||||||
// 当前路由的父级路径组成的数组
|
// 当前路由的父级路径组成的数组
|
||||||
const parentRoutes = getParentPaths(
|
const parentRoutes = getParentPaths(
|
||||||
@ -53,15 +49,7 @@ const getBreadcrumb = (): void => {
|
|||||||
|
|
||||||
if (currentRoute?.path !== "/welcome") matched.push(currentRoute);
|
if (currentRoute?.path !== "/welcome") matched.push(currentRoute);
|
||||||
|
|
||||||
if (!isDashboard(matched[0])) {
|
if (VITE_HIDE_HOME === "false") matched = routerArrays.concat(matched);
|
||||||
matched = [
|
|
||||||
{
|
|
||||||
path: "/welcome",
|
|
||||||
parentPath: "/",
|
|
||||||
meta: { title: "menus.hshome" }
|
|
||||||
} as unknown as RouteLocationMatched
|
|
||||||
].concat(matched);
|
|
||||||
}
|
|
||||||
|
|
||||||
matched.forEach((item, index) => {
|
matched.forEach((item, index) => {
|
||||||
if (currentRoute?.query || currentRoute?.params) return;
|
if (currentRoute?.query || currentRoute?.params) return;
|
||||||
|
@ -19,7 +19,7 @@ const {
|
|||||||
title,
|
title,
|
||||||
routers,
|
routers,
|
||||||
logout,
|
logout,
|
||||||
backHome,
|
backTopMenu,
|
||||||
onPanel,
|
onPanel,
|
||||||
menuSelect,
|
menuSelect,
|
||||||
username,
|
username,
|
||||||
@ -45,7 +45,7 @@ watch(
|
|||||||
v-loading="usePermissionStoreHook().wholeMenus.length === 0"
|
v-loading="usePermissionStoreHook().wholeMenus.length === 0"
|
||||||
class="horizontal-header"
|
class="horizontal-header"
|
||||||
>
|
>
|
||||||
<div class="horizontal-header-left" @click="backHome">
|
<div class="horizontal-header-left" @click="backTopMenu">
|
||||||
<img src="/logo.svg" alt="logo" />
|
<img src="/logo.svg" alt="logo" />
|
||||||
<span>{{ title }}</span>
|
<span>{{ title }}</span>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
import { getTopMenu } from "@/router/utils";
|
||||||
import { useNav } from "@/layout/hooks/useNav";
|
import { useNav } from "@/layout/hooks/useNav";
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
@ -6,6 +7,7 @@ const props = defineProps({
|
|||||||
});
|
});
|
||||||
|
|
||||||
const { title } = useNav();
|
const { title } = useNav();
|
||||||
|
const topPath = getTopMenu().path;
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@ -16,7 +18,7 @@ const { title } = useNav();
|
|||||||
key="props.collapse"
|
key="props.collapse"
|
||||||
:title="title"
|
:title="title"
|
||||||
class="sidebar-logo-link"
|
class="sidebar-logo-link"
|
||||||
to="/"
|
:to="topPath"
|
||||||
>
|
>
|
||||||
<img src="/logo.svg" alt="logo" />
|
<img src="/logo.svg" alt="logo" />
|
||||||
<span class="sidebar-title">{{ title }}</span>
|
<span class="sidebar-title">{{ title }}</span>
|
||||||
@ -26,7 +28,7 @@ const { title } = useNav();
|
|||||||
key="expand"
|
key="expand"
|
||||||
:title="title"
|
:title="title"
|
||||||
class="sidebar-logo-link"
|
class="sidebar-logo-link"
|
||||||
to="/"
|
:to="topPath"
|
||||||
>
|
>
|
||||||
<img src="/logo.svg" alt="logo" />
|
<img src="/logo.svg" alt="logo" />
|
||||||
<span class="sidebar-title">{{ title }}</span>
|
<span class="sidebar-title">{{ title }}</span>
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import path from "path";
|
import path from "path";
|
||||||
import { getConfig } from "@/config";
|
import { getConfig } from "@/config";
|
||||||
|
import { menuType } from "../../types";
|
||||||
import extraIcon from "./extraIcon.vue";
|
import extraIcon from "./extraIcon.vue";
|
||||||
import { childrenType } from "../../types";
|
|
||||||
import { useNav } from "@/layout/hooks/useNav";
|
import { useNav } from "@/layout/hooks/useNav";
|
||||||
import { transformI18n } from "@/plugins/i18n";
|
import { transformI18n } from "@/plugins/i18n";
|
||||||
import { useRenderIcon } from "@/components/ReIcon/src/hooks";
|
import { useRenderIcon } from "@/components/ReIcon/src/hooks";
|
||||||
@ -17,7 +17,7 @@ const { layout, isCollapse, tooltipEffect, getDivStyle } = useNav();
|
|||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
item: {
|
item: {
|
||||||
type: Object as PropType<childrenType>
|
type: Object as PropType<menuType>
|
||||||
},
|
},
|
||||||
isNest: {
|
isNest: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
@ -112,7 +112,7 @@ const expandCloseIcon = computed(() => {
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
const onlyOneChild: childrenType = ref(null);
|
const onlyOneChild: menuType = ref(null);
|
||||||
// 存放菜单是否存在showTooltip属性标识
|
// 存放菜单是否存在showTooltip属性标识
|
||||||
const hoverMenuMap = new WeakMap();
|
const hoverMenuMap = new WeakMap();
|
||||||
// 存储菜单文本dom元素
|
// 存储菜单文本dom元素
|
||||||
@ -149,10 +149,7 @@ function overflowSlice(text, item?: any) {
|
|||||||
return newText;
|
return newText;
|
||||||
}
|
}
|
||||||
|
|
||||||
function hasOneShowingChild(
|
function hasOneShowingChild(children: menuType[] = [], parent: menuType) {
|
||||||
children: childrenType[] = [],
|
|
||||||
parent: childrenType
|
|
||||||
) {
|
|
||||||
const showingChildren = children.filter((item: any) => {
|
const showingChildren = children.filter((item: any) => {
|
||||||
onlyOneChild.value = item;
|
onlyOneChild.value = item;
|
||||||
return true;
|
return true;
|
||||||
|
@ -4,11 +4,11 @@ import { emitter } from "@/utils/mitt";
|
|||||||
import { RouteConfigs } from "../../types";
|
import { RouteConfigs } from "../../types";
|
||||||
import { useTags } from "../../hooks/useTag";
|
import { useTags } from "../../hooks/useTag";
|
||||||
import { routerArrays } from "@/layout/types";
|
import { routerArrays } from "@/layout/types";
|
||||||
import { handleAliveRoute } from "@/router/utils";
|
|
||||||
import { isEqual, isAllEmpty } from "@pureadmin/utils";
|
import { isEqual, isAllEmpty } from "@pureadmin/utils";
|
||||||
|
import { handleAliveRoute, getTopMenu } from "@/router/utils";
|
||||||
import { useSettingStoreHook } from "@/store/modules/settings";
|
import { useSettingStoreHook } from "@/store/modules/settings";
|
||||||
import { ref, watch, unref, nextTick, onBeforeMount } from "vue";
|
|
||||||
import { useMultiTagsStoreHook } from "@/store/modules/multiTags";
|
import { useMultiTagsStoreHook } from "@/store/modules/multiTags";
|
||||||
|
import { ref, watch, unref, toRaw, nextTick, onBeforeMount } from "vue";
|
||||||
import { useResizeObserver, useDebounceFn, useFullscreen } from "@vueuse/core";
|
import { useResizeObserver, useDebounceFn, useFullscreen } from "@vueuse/core";
|
||||||
|
|
||||||
import ExitFullscreen from "@iconify-icons/ri/fullscreen-exit-fill";
|
import ExitFullscreen from "@iconify-icons/ri/fullscreen-exit-fill";
|
||||||
@ -50,6 +50,8 @@ const tabDom = ref();
|
|||||||
const containerDom = ref();
|
const containerDom = ref();
|
||||||
const scrollbarDom = ref();
|
const scrollbarDom = ref();
|
||||||
const isShowArrow = ref(false);
|
const isShowArrow = ref(false);
|
||||||
|
const topPath = getTopMenu().path;
|
||||||
|
const { VITE_HIDE_HOME } = import.meta.env;
|
||||||
const { isFullscreen, toggle } = useFullscreen();
|
const { isFullscreen, toggle } = useFullscreen();
|
||||||
|
|
||||||
const dynamicTagView = () => {
|
const dynamicTagView = () => {
|
||||||
@ -165,7 +167,7 @@ function onFresh() {
|
|||||||
const { fullPath, query } = unref(route);
|
const { fullPath, query } = unref(route);
|
||||||
router.replace({
|
router.replace({
|
||||||
path: "/redirect" + fullPath,
|
path: "/redirect" + fullPath,
|
||||||
query: query
|
query
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -190,7 +192,10 @@ function deleteDynamicTag(obj: any, current: any, tag?: string) {
|
|||||||
other?: boolean
|
other?: boolean
|
||||||
): void => {
|
): void => {
|
||||||
if (other) {
|
if (other) {
|
||||||
useMultiTagsStoreHook().handleTags("equal", [routerArrays[0], obj]);
|
useMultiTagsStoreHook().handleTags("equal", [
|
||||||
|
VITE_HIDE_HOME === "false" ? routerArrays[0] : toRaw(getTopMenu()),
|
||||||
|
obj
|
||||||
|
]);
|
||||||
} else {
|
} else {
|
||||||
useMultiTagsStoreHook().handleTags("splice", "", {
|
useMultiTagsStoreHook().handleTags("splice", "", {
|
||||||
startIndex,
|
startIndex,
|
||||||
@ -283,7 +288,7 @@ function onClickDrop(key, item, selectRoute?: RouteConfigs) {
|
|||||||
startIndex: 1,
|
startIndex: 1,
|
||||||
length: multiTags.value.length
|
length: multiTags.value.length
|
||||||
});
|
});
|
||||||
router.push("/welcome");
|
router.push(topPath);
|
||||||
handleAliveRoute(route as toRouteType);
|
handleAliveRoute(route as toRouteType);
|
||||||
break;
|
break;
|
||||||
case 6:
|
case 6:
|
||||||
@ -340,7 +345,7 @@ function disabledMenus(value: boolean) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 检查当前右键的菜单两边是否存在别的菜单,如果左侧的菜单是首页,则不显示关闭左侧标签页,如果右侧没有菜单,则不显示关闭右侧标签页 */
|
/** 检查当前右键的菜单两边是否存在别的菜单,如果左侧的菜单是顶级菜单,则不显示关闭左侧标签页,如果右侧没有菜单,则不显示关闭右侧标签页 */
|
||||||
function showMenuModel(
|
function showMenuModel(
|
||||||
currentPath: string,
|
currentPath: string,
|
||||||
query: object = {},
|
query: object = {},
|
||||||
@ -362,11 +367,11 @@ function showMenuModel(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* currentIndex为1时,左侧的菜单是首页,则不显示关闭左侧标签页
|
* currentIndex为1时,左侧的菜单顶级菜单,则不显示关闭左侧标签页
|
||||||
* 如果currentIndex等于routeLength-1,右侧没有菜单,则不显示关闭右侧标签页
|
* 如果currentIndex等于routeLength-1,右侧没有菜单,则不显示关闭右侧标签页
|
||||||
*/
|
*/
|
||||||
if (currentIndex === 1 && routeLength !== 2) {
|
if (currentIndex === 1 && routeLength !== 2) {
|
||||||
// 左侧的菜单是首页,右侧存在别的菜单
|
// 左侧的菜单是顶级菜单,右侧存在别的菜单
|
||||||
tagsViews[2].show = false;
|
tagsViews[2].show = false;
|
||||||
Array.of(1, 3, 4, 5).forEach(v => {
|
Array.of(1, 3, 4, 5).forEach(v => {
|
||||||
tagsViews[v].disabled = false;
|
tagsViews[v].disabled = false;
|
||||||
@ -374,7 +379,7 @@ function showMenuModel(
|
|||||||
tagsViews[2].disabled = true;
|
tagsViews[2].disabled = true;
|
||||||
} else if (currentIndex === 1 && routeLength === 2) {
|
} else if (currentIndex === 1 && routeLength === 2) {
|
||||||
disabledMenus(false);
|
disabledMenus(false);
|
||||||
// 左侧的菜单是首页,右侧不存在别的菜单
|
// 左侧的菜单是顶级菜单,右侧不存在别的菜单
|
||||||
Array.of(2, 3, 4).forEach(v => {
|
Array.of(2, 3, 4).forEach(v => {
|
||||||
tagsViews[v].show = false;
|
tagsViews[v].show = false;
|
||||||
tagsViews[v].disabled = true;
|
tagsViews[v].disabled = true;
|
||||||
@ -386,8 +391,8 @@ function showMenuModel(
|
|||||||
tagsViews[v].disabled = false;
|
tagsViews[v].disabled = false;
|
||||||
});
|
});
|
||||||
tagsViews[3].disabled = true;
|
tagsViews[3].disabled = true;
|
||||||
} else if (currentIndex === 0 || currentPath === "/redirect/welcome") {
|
} else if (currentIndex === 0 || currentPath === `/redirect${topPath}`) {
|
||||||
// 当前路由为首页
|
// 当前路由为顶级菜单
|
||||||
disabledMenus(true);
|
disabledMenus(true);
|
||||||
} else {
|
} else {
|
||||||
disabledMenus(false);
|
disabledMenus(false);
|
||||||
@ -396,8 +401,8 @@ function showMenuModel(
|
|||||||
|
|
||||||
function openMenu(tag, e) {
|
function openMenu(tag, e) {
|
||||||
closeMenu();
|
closeMenu();
|
||||||
if (tag.path === "/welcome") {
|
if (tag.path === topPath) {
|
||||||
// 右键菜单为首页,只显示刷新
|
// 右键菜单为顶级菜单,只显示刷新
|
||||||
showMenus(false);
|
showMenus(false);
|
||||||
tagsViews[0].show = true;
|
tagsViews[0].show = true;
|
||||||
} else if (route.path !== tag.path && route.name !== tag.name) {
|
} else if (route.path !== tag.path && route.name !== tag.name) {
|
||||||
|
@ -3,6 +3,7 @@ import { getConfig } from "@/config";
|
|||||||
import { useRouter } from "vue-router";
|
import { useRouter } from "vue-router";
|
||||||
import { emitter } from "@/utils/mitt";
|
import { emitter } from "@/utils/mitt";
|
||||||
import { routeMetaType } from "../types";
|
import { routeMetaType } from "../types";
|
||||||
|
import { getTopMenu } from "@/router/utils";
|
||||||
import { useGlobal } from "@pureadmin/utils";
|
import { useGlobal } from "@pureadmin/utils";
|
||||||
import { transformI18n } from "@/plugins/i18n";
|
import { transformI18n } from "@/plugins/i18n";
|
||||||
import { router, remainingPaths } from "@/router";
|
import { router, remainingPaths } from "@/router";
|
||||||
@ -85,8 +86,8 @@ export function useNav() {
|
|||||||
useUserStoreHook().logOut();
|
useUserStoreHook().logOut();
|
||||||
}
|
}
|
||||||
|
|
||||||
function backHome() {
|
function backTopMenu() {
|
||||||
router.push("/welcome");
|
router.push(getTopMenu().path);
|
||||||
}
|
}
|
||||||
|
|
||||||
function onPanel() {
|
function onPanel() {
|
||||||
@ -154,7 +155,7 @@ export function useNav() {
|
|||||||
logout,
|
logout,
|
||||||
routers,
|
routers,
|
||||||
$storage,
|
$storage,
|
||||||
backHome,
|
backTopMenu,
|
||||||
onPanel,
|
onPanel,
|
||||||
getDivStyle,
|
getDivStyle,
|
||||||
changeTitle,
|
changeTitle,
|
||||||
|
@ -1,15 +1,19 @@
|
|||||||
import type { IconifyIcon } from "@iconify/vue";
|
import type { IconifyIcon } from "@iconify/vue";
|
||||||
|
const { VITE_HIDE_HOME } = import.meta.env;
|
||||||
|
|
||||||
export const routerArrays: Array<RouteConfigs> = [
|
export const routerArrays: Array<RouteConfigs> =
|
||||||
{
|
VITE_HIDE_HOME === "false"
|
||||||
path: "/welcome",
|
? [
|
||||||
parentPath: "/",
|
{
|
||||||
meta: {
|
path: "/welcome",
|
||||||
title: "menus.hshome",
|
parentPath: "/",
|
||||||
icon: "homeFilled"
|
meta: {
|
||||||
}
|
title: "menus.hshome",
|
||||||
}
|
icon: "homeFilled"
|
||||||
];
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
: [];
|
||||||
|
|
||||||
export type routeMetaType = {
|
export type routeMetaType = {
|
||||||
title?: string;
|
title?: string;
|
||||||
@ -58,20 +62,23 @@ export interface setType {
|
|||||||
hideTabs: boolean;
|
hideTabs: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type childrenType = {
|
export type menuType = {
|
||||||
|
id?: number;
|
||||||
path?: string;
|
path?: string;
|
||||||
noShowingChildren?: boolean;
|
noShowingChildren?: boolean;
|
||||||
children?: childrenType[];
|
children?: menuType[];
|
||||||
value: unknown;
|
value: unknown;
|
||||||
meta?: {
|
meta?: {
|
||||||
icon?: string;
|
icon?: string;
|
||||||
title?: string;
|
title?: string;
|
||||||
|
rank?: number;
|
||||||
showParent?: boolean;
|
showParent?: boolean;
|
||||||
extraIcon?: string;
|
extraIcon?: string;
|
||||||
};
|
};
|
||||||
showTooltip?: boolean;
|
showTooltip?: boolean;
|
||||||
parentId?: number;
|
parentId?: number;
|
||||||
pathList?: number[];
|
pathList?: number[];
|
||||||
|
redirect?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type themeColorsType = {
|
export type themeColorsType = {
|
||||||
|
@ -13,6 +13,7 @@ import {
|
|||||||
} from "vue-router";
|
} from "vue-router";
|
||||||
import {
|
import {
|
||||||
ascending,
|
ascending,
|
||||||
|
getTopMenu,
|
||||||
initRouter,
|
initRouter,
|
||||||
isOneOfArray,
|
isOneOfArray,
|
||||||
getHistoryMode,
|
getHistoryMode,
|
||||||
@ -96,6 +97,8 @@ export function resetRouter() {
|
|||||||
/** 路由白名单 */
|
/** 路由白名单 */
|
||||||
const whiteList = ["/login"];
|
const whiteList = ["/login"];
|
||||||
|
|
||||||
|
const { VITE_HIDE_HOME } = import.meta.env;
|
||||||
|
|
||||||
router.beforeEach((to: toRouteType, _from, next) => {
|
router.beforeEach((to: toRouteType, _from, next) => {
|
||||||
if (to.meta?.keepAlive) {
|
if (to.meta?.keepAlive) {
|
||||||
handleAliveRoute(to, "add");
|
handleAliveRoute(to, "add");
|
||||||
@ -125,6 +128,10 @@ router.beforeEach((to: toRouteType, _from, next) => {
|
|||||||
if (to.meta?.roles && !isOneOfArray(to.meta?.roles, userInfo?.roles)) {
|
if (to.meta?.roles && !isOneOfArray(to.meta?.roles, userInfo?.roles)) {
|
||||||
next({ path: "/error/403" });
|
next({ path: "/error/403" });
|
||||||
}
|
}
|
||||||
|
// 开启隐藏首页后在浏览器地址栏手动输入首页welcome路由则跳转到404页面
|
||||||
|
if (VITE_HIDE_HOME === "true" && to.fullPath === "/welcome") {
|
||||||
|
next({ path: "/error/404" });
|
||||||
|
}
|
||||||
if (_from?.name) {
|
if (_from?.name) {
|
||||||
// name为超链接
|
// name为超链接
|
||||||
if (externalLink) {
|
if (externalLink) {
|
||||||
@ -146,6 +153,7 @@ router.beforeEach((to: toRouteType, _from, next) => {
|
|||||||
path,
|
path,
|
||||||
router.options.routes[0].children
|
router.options.routes[0].children
|
||||||
);
|
);
|
||||||
|
getTopMenu(true);
|
||||||
// query、params模式路由传参数的标签页不在此处处理
|
// query、params模式路由传参数的标签页不在此处处理
|
||||||
if (route && route.meta?.title) {
|
if (route && route.meta?.title) {
|
||||||
useMultiTagsStoreHook().handleTags("push", {
|
useMultiTagsStoreHook().handleTags("push", {
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import { $t } from "@/plugins/i18n";
|
import { $t } from "@/plugins/i18n";
|
||||||
import { home } from "@/router/enums";
|
import { home } from "@/router/enums";
|
||||||
|
const { VITE_HIDE_HOME } = import.meta.env;
|
||||||
const Layout = () => import("@/layout/index.vue");
|
const Layout = () => import("@/layout/index.vue");
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
@ -18,7 +19,8 @@ export default {
|
|||||||
name: "Welcome",
|
name: "Welcome",
|
||||||
component: () => import("@/views/welcome/index.vue"),
|
component: () => import("@/views/welcome/index.vue"),
|
||||||
meta: {
|
meta: {
|
||||||
title: $t("menus.hshome")
|
title: $t("menus.hshome"),
|
||||||
|
showLink: VITE_HIDE_HOME === "true" ? false : true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@ -16,8 +16,7 @@ export default [
|
|||||||
path: "/redirect",
|
path: "/redirect",
|
||||||
component: Layout,
|
component: Layout,
|
||||||
meta: {
|
meta: {
|
||||||
icon: "homeFilled",
|
title: $t("status.hsLoad"),
|
||||||
title: $t("menus.hshome"),
|
|
||||||
showLink: false,
|
showLink: false,
|
||||||
rank: 102
|
rank: 102
|
||||||
},
|
},
|
||||||
|
@ -17,8 +17,10 @@ import {
|
|||||||
isIncludeAllChildren
|
isIncludeAllChildren
|
||||||
} from "@pureadmin/utils";
|
} from "@pureadmin/utils";
|
||||||
import { getConfig } from "@/config";
|
import { getConfig } from "@/config";
|
||||||
|
import { menuType } from "@/layout/types";
|
||||||
import { buildHierarchyTree } from "@/utils/tree";
|
import { buildHierarchyTree } from "@/utils/tree";
|
||||||
import { sessionKey, type DataInfo } from "@/utils/auth";
|
import { sessionKey, type DataInfo } from "@/utils/auth";
|
||||||
|
import { useMultiTagsStoreHook } from "@/store/modules/multiTags";
|
||||||
import { usePermissionStoreHook } from "@/store/modules/permission";
|
import { usePermissionStoreHook } from "@/store/modules/permission";
|
||||||
const IFrame = () => import("@/layout/frameView.vue");
|
const IFrame = () => import("@/layout/frameView.vue");
|
||||||
// https://cn.vitejs.dev/guide/features.html#glob-import
|
// https://cn.vitejs.dev/guide/features.html#glob-import
|
||||||
@ -351,12 +353,20 @@ function hasAuth(value: string | Array<string>): boolean {
|
|||||||
return isAuths ? true : false;
|
return isAuths ? true : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** 获取所有菜单中的第一个菜单(顶级菜单)*/
|
||||||
|
function getTopMenu(tag = false): menuType {
|
||||||
|
const topMenu = usePermissionStoreHook().wholeMenus[0]?.children[0];
|
||||||
|
tag && useMultiTagsStoreHook().handleTags("push", topMenu);
|
||||||
|
return topMenu;
|
||||||
|
}
|
||||||
|
|
||||||
export {
|
export {
|
||||||
hasAuth,
|
hasAuth,
|
||||||
getAuths,
|
getAuths,
|
||||||
ascending,
|
ascending,
|
||||||
filterTree,
|
filterTree,
|
||||||
initRouter,
|
initRouter,
|
||||||
|
getTopMenu,
|
||||||
addPathMatch,
|
addPathMatch,
|
||||||
isOneOfArray,
|
isOneOfArray,
|
||||||
getHistoryMode,
|
getHistoryMode,
|
||||||
|
@ -31,7 +31,7 @@ export const injectResponsiveStorage = (app: App, config: ServerConfigs) => {
|
|||||||
},
|
},
|
||||||
config.MultiTagsCache
|
config.MultiTagsCache
|
||||||
? {
|
? {
|
||||||
// 默认显示首页tag
|
// 默认显示顶级菜单tag
|
||||||
tags: Storage.getData("tags", nameSpace) ?? routerArrays
|
tags: Storage.getData("tags", nameSpace) ?? routerArrays
|
||||||
}
|
}
|
||||||
: {}
|
: {}
|
||||||
|
@ -18,13 +18,13 @@ import TypeIt from "@/components/ReTypeit";
|
|||||||
import qrCode from "./components/qrCode.vue";
|
import qrCode from "./components/qrCode.vue";
|
||||||
import regist from "./components/regist.vue";
|
import regist from "./components/regist.vue";
|
||||||
import update from "./components/update.vue";
|
import update from "./components/update.vue";
|
||||||
import { initRouter } from "@/router/utils";
|
|
||||||
import { useNav } from "@/layout/hooks/useNav";
|
import { useNav } from "@/layout/hooks/useNav";
|
||||||
import type { FormInstance } from "element-plus";
|
import type { FormInstance } from "element-plus";
|
||||||
import { $t, transformI18n } from "@/plugins/i18n";
|
import { $t, transformI18n } from "@/plugins/i18n";
|
||||||
import { operates, thirdParty } from "./utils/enums";
|
import { operates, thirdParty } from "./utils/enums";
|
||||||
import { useLayout } from "@/layout/hooks/useLayout";
|
import { useLayout } from "@/layout/hooks/useLayout";
|
||||||
import { useUserStoreHook } from "@/store/modules/user";
|
import { useUserStoreHook } from "@/store/modules/user";
|
||||||
|
import { initRouter, getTopMenu } from "@/router/utils";
|
||||||
import { bg, avatar, illustration } from "./utils/static";
|
import { bg, avatar, illustration } from "./utils/static";
|
||||||
import { ReImageVerify } from "@/components/ReImageVerify";
|
import { ReImageVerify } from "@/components/ReImageVerify";
|
||||||
import { useRenderIcon } from "@/components/ReIcon/src/hooks";
|
import { useRenderIcon } from "@/components/ReIcon/src/hooks";
|
||||||
@ -76,7 +76,7 @@ const onLogin = async (formEl: FormInstance | undefined) => {
|
|||||||
if (res.success) {
|
if (res.success) {
|
||||||
// 获取后端路由
|
// 获取后端路由
|
||||||
initRouter().then(() => {
|
initRouter().then(() => {
|
||||||
router.push("/");
|
router.push(getTopMenu(true).path);
|
||||||
message("登录成功", { type: "success" });
|
message("登录成功", { type: "success" });
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
1
types/global.d.ts
vendored
1
types/global.d.ts
vendored
@ -63,6 +63,7 @@ declare global {
|
|||||||
VITE_PUBLIC_PATH: string;
|
VITE_PUBLIC_PATH: string;
|
||||||
VITE_ROUTER_HISTORY: string;
|
VITE_ROUTER_HISTORY: string;
|
||||||
VITE_CDN: boolean;
|
VITE_CDN: boolean;
|
||||||
|
VITE_HIDE_HOME: string;
|
||||||
VITE_COMPRESSION: ViteCompression;
|
VITE_COMPRESSION: ViteCompression;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user