Przeglądaj źródła

系统导航栏布局重构

Zhu Jiaqi 5 miesięcy temu
rodzic
commit
2fb41b2f87

BIN
src/assets/logo/dtm_logo.png


+ 32 - 5
src/assets/styles/sidebar.scss

@@ -24,8 +24,7 @@
     left: 0;
     z-index: 1001;
     overflow: hidden;
-    -webkit-box-shadow: 2px 0 6px rgba(0,21,41,.35);
-    box-shadow: 0px 0px 8px 0px rgba(0, 0, 0, 0.1);
+    box-shadow: 2px 0 12px rgba(0, 0, 0, 0.08);
 
     // reset element-ui css
     .horizontal-collapse-transition {
@@ -46,7 +45,7 @@
 
     &.has-logo {
       .el-scrollbar {
-        height: calc(100% - 50px);
+        height: calc(100% - 64px);
       }
     }
 
@@ -62,6 +61,7 @@
 
     .svg-icon {
       margin-right: 16px;
+      transition: all 0.3s ease;
     }
 
     .el-menu {
@@ -74,13 +74,21 @@
       overflow: hidden !important;
       text-overflow: ellipsis !important;
       white-space: nowrap !important;
+      transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
+      border-radius: 8px;
+      margin: 4px 8px;
+      padding-left: 16px !important;
+      
+      &:hover {
+        transform: translateX(4px);
+      }
     }
 
     // menu hover
     .submenu-title-noDropdown,
     .el-submenu__title {
       &:hover {
-        background-color: rgba(0, 0, 0, 0.06) !important;
+        background-color: rgba(102, 126, 234, 0.1) !important;
       }
     }
 
@@ -93,7 +101,7 @@
       min-width: $base-sidebar-width !important;
 
       &:hover {
-        background-color: rgba(0, 0, 0, 0.06) !important;
+        background-color: rgba(102, 126, 234, 0.08) !important;
       }
     }
 
@@ -105,6 +113,25 @@
         background-color: $base-sub-menu-hover !important;
       }
     }
