Skip to content

在设置面板中,除了主题颜色的选择设置,还可以添加其他全局配置选项,如 tagsView 导航栏,Logo 的显示隐藏配置等。

Settings 的 Pinia 配置

在 src/stores/settings.ts 中添加要持久存储的全局配置项,这里是 tagsView 和 sidebarLogo,代码如下:

typescript
//src/stores/settings.ts
import variables from "@/style/variables.module.scss";
// 定义一个名为 "setting" 的 Vuex 存储,用于管理应用的设置
export const useSettingStore = defineStore(
  "setting",
  () => {
    // 如果选择的是同样的主题颜色,就不更改,节省
    const settings = reactive({
      theme: variables.theme, //当前选择的颜色
      originalTheme: "", //正在应用的颜色
      tagsView: true,
      sidebarLogo: true,
    });
    type ISetting = typeof settings;
    // 定义一个方法来更改设置
    const changeSetting = <T extends keyof ISetting>({
      key,
      value,
    }: {
      key: T;
      value: ISetting[T];
    }) => {
      settings[key] = value;
    };
    return { changeSetting, settings };
  },
  {
    persist: {
      storage: sessionStorage, // 使用 sessionStorage 作为持久化存储
      pick: ["settings.theme", "settings.tagsView", "settings.sidebarLogo"], // 仅持久化 theme、tagsView、sidebarLogo 三个设置
    },
  }
);

Settings 组件

在 src/layout/components/Settings/index.vue 中增加要添加的全局配置内容,代码如下:

html
//src/layout/components/Settings/index.vue
<template>
  <div class="drawer-item">
    <span>主题色</span>
    <theme-picker></theme-picker>
  </div>
  <div class="drawer-item">
    <span>是否展示TagsView</span>
    <el-switch v-model="isShowTagsView"></el-switch>
  </div>
  <div class="drawer-item">
    <span>是否展示Logo</span>
    <el-switch v-model="isShowLogo"></el-switch>
  </div>
</template>
<script lang="ts" setup>
  import { useSettingStore } from "@/stores/settings";
  const settingsStore = useSettingStore();
  const sidebarLogo = computed(() => settingsStore.settings.sidebarLogo);
  const tagsView = computed(() => settingsStore.settings.tagsView);
  const isShowTagsView = computed({
    get() {
      return tagsView.value;
    },
    set(val: boolean) {
      settingsStore.changeSetting({ key: "tagsView", value: val });
    },
  });
  const isShowLogo = computed({
    get() {
      return sidebarLogo.value;
    },
    set(val: boolean) {
      settingsStore.changeSetting({ key: "sidebarLogo", value: val });
    },
  });
</script>

添加页面控制

3.1 TagsView 配置

3.1.1 导出样式高度

在 src/style/variables.module.scss 中将需要参与高度计算的样式变量导出(navBarHeight、tagsViewHeight)并在 src/style/variables.module.scss.d.ts 中定义类型,代码如下:

scss
//src/style/variables.module.scss
$sideBarWidth: 210px;
$navBarHeight: 50px;
$tagsViewHeight: 34px;
// 导航颜色
$menuText: #bfcbd9;
// 导航激活的颜色
$menuActiveText: #409eff;
// 菜单背景色
$menuBg: #304156;
$theme: #409eff;
:export {
  menuText: $menuText;
  menuActiveText: $menuActiveText;
  menuBg: $menuBg;
  theme: $theme;
  navBarHeight: $navBarHeight;
  tagsViewHeight: $tagsViewHeight;
}
typescript
//src/style/variables.module.scss.d.ts
interface IVaraibles {
  menuText: string;
  menuActiveText: string;
  menuBg: string;
  theme: string;
  navBarHeight: string;
  tagsViewHeight: string;
}
export const varaibles: IVaraibles;
export default varaibles;

3.1.2 页面修改

在 src/layout/index.vue 中添加选项控制属性,并根据 tagsView 的显示隐藏状态,动态计算页面高度,代码如下:

