ant-design-vue三级菜单

2023-12-19

<template>
  <div class="MySider">
    <div class="logo" @click="handleCollapsed" :class="{ collapsed: collapsed }">
      <img :src="collapsed ? logo_c : logo" />
    </div>
    <a-menu theme="light" v-model:openKeys="openKeys" v-model:selectedKeys="selectedKeys" mode="inline"
      :inlineCollapsed="collapsed">
      <template v-for="item of showList" :key="item.path">
        <a-menu-item :key="item.path" v-if="item.meta.is_leaf" @click="routerChange(item.path)">
          <i class="icon" :class="item.meta.icon" />
          <span :class="{ 'collapsed-title': collapsed }">{{
            item.meta.title_zh
          }}</span>
        </a-menu-item>
        <a-sub-menu :key="'sub-menu' + item.path" v-else>
          <template #title>
            <i class="icon" :class="item.meta.icon" />
            <span v-show="!collapsed">{{ item.meta.title_zh }}</span>
          </template>
          <template v-for="i of item.children">
            <a-sub-menu :key="'sub-menu' + i.path" v-if="i.children && i.children.length > 0">
              <template #title>
                <span>{{ i.meta.title_zh }}</span>
              </template>

              <!-- 循环显示三级菜单项 -->
              <template v-for="j of i.children">
                <a-menu-item :key="'sub-menu' + i.path + '/' + j.path" @click="routerChange(i.path + '/' + j.path)"
                  v-if="showMenuItem(j)">
                  <span>{{ j.meta.title_zh }}</span>
                </a-menu-item>
              </template>
            </a-sub-menu>

            <!-- 如果没有三级菜单,则显示二级菜单项 -->
            <a-menu-item :key="'sub-menu' + item.path + '/' + i.path" @click="routerChange(item.path + '/' + i.path)"
              v-else-if="showMenuItem(i)">
              <span>{{ i.meta.title_zh }}</span>
            </a-menu-item>
          </template>
        </a-sub-menu>
      </template>
    </a-menu>
  </div>
</template>
<!-- item.children.length === 1 || -->
<script setup>
import { storeToRefs } from "pinia";
import { ref, watch, computed, getCurrentInstance } from "vue";
import { useRoute, useRouter } from "vue-router";

import logo from "@/assets/images/logo.png";
import logo_c from "@/assets/images/logo-c.png";

import Core from "@/core";
import routes from "@/router/routes";
import useStore from "@/core/store/index.js";

const route = useRoute();
const router = useRouter();
const { permission } = useStore();
const { permissionObj, showList } = storeToRefs(permission);
const { getRouterArray } = permission;
const emits = defineEmits(["collapsed"]);

const userType = Core.Data.getUserType();
// 获取展示用列表
getShowList();
function getShowList() {
  getRouterArray();
}

const openKeys = ref([]);
const selectedKeys = ref([route.path]);
// 获取当前展开
for (const item of routes) {
  if (item.hidden || item.children.length === 1) {
    continue;
  }
  for (const i of item.children) {
    if (item.path + "/" + i.path === route.path) {
      openKeys.value = [item.path];
      break;
    }
  }
}
// 获取当前高亮
watch(
  () => route,
  (n) => {
    console.log("watch route n:", n);
    if (n.matched && n.matched.length >= 2) {
      let firstItem = n.matched[0];
      let lastItem = n.matched[n.matched.length - 1];
      if (firstItem?.meta?.is_leaf) {
        selectedKeys.value = [firstItem.path];
      } else {
        selectedKeys.value = [lastItem.path];
      }
    } else {
      selectedKeys.value = [n.path];
    }
    // console.log('selectedKeys.value:', selectedKeys.value)
  },
  { deep: true, immediate: true }
);

// 路由跳转
function routerChange(path) {
  console.log("routerChange path:", path);
  router.push(path);
}

// 二级菜单的展示控制
function showMenuItem(i) {
  const auth = i.meta ? i.meta.auth || [] : [];
  const roles = i.meta ? i.meta.roles : "";
  return (
    Core.Util.auth(...auth) && !i.hidden && (!roles || roles.includes(userType))
  );
}

// 展开收缩
const collapsed = ref(false);
function handleCollapsed() {
  collapsed.value = !collapsed.value;
  emits("collapsed", collapsed.value);
  if (collapsed.value) {
    window.document.getElementById("showLayoutSider").style.left = "80px";
  } else {
    window.document.getElementById("showLayoutSider").style.left = "180px";
  }
}
</script>

