Bläddra i källkod

# feat:搭建用户布局和后台管理布局,菜单项目根据路由动态显示

yang yi 1 månad sedan
förälder
incheckning
532fee3408
6 ändrade filer med 204 tillägg och 16 borttagningar
  1. 3 1
      src/App.vue
  2. 123 0
      src/layout/AdminLayout.vue
  3. 19 9
      src/layout/UserLayout.vue
  4. 48 6
      src/router/index.ts
  5. 0 0
      src/util/index.ts
  6. 11 0
      src/view/UserView.vue

+ 3 - 1
src/App.vue

@@ -6,5 +6,7 @@
 </template>
 
 <style scoped>
-
+*{
+  margin: 0;
+}
 </style>

+ 123 - 0
src/layout/AdminLayout.vue

@@ -0,0 +1,123 @@
+<script setup lang="ts">
+import {useLoginUserStore} from "../store";
+import {computed, type ComputedRef, ref} from "vue";
+import type {RouteRecordRaw} from "vue-router";
+import router, {adminRoutes} from "../router";
+
+const title = ref<string>("标题");
+const loginUserStore = useLoginUserStore()
+const login = computed(()=>loginUserStore.loginUser.isLogin)
+const loginHandler = () => {
+
+}
+const logoutHandler = () => {
+
+}
+const menus:ComputedRef<RouteRecordRaw[] | undefined> = computed(()=>{
+  return adminRoutes[0].children;
+})
+const isCollapse = ref(false)
+const handleOpen = (key: string, keyPath: string[]) => {
+  console.log(key, keyPath)
+}
+const handleClose = (key: string, keyPath: string[]) => {
+  console.log(key, keyPath)
+}
+</script>
+
+<template>
+  <el-container>
+    <el-header class="header">
+      <div class="header-left" @click="router.push('/')">
+        <img src="/src/assets/logo.svg" alt="logo" class="logo">
+        <h2 class="title">{{title}}</h2>
+      </div>
+      <h1>后台管理</h1>
+      <div class="header-right">
+        <template v-if="login">
+          <el-dropdown placement="bottom">
+            <el-button> {{ loginUserStore.loginUser?.user?.name }} </el-button>
+            <template #dropdown>
+              <el-dropdown-menu>
+                <el-dropdown-item>个人信息</el-dropdown-item>
+                <el-dropdown-item @click="logoutHandler">退出</el-dropdown-item>
+              </el-dropdown-menu>
+            </template>
+          </el-dropdown>
+        </template>
+        <template v-else>
+          <el-button type="primary" size="small" @click="loginHandler">登录</el-button>
+          <el-button size="small">注册</el-button>
+        </template>
+      </div>
+    </el-header>
+
+    <el-container class="main-container">
+      <el-aside class="menu">
+        <el-radio-group v-model="isCollapse" style="margin-bottom: 20px;display: flex;justify-content: center">
+          <el-radio-button :value="false">expand</el-radio-button>
+          <el-radio-button :value="true">collapse</el-radio-button>
+        </el-radio-group>
+        <el-menu
+            router
+            class="el-menu-vertical"
+            :collapse="isCollapse"
+            @open="handleOpen"
+            @close="handleClose"
+        >
+          <el-menu-item :index="menu.path" v-for="menu in menus" :key="menu.path">
+            <el-icon><Component :is="menu.meta?.icon"/></el-icon>
+            <template #title>{{menu.meta?.title}}</template>
+          </el-menu-item>
+        </el-menu>
+      </el-aside>
+      <el-main>
+        <router-view/>
+      </el-main>
+    </el-container>
+  </el-container>
+
+</template>
+<style scoped>
+.el-container {
+  height: 100vh;
+}
+.header {
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+  padding: 0 20px;
+  margin-bottom: 10px;
+  border-bottom: 1px solid
+}
+.header-left {
+  display: flex;
+  align-items: center;
+  gap: 10px;
+}
+.logo {
+  width: 40px;
+  height: 40px;
+}
+.title {
+  margin: 0;
+  font-size: 20px;
+}
+
+.header-right {
+  display: flex;
+  align-items: center;
+  gap: 10px;
+}
+
+.menu{
+  width: 200px;
+}
+.main-container {
+  flex: 1;
+}
+.el-menu-vertical-demo:not(.el-menu--collapse) {
+  width: 200px;
+  min-height: 400px;
+}
+</style>

+ 19 - 9
src/layout/CommonLayout.vue → src/layout/UserLayout.vue

