mirror of
https://github.com/pure-admin/vue-pure-admin.git
synced 2025-06-04 07:27:41 +08:00
feat: 菜单支持a
标签右键的所有浏览器行为(在新标签页中、新窗口中打开链接,拖拽到新标签页打开等) (#936)
* feat: 菜单支持a标签右键的所有浏览器行为(在新标签页中、新窗口中打开链接,拖拽到新标签页打开等) * feat: 修复添加a标签样式问题 * feat: 修复windows下双滚动条问题 * feat: 修复添加a标签样式问题
This commit is contained in:
parent
51809546ed
commit
2b71e8bd54
36
src/layout/components/sidebar/linkItem.vue
Normal file
36
src/layout/components/sidebar/linkItem.vue
Normal file
@ -0,0 +1,36 @@
|
||||
<script setup lang="ts">
|
||||
import { computed } from "vue";
|
||||
import { isUrl } from "@pureadmin/utils";
|
||||
import { menuType } from "@/layout/types";
|
||||
|
||||
defineOptions({
|
||||
name: "LinkItem"
|
||||
});
|
||||
|
||||
const props = defineProps<{
|
||||
to: menuType;
|
||||
}>();
|
||||
|
||||
const isExternalLink = computed(() => isUrl(props.to.name));
|
||||
const getLinkProps = (item: menuType) => {
|
||||
if (isExternalLink.value) {
|
||||
return {
|
||||
href: item.name,
|
||||
target: "_blank",
|
||||
rel: "noopener"
|
||||
};
|
||||
}
|
||||
return {
|
||||
to: item
|
||||
};
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<component
|
||||
:is="isExternalLink ? 'a' : 'router-link'"
|
||||
v-bind="getLinkProps(to)"
|
||||
>
|
||||
<slot />
|
||||
</component>
|
||||
</template>
|
@ -48,6 +48,7 @@ const { title, getLogo } = useNav();
|
||||
flex-wrap: nowrap;
|
||||
align-items: center;
|
||||
height: 100%;
|
||||
padding-left: 10px;
|
||||
|
||||
img {
|
||||
display: inline-block;
|
||||
|
@ -1,19 +1,28 @@
|
||||
<script setup lang="ts">
|
||||
import path from "path";
|
||||
import { getConfig } from "@/config";
|
||||
import LinkItem from "./linkItem.vue";
|
||||
import { menuType } from "../../types";
|
||||
import extraIcon from "./extraIcon.vue";
|
||||
import { ReText } from "@/components/ReText";
|
||||
import { useNav } from "@/layout/hooks/useNav";
|
||||
import { transformI18n } from "@/plugins/i18n";
|
||||
import { useRenderIcon } from "@/components/ReIcon/src/hooks";
|
||||
import { type CSSProperties, type PropType, computed, ref, toRaw } from "vue";
|
||||
import {
|
||||
type PropType,
|
||||
type CSSProperties,
|
||||
ref,
|
||||
toRaw,
|
||||
computed,
|
||||
useAttrs
|
||||
} from "vue";
|
||||
|
||||
import ArrowUp from "@iconify-icons/ep/arrow-up-bold";
|
||||
import EpArrowDown from "@iconify-icons/ep/arrow-down-bold";
|
||||
import ArrowLeft from "@iconify-icons/ep/arrow-left-bold";
|
||||
import ArrowRight from "@iconify-icons/ep/arrow-right-bold";
|
||||
|
||||
const attrs = useAttrs();
|
||||
const { layout, isCollapse, tooltipEffect, getDivStyle } = useNav();
|
||||
|
||||
const props = defineProps({
|
||||
@ -32,6 +41,7 @@ const props = defineProps({
|
||||
|
||||
const getNoDropdownStyle = computed((): CSSProperties => {
|
||||
return {
|
||||
width: "100%",
|
||||
display: "flex",
|
||||
alignItems: "center"
|
||||
};
|
||||
@ -96,61 +106,66 @@ function resolvePath(routePath) {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<el-menu-item
|
||||
<link-item
|
||||
v-if="
|
||||
hasOneShowingChild(props.item.children, props.item) &&
|
||||
(!onlyOneChild.children || onlyOneChild.noShowingChildren)
|
||||
"
|
||||
:index="resolvePath(onlyOneChild.path)"
|
||||
:class="{ 'submenu-title-noDropdown': !isNest }"
|
||||
:style="getNoDropdownStyle"
|
||||
:to="item"
|
||||
>
|
||||
<div
|
||||
v-if="toRaw(props.item.meta.icon)"
|
||||
class="sub-menu-icon"
|
||||
:style="getSubMenuIconStyle"
|
||||
<el-menu-item
|
||||
:index="resolvePath(onlyOneChild.path)"
|
||||
:class="{ 'submenu-title-noDropdown': !isNest }"
|
||||
:style="getNoDropdownStyle"
|
||||
v-bind="attrs"
|
||||
>
|
||||
<component
|
||||
:is="
|
||||
useRenderIcon(
|
||||
toRaw(onlyOneChild.meta.icon) ||
|
||||
(props.item.meta && toRaw(props.item.meta.icon))
|
||||
)
|
||||
"
|
||||
/>
|
||||
</div>
|
||||
<el-text
|
||||
v-if="
|
||||
(!props.item?.meta.icon &&
|
||||
isCollapse &&
|
||||
layout === 'vertical' &&
|
||||
props.item?.pathList?.length === 1) ||
|
||||
(!onlyOneChild.meta.icon &&
|
||||
isCollapse &&
|
||||
layout === 'mix' &&
|
||||
props.item?.pathList?.length === 2)
|
||||
"
|
||||
truncated
|
||||
class="!px-4 !text-inherit"
|
||||
>
|
||||
{{ transformI18n(onlyOneChild.meta.title) }}
|
||||
</el-text>
|
||||
|
||||
<template #title>
|
||||
<div :style="getDivStyle">
|
||||
<ReText
|
||||
:tippyProps="{
|
||||
offset: [0, -10],
|
||||
theme: tooltipEffect
|
||||
}"
|
||||
class="!text-inherit"
|
||||
>
|
||||
{{ transformI18n(onlyOneChild.meta.title) }}
|
||||
</ReText>
|
||||
<extraIcon :extraIcon="onlyOneChild.meta.extraIcon" />
|
||||
<div
|
||||
v-if="toRaw(props.item.meta.icon)"
|
||||
class="sub-menu-icon"
|
||||
:style="getSubMenuIconStyle"
|
||||
>
|
||||
<component
|
||||
:is="
|
||||
useRenderIcon(
|
||||
toRaw(onlyOneChild.meta.icon) ||
|
||||
(props.item.meta && toRaw(props.item.meta.icon))
|
||||
)
|
||||
"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
</el-menu-item>
|
||||
<el-text
|
||||
v-if="
|
||||
(!props.item?.meta.icon &&
|
||||
isCollapse &&
|
||||
layout === 'vertical' &&
|
||||
props.item?.pathList?.length === 1) ||
|
||||
(!onlyOneChild.meta.icon &&
|
||||
isCollapse &&
|
||||
layout === 'mix' &&
|
||||
props.item?.pathList?.length === 2)
|
||||
"
|
||||
truncated
|
||||
class="!px-4 !text-inherit"
|
||||
>
|
||||
{{ transformI18n(onlyOneChild.meta.title) }}
|
||||
</el-text>
|
||||
|
||||
<template #title>
|
||||
<div :style="getDivStyle">
|
||||
<ReText
|
||||
:tippyProps="{
|
||||
offset: [0, -10],
|
||||
theme: tooltipEffect
|
||||
}"
|
||||
class="!text-inherit"
|
||||
>
|
||||
{{ transformI18n(onlyOneChild.meta.title) }}
|
||||
</ReText>
|
||||
<extraIcon :extraIcon="onlyOneChild.meta.extraIcon" />
|
||||
</div>
|
||||
</template>
|
||||
</el-menu-item>
|
||||
</link-item>
|
||||
<el-sub-menu
|
||||
v-else
|
||||
ref="subMenu"
|
||||
|
@ -62,6 +62,7 @@ export interface setType {
|
||||
|
||||
export type menuType = {
|
||||
id?: number;
|
||||
name?: string;
|
||||
path?: string;
|
||||
noShowingChildren?: boolean;
|
||||
children?: menuType[];
|
||||
|
@ -14,6 +14,11 @@
|
||||
}
|
||||
}
|
||||
|
||||
/* 修复 windows 下双滚动条问题 https://github.com/pure-admin/vue-pure-admin/pull/936#issuecomment-1968125992 */
|
||||
.el-popper.pure-scrollbar {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* popper menu 超出内容区可滚动 */
|
||||
.pure-scrollbar {
|
||||
max-height: calc(100vh - calc(50px * 2.5));
|
||||
@ -130,11 +135,9 @@
|
||||
}
|
||||
|
||||
a {
|
||||
display: inline-block;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
width: 100%;
|
||||
padding-left: 10px;
|
||||
}
|
||||
|
||||
.el-menu {
|
||||
@ -331,9 +334,18 @@
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
/* 无子菜单时激活 border-bottom */
|
||||
a > .is-active.submenu-title-noDropdown {
|
||||
border-bottom: 2px solid var(--el-menu-active-color);
|
||||
}
|
||||
|
||||
.el-menu--popup {
|
||||
background-color: $subMenuBg !important;
|
||||
|
||||
a > .is-active.submenu-title-noDropdown {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.el-menu-item {
|
||||
color: $menuText;
|
||||
background-color: $subMenuBg;
|
||||
@ -348,12 +360,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
/* 无子菜单时激活 border-bottom */
|
||||
.router-link-exact-active > .submenu-title-noDropdown {
|
||||
height: 60px;
|
||||
border-bottom: 2px solid var(--el-menu-active-color);
|
||||
}
|
||||
|
||||
/* 子菜单中还有子菜单 */
|
||||
.el-menu .el-sub-menu__title {
|
||||
min-width: $sideBarWidth !important;
|
||||
|
Loading…
x
Reference in New Issue
Block a user