html
//src/layout/index.vue
<template>
  <div class="app-wrapper">
    <div class="sidebar-container">
      <sidebar></sidebar>
    </div>
    <div class="main-container">
      <div class="header">
        <!--  上边包含收缩的导航条 -->
        <navbar @showSetting="openSetting"></navbar>
        <tags-view v-if="isShowTagsView"></tags-view>
      </div>
      <div class="app-main">
        <app-main></app-main>
      </div>
    </div>
    <right-panel v-model="setting" title="设置">
      <!-- 设置功能 -->
      <Settings></Settings>
    </right-panel>
  </div>
</template>
<script lang="ts" setup>
  import { useSettingStore } from "@/stores/settings";
  import variables from "@/style/variables.module.scss";
  const setting = ref(false);
  const openSetting = () => {
    setting.value = true;
  };
  const settingsStore = useSettingStore();
  const isShowTagsView = computed(() => settingsStore.settings.tagsView);
  const outerHeight = computed(() => {
    return (
      (isShowTagsView.value
        ? parseInt(variables.navBarHeight) + parseInt(variables.tagsViewHeight)
        : parseInt(variables.navBarHeight)) + "px"
    );
  });
</script>
<style lang="scss" scoped>
  .app-wrapper {
    @apply flex w-full h-full;
    .app-main {
      @apply overflow-hidden pos-relative;
      min-height: calc(100vh - v-bind(outerHeight));
    }
    .sidebar-container {
      // 跨组件设置样式
      @apply bg-[var(--menu-bg)];
      :deep(.sidebar-container-menu:not(.el-menu--collapse)) {
        @apply w-[var(--sidebar-width)];
      }
    }
    .main-container {
      @apply flex flex-col flex-1 overflow-hidden;
    }
  }
</style>

3.2 Logo 配置

3.2.1 Logo 组件开发

开发 Logo 组件,在 src/layout/components/Sidebar 下新建 logo.vue,代码如下:

html
//src/layout/components/Sidebar/logo.vue
<template>
  <div class="sidebar-logo-container" :class="{ collapse }">
    <transition name="logo-fade">
      <router-link to="/" :key="collapse ? 'a' : 'b'" class="sidebar-logo">
        <img :src="logo" alt="" />
        <h1 v-if="!collapse" class="sidebar-logo-title">Vue admin</h1>
      </router-link>
    </transition>
  </div>
</template>
<script lang="ts" setup>
  import logo from "@/assets/vue.svg";
  defineProps({
    collapse: {
      type: Boolean,
    },
  });
</script>
<style scoped lang="scss">
  .sidebar-logo {
    @apply w-full h-60px lead-60px flex items-center justify-center;
  }
  .sidebar-logo-title {
    @apply inline-block text-20px text-white mx-10px;
  }
  .logo-fade-enter-from,
  .logo-fade-leave-to {
    @apply opacity-0;
  }
  .logo-fade-enter-active {
    @apply transition-opacity duration-150;
  }
</style>

3.2.2 页面引入

在 src/layout/components/Sidebar/index.vue 中引入 Logo 组件,代码如下:

html
//src/layout/components/Sidebar/index.vue
<template>
  <div>
    <logo v-if="sidebarLogo" :collapse="sidebar.opened"></logo>
    <el-menu
      class="sidebar-container-menu"
      router
      :default-active="defaultActive"
      :background-color="varaibles.menuBg"
      :text-color="varaibles.menuText"
      :active-text-color="theme"
      :collapse="sidebar.opened"
    >
      <sidebar-item
        v-for="route in routes"
        :key="route.path"
        :item="route"
        :base-path="route.path"
      />
      <!-- 增加父路径,用于el-menu-item渲染的时候拼接 -->
    </el-menu>
  </div>
  <!-- :collapse="true" -->
</template>
<script lang="ts" setup>
  import { useAppStore } from "@/stores/app";
  import varaibles from "@/style/variables.module.scss";
  import { routes } from "@/router";
  import { useSettingStore } from "@/stores/settings";
  const route = useRoute();
  const { sidebar } = useAppStore();
  const defaultActive = computed(() => {
    // .....
    return route.path;
  });
  const settingsStore = useSettingStore();
  const theme = computed(() => settingsStore.settings.theme);
  const sidebarLogo = computed(() => settingsStore.settings.sidebarLogo);
</script>
<style scoped></style>

完成后,npm run dev 启动,页面效果如下:

图片

以上,就是其他全局设置项的全部内容。