<style lang='scss' scoped>
.MySider {
  height: 100vh;

  .logo {
    width: 100%;
    height: 50px;
    display: flex;
    align-items: center;
    overflow: hidden;

    // border-bottom: 1px solid #e6eaee;
    img {
      max-width: calc(100% - 40px);
      margin-left: 20px;
    }

    &.collapsed {
      justify-content: center;

      img {
        max-width: calc(80%);
        max-height: 70%;
        margin-left: 0;
      }
    }
  }

  i.icon {
    margin-right: 14px;
    font-size: 14px;
    transition: color 0.3s;
  }

  .collapsed-title {
    padding-left: 50px;
  }

  .ant-menu.ant-menu-inline {
    height: calc(100% - 50px);
    overflow-y: auto;
    overflow-x: hidden;
    border-right: 0;

    .ant-menu-item {
      height: 40px;
      line-height: 40px;
      margin: 0;
    }

    .ant-menu-submenu-title {
      height: 40px;
      line-height: 40px;
      margin: 0;
    }

    .ant-menu-submenu {
      .ant-menu-item {
        margin-bottom: 0;
      }
    }

    @include scrollbar(2px);
  }

  .ant-menu-inline .ant-menu-item,
  .ant-menu-inline .ant-menu-submenu-title {
    width: 100%;
    font-size: 13px !important;
    color: #334d6e;

    .icon {
      color: #c2cfe0;
    }
  }

  .ant-menu-inline-collapsed {
    border: 0;
  }

  li.ant-menu-item {
    background-color: transparent !important;
  }

  ul.ant-menu-sub {
    background-color: transparent;
  }

  .ant-menu-item-selected::after {
    display: none;
  }

  .ant-menu-item-selected .ant-menu-title-content,
  .ant-menu-item:hover .ant-menu-title-content {
    color: $primary;

    .icon {
      color: $primary;
    }
  }

  .ant-menu-submenu.ant-menu-submenu-selected .ant-menu-submenu-title,
  .ant-menu-submenu .ant-menu-submenu-title:hover {
    color: $primary;

    .icon {
      color: $primary;
    }

    .ant-menu-submenu-arrow {
      color: $primary;
    }
  }

  .ant-menu-submenu .ant-menu-item .ant-menu-title-content {
    padding-left: 4px;
  }
}

.ant-menu-inline-collapsed-tooltip {
  font-size: 13px;

  i.icon {
    display: none;
  }
}

.ant-menu-vertical.ant-menu-sub>.ant-menu-item {
  width: 100%;
  font-size: 13px !important;
  margin: 4px 0 !important;
  height: 32px;
  line-height: 32px;
}
</style>

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