+    
+    // 添加菜单项激活样式
+    .el-menu-item.is-active {
+      background: linear-gradient(90deg, rgba(102, 126, 234, 0.15) 0%, rgba(118, 75, 162, 0.1) 100%) !important;
+      color: #667eea !important;
+      font-weight: 600;
+      
+      &::before {
+        content: '';
+        position: absolute;
+        left: 0;
+        top: 50%;
+        transform: translateY(-50%);
+        width: 4px;
+        height: 60%;
+        background: linear-gradient(180deg, #667eea 0%, #764ba2 100%);
+        border-radius: 0 4px 4px 0;
+      }
+    }
   }
 
   .hideSidebar {

+ 14 - 7
src/layout/components/Sidebar/Logo.vue

@@ -3,18 +3,16 @@
     <transition name="sidebarLogoFade">
       <router-link v-if="collapse" key="collapse" class="sidebar-logo-link" to="/">
         <img v-if="logo" :src="logo" class="sidebar-logo" />
-        <h1 v-else class="sidebar-title" :style="{ color: sideTheme === 'theme-dark' ? variables.logoTitleColor : variables.logoLightTitleColor }">{{ title }} </h1>
       </router-link>
       <router-link v-else key="expand" class="sidebar-logo-link" to="/">
         <img v-if="logo" :src="logo" class="sidebar-logo" />
-        <h1 class="sidebar-title" :style="{ color: sideTheme === 'theme-dark' ? variables.logoTitleColor : variables.logoLightTitleColor }">{{ title }} </h1>
       </router-link>
     </transition>
   </div>
 </template>
 
 <script>
-import logoImg from '@/assets/logo/logo.png'
+import logoImg from '@/assets/logo/dtm_logo.png'
 import variables from '@/assets/styles/variables.scss'
 
 export default {
@@ -55,21 +53,28 @@ export default {
 .sidebar-logo-container {
   position: relative;
   width: 100%;
-  height: 50px;
-  line-height: 50px;
+  height: 64px;
+  line-height: 64px;
   background: #2b2f3a;
   text-align: center;
   overflow: hidden;
+  display: flex;
+  align-items: center;
+  justify-content: center;
 
   & .sidebar-logo-link {
     height: 100%;
     width: 100%;
+    display: flex;
+    align-items: center;
+    justify-content: center;
 
     & .sidebar-logo {
-      width: 32px;
-      height: 32px;
+      width: 80px;
+      height: 80px;
       vertical-align: middle;
       margin-right: 12px;
+      object-fit: contain;
     }
 
     & .sidebar-title {
@@ -87,6 +92,8 @@ export default {
   &.collapse {
     .sidebar-logo {
       margin-right: 0px;
+      width: 40px;
+      height: 40px;
     }
   }
 }

+ 19 - 12
src/layout/components/Sidebar/SidebarItem.vue

@@ -8,19 +8,12 @@
       </app-link>
     </template>
 
-    <el-submenu v-else ref="subMenu" :index="resolvePath(item.path)" popper-append-to-body>
-      <template slot="title">
+    <!-- 修改:点击模块后跳转到子菜单页面 -->
+    <app-link v-else :to="getModuleRoute(item)">
+      <el-menu-item :index="resolvePath(item.path)" :class="{'submenu-title-noDropdown':!isNest}">
         <item v-if="item.meta" :icon="item.meta && item.meta.icon" :title="item.meta.title" />
-      </template>
-      <sidebar-item
-        v-for="(child, index) in item.children"
-        :key="child.path + index"
-        :is-nest="true"
-        :item="child"
-        :base-path="resolvePath(child.path)"
-        class="nest-menu"
-      />
-    </el-submenu>
+      </el-menu-item>
+    </app-link>
   </div>
 </template>
 
@@ -93,6 +86,20 @@ export default {
         return { path: path.resolve(this.basePath, routePath), query: query }
       }
       return path.resolve(this.basePath, routePath)
+    },
+    // 获取模块子菜单路由
+    getModuleRoute(item) {
+      // 如果有子菜单,跳转到子菜单页面
+      if (item.children && item.children.length > 0) {
+        return {
+          path: '/module-submenu',
+          query: {
+            modulePath: item.path,
+            moduleTitle: item.meta ? item.meta.title : item.name
+          }
+        }
+      }
+      return this.resolvePath(item.path)
     }
   }
 }

+ 13 - 0
src/router/index.js

@@ -87,6 +87,19 @@ export const constantRoutes = [
         meta: { title: '个人中心', icon: 'user' }
       }
     ]
+  },
+  {
+    path: '/module-submenu',
+    component: Layout,
+    hidden: true,
+    children: [
+      {
+        path: '',
+        component: () => import('@/views/module-submenu'),
+        name: 'ModuleSubmenu',
+        meta: { title: '功能菜单' }
+      }
+    ]
   }
 ]
 

+ 295 - 69
src/views/index.vue

@@ -1,71 +1,39 @@
 <template>
   <div class="app-container home">
-    <el-row :gutter="20">
-      <el-col :sm="24" :lg="12" style="padding-left: 20px">
-        <h2>若依后台管理框架</h2>
-        <p>
-          一直想做一款后台管理系统,看了很多优秀的开源项目但是发现没有合适自己的。于是利用空闲休息时间开始自己写一套后台系统。如此有了若依管理系统,她可以用于所有的Web应用程序,如网站管理后台,网站会员中心,CMS,CRM,OA等等,当然,您也可以对她进行深度定制,以做出更强系统。所有前端后台代码封装过后十分精简易上手,出错概率低。同时支持移动客户端访问。系统会陆续更新一些实用功能。
-        </p>
-        <p>
-          <b>当前版本:</b> <span>v{{ version }}</span>
-        </p>
-        <p>
-          <el-tag type="danger">&yen;免费开源</el-tag>
-        </p>
-        <p>
-          <el-button
-            type="primary"
-            size="mini"
-            icon="el-icon-cloudy"
-            plain
-            @click="goTarget('https://gitee.com/y_project/RuoYi-Vue')"
-            >访问码云</el-button
-          >
-          <el-button
-            size="mini"
-            icon="el-icon-s-home"
-            plain
-            @click="goTarget('http://ruoyi.vip')"
-            >访问主页</el-button
-          >
-        </p>
-      </el-col>
+    <!-- 功能模块宫格 -->
+    <div class="module-grid-container">
+      <div class="page-header">
+        <h2><i class="el-icon-menu"></i> 功能导航</h2>
+        <p>选择您需要的功能模块,开始您的工作</p>
+      </div>
 
