Explorar el Código

style: 优化第四种布局

kailong321200875 hace 2 años
padre
commit
122fa62d85

+ 12 - 0
src/components/Setting/src/components/InterfaceDisplay.vue

@@ -115,6 +115,13 @@ const dynamicRouterChange = (show: boolean) => {
   appStore.setDynamicRouter(show)
 }
 
+// 固定菜单
+const fixedMenu = ref(appStore.getFixedMenu)
+
+const fixedMenuChange = (show: boolean) => {
+  appStore.setFixedMenu(show)
+}
+
 const layout = computed(() => appStore.getLayout)
 
 watch(
@@ -198,5 +205,10 @@ watch(
       <span class="text-14px">{{ t('setting.dynamicRouter') }}</span>
       <ElSwitch v-model="dynamicRouter" @change="dynamicRouterChange" />
     </div>
+
+    <div class="flex justify-between items-center">
+      <span class="text-14px">{{ t('setting.fixedMenu') }}</span>
+      <ElSwitch v-model="fixedMenu" @change="fixedMenuChange" />
+    </div>
   </div>
 </template>

+ 39 - 9
src/components/TabMenu/src/TabMenu.vue

@@ -1,7 +1,7 @@
 <script lang="tsx">
 import { usePermissionStore } from '@/store/modules/permission'
 import { useAppStore } from '@/store/modules/app'
-import { computed, unref, defineComponent, watch, ref } from 'vue'
+import { computed, unref, defineComponent, watch, ref, onMounted } from 'vue'
 import { useI18n } from '@/hooks/web/useI18n'
 import { ElScrollbar } from 'element-plus'
 import { Icon } from '@/components/Icon'
@@ -28,6 +28,8 @@ export default defineComponent({
 
     const collapse = computed(() => appStore.getCollapse)
 
+    const fixedMenu = computed(() => appStore.getFixedMenu)
+
     const permissionStore = usePermissionStore()
 
     const routers = computed(() => permissionStore.getRouters)
@@ -38,6 +40,27 @@ export default defineComponent({
       appStore.setCollapse(!unref(collapse))
     }
 
+    onMounted(() => {
+      if (unref(fixedMenu)) {
+        const path = `/${unref(currentRoute).path.split('/')[1]}`
+        const children = unref(tabRouters).find(
+          (v) =>
+            (v.meta?.alwaysShow || (v?.children?.length && v?.children?.length > 1)) &&
+            v.path === path
+        )?.children
+
+        tabActive.value = path
+        if (children) {
+          permissionStore.setMenuTabRouters(
+            cloneDeep(children).map((v) => {
+              v.path = pathResolve(unref(tabActive), v.path)
+              return v
+            })
+          )
+        }
+      }
+    })
+
     watch(
       () => routers.value,
       (routers: AppRouteRecordRaw[]) => {
@@ -55,6 +78,9 @@ export default defineComponent({
     watch(
       () => collapse.value,
       (collapse: boolean) => {
+        if (unref(fixedMenu)) {
+          return
+        }
         if (!collapse) {
           setTimeout(() => {
             showTitle.value = !collapse
@@ -66,7 +92,7 @@ export default defineComponent({
     )
 
     // 是否显示菜单
-    const showMenu = ref(false)
+    const showMenu = ref(unref(fixedMenu) ? true : false)
 
     // tab高亮
     const tabActive = ref('')
@@ -77,9 +103,13 @@ export default defineComponent({
         window.open(item.path)
         return
       }
+      const newPath = item.children ? item.path : item.path.split('/')[0]
+      const oldPath = unref(tabActive)
       tabActive.value = item.children ? item.path : item.path.split('/')[0]
       if (item.children) {
-        showMenu.value = !unref(showMenu)
+        if (newPath === oldPath || !unref(showMenu)) {
+          showMenu.value = unref(fixedMenu) ? true : !unref(showMenu)
+        }
         if (unref(showMenu)) {
           permissionStore.setMenuTabRouters(
             cloneDeep(item.children).map((v) => {
@@ -96,7 +126,7 @@ export default defineComponent({
     }
 
     // 设置高亮
-    const isActice = (currentPath: string) => {
+    const isActive = (currentPath: string) => {
       const { path } = unref(currentRoute)
       if (tabPathMap[currentPath].includes(path)) {
         return true
@@ -105,7 +135,7 @@ export default defineComponent({
     }
 
     const mouseleave = () => {
-      if (!unref(showMenu)) return
+      if (!unref(showMenu) || unref(fixedMenu)) return
       showMenu.value = false
     }
 
@@ -114,7 +144,7 @@ export default defineComponent({
         id={`${variables.namespace}-menu`}
         class={[
           prefixCls,
-          'relative bg-[var(--left-menu-bg-color)] top-1px z-999',
+          'relative bg-[var(--left-menu-bg-color)] top-1px z-99999',
           {
             'w-[var(--tab-menu-max-width)]': !unref(collapse),
             'w-[var(--tab-menu-min-width)]': unref(collapse)
@@ -140,7 +170,7 @@ export default defineComponent({
                       `${prefixCls}__item`,
                       'text-center text-12px relative py-12px cursor-pointer',
                       {
-                        'is-active': isActice(v.path)
+                        'is-active': isActive(v.path)
                       }
                     ]}
                     onClick={() => {
@@ -174,8 +204,8 @@ export default defineComponent({
             {
               '!left-[var(--tab-menu-min-width)]': unref(collapse),
               '!left-[var(--tab-menu-max-width)]': !unref(collapse),
-              '!w-[calc(var(--left-menu-max-width)+1px)]': unref(showMenu),
-              '!w-0': !unref(showMenu)
+              '!w-[calc(var(--left-menu-max-width)+1px)]': unref(showMenu) || unref(fixedMenu),
+              '!w-0': !unref(showMenu) && !unref(fixedMenu)
             }
           ]}
           style="transition: width var(--transition-time-02), left var(--transition-time-02);"

+ 4 - 4
src/components/TabMenu/src/helper.ts

@@ -28,9 +28,9 @@ export const filterMenusPath = (
     let data: Nullable<AppRouteRecordRaw> = null
     const meta = (v.meta ?? {}) as RouteMeta
     if (!meta.hidden || meta.canTo) {
-      const allParentPaht = getAllParentPath<AppRouteRecordRaw>(allRoutes, v.path)
+      const allParentPath = getAllParentPath<AppRouteRecordRaw>(allRoutes, v.path)
 
-      const fullPath = isUrl(v.path) ? v.path : allParentPaht.join('/')
+      const fullPath = isUrl(v.path) ? v.path : allParentPath.join('/')
 
       data = cloneDeep(v)
       data.path = fullPath
@@ -42,8 +42,8 @@ export const filterMenusPath = (
         res.push(data)
       }
 
-      if (allParentPaht.length && Reflect.has(tabPathMap, allParentPaht[0])) {
-        tabPathMap[allParentPaht[0]].push(fullPath)
+      if (allParentPath.length && Reflect.has(tabPathMap, allParentPath[0])) {
+        tabPathMap[allParentPath[0]].push(fullPath)
       }
     }
   }

+ 16 - 3
src/layout/components/useRenderLayout.tsx

@@ -32,6 +32,9 @@ const fixedHeader = computed(() => appStore.getFixedHeader)
 // 是否是移动端
 const mobile = computed(() => appStore.getMobile)
 
+// 固定菜单
+const fixedMenu = computed(() => appStore.getFixedMenu)
+
 export const useRenderLayout = () => {
   const renderClassic = () => {
     return (
@@ -213,9 +216,13 @@ export const useRenderLayout = () => {
               'h-[100%]',
               {
                 'w-[calc(100%-var(--tab-menu-min-width))] left-[var(--tab-menu-min-width)]':
-                  collapse.value,
+                  collapse.value && !fixedMenu.value,
                 'w-[calc(100%-var(--tab-menu-max-width))] left-[var(--tab-menu-max-width)]':
-                  !collapse.value
+                  !collapse.value && !fixedMenu.value,
+                'w-[calc(100%-var(--tab-menu-min-width)-var(--left-menu-max-width))] ml-[var(--left-menu-max-width)]':
+                  collapse.value && fixedMenu.value,
+                'w-[calc(100%-var(--tab-menu-max-width)-var(--left-menu-max-width))] ml-[var(--left-menu-max-width)]':
+                  !collapse.value && fixedMenu.value
               }
             ]}
             style="transition: all var(--transition-time-02);"
@@ -239,7 +246,13 @@ export const useRenderLayout = () => {
                       'w-[calc(100%-var(--tab-menu-min-width))] left-[var(--tab-menu-min-width)] mt-[var(--logo-height)]':
                         collapse.value && fixedHeader.value,
                       'w-[calc(100%-var(--tab-menu-max-width))] left-[var(--tab-menu-max-width)] mt-[var(--logo-height)]':
-                        !collapse.value && fixedHeader.value
+                        !collapse.value && fixedHeader.value,
+                      '!fixed top-0 left-[var(--tab-menu-min-width)+var(--left-menu-max-width)] z-10':
+                        fixedHeader.value && fixedMenu.value,
+                      'w-[calc(100%-var(--tab-menu-min-width)-var(--left-menu-max-width))] left-[var(--tab-menu-min-width)+var(--left-menu-max-width)] mt-[var(--logo-height)]':
+                        collapse.value && fixedHeader.value && fixedMenu.value,
+                      'w-[calc(100%-var(--tab-menu-max-width)-var(--left-menu-max-width))] left-[var(--tab-menu-max-width)+var(--left-menu-max-width)] mt-[var(--logo-height)]':
+                        !collapse.value && fixedHeader.value && fixedMenu.value
                     }
                   ]}
                   style="transition: width var(--transition-time-02), left var(--transition-time-02);"

+ 2 - 1
src/locales/en.ts

@@ -76,7 +76,8 @@ export default {
     uniqueOpened: 'Unique opened',
     tagsViewIcon: 'Tags view icon',
     dynamicRouter: 'Dynamic router',
-    reExperienced: 'Please exit the login experience again'
+    reExperienced: 'Please exit the login experience again',
+    fixedMenu: 'Fixed menu'
   },
   size: {
     default: 'Default',

+ 2 - 1
src/locales/zh-CN.ts

@@ -76,7 +76,8 @@ export default {
     uniqueOpened: '菜单手风琴',
     tagsViewIcon: '标签页图标',
     dynamicRouter: '动态路由',
-    reExperienced: '请重新退出登录体验'
+    reExperienced: '请重新退出登录体验',
+    fixedMenu: '固定菜单'
   },
   size: {
     default: '默认',

+ 9 - 0
src/store/modules/app.ts

@@ -34,6 +34,7 @@ interface AppState {
   mobile: boolean
   footer: boolean
   theme: ThemeTypes
+  fixedMenu: boolean
 }
 
 export const useAppStore = defineStore('app', {
@@ -60,6 +61,7 @@ export const useAppStore = defineStore('app', {
       footer: true, // 显示页脚
       greyMode: false, // 是否开始灰色模式,用于特殊悼念日
       dynamicRouter: wsCache.get('dynamicRouter') || false, // 是否动态路由
+      fixedMenu: wsCache.get('fixedMenu') || false, // 是否固定菜单
 
       layout: wsCache.get('layout') || 'classic', // layout布局
       isDark: wsCache.get('isDark') || false, // 是否是暗黑模式
@@ -139,6 +141,9 @@ export const useAppStore = defineStore('app', {
     getDynamicRouter(): boolean {
       return this.dynamicRouter
     },
+    getFixedMenu(): boolean {
+      return this.fixedMenu
+    },
     getPageLoading(): boolean {
       return this.pageLoading
     },
@@ -214,6 +219,10 @@ export const useAppStore = defineStore('app', {
       wsCache.set('dynamicRouter', dynamicRouter)
       this.dynamicRouter = dynamicRouter
     },
+    setFixedMenu(fixedMenu: boolean) {
+      wsCache.set('fixedMenu', fixedMenu)
+      this.fixedMenu = fixedMenu
+    },
     setPageLoading(pageLoading: boolean) {
       this.pageLoading = pageLoading
     },