feat: add useLayoutMode
This commit is contained in:
parent
0a4d896965
commit
02dca40083
@ -1,11 +1,12 @@
|
|||||||
import { getConfigLayout } from "@/utils/cache/local-storage"
|
import { getConfigLayout } from "@/utils/cache/local-storage"
|
||||||
|
import { LayoutModeEnum } from "@/constants/app-key"
|
||||||
|
|
||||||
/** 项目配置类型 */
|
/** 项目配置类型 */
|
||||||
export interface LayoutSettings {
|
export interface LayoutSettings {
|
||||||
/** 是否显示 Settings Panel */
|
/** 是否显示 Settings Panel */
|
||||||
showSettings: boolean
|
showSettings: boolean
|
||||||
/** 布局模式 */
|
/** 布局模式 */
|
||||||
layoutMode: "left" | "top" | "left-top"
|
layoutMode: LayoutModeEnum
|
||||||
/** 是否显示标签栏 */
|
/** 是否显示标签栏 */
|
||||||
showTagsView: boolean
|
showTagsView: boolean
|
||||||
/** 是否显示 Logo */
|
/** 是否显示 Logo */
|
||||||
@ -34,7 +35,7 @@ export interface LayoutSettings {
|
|||||||
|
|
||||||
/** 默认配置 */
|
/** 默认配置 */
|
||||||
const defaultSettings: LayoutSettings = {
|
const defaultSettings: LayoutSettings = {
|
||||||
layoutMode: "left",
|
layoutMode: LayoutModeEnum.Left,
|
||||||
showSettings: true,
|
showSettings: true,
|
||||||
showTagsView: true,
|
showTagsView: true,
|
||||||
fixedHeader: true,
|
fixedHeader: true,
|
||||||
|
@ -4,6 +4,13 @@ export enum DeviceEnum {
|
|||||||
Desktop
|
Desktop
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** 布局模式 */
|
||||||
|
export enum LayoutModeEnum {
|
||||||
|
Left = "left",
|
||||||
|
Top = "top",
|
||||||
|
LeftTop = "left-top"
|
||||||
|
}
|
||||||
|
|
||||||
/** 侧边栏打开状态常量 */
|
/** 侧边栏打开状态常量 */
|
||||||
export const SIDEBAR_OPENED = "opened"
|
export const SIDEBAR_OPENED = "opened"
|
||||||
/** 侧边栏关闭状态常量 */
|
/** 侧边栏关闭状态常量 */
|
||||||
|
16
src/hooks/useLayoutMode.ts
Normal file
16
src/hooks/useLayoutMode.ts
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
import { computed } from "vue"
|
||||||
|
import { useSettingsStore } from "@/store/modules/settings"
|
||||||
|
import { LayoutModeEnum } from "@/constants/app-key"
|
||||||
|
|
||||||
|
const settingsStore = useSettingsStore()
|
||||||
|
const isLeft = computed(() => settingsStore.layoutMode === LayoutModeEnum.Left)
|
||||||
|
const isTop = computed(() => settingsStore.layoutMode === LayoutModeEnum.Top)
|
||||||
|
const isLeftTop = computed(() => settingsStore.layoutMode === LayoutModeEnum.LeftTop)
|
||||||
|
|
||||||
|
const setLayoutMode = (mode: LayoutModeEnum) => {
|
||||||
|
settingsStore.layoutMode = mode
|
||||||
|
}
|
||||||
|
|
||||||
|
export function useLayoutMode() {
|
||||||
|
return { isLeft, isTop, isLeftTop, setLayoutMode }
|
||||||
|
}
|
@ -1,6 +1,5 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { storeToRefs } from "pinia"
|
import { useLayoutMode } from "@/hooks/useLayoutMode"
|
||||||
import { useSettingsStore } from "@/store/modules/settings"
|
|
||||||
import logo from "@/assets/layouts/logo.png?url"
|
import logo from "@/assets/layouts/logo.png?url"
|
||||||
import logoText1 from "@/assets/layouts/logo-text-1.png?url"
|
import logoText1 from "@/assets/layouts/logo-text-1.png?url"
|
||||||
import logoText2 from "@/assets/layouts/logo-text-2.png?url"
|
import logoText2 from "@/assets/layouts/logo-text-2.png?url"
|
||||||
@ -13,18 +12,17 @@ const props = withDefaults(defineProps<Props>(), {
|
|||||||
collapse: true
|
collapse: true
|
||||||
})
|
})
|
||||||
|
|
||||||
const settingsStore = useSettingsStore()
|
const { isLeft, isTop } = useLayoutMode()
|
||||||
const { layoutMode } = storeToRefs(settingsStore)
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="layout-logo-container" :class="{ collapse: props.collapse, 'layout-mode-top': layoutMode === 'top' }">
|
<div class="layout-logo-container" :class="{ collapse: props.collapse, 'layout-mode-top': isTop }">
|
||||||
<transition name="layout-logo-fade">
|
<transition name="layout-logo-fade">
|
||||||
<router-link v-if="props.collapse" key="collapse" to="/">
|
<router-link v-if="props.collapse" key="collapse" to="/">
|
||||||
<img :src="logo" class="layout-logo" />
|
<img :src="logo" class="layout-logo" />
|
||||||
</router-link>
|
</router-link>
|
||||||
<router-link v-else key="expand" to="/">
|
<router-link v-else key="expand" to="/">
|
||||||
<img :src="layoutMode !== 'left' ? logoText2 : logoText1" class="layout-logo-text" />
|
<img :src="!isLeft ? logoText2 : logoText1" class="layout-logo-text" />
|
||||||
</router-link>
|
</router-link>
|
||||||
</transition>
|
</transition>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { computed } from "vue"
|
|
||||||
import { useRouter } from "vue-router"
|
import { useRouter } from "vue-router"
|
||||||
import { storeToRefs } from "pinia"
|
import { storeToRefs } from "pinia"
|
||||||
import { useAppStore } from "@/store/modules/app"
|
import { useAppStore } from "@/store/modules/app"
|
||||||
@ -14,15 +13,15 @@ import ThemeSwitch from "@/components/ThemeSwitch/index.vue"
|
|||||||
import Screenfull from "@/components/Screenfull/index.vue"
|
import Screenfull from "@/components/Screenfull/index.vue"
|
||||||
import SearchMenu from "@/components/SearchMenu/index.vue"
|
import SearchMenu from "@/components/SearchMenu/index.vue"
|
||||||
import { useDevice } from "@/hooks/useDevice"
|
import { useDevice } from "@/hooks/useDevice"
|
||||||
|
import { useLayoutMode } from "@/hooks/useLayoutMode"
|
||||||
|
|
||||||
const { isMobile } = useDevice()
|
const { isMobile } = useDevice()
|
||||||
|
const { isTop } = useLayoutMode()
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const appStore = useAppStore()
|
const appStore = useAppStore()
|
||||||
const userStore = useUserStore()
|
const userStore = useUserStore()
|
||||||
const settingsStore = useSettingsStore()
|
const settingsStore = useSettingsStore()
|
||||||
const { layoutMode, showNotify, showThemeSwitch, showScreenfull, showSearchMenu } = storeToRefs(settingsStore)
|
const { showNotify, showThemeSwitch, showScreenfull, showSearchMenu } = storeToRefs(settingsStore)
|
||||||
|
|
||||||
const isTop = computed(() => layoutMode.value === "top")
|
|
||||||
|
|
||||||
/** 切换侧边栏 */
|
/** 切换侧边栏 */
|
||||||
const toggleSidebar = () => {
|
const toggleSidebar = () => {
|
||||||
|
@ -1,20 +1,14 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { computed } from "vue"
|
import { useLayoutMode } from "@/hooks/useLayoutMode"
|
||||||
import { storeToRefs } from "pinia"
|
import { LayoutModeEnum } from "@/constants/app-key"
|
||||||
import { useSettingsStore } from "@/store/modules/settings"
|
|
||||||
|
|
||||||
const settingsStore = useSettingsStore()
|
const { isLeft, isTop, isLeftTop, setLayoutMode } = useLayoutMode()
|
||||||
const { layoutMode } = storeToRefs(settingsStore)
|
|
||||||
|
|
||||||
const isLeft = computed(() => layoutMode.value === "left")
|
|
||||||
const isTop = computed(() => layoutMode.value === "top")
|
|
||||||
const isLeftTop = computed(() => layoutMode.value === "left-top")
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="select-layout-mode">
|
<div class="select-layout-mode">
|
||||||
<el-tooltip content="左侧模式">
|
<el-tooltip content="左侧模式">
|
||||||
<el-container class="layout-mode left" :class="{ active: isLeft }" @click="layoutMode = 'left'">
|
<el-container class="layout-mode left" :class="{ active: isLeft }" @click="setLayoutMode(LayoutModeEnum.Left)">
|
||||||
<el-aside />
|
<el-aside />
|
||||||
<el-container>
|
<el-container>
|
||||||
<el-header />
|
<el-header />
|
||||||
@ -23,13 +17,17 @@ const isLeftTop = computed(() => layoutMode.value === "left-top")
|
|||||||
</el-container>
|
</el-container>
|
||||||
</el-tooltip>
|
</el-tooltip>
|
||||||
<el-tooltip content="顶部模式">
|
<el-tooltip content="顶部模式">
|
||||||
<el-container class="layout-mode top" :class="{ active: isTop }" @click="layoutMode = 'top'">
|
<el-container class="layout-mode top" :class="{ active: isTop }" @click="setLayoutMode(LayoutModeEnum.Top)">
|
||||||
<el-header />
|
<el-header />
|
||||||
<el-main />
|
<el-main />
|
||||||
</el-container>
|
</el-container>
|
||||||
</el-tooltip>
|
</el-tooltip>
|
||||||
<el-tooltip content="混合模式">
|
<el-tooltip content="混合模式">
|
||||||
<el-container class="layout-mode left-top" :class="{ active: isLeftTop }" @click="layoutMode = 'left-top'">
|
<el-container
|
||||||
|
class="layout-mode left-top"
|
||||||
|
:class="{ active: isLeftTop }"
|
||||||
|
@click="setLayoutMode(LayoutModeEnum.LeftTop)"
|
||||||
|
>
|
||||||
<el-header />
|
<el-header />
|
||||||
<el-container>
|
<el-container>
|
||||||
<el-aside />
|
<el-aside />
|
||||||
|
@ -2,15 +2,16 @@
|
|||||||
import { watchEffect } from "vue"
|
import { watchEffect } from "vue"
|
||||||
import { storeToRefs } from "pinia"
|
import { storeToRefs } from "pinia"
|
||||||
import { useSettingsStore } from "@/store/modules/settings"
|
import { useSettingsStore } from "@/store/modules/settings"
|
||||||
|
import { useLayoutMode } from "@/hooks/useLayoutMode"
|
||||||
import { resetConfigLayout } from "@/utils"
|
import { resetConfigLayout } from "@/utils"
|
||||||
import SelectLayoutMode from "./SelectLayoutMode.vue"
|
import SelectLayoutMode from "./SelectLayoutMode.vue"
|
||||||
import { Refresh } from "@element-plus/icons-vue"
|
import { Refresh } from "@element-plus/icons-vue"
|
||||||
|
|
||||||
|
const { isLeft } = useLayoutMode()
|
||||||
const settingsStore = useSettingsStore()
|
const settingsStore = useSettingsStore()
|
||||||
|
|
||||||
/** 使用 storeToRefs 将提取的属性保持其响应性 */
|
/** 使用 storeToRefs 将提取的属性保持其响应性 */
|
||||||
const {
|
const {
|
||||||
layoutMode,
|
|
||||||
showTagsView,
|
showTagsView,
|
||||||
showLogo,
|
showLogo,
|
||||||
fixedHeader,
|
fixedHeader,
|
||||||
@ -43,7 +44,7 @@ const switchSettings = {
|
|||||||
|
|
||||||
/** 非左侧模式时,Header 都是 fixed 布局 */
|
/** 非左侧模式时,Header 都是 fixed 布局 */
|
||||||
watchEffect(() => {
|
watchEffect(() => {
|
||||||
layoutMode.value !== "left" && (fixedHeader.value = true)
|
isLeft.value && (fixedHeader.value = true)
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@ -55,7 +56,7 @@ watchEffect(() => {
|
|||||||
<h4>功能配置</h4>
|
<h4>功能配置</h4>
|
||||||
<div class="setting-item" v-for="(settingValue, settingName, index) in switchSettings" :key="index">
|
<div class="setting-item" v-for="(settingValue, settingName, index) in switchSettings" :key="index">
|
||||||
<span class="setting-name">{{ settingName }}</span>
|
<span class="setting-name">{{ settingName }}</span>
|
||||||
<el-switch v-model="settingValue.value" :disabled="layoutMode !== 'left' && settingName === '固定 Header'" />
|
<el-switch v-model="settingValue.value" :disabled="!isLeft && settingName === '固定 Header'" />
|
||||||
</div>
|
</div>
|
||||||
<el-button type="danger" :icon="Refresh" @click="resetConfigLayout">重 置</el-button>
|
<el-button type="danger" :icon="Refresh" @click="resetConfigLayout">重 置</el-button>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { computed } from "vue"
|
import { computed } from "vue"
|
||||||
import { useRoute } from "vue-router"
|
import { useRoute } from "vue-router"
|
||||||
import { storeToRefs } from "pinia"
|
|
||||||
import { useAppStore } from "@/store/modules/app"
|
import { useAppStore } from "@/store/modules/app"
|
||||||
import { usePermissionStore } from "@/store/modules/permission"
|
import { usePermissionStore } from "@/store/modules/permission"
|
||||||
import { useSettingsStore } from "@/store/modules/settings"
|
import { useSettingsStore } from "@/store/modules/settings"
|
||||||
import SidebarItem from "./SidebarItem.vue"
|
import SidebarItem from "./SidebarItem.vue"
|
||||||
import Logo from "../Logo/index.vue"
|
import Logo from "../Logo/index.vue"
|
||||||
import { useDevice } from "@/hooks/useDevice"
|
import { useDevice } from "@/hooks/useDevice"
|
||||||
|
import { useLayoutMode } from "@/hooks/useLayoutMode"
|
||||||
import { getCssVariableValue } from "@/utils"
|
import { getCssVariableValue } from "@/utils"
|
||||||
|
|
||||||
const v3SidebarMenuBgColor = getCssVariableValue("--v3-sidebar-menu-bg-color")
|
const v3SidebarMenuBgColor = getCssVariableValue("--v3-sidebar-menu-bg-color")
|
||||||
@ -15,11 +15,11 @@ const v3SidebarMenuTextColor = getCssVariableValue("--v3-sidebar-menu-text-color
|
|||||||
const v3SidebarMenuActiveTextColor = getCssVariableValue("--v3-sidebar-menu-active-text-color")
|
const v3SidebarMenuActiveTextColor = getCssVariableValue("--v3-sidebar-menu-active-text-color")
|
||||||
|
|
||||||
const { isMobile } = useDevice()
|
const { isMobile } = useDevice()
|
||||||
|
const { isLeft, isTop } = useLayoutMode()
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
const appStore = useAppStore()
|
const appStore = useAppStore()
|
||||||
const permissionStore = usePermissionStore()
|
const permissionStore = usePermissionStore()
|
||||||
const settingsStore = useSettingsStore()
|
const settingsStore = useSettingsStore()
|
||||||
const { layoutMode, showLogo } = storeToRefs(settingsStore)
|
|
||||||
|
|
||||||
const activeMenu = computed(() => {
|
const activeMenu = computed(() => {
|
||||||
const {
|
const {
|
||||||
@ -30,24 +30,22 @@ const activeMenu = computed(() => {
|
|||||||
})
|
})
|
||||||
const noHiddenRoutes = computed(() => permissionStore.routes.filter((item) => !item.meta?.hidden))
|
const noHiddenRoutes = computed(() => permissionStore.routes.filter((item) => !item.meta?.hidden))
|
||||||
const isCollapse = computed(() => !appStore.sidebar.opened)
|
const isCollapse = computed(() => !appStore.sidebar.opened)
|
||||||
const isLeft = computed(() => layoutMode.value === "left")
|
const isLogo = computed(() => isLeft.value && settingsStore.showLogo)
|
||||||
const isTop = computed(() => layoutMode.value === "top")
|
|
||||||
const isLogo = computed(() => isLeft.value && showLogo.value)
|
|
||||||
const backgroundColor = computed(() => (isLeft.value ? v3SidebarMenuBgColor : undefined))
|
const backgroundColor = computed(() => (isLeft.value ? v3SidebarMenuBgColor : undefined))
|
||||||
const textColor = computed(() => (isLeft.value ? v3SidebarMenuTextColor : undefined))
|
const textColor = computed(() => (isLeft.value ? v3SidebarMenuTextColor : undefined))
|
||||||
const activeTextColor = computed(() => (isLeft.value ? v3SidebarMenuActiveTextColor : undefined))
|
const activeTextColor = computed(() => (isLeft.value ? v3SidebarMenuActiveTextColor : undefined))
|
||||||
const sidebarMenuItemHeight = computed(() => {
|
const sidebarMenuItemHeight = computed(() => {
|
||||||
return layoutMode.value !== "top" ? "var(--v3-sidebar-menu-item-height)" : "var(--v3-navigationbar-height)"
|
return !isTop.value ? "var(--v3-sidebar-menu-item-height)" : "var(--v3-navigationbar-height)"
|
||||||
})
|
})
|
||||||
const sidebarMenuHoverBgColor = computed(() => {
|
const sidebarMenuHoverBgColor = computed(() => {
|
||||||
return layoutMode.value !== "top" ? "var(--v3-sidebar-menu-hover-bg-color)" : "transparent"
|
return !isTop.value ? "var(--v3-sidebar-menu-hover-bg-color)" : "transparent"
|
||||||
})
|
})
|
||||||
const tipLineWidth = computed(() => {
|
const tipLineWidth = computed(() => {
|
||||||
return layoutMode.value !== "top" ? "2px" : "0px"
|
return !isTop.value ? "2px" : "0px"
|
||||||
})
|
})
|
||||||
// 当为顶部模式时隐藏垂直滚动条
|
// 当为顶部模式时隐藏垂直滚动条
|
||||||
const hiddenScrollbarVerticalBar = computed(() => {
|
const hiddenScrollbarVerticalBar = computed(() => {
|
||||||
return layoutMode.value === "top" ? "none" : "block"
|
return isTop.value ? "none" : "block"
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@ -5,6 +5,7 @@ import { useSettingsStore } from "@/store/modules/settings"
|
|||||||
import useResize from "./hooks/useResize"
|
import useResize from "./hooks/useResize"
|
||||||
import { useWatermark } from "@/hooks/useWatermark"
|
import { useWatermark } from "@/hooks/useWatermark"
|
||||||
import { useDevice } from "@/hooks/useDevice"
|
import { useDevice } from "@/hooks/useDevice"
|
||||||
|
import { useLayoutMode } from "@/hooks/useLayoutMode"
|
||||||
import LeftMode from "./LeftMode.vue"
|
import LeftMode from "./LeftMode.vue"
|
||||||
import TopMode from "./TopMode.vue"
|
import TopMode from "./TopMode.vue"
|
||||||
import LeftTopMode from "./LeftTopMode.vue"
|
import LeftTopMode from "./LeftTopMode.vue"
|
||||||
@ -16,9 +17,9 @@ useResize()
|
|||||||
|
|
||||||
const { setWatermark, clearWatermark } = useWatermark()
|
const { setWatermark, clearWatermark } = useWatermark()
|
||||||
const { isMobile } = useDevice()
|
const { isMobile } = useDevice()
|
||||||
|
const { isLeft, isTop, isLeftTop } = useLayoutMode()
|
||||||
const settingsStore = useSettingsStore()
|
const settingsStore = useSettingsStore()
|
||||||
const { showSettings, layoutMode, showTagsView, showWatermark, showGreyMode, showColorWeakness } =
|
const { showSettings, showTagsView, showWatermark, showGreyMode, showColorWeakness } = storeToRefs(settingsStore)
|
||||||
storeToRefs(settingsStore)
|
|
||||||
|
|
||||||
const classes = computed(() => {
|
const classes = computed(() => {
|
||||||
return {
|
return {
|
||||||
@ -46,11 +47,11 @@ watchEffect(() => {
|
|||||||
<template>
|
<template>
|
||||||
<div :class="classes">
|
<div :class="classes">
|
||||||
<!-- 左侧模式 -->
|
<!-- 左侧模式 -->
|
||||||
<LeftMode v-if="layoutMode === 'left' || isMobile" />
|
<LeftMode v-if="isLeft || isMobile" />
|
||||||
<!-- 顶部模式 -->
|
<!-- 顶部模式 -->
|
||||||
<TopMode v-else-if="layoutMode === 'top'" />
|
<TopMode v-else-if="isTop" />
|
||||||
<!-- 混合模式 -->
|
<!-- 混合模式 -->
|
||||||
<LeftTopMode v-else-if="layoutMode === 'left-top'" />
|
<LeftTopMode v-else-if="isLeftTop" />
|
||||||
<!-- 右侧设置面板 -->
|
<!-- 右侧设置面板 -->
|
||||||
<RightPanel v-if="showSettings">
|
<RightPanel v-if="showSettings">
|
||||||
<Settings />
|
<Settings />
|
||||||
|
Loading…
x
Reference in New Issue
Block a user