-      <el-col :sm="24" :lg="12" style="padding-left: 50px">
-        <el-row>
-          <el-col :span="12">
-            <h2>技术选型</h2>
-          </el-col>
-        </el-row>
-        <el-row>
-          <el-col :span="6">
-            <h4>后端技术</h4>
-            <ul>
-              <li>SpringBoot</li>
-              <li>Spring Security</li>
-              <li>JWT</li>
-              <li>MyBatis</li>
-              <li>Druid</li>
-              <li>Fastjson</li>
-              <li>...</li>
-            </ul>
-          </el-col>
-          <el-col :span="6">
-            <h4>前端技术</h4>
-            <ul>
-              <li>Vue</li>
-              <li>Vuex</li>
-              <li>Element-ui</li>
-              <li>Axios</li>
-              <li>Sass</li>
-              <li>Quill</li>
-              <li>...</li>
-            </ul>
-          </el-col>
-        </el-row>
-      </el-col>
-    </el-row>
-    <el-divider />
+      <div class="module-grid">
+        <div
+          v-for="module in allModules"
+          :key="module.path"
+          class="module-card"
+          @click="handleModuleClick(module)"
+        >
+          <div class="module-badge" v-if="module.children && module.children.length">
+            <span>{{ module.children.length }}</span>
+          </div>
+          <div class="module-icon">
+            <svg-icon v-if="module.meta && module.meta.icon" :icon-class="module.meta.icon" class="icon" />
+            <i v-else class="el-icon-menu icon"></i>
+          </div>
+          <div class="module-content">
+            <div class="module-title">{{ module.meta ? module.meta.title : module.name }}</div>
+            <div class="module-desc" v-if="module.children && module.children.length">
+              {{ module.children.length }} 个功能
+            </div>
+          </div>
+          <div class="module-arrow">
+            <i class="el-icon-arrow-right"></i>
+          </div>
+        </div>
+      </div>
+    </div>
+    <!-- <el-divider />
     <el-row :gutter="20">
       <el-col :xs="24" :sm="24" :md="12" :lg="8">
         <el-card class="update-log">
@@ -83,9 +51,9 @@
             <p>
               <i class="el-icon-user-solid"></i> QQ群:<s> 满937441 </s> <s> 满887144332 </s>
               <s> 满180251782 </s> <s> 满104180207 </s> <s> 满186866453 </s> <s> 满201396349 </s>
-              <s> 满101456076 </s> <s> 满101539465 </s> <s> 满264312783 </s> <s> 满167385320 </s> 
-              <s> 满104748341 </s> <s> 满160110482 </s> <s> 满170801498 </s> <s> 满108482800 </s> 
-              <s> 满101046199 </s> <s> 满136919097 </s> <s> 满143961921 </s> <s> 满174951577 </s> 
+              <s> 满101456076 </s> <s> 满101539465 </s> <s> 满264312783 </s> <s> 满167385320 </s>
+              <s> 满104748341 </s> <s> 满160110482 </s> <s> 满170801498 </s> <s> 满108482800 </s>
+              <s> 满101046199 </s> <s> 满136919097 </s> <s> 满143961921 </s> <s> 满174951577 </s>
               <s> 满161281055 </s> <s> 满138988063 </s> <s> 满151450850 </s> <s> 满224622315 </s>
               <s> 满287842588 </s> <s> 满187944233 </s> <s> 满228578329 </s> <s> 满191164766 </s>
 			  <a href="http://qm.qq.com/cgi-bin/qm/qr?_wv=1027&k=EeCBXu51I1zPWRia2uskpjDRx6VrbnFN&authKey=Xm8yDxk0%2FyYGI11oxhXaQnTn4K7UwCk7Kn2MZTh3P1JxLctollAkyeySjnaILDkb&noverify=0&group_code=174569686" target="_blank">174569686</a>
@@ -1050,11 +1018,13 @@
           </div>
         </el-card>
       </el-col>