ant-design-vue三级菜单 的相关文章

  • 有没有办法动态更改 jqGrid 的单元格值?

    这个问题可能已经被问过很多次了 但我想知道是否可以动态更改 jqgrid 的单元格值 我基本上有一个网格 它通过 JSON 字符串加载数据 在特定列的某些行上 该值可能为 null 因此 预先知道哪个行 ID 是一个问题 然后能够将 nul
  • JAVASCRIPT - 为什么这个对象没有改变?

    function myFunc theObject theObject make Ford model Focus year 2006 var mycar make Honda model Accord year 1998 var x my
  • 在上传之前预览图像 VUEjs [重复]

    这个问题在这里已经有答案了 我知道这个问题已经被问过 但我不知道如何在vuejs中使用代码 我尝试了很多但没有任何结果 我还添加了我的代码 有人可以帮帮我吗 这是我的代码 谢谢 html
  • 更新存储在 chrome 扩展本地存储中的对象

    我正在开发一个 chrome 扩展 我将存储服务器发送的对象 例如 我将收到 命令 id 1 类型 A 大小 B 优先级 C 如果我有一个数据库 我会将其作为表中的一行插入commands 使用 chrome storage 我将这些对象的
  • 我可以在 GWT 中使用第三方 Javascript 库吗

    例如穆工具 用 js 编码对我来说很舒服 但显然不适合所有人 你当然可以 最好的事情就是给自己写一些好看的JavaScript 覆盖类型 http code google com webtoolkit doc latest DevGuide
  • Apache Thrift Java-Javascript 通信

    我正在编写一个基于 Apache Thrift 的 Java 服务器 它将从 Javascript 客户端接收数据 我已经完成了 Java 服务器 但问题是我可以获得 Javascript 客户端的工作示例 我无法找到一个好的示例 构建文档
  • EmberJS:对象作为查询参数来刷新模型

    我遵循了查询参数指南 http guides emberjs com v1 11 0 routing query params http guides emberjs com v1 11 0 routing query params 而且效
  • .points 不透明度/大小在三个.js 内

    我回来回答有关 points 的第二个问题 这次想知道如何将不透明度从 0 更改为 1 然后又回到距发射器的特定像素距离内 var particleCount 14 particles new THREE Geometry pMateria
  • jquery 中的函数返回未定义[重复]

    这个问题在这里已经有答案了 我在 jquery 中调用的函数返回未定义 我检查了该函数 当我对其进行调试时 它返回正确的数据 function addToPlaylist component type add to pl value pl
  • jQuery:将文本区域滚动到给定位置

    我有一个包含很多文本的文本区域
  • 可以禁用幻灯片的触摸模拟但不能禁用滚动条(危险的滑动器)吗?

    我的页面上有一个危险的滑动器 它成功地模拟了幻灯片和随附滚动条上的触摸事件 允许单击鼠标并移动以向左或向右滑动幻灯片 这很好 但我现在在滑动器内的幻灯片上调用了可拖动 这意味着我需要停止此触摸模拟 拖动幻灯片并同时移动它们会引起混乱 但仅限
  • ES6 模块范围

    我有代码 lib js var a a export var b b main js console log a a variable is not available in a global scope import b from lib
  • 如何从 html 页面 [javascript] 调用 Web 服务方法而不刷新页面

    我有一个webservice这将返回一个值 我的要求是 我需要调用它webservice从一个index html页面 该页面有一个 html 提交按钮 在该按钮上单击我正在呼叫JavaScript 从那里我想调用网络方法 我怎样才能做到这
  • 如何从 CSS 选择器中提取类名?

    故事 我目前正在构建一个 ESLint 规则 以警告在 CSS 选择器定位器中使用引导布局导向和角度技术类 目前我在字符串方法中使用简单的子字符串 for var i 0 i lt prohibitedClasses length i if
  • 了解 Document.createElement()

    我在用着GWT及其底层DOM能力 我基本上想要实现的是 Have a div包含一些文本的元素 其中一些文本将被包围span元素 span 元素可相互拖动并提供上下文菜单 New span元素可以由最终用户动态创建 它可能是这样的 在应用程
  • Firebase + Node.js:错误:找不到 XMLHttpRequest 兼容性库

    Firebase Node js On iOS 安装的 Node js npm 安装 firebase save 节点测试 js 其中 test js 是一个非常简单的连接到 Firebase 的脚本 var firebase requir
  • Google 地图 API - 地图未显示 - 没有错误

    我正在尝试将地图从 Google API 加载到 div 中 但是 地图未加载 并且没有输出任何错误 这是代码 google maps var geocoder map function codeAddress address geocod
  • 如何跨多个文件跨越 javascript 命名空间?

    我永远忽略了javascript 几年前我开始使用 jQuery 这样我就可以过得去 但随着我开始更多地进行 TDD 我昨天决定真正深入研究 javascript 之后可能还有咖啡脚本 在我的 ASP NET Web 窗体应用程序中 我有很
  • Vue.js - 当标头中使用 multipart/form-data 时,axios 中的文件上传验证失败

    我正在构建一个 Laravel Vue js SPA 单页应用程序 BootstrapVue https bootstrap vue js org Vee验证 https logaretm github io vee validate gu
  • 将引导程序弹出框保留在视口内

    我正在尝试使用带有按钮的侧边栏创建一个菜单 每个按钮都有一个指定的包含相关数据的弹出窗口 不幸的是 其中一个弹出窗口可能包含任意数量的行 并且在某些情况下它可能部分位于视口之外 See http jsfiddle net bfd9f 1 h

