(十八)Vue3-huohuo-admin 标签栏

298 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第7天

标签栏

本篇文章主要围绕项目的标签栏来讲,主要包括标签页、标签栏上的系统性功能来展开

标签栏设计

标签栏主要分为两大块,一块为标签页的展示与管理,一块为放置在标签栏上的系统性功能。

标签页与菜单是紧密联系的,我们可以通过标签页上的选项,动态地看到当前页的父子集菜单关系,并便捷地进行显示菜单的控制。

标签栏的开发

骨架搭建:

  • 标签显示模块:已打开的菜单页面以标签页的形式显示,分上下两栏显示
  • 标签控制模块:标签页的动画效果、跳转功能、编辑功能

通过标签页,我们可以快速定位当前页面所在的菜单目录,与菜单进行友好的联动。我们还能十分便捷地对标签页进行控制,如:

  • 打开标签页过多时,响应式变化、左右移动变化
  • 标签页的重新加载(全部重新加载、单个页面重新加载)
  • 关闭当前、左侧、其他、全部标签页

非标签功能开发

一般我们还会在标签栏上放置一些常用的全局系统性功能,如:

  • 搜索功能
  • 消息通知
  • 全屏与最大化
  • 语言切换
  • 用户头像及名称展示,用户的推出功能
  • 系统配置

全局搜索

类似Vue.js官网的搜索功能,可以进行全局的关键字搜索哦~

主要代码:

<script lang="ts" setup>
/** 菜单树形结构 */
const menusData = computed(() => {
  return deleteChildren(usePermissionStoreHook().menusTree);
});

/** 将菜单树形结构扁平化为一维数组,用于菜单查询 */
function flatTree(arr) {
  const res = [];
  function deep(arr) {
    arr.forEach((item) => {
      res.push(item);
      item.children && deep(item.children);
    });
  }
  deep(arr);
  return res;
}

/** 查询 */
function search() {
  const flatMenusData = flatTree(menusData.value);
  resultOptions.value = flatMenusData.filter(
    (menu) =>
      keyword.value &&
      transformI18n(menu.meta?.title)
        .toLocaleLowerCase()
        .includes(keyword.value.toLocaleLowerCase().trim())
  );
  if (resultOptions.value?.length > 0) {
    activePath.value = resultOptions.value[0].path;
  } else {
    activePath.value = "";
  }
}

function handleClose() {
  show.value = false;
  /** 延时处理防止用户看到某些操作 */
  setTimeout(() => {
    resultOptions.value = [];
    keyword.value = "";
  }, 200);
}
</script>

<template>
  <el-dialog top="5vh" v-model="show" :before-close="handleClose">
    <el-input
      ref="inputRef"
      v-model="keyword"
      clearable
      placeholder="请输入关键词搜索"
      @input="handleSearch"
    >
      <template #prefix>
        <span class="el-input__icon">
          <IconifyIconOffline icon="search" />
        </span>
      </template>
    </el-input>
    <div class="search-result-container">
      <el-empty v-if="resultOptions.length === 0" description="暂无搜索结果" />
      <SearchResult
        v-else
        v-model:value="activePath"
        :options="resultOptions"
        @click="handleEnter"
      />
    </div>
    <template #footer>
      <SearchFooter />
    </template>
  </el-dialog>
</template>

消息通知

如果你的项目需要又消息推送功能,那么这个模块就非常合适了。能够方便地进行消息通知管理。

<el-dropdown ref="dropdownDom" trigger="click" placement="bottom-end">
  <span class="dropdown-badge">
    <el-badge :value="noticesNum" :max="99">
      <span class="header-notice-icon">
        <IconifyIconOffline icon="bell" />
      </span>
    </el-badge>
  </span>
  <template #dropdown>
    <el-dropdown-menu>
      <Tabs
        centered
        class="dropdown-tabs"
        v-model:activeName="activeName"
        @tabClick="tabClick"
      >
        <template v-for="item in notices" :key="item.key">
          <TabPane :tab="`${item.name}(${item.list.length})`">
            <el-scrollbar max-height="330px">
              <div class="noticeList-container">
                <NoticeList :list="item.list" />
              </div>
            </el-scrollbar>
          </TabPane>
        </template>
      </Tabs>
    </el-dropdown-menu>
  </template>
</el-dropdown>

全屏与最大化

这里主要使用了vueuse中封装的全屏与放大工具函数useFullscreen

<script setup lang="ts">
import { useFullscreen } from "@vueuse/core";

const { isFullscreen, toggle } = useFullscreen();
</script>

<template>
  <div class="screen-full" @click="toggle">
    <FontIcon
      :title="
        isFullscreen ? t('buttons.hsexitfullscreen') : t('buttons.hsfullscreen')
      "
      :icon="isFullscreen ? 'team-iconexit-fullscreen' : 'team-iconfullscreen'"
    />
  </div>
</template>

语言切换

<!-- 国际化 -->
<el-dropdown id="header-translation" trigger="click">
  <globalization />
  <template #dropdown>
    <el-dropdown-menu class="translation">
      <el-dropdown-item
        :style="getDropdownItemStyle(locale, 'zh')"
        @click="translationCh"
      >
        <span class="check-zh" v-show="locale === 'zh'">
          <IconifyIconOffline icon="check" />
        </span>
        简体中文
      </el-dropdown-item>
      <el-dropdown-item
        :style="getDropdownItemStyle(locale, 'en')"
        @click="translationEn"
      >
        <span class="check-en" v-show="locale === 'en'">
          <IconifyIconOffline icon="check" />
        </span>
        English
      </el-dropdown-item>
    </el-dropdown-menu>
  </template>
</el-dropdown>

用户行为

目前只做了退出登录功能、其实还可以将个人中心放在此处

<!-- 退出登录 -->
<el-dropdown trigger="click">
  <span class="el-dropdown-link">
    <img v-if="avatars" :src="avatars" :style="avatarsStyle" />
    <p v-if="username">{{ username }}</p>
  </span>
  <template #dropdown>
    <el-dropdown-menu class="logout">
      <el-dropdown-item @click="logout">
        <IconifyIconOffline icon="logout-circle-r-line" style="margin: 5px" />
        {{ t("buttons.hsLoginOut") }}
      </el-dropdown-item>
    </el-dropdown-menu>
  </template>
</el-dropdown>

项目配置

项目的配置功能主要包括:

  • 正常主题与暗黑主题
  • 导航栏模式(三种)
  • 主题色(9 种)
  • 灰色模式
  • 色弱模式
  • 是否隐藏标签栏的标签页
  • 侧边栏 Logo 是否显示
  • 标签页是否持久化
  • 标签页的风格
  • 清空缓存退至登录页按钮