-    </el-row>
+    </el-row>-->
   </div>
 </template>
 
 <script>
+import { mapGetters } from 'vuex'
+
 export default {
   name: "Index",
   data() {
@@ -1063,9 +1033,42 @@ export default {
       version: "3.9.0"
     }
   },
+  computed: {
+    ...mapGetters(['sidebarRouters']),
+    // 所有模块(包括系统菜单和KPI模块)
+    allModules() {
+      const modules = []
+      // 添加系统菜单
+      if (this.sidebarRouters && this.sidebarRouters.length > 0) {
+        this.sidebarRouters.forEach(route => {
+          if (!route.hidden && route.path !== '/index' && route.path !== '') {
+              modules.push(route)
+          }
+        })
+      }
+
+      return modules
+    }
+  },
   methods: {
     goTarget(href) {
       window.open(href, "_blank")
+    },
+    // 处理模块点击
+    handleModuleClick(module) {
+      // 如果有子菜单,跳转到子菜单页面
+      if (module.children && module.children.length > 0) {
+        this.$router.push({
+          path: '/module-submenu',
+          query: {
+            modulePath: module.path,
+            moduleTitle: module.meta ? module.meta.title : module.name
+          }
+        })
+      } else {
+        // 直接跳转
+        this.$router.push(module.path)
+      }
     }
   }
 }