随机推荐

  • 如何在项目管理中跟踪资源可用性?

    项目是有计划 有安排的 在不超支预算的情况下按期执行项目 项目经理必须了解资源的可用性 这是资源管理流程的一部分 什么是资源可用性 资源可用性是指了解执行项目所需的资源 何时需要以及在何种情况下需要 能够协调完成项目所需的资源 是项目成功的
  • 2023 年排名前八的 Kali Linux 工具

    一 排名前八的 Kali Linux 渗透测试工具 信息收集 密码破解 社交工程 网络犯罪对我们的 IT 世界构成严重威胁 并且可以采用许多不同的策略来打击它 道德黑客 也称为 白黑客 使用各种网络安全工具来测试网络和数据系统是否存在黑客可
  • 为什么要学习Python?

    前言 Python 是当今非常流行的编程语言 在互联网上经常可以看到他的身影 它应用非常广泛 例如编程 Web 开发 机器学习和 数据科学Q 等 TIOBE 官网近日公布了 2023 年 8 月的编程语言排行榜 Python 依然排行第一
  • 免费、好用!IDEA插件用这款!

    IDEA插件市场中的API调试插件不是收费 Fast Request 就是不好用 apidoc apidocx等等 今天给大家介绍一款国产的API调试插件 Apipost Helper 完全免费且好看好用 这款插件由Apipost团队开发的
  • 要想用好linux,先把shell 搞明白

    一 变量 1 环境变量 echo PATH 2 自定义变量 hello hello world echo hello 3 存储 Linux 命令执行结果作为变量 2 种方式 推荐使用第二中 第一种是 键上面的斜点比较难识别 files ls
  • API调试神器!Apipost

    前言 Apipost是一款支持 RESTful API SOAP API GraphQL API等多种API类型 支持 HTTPS WebSocket gRPC多种通信协议的API调试工具 除此之外 Apipost 还提供了自动化测试 团队
  • 元宇宙3d展厅全景导览系统为现代展会的举办带来了全新的可能性和机遇。

    3D元宇宙展会搭建平台的亮点 随着科技的不断进步 3D元宇宙展会搭建平台已经成为了现代展会的新趋势 这种全新的展会形式不仅给人们带来了前所未有的视觉体验 还具备许多亮点和优势 让展会的举办更加高效 便捷和创新 一 突破时空限制 3D元宇宙展
  • 软件测试/测试开发/人工智能丨如何通过分组 AUC 从不同的维度验证模型的能力

    通过分组 AUC Area Under the Curve 从不同维度验证模型的能力是一种有效的方法 特别适用于面对多个子群体或子问题的场景 以下是一些步骤 以及在不同维度验证模型性能时可能的一些策略 步骤 定义分组维度 确定模型性能需要在
  • 简单搭建一个Python自动化测试框架

    1 安装 Python 首先需要安装Python 可以从官网下载对应的版本 安装完成后 可以在终端中输入python来检查是否安装成功 2 安装pip pip是Python的包管理工具 用于安装和管理Python模块 可以在终端中输入以下命
  • zkSend — — 在Sui上发红包像发电子邮件一样简单

    12月14日 知名区块链媒体平台The Block发表了这篇关于对Mysten Labs联合创始人Adeniyi Abiodun的采访 文中 我们 指代该媒体 数据均为截止撰写文章时数据 以下是正文 两年前 当五名前Facebook工程师创
  • 玩转Docker(七):Docker Compose

    文章目录 一 什么是Docker Compose 二 一个完整的例子 一 什么是Docker Compose Docker Compose是一个用于定义和运行多个Docker容器应用的工具 它使用YAML文件来配置应用的服务 网络 卷等 通
  • NFTScan | 12.11~12.17 NFT 市场热点汇总

    欢迎来到由 NFT 基础设施 NFTScan 出品的 NFT 生态热点事件每周汇总 周期 2023 12 11 2023 12 17 NFT Hot News 01 Pudgy Penguins 衍生 NFT Lil Pudgys 过去一天
  • nodejs使用nodejieba

    Nodejieba是一个基于Node js平台的中文分词模块 用于将中文文本切分成有意义的词汇 它是结巴中文分词的Node js版本 结巴分词是一种开源的中文分词工具 广泛应用于中文自然语言处理领域 优点 高性能 Nodejieba的底层实
  • 判断API接口优劣的标准

    随着互联网的发展 API接口已经成为了应用程序之间进行数据交互的重要方式 然而 在众多的API接口中 如何判断其优劣呢 本文将介绍一些判断API接口优劣的标准 一 稳定性和可用性 一个优秀的API接口必须具备稳定性和可用性 稳定性是指接口在
  • 蚂蚁集团5大开源项目获开放原子 “2023快速成长开源项目”

    12月16日 在开放原子开源基金会主办的 2023开放原子开发者大会 上 蚂蚁集团主导开源的图数据库TuGraph 时序数据库CeresDB 隐私计算框架隐语SecretFlow 前端框架OpenSumi 数据域大模型开源框架DB GPT入
  • 【ranger】CDP环境 更新 ranger 权限策略会发生低概率丢失权限策略的解决方法

    一 问题描述 我们的 kafka 服务在更新 添加 ranger 权限时 会有极低的概率导致 MM2 同步服务报错 报错内容 Not Authorized 但是查看 ranger 权限是赋予的 并且很早配置的权限策略也会报错 相关组件版本
  • 软件测试/测试开发|最容易上手的Ubuntu虚拟机安装教程

    简介 我们在日常的学习和工作中 经常需要我们在Linux系统上部署环境或者执行测试 但是有时候服务器资源并没有这么好申请 特别是当我们在学习时 购买服务器会增加我们的成本 在这个时候 我们就可以使用虚拟机了 我们使用虚拟机来安装Linux系
  • 用友出席操作系统大会,携手麒麟软件深度服务企业数智化

    12月15日 操作系统大会 openEulerSummit2023在北京召开 用友受邀参加麒麟软件分论坛 与行业大咖一道 共话产业链生态引领基础软件加速技术创新 在企业数智化转型大潮中 用友聚合各行各业生态伙伴 共同营建全球领先的数智商业创
  • 云服务器1核1G能干什么?

    随着云计算技术的不断发展 云服务器已经成为企业和个人用户的重要选择 其中 1核1G的云服务器是市场上比较常见的一种配置 那么 1核1G的云服务器有哪些用途呢 搭建小型网站或个人博客 对于一些小型网站或个人博客来说 并不需要太多的计算资源和存
  • ant-design-vue三级菜单