@@ -1,8 +1,8 @@
 <template>
-  <div class="common-layout">
+  <div class="user-layout">
     <el-container>
       <el-header class="header">
-        <div class="header-left">
+        <div class="header-left" @click="router.push('/')">
           <img src="/src/assets/logo.svg" alt="logo" class="logo">
           <h2 class="title">{{title}}</h2>
         </div>
@@ -13,15 +13,17 @@
             @select="handleSelect"
             class="nav-menu"
         >
-          <el-menu-item index="/">首页</el-menu-item>
-          <el-sub-menu index="2">
-            <template #title>其他</template>
-            <el-menu-item index="/about">关于</el-menu-item>
-          </el-sub-menu>
+          <el-menu-item :index="menu.path" v-for="menu in menus" :key="menu.path">
+            <el-icon><component :is="menu.meta?.icon"/></el-icon>
+            <template #title>{{ menu.meta?.title }}</template>
+          </el-menu-item>
+          <el-menu-item index="/admin">
+            <el-icon><Tools/></el-icon>
+            <template #title>后台管理</template>
+          </el-menu-item>
         </el-menu>
         <div class="header-right">
           <template v-if="login">
-<!--            <span class="username"></span>-->
             <el-dropdown placement="bottom">
               <el-button> {{ loginUserStore.loginUser?.user?.name }} </el-button>
               <template #dropdown>
@@ -51,6 +53,11 @@
 <script setup lang="ts">
 import {computed, ref} from 'vue'
 import {useLoginUserStore} from "../store";
+import router, {userRoutes} from "../router";
+import {
+  Tools
+} from '@element-plus/icons-vue'
+
 const title = ref("标题")
 const loginUserStore = useLoginUserStore()
 const login = computed(() => loginUserStore.loginUser.isLogin)
@@ -63,6 +70,9 @@ const loginHandler = () => {
   });
 }
 let activeIndex = ref('/')
+const menus = computed(()=>{
+  return userRoutes[0].children;
+})
 const handleSelect = () => {
   //todo: 处理菜单选择
 }
@@ -71,7 +81,7 @@ const logoutHandler = () => {
 }
 </script>
 <style scoped>
-.common-layout {
+.user-layout {
   display: flex;
   flex-direction: column;
   min-height: 100vh;

+ 48 - 6
src/router/index.ts

@@ -2,30 +2,72 @@ import {createRouter, createWebHistory, type Router, type RouteRecordRaw} from '
 
 import HomeView from '../view/HomeView.vue'
 import AboutView from '../view/AboutView.vue'
-import CommonLayout from '../layout/CommonLayout.vue'
+import UserLayout from '../layout/UserLayout.vue'
+import AdminLayout from "../layout/AdminLayout.vue";
+import UserView from "../view/UserView.vue";
+import {
+    HomeFilled,
+    Menu,
+    User,
+} from '@element-plus/icons-vue'
 
-const routes:RouteRecordRaw[] = [
+export const userRoutes:RouteRecordRaw[] = [
     {
         path: '/',
         name: 'commonLayout',
-        component: CommonLayout,
+        component: UserLayout,
         children: [
             {
                 path: '/',
                 name: 'home',
-                component: HomeView
+                component: HomeView,
+                meta: {
+                    title: '首页',
+                    icon: HomeFilled
+                }
             },
             {
                 path: '/about',
                 name: 'about',
-                component: AboutView
+                component: AboutView,
+                meta: {
+                    title: '关于',
+                    icon: Menu
+                }
             },
         ],
     },
 ]
+export const adminRoutes:RouteRecordRaw[] = [
+    {
+        path: '/admin',
+        name: 'adminLayout',
+        component: AdminLayout,
+        children:[
+            {
+                path: '/admin/users',
+                name: 'users',
+                component: UserView,
+                meta:{
+                    title: '用户管理',
+                    icon: User
+                }
+            },
+            {
+                path:'/admin/other',
+                name:'other',
+                component: AdminLayout,
+                meta:{
+                    title: '其他',
+                    icon: Menu
+                }
+            }
+        ]
+    }
+]
 
 const router : Router = createRouter({
     history: createWebHistory(),
-    routes: routes,
+    routes: [...userRoutes,...adminRoutes],
 });
 export default router

+ 0 - 0
src/util/index.ts


+ 11 - 0
src/view/UserView.vue

@@ -0,0 +1,11 @@
+<script setup lang="ts">
+
+</script>
+
+<template>
+用户视图
+</template>
+
+<style scoped>
+
+</style>