@@ -1073,6 +1076,229 @@ export default {
 
 <style scoped lang="scss">
 .home {
+  // ... existing code ...
+
+  .module-grid-container {
+    margin-bottom: 30px;
+    padding: 20px;
+    background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
+    border-radius: 16px;
+    box-shadow: 0 8px 32px 0 rgba(102, 126, 234, 0.2);
+
+    .page-header {
+      text-align: center;
+      margin-bottom: 40px;
+
+      h2 {
+        font-size: 32px;
+        font-weight: 700;
+        color: #ffffff;
+        margin-bottom: 12px;
+        text-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
+
+        i {
+          margin-right: 10px;
+          font-size: 28px;
+        }
+      }
+
+      p {
+        font-size: 16px;
+        color: rgba(255, 255, 255, 0.9);
+        font-weight: 300;
+      }
+    }
+
+    .module-grid {
+      display: grid;
+      grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
+      gap: 24px;
+
+      .module-card {
+        position: relative;
+        background: #ffffff;
+        border-radius: 12px;
+        padding: 24px;
+        display: flex;
+        align-items: center;
+        cursor: pointer;
+        transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
+        box-shadow: 0 4px 12px 0 rgba(0, 0, 0, 0.08);
+        overflow: hidden;
+
+        &::before {
+          content: '';
+          position: absolute;
+          top: 0;
+          left: 0;
+          width: 4px;
+          height: 100%;
+          background: linear-gradient(180deg, #667eea 0%, #764ba2 100%);
+          transform: scaleY(0);
+          transition: transform 0.3s ease;
+        }
+
+        &:hover {
+          transform: translateX(8px);
+          box-shadow: 0 8px 24px 0 rgba(102, 126, 234, 0.3);
+
+          &::before {
+            transform: scaleY(1);
+          }
+
+          .module-icon {
+            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
+            transform: scale(1.1) rotate(5deg);
+
+            ::v-deep(.svg-icon),
+            .icon {
+              color: #ffffff;
+            }
+          }
+
+          .module-arrow {
+            opacity: 1;
+            transform: translateX(0);
+          }
+        }
+
+        .module-badge {
+          position: absolute;
+          top: 12px;
+          right: 12px;
+          background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%);
+          color: #ffffff;
+          font-size: 12px;
+          font-weight: 600;
+          padding: 4px 10px;
+          border-radius: 12px;
+          box-shadow: 0 2px 8px rgba(245, 87, 108, 0.3);
+
+          span {
+            display: block;
+          }
+        }
+
+        .module-icon {
+          flex-shrink: 0;
+          display: inline-flex;
+          align-items: center;
+          justify-content: center;
+          width: 64px;
+          height: 64px;
+          border-radius: 16px;
+          background: linear-gradient(135deg, #f5f7fa 0%, #e4e7ed 100%);
+          margin-right: 20px;
+          transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
+          box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05);
+
+          ::v-deep(.svg-icon) {
+            font-size: 32px;
+            color: #606266;
+            transition: color 0.3s ease;
+          }
+
+          .icon {
+            font-size: 32px;
+            color: #606266;
+            transition: color 0.3s ease;
+          }
+        }
+
+        .module-content {
+          flex: 1;
+          min-width: 0;
+
+          .module-title {
+            font-size: 18px;
+            font-weight: 600;
+            color: #303133;
+            margin-bottom: 6px;
+            overflow: hidden;
+            text-overflow: ellipsis;
+            white-space: nowrap;
+          }
+
+          .module-desc {
+            font-size: 13px;
+            color: #909399;
+            font-weight: 400;
+          }
+        }
+
+        .module-arrow {
+          flex-shrink: 0;
+          opacity: 0;
+          transform: translateX(-10px);
+          transition: all 0.3s ease;
+
+          i {
+            font-size: 20px;
+            color: #909399;
+          }
+        }
+      }
+    }
+
+    // 响应式布局
+    @media (max-width: 1200px) {
+      .module-grid {
+        grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
+        gap: 20px;
+      }
+    }
+
+    @media (max-width: 768px) {
+      padding: 16px;
+
+      .page-header {
+        margin-bottom: 24px;
+
+        h2 {
+          font-size: 24px;
+
+          i {
+            font-size: 20px;
+          }
+        }
+
+        p {
+          font-size: 14px;
+        }
+      }
+
+      .module-grid {
+        grid-template-columns: 1fr;
+        gap: 16px;
+
+        .module-card {
+          padding: 20px;
+
+          .module-icon {
+            width: 56px;
+            height: 56px;
+            margin-right: 16px;
+
+            ::v-deep(.svg-icon),
+            .icon {
+              font-size: 28px;
+            }
+          }
+
+          .module-content {
+            .module-title {
+              font-size: 16px;
+            }
+
+            .module-desc {
+              font-size: 12px;
+            }
+          }
+        }
+      }
+    }
+  }
+
   blockquote {
     padding: 10px 20px;
     margin: 0 0 20px;

+ 249 - 0
src/views/module-submenu.vue

@@ -0,0 +1,249 @@
+<template>
+  <div class="app-container submenu-container">
+    <div class="page-header">
+      <h2>{{ moduleTitle }}</h2>
+      <p>请选择具体功能</p>
+    </div>
+
+    <div class="submenu-grid">
+      <div
+        v-for="item in menuItems"
+        :key="item.path"
+        class="submenu-card"
+        @click="handleItemClick(item)"
+      >
+        <div class="submenu-icon">
+          <svg-icon v-if="item.meta && item.meta.icon" :icon-class="item.meta.icon" class="icon" />
+          <i v-else class="el-icon-document icon"></i>
+        </div>
+        <div class="submenu-title">{{ item.meta ? item.meta.title : item.name }}</div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script>
+import { mapGetters } from 'vuex'
+
+export default {
+  name: 'ModuleSubmenu',
+  data() {
+    return {
+      moduleTitle: '',
+      menuItems: []
+    }
+  },
+  computed: {
+    ...mapGetters(['sidebarRouters'])
+  },
+  created() {
+    this.loadMenuItems()
+  },
+  watch: {
+    '$route.query': {
+      handler() {
+        this.loadMenuItems()
+      },
+      deep: true
+    }
+  },
+  methods: {
+    loadMenuItems() {
+      const { modulePath, moduleTitle } = this.$route.query
+      this.moduleTitle = moduleTitle || '功能菜单'
+
+      // 查找对应的菜单项
+      this.menuItems = this.findMenuItems(modulePath)
+    },
+    findMenuItems(modulePath) {
+      // 从系统菜单查找
+      if (this.sidebarRouters && this.sidebarRouters.length > 0) {
+        for (const route of this.sidebarRouters) {
+          if (route.path === modulePath && route.children) {
+            // 返回系统模块的子菜单,确保路径完整
+            return route.children
+              .filter(child => !child.hidden)
+              .map(child => {
+                // 如果路径是相对路径,需要拼接父路径
+                const fullPath = child.path.startsWith('/') ? child.path : `${route.path}/${child.path}`
+                return {
+                  ...child,
+                  path: fullPath
+                }
+              })
+          }
+        }
+      }
+
+      return []
+    },
+    handleItemClick(item) {
+      this.$router.push(item.path)
+    }
+  }
+}
+</script>
+
+<style scoped lang="scss">
+.submenu-container {
+  .page-header {
+    text-align: center;
+    margin-bottom: 48px;
+    padding: 32px 24px;
+    background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
+    border-radius: 16px;
+    box-shadow: 0 8px 32px 0 rgba(102, 126, 234, 0.2);
+
+    h2 {
+      font-size: 32px;
+      font-weight: 700;
+      color: #ffffff;
+      margin-bottom: 12px;
+      text-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
+    }
+
+    p {
+      font-size: 16px;
+      color: rgba(255, 255, 255, 0.9);
+      font-weight: 300;
+    }
+  }
+
+  .submenu-grid {
+    display: grid;
+    grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
+    gap: 24px;
+
+    .submenu-card {
+      background: #ffffff;
+      border-radius: 12px;
+      padding: 32px 24px;
+      text-align: center;
+      cursor: pointer;
+      transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
+      border: 2px solid transparent;
+      box-shadow: 0 4px 12px 0 rgba(0, 0, 0, 0.08);
+      position: relative;
+      overflow: hidden;
+
+      &::before {
+        content: '';
+        position: absolute;
+        top: 0;
+        left: 0;
+        right: 0;
+        height: 4px;
+        background: linear-gradient(90deg, #667eea 0%, #764ba2 100%);
+        transform: scaleX(0);
+        transition: transform 0.3s ease;
+      }
+
+      &:hover {
+        background: #ffffff;
+        border-color: transparent;
+        transform: translateY(-8px);
+        box-shadow: 0 12px 32px 0 rgba(102, 126, 234, 0.25);
+
+        &::before {
+          transform: scaleX(1);
+        }
+
+        .submenu-icon {
+          background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
+          transform: scale(1.1) rotate(5deg);
+          box-shadow: 0 8px 24px rgba(102, 126, 234, 0.3);
+
+          ::v-deep(.svg-icon),
+          .icon {
+            color: #ffffff;
+          }
+        }
+
+        .submenu-title {
+          color: #667eea;
+        }
+      }
+
+      .submenu-icon {
+        display: inline-flex;
+        align-items: center;
+        justify-content: center;
+        width: 72px;
+        height: 72px;
+        border-radius: 16px;
+        background: linear-gradient(135deg, #f5f7fa 0%, #e4e7ed 100%);
+        margin: 0 auto 20px;
+        transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
+        box-shadow: 0 4px 12px rgba(0, 0, 0, 0.05);
+
+        ::v-deep(.svg-icon) {
+          font-size: 36px;
+          color: #606266;
+          transition: color 0.3s ease;
+        }
+
+        .icon {
+          font-size: 36px;
+          color: #606266;
+          transition: color 0.3s ease;
+        }
+      }
+
+      .submenu-title {
+        font-size: 17px;
+        font-weight: 600;
+        color: #303133;
+        transition: color 0.3s ease;
+        line-height: 1.5;
+      }
+    }
+  }
+
+  // 响应式布局
+  @media (max-width: 1200px) {
+    .submenu-grid {
+      grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
+      gap: 20px;
+    }
+  }
+
+  @media (max-width: 768px) {
+    .page-header {
+      margin-bottom: 32px;
+      padding: 24px 16px;
+
+      h2 {
+        font-size: 24px;
+      }
+
+      p {
+        font-size: 14px;
+      }
+    }
+
+    .submenu-grid {
+      grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
+      gap: 16px;
+
+      .submenu-card {
+        padding: 28px 20px;
+
+        .submenu-icon {
+          width: 60px;
+          height: 60px;
+          margin-bottom: 16px;
+
+          ::v-deep(.svg-icon),
+          .icon {
+            font-size: 30px;
+          }
+        }
+
+        .submenu-title {
+          font-size: 15px;
+        }
+      }
+    }
+  }
+}
+</style>