二级Layout与隐藏路由,个人中心Layout
This commit is contained in:
parent
dbf7b68027
commit
1710ca21e6
|
@ -1,6 +1,6 @@
|
|||
import NProgress from 'nprogress'
|
||||
import type { RouteRecordName } from 'vue-router'
|
||||
import Layout from '@/layout/index.vue'
|
||||
import Layout from '@/layout/default/index.vue'
|
||||
import router, { asyncRoutes, constantRoutes } from '@/router'
|
||||
import 'nprogress/nprogress.css'
|
||||
import { useBasicStore } from '@/store/basic'
|
||||
|
|
8
src/layout/UserProfileLayout.vue
Normal file
8
src/layout/UserProfileLayout.vue
Normal file
|
@ -0,0 +1,8 @@
|
|||
<template>
|
||||
<sub-menu :parent-router="userRoute" />
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import SubMenu from "@/layout/submenu/index.vue";
|
||||
import { userRoute } from "@/router/modules/user";
|
||||
</script>
|
|
@ -70,7 +70,7 @@ import { elMessage } from "@/hooks/use-element";
|
|||
import { useBasicStore } from "@/store/basic";
|
||||
import { langTitle } from "@/hooks/use-common";
|
||||
import userImage from "@/assets/layout/user.png";
|
||||
import Debugger from "@/layout/app-main/component/Debugger.vue";
|
||||
import Debugger from "@/layout/default/app-main/component/Debugger.vue";
|
||||
|
||||
const basicStore = useBasicStore();
|
||||
const { settings, sidebar, setToggleSideBar, userInfo } = basicStore;
|
|
@ -28,7 +28,7 @@
|
|||
import { ref } from 'vue'
|
||||
import { resolve } from 'path-browserify'
|
||||
import Link from './Link.vue'
|
||||
import MenuIcon from '../../components/MenuIcon.vue'
|
||||
import MenuIcon from '../../../components/MenuIcon.vue'
|
||||
import type { RouteRawConfig } from '~/basic'
|
||||
import { isExternal } from '@/hooks/use-layout'
|
||||
import { langTitle } from '@/hooks/use-common'
|
84
src/layout/submenu/index.vue
Normal file
84
src/layout/submenu/index.vue
Normal file
|
@ -0,0 +1,84 @@
|
|||
<template>
|
||||
<div :class="classObj" class="layout-wrapper">
|
||||
<!--left side-->
|
||||
<Sidebar v-if="settings.showLeftMenu" class="sidebar-container" :parent-router="prop.parentRouter" />
|
||||
<!--right container-->
|
||||
<div class="main-container">
|
||||
<Navbar v-if="settings.showTopNavbar" class="nav-bar" />
|
||||
<TagsView v-if="settings.showTagsView" />
|
||||
<AppMain class="app-main" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts" name="SubMenuLayout">
|
||||
import { computed } from 'vue'
|
||||
import Sidebar from './sidebar/index.vue'
|
||||
import AppMain from '../default/app-main/index.vue'
|
||||
import Navbar from '../default/app-main/Navbar.vue'
|
||||
import TagsView from '../default/app-main/TagsView.vue'
|
||||
import { useBasicStore } from '@/store/basic'
|
||||
import { resizeHandler } from '@/hooks/use-layout'
|
||||
import type { RouteRawConfig } from '~/basic'
|
||||
|
||||
const prop = defineProps<{
|
||||
parentRouter: RouteRawConfig
|
||||
}>()
|
||||
|
||||
const { sidebar, settings } = useBasicStore()
|
||||
const classObj = computed(() => {
|
||||
return {
|
||||
closeSidebar: !sidebar.opened,
|
||||
hideSidebar: !settings.showLeftMenu
|
||||
}
|
||||
})
|
||||
resizeHandler()
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.main-container {
|
||||
transition: margin-left var(--sideBar-switch-duration);
|
||||
margin-left: var(--side-bar-width);
|
||||
position: relative;
|
||||
height: 100vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
.nav-bar {
|
||||
flex-shrink: 0;
|
||||
height: 50px;
|
||||
}
|
||||
.app-main {
|
||||
flex-grow: 1;
|
||||
overflow: auto;
|
||||
}
|
||||
}
|
||||
.sidebar-container {
|
||||
transition: width var(--sideBar-switch-duration);
|
||||
width: var(--side-bar-width) !important;
|
||||
background-color: var(--el-menu-bg-color);
|
||||
height: 100%;
|
||||
position: fixed;
|
||||
font-size: 0;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
z-index: 1001;
|
||||
overflow: hidden;
|
||||
border-right: 0.5px solid var(--side-bar-border-right-color);
|
||||
}
|
||||
.closeSidebar {
|
||||
.sidebar-container {
|
||||
width: 54px !important;
|
||||
}
|
||||
.main-container {
|
||||
margin-left: 54px !important;
|
||||
}
|
||||
}
|
||||
.hideSidebar {
|
||||
.sidebar-container {
|
||||
width: 0 !important;
|
||||
}
|
||||
.main-container {
|
||||
margin-left: 0;
|
||||
}
|
||||
}
|
||||
</style>
|
67
src/layout/submenu/sidebar/index.vue
Normal file
67
src/layout/submenu/sidebar/index.vue
Normal file
|
@ -0,0 +1,67 @@
|
|||
<template>
|
||||
<div id="Sidebar" class="reset-menu-style">
|
||||
<!--logo-->
|
||||
<Logo v-if="settings.sidebarLogo" :collapse="!sidebar.opened" />
|
||||
<!--router menu-->
|
||||
<el-scrollbar>
|
||||
<el-menu
|
||||
class="el-menu-vertical"
|
||||
:collapse="!sidebar.opened"
|
||||
:default-active="activeMenu"
|
||||
:collapse-transition="false"
|
||||
mode="vertical"
|
||||
>
|
||||
<sidebar-item v-for="r in routes" :key="r.path" :item="r" :base-path="basePath(r.path)" />
|
||||
</el-menu>
|
||||
</el-scrollbar>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts" name="SubMenuSideBar">
|
||||
import { computed } from 'vue'
|
||||
import { storeToRefs } from 'pinia/dist/pinia'
|
||||
import { useRoute } from 'vue-router'
|
||||
import Logo from '@/layout/default/sidebar/Logo.vue'
|
||||
import SidebarItem from '@/layout/default/sidebar/SidebarItem.vue'
|
||||
import { useBasicStore } from '@/store/basic'
|
||||
|
||||
const { settings, sidebar } = storeToRefs(useBasicStore())
|
||||
const route = useRoute()
|
||||
const activeMenu = ref<any>(route.path)
|
||||
import type { BootstrapIcons, RouteRawConfig, RouterTypes } from '~/basic'
|
||||
|
||||
const prop = defineProps<{
|
||||
parentRouter: RouteRawConfig
|
||||
}>()
|
||||
|
||||
watch(
|
||||
() => route.path,
|
||||
(val) => {
|
||||
activeMenu.value = val
|
||||
}
|
||||
)
|
||||
|
||||
const routes = computed(() => {
|
||||
return [
|
||||
{
|
||||
path: '/',
|
||||
meta: {
|
||||
title: '返回',
|
||||
icon: 'arrow-left-square' as BootstrapIcons
|
||||
}
|
||||
},
|
||||
...prop.parentRouter.children!
|
||||
] as RouterTypes
|
||||
})
|
||||
|
||||
function basePath(path: string) {
|
||||
if (path.startsWith('/')) return `/${path}`
|
||||
else return `${prop.parentRouter.path}/${path}`
|
||||
}
|
||||
</script>
|
||||
<style lang="scss">
|
||||
//fix open the item style issue
|
||||
.el-menu-vertical {
|
||||
width: var(--side-bar-width);
|
||||
}
|
||||
</style>
|
|
@ -1,7 +1,8 @@
|
|||
import { createRouter, createWebHistory } from 'vue-router'
|
||||
import type { RouterTypes } from '~/basic'
|
||||
import settings from '@/settings'
|
||||
const Layout = () => import('@/layout/index.vue')
|
||||
import { userRoute } from '@/router/modules/user'
|
||||
const Layout = () => import('@/layout/default/index.vue')
|
||||
|
||||
export const constantRoutes: RouterTypes = [
|
||||
{
|
||||
|
@ -38,19 +39,7 @@ export const constantRoutes: RouterTypes = [
|
|||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
path: '/user',
|
||||
name: '用户',
|
||||
component: Layout,
|
||||
hidden: true,
|
||||
children: [
|
||||
{
|
||||
path: 'profile',
|
||||
name: '首选项',
|
||||
component: () => import('@/views/user/profile/index.vue')
|
||||
}
|
||||
]
|
||||
}
|
||||
userRoute
|
||||
]
|
||||
|
||||
//角色和code数组动态路由
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import Layout from '@/layout/index.vue'
|
||||
import Layout from '@/layout/default/index.vue'
|
||||
const BasicDemo = {
|
||||
path: '/basic-demo',
|
||||
component: Layout,
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/** When your routing table is too long, you can split it into small modules**/
|
||||
|
||||
import Layout from '@/layout/index.vue'
|
||||
import Layout from '@/layout/default/index.vue'
|
||||
|
||||
const chartsRouter = {
|
||||
path: '/charts',
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import Layout from '@/layout/index.vue'
|
||||
import Layout from '@/layout/default/index.vue'
|
||||
|
||||
const directive = {
|
||||
path: '/directive',
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import Layout from '@/layout/index.vue'
|
||||
import Layout from '@/layout/default/index.vue'
|
||||
const excel = {
|
||||
path: '/excel',
|
||||
component: Layout,
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import Layout from '@/layout/index.vue'
|
||||
import Layout from '@/layout/default/index.vue'
|
||||
const guid = {
|
||||
path: '/guide',
|
||||
component: Layout,
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import Layout from '@/layout/index.vue'
|
||||
import Layout from '@/layout/default/index.vue'
|
||||
const other = {
|
||||
path: '/other',
|
||||
component: Layout,
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import Layout from '@/layout/index.vue'
|
||||
import Layout from '@/layout/default/index.vue'
|
||||
const richText = {
|
||||
path: '/rich-text',
|
||||
component: Layout,
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import Layout from '@/layout/index.vue'
|
||||
import Layout from '@/layout/default/index.vue'
|
||||
const table = {
|
||||
path: '/table',
|
||||
component: Layout,
|
||||
|
|
17
src/router/modules/user.ts
Normal file
17
src/router/modules/user.ts
Normal file
|
@ -0,0 +1,17 @@
|
|||
import type { BootstrapIcons, RouteRawConfig } from "~/basic";
|
||||
|
||||
export const userRoute = {
|
||||
path: '/user',
|
||||
name: 'User',
|
||||
component: () => import('@/layout/UserProfileLayout.vue'),
|
||||
meta: { title: '用户中心', icon: 'person' as BootstrapIcons },
|
||||
hidden: true,
|
||||
children: [
|
||||
{
|
||||
path: 'profile',
|
||||
name: 'Profile',
|
||||
meta: {title: '个人信息', icon: 'text-left' as BootstrapIcons},
|
||||
component: () => import('@/views/user/profile/index.vue')
|
||||
}
|
||||
]
|
||||
} as RouteRawConfig
|
65
typings/basic.d.ts
vendored
65
typings/basic.d.ts
vendored
|
@ -11,31 +11,50 @@
|
|||
|
||||
/*router*/
|
||||
import type { RouteRecordRaw } from 'vue-router'
|
||||
export interface rawConfig {
|
||||
hidden?: boolean
|
||||
alwaysShow?: boolean
|
||||
code?: number
|
||||
name?: string
|
||||
fullPath?: string
|
||||
path?: string
|
||||
meta?: {
|
||||
|
||||
import type icons from 'bootstrap-icons/font/bootstrap-icons.json'
|
||||
export type BootstrapIcons = keyof typeof icons;
|
||||
|
||||
export interface RawConfig {
|
||||
/** 是否隐藏路由 */
|
||||
hidden: boolean
|
||||
/** TODO 不知道。 */
|
||||
alwaysShow: boolean
|
||||
/** TODO 不知道。 */
|
||||
code: number
|
||||
/** 路由名称 */
|
||||
name: string
|
||||
/** 完整路径,一般不填 */
|
||||
fullPath: string
|
||||
/** 路径,可以为相对路径 */
|
||||
path: string
|
||||
/** 元数据,没有元数据时不显示菜单 */
|
||||
meta: Omit<Partial<RawConfigMeta>, 'title'> & Required<Pick<RawConfigMeta, 'title'>>
|
||||
/** 子路由 */
|
||||
children: RouterTypes
|
||||
/** 重定向,绝对路径 */
|
||||
redirect: string
|
||||
/** 是否显示子菜单 */
|
||||
expand: boolean
|
||||
}
|
||||
|
||||
export interface RawConfigMeta {
|
||||
/** 路由标题,显示在菜单按钮上 */
|
||||
title: string
|
||||
icon?: string
|
||||
affix?: boolean
|
||||
activeMenu?: string
|
||||
breadcrumb?: boolean
|
||||
roles?: Array<string>
|
||||
elSvgIcon?: string
|
||||
code?: number
|
||||
cachePage?: boolean
|
||||
leaveRmCachePage?: boolean
|
||||
closeTabRmCache?: boolean
|
||||
/** 路由图标 */
|
||||
icon: BootstrapIcons
|
||||
affix: boolean
|
||||
activeMenu: string
|
||||
breadcrumb: boolean
|
||||
roles: Array<string>
|
||||
code: number
|
||||
cachePage: boolean
|
||||
leaveRmCachePage: boolean
|
||||
closeTabRmCache: boolean
|
||||
}
|
||||
children?: RouterOptions
|
||||
redirect?: string
|
||||
}
|
||||
export type RouteRawConfig = RouteRecordRaw & rawConfig
|
||||
export type RouterTypes = Array<rawProp>
|
||||
|
||||
export type RouteRawConfig = RouteRecordRaw & Partial<RawConfig>
|
||||
export type RouterTypes = Array<RouteRawConfig>
|
||||
|
||||
/*settings*/
|
||||
export interface SettingsConfig {
|
||||
|
|
Loading…
Reference in New Issue
Block a user