mirror of
https://github.com/pure-admin/vue-pure-admin.git
synced 2025-11-09 13:53:38 +08:00
feat(ReText): 新增ReText组件,支持自动省略显示Tooltip功能, 支持多行省略, 高可复用性 (#898)
* feat(ReText): 新增ReText组件 - 基于El-Text, 增加自动省略显示Tooltip功能, 高可复用性
This commit is contained in:
@@ -3,10 +3,12 @@ import path from "path";
|
||||
import { getConfig } from "@/config";
|
||||
import { menuType } from "../../types";
|
||||
import extraIcon from "./extraIcon.vue";
|
||||
import { useDark } from "@pureadmin/utils";
|
||||
import { ReText } from "@/components/ReText";
|
||||
import { useNav } from "@/layout/hooks/useNav";
|
||||
import { transformI18n } from "@/plugins/i18n";
|
||||
import { useRenderIcon } from "@/components/ReIcon/src/hooks";
|
||||
import { ref, toRaw, PropType, nextTick, computed, CSSProperties } from "vue";
|
||||
import { type CSSProperties, type PropType, computed, ref, toRaw } from "vue";
|
||||
|
||||
import ArrowUp from "@iconify-icons/ep/arrow-up-bold";
|
||||
import EpArrowDown from "@iconify-icons/ep/arrow-down-bold";
|
||||
@@ -14,6 +16,7 @@ import ArrowLeft from "@iconify-icons/ep/arrow-left-bold";
|
||||
import ArrowRight from "@iconify-icons/ep/arrow-right-bold";
|
||||
|
||||
const { layout, isCollapse, tooltipEffect, getDivStyle } = useNav();
|
||||
const { isDark } = useDark();
|
||||
|
||||
const props = defineProps({
|
||||
item: {
|
||||
@@ -29,13 +32,6 @@ const props = defineProps({
|
||||
}
|
||||
});
|
||||
|
||||
const getSpanStyle = computed((): CSSProperties => {
|
||||
return {
|
||||
width: "100%",
|
||||
textAlign: "center"
|
||||
};
|
||||
});
|
||||
|
||||
const getNoDropdownStyle = computed((): CSSProperties => {
|
||||
return {
|
||||
display: "flex",
|
||||
@@ -43,15 +39,7 @@ const getNoDropdownStyle = computed((): CSSProperties => {
|
||||
};
|
||||
});
|
||||
|
||||
const getMenuTextStyle = computed(() => {
|
||||
return {
|
||||
overflow: "hidden",
|
||||
textOverflow: "ellipsis",
|
||||
outline: "none"
|
||||
};
|
||||
});
|
||||
|
||||
const getsubMenuIconStyle = computed((): CSSProperties => {
|
||||
const getSubMenuIconStyle = computed((): CSSProperties => {
|
||||
return {
|
||||
display: "flex",
|
||||
justifyContent: "center",
|
||||
@@ -65,43 +53,6 @@ const getsubMenuIconStyle = computed((): CSSProperties => {
|
||||
};
|
||||
});
|
||||
|
||||
const getSubTextStyle = computed((): CSSProperties => {
|
||||
if (!isCollapse.value) {
|
||||
return {
|
||||
width: "210px",
|
||||
display: "inline-block",
|
||||
overflow: "hidden",
|
||||
textOverflow: "ellipsis"
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
width: ""
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
const getSubMenuDivStyle = computed((): any => {
|
||||
return item => {
|
||||
return !isCollapse.value
|
||||
? {
|
||||
width: "100%",
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
justifyContent: "space-between",
|
||||
overflow: "hidden"
|
||||
}
|
||||
: {
|
||||
width: "100%",
|
||||
textAlign:
|
||||
item?.parentId === null
|
||||
? "center"
|
||||
: layout.value === "mix" && item?.pathList?.length === 2
|
||||
? "center"
|
||||
: ""
|
||||
};
|
||||
};
|
||||
});
|
||||
|
||||
const expandCloseIcon = computed(() => {
|
||||
if (!getConfig()?.MenuArrowIconNoTransition) return "";
|
||||
return {
|
||||
@@ -113,41 +64,6 @@ const expandCloseIcon = computed(() => {
|
||||
});
|
||||
|
||||
const onlyOneChild: menuType = ref(null);
|
||||
// 存放菜单是否存在showTooltip属性标识
|
||||
const hoverMenuMap = new WeakMap();
|
||||
// 存储菜单文本dom元素
|
||||
const menuTextRef = ref(null);
|
||||
|
||||
function hoverMenu(key) {
|
||||
// 如果当前菜单showTooltip属性已存在,退出计算
|
||||
if (hoverMenuMap.get(key)) return;
|
||||
|
||||
nextTick(() => {
|
||||
// 如果文本内容的整体宽度大于其可视宽度,则文本溢出
|
||||
menuTextRef.value?.scrollWidth > menuTextRef.value?.clientWidth
|
||||
? Object.assign(key, {
|
||||
showTooltip: true
|
||||
})
|
||||
: Object.assign(key, {
|
||||
showTooltip: false
|
||||
});
|
||||
hoverMenuMap.set(key, true);
|
||||
});
|
||||
}
|
||||
|
||||
// 左侧菜单折叠后,当菜单没有图标时只显示第一个文字并加上省略号
|
||||
function overflowSlice(text, item?: any) {
|
||||
const newText =
|
||||
(text?.length > 1 ? text.toString().slice(0, 1) : text) + "...";
|
||||
if (item && !(isCollapse.value && item?.parentId === null)) {
|
||||
return layout.value === "mix" &&
|
||||
item?.pathList?.length === 2 &&
|
||||
isCollapse.value
|
||||
? newText
|
||||
: text;
|
||||
}
|
||||
return newText;
|
||||
}
|
||||
|
||||
function hasOneShowingChild(children: menuType[] = [], parent: menuType) {
|
||||
const showingChildren = children.filter((item: any) => {
|
||||
@@ -194,7 +110,7 @@ function resolvePath(routePath) {
|
||||
<div
|
||||
v-if="toRaw(props.item.meta.icon)"
|
||||
class="sub-menu-icon"
|
||||
:style="getsubMenuIconStyle"
|
||||
:style="getSubMenuIconStyle"
|
||||
>
|
||||
<component
|
||||
:is="
|
||||
@@ -205,51 +121,34 @@ function resolvePath(routePath) {
|
||||
"
|
||||
/>
|
||||
</div>
|
||||
<span
|
||||
<el-text
|
||||
v-if="
|
||||
!props.item?.meta.icon &&
|
||||
isCollapse &&
|
||||
layout === 'vertical' &&
|
||||
props.item?.pathList?.length === 1
|
||||
(!props.item?.meta.icon &&
|
||||
isCollapse &&
|
||||
layout === 'vertical' &&
|
||||
props.item?.pathList?.length === 1) ||
|
||||
(!onlyOneChild.meta.icon &&
|
||||
isCollapse &&
|
||||
layout === 'mix' &&
|
||||
props.item?.pathList?.length === 2)
|
||||
"
|
||||
:style="getSpanStyle"
|
||||
truncated
|
||||
class="!px-4 !text-inherit"
|
||||
>
|
||||
{{ overflowSlice(transformI18n(onlyOneChild.meta.title)) }}
|
||||
</span>
|
||||
<span
|
||||
v-if="
|
||||
!onlyOneChild.meta.icon &&
|
||||
isCollapse &&
|
||||
layout === 'mix' &&
|
||||
props.item?.pathList?.length === 2
|
||||
"
|
||||
:style="getSpanStyle"
|
||||
>
|
||||
{{ overflowSlice(transformI18n(onlyOneChild.meta.title)) }}
|
||||
</span>
|
||||
{{ transformI18n(onlyOneChild.meta.title) }}
|
||||
</el-text>
|
||||
|
||||
<template #title>
|
||||
<div :style="getDivStyle">
|
||||
<span v-if="layout === 'horizontal'">
|
||||
{{ transformI18n(onlyOneChild.meta.title) }}
|
||||
</span>
|
||||
<el-tooltip
|
||||
v-else
|
||||
placement="top"
|
||||
:effect="tooltipEffect"
|
||||
:offset="-10"
|
||||
:disabled="!onlyOneChild.showTooltip"
|
||||
<ReText
|
||||
:tippyProps="{
|
||||
offset: [0, -10],
|
||||
theme: !isDark ? tooltipEffect : undefined
|
||||
}"
|
||||
class="!text-inherit"
|
||||
>
|
||||
<template #content>
|
||||
{{ transformI18n(onlyOneChild.meta.title) }}
|
||||
</template>
|
||||
<span
|
||||
ref="menuTextRef"
|
||||
:style="getMenuTextStyle"
|
||||
@mouseover="hoverMenu(onlyOneChild)"
|
||||
>
|
||||
{{ transformI18n(onlyOneChild.meta.title) }}
|
||||
</span>
|
||||
</el-tooltip>
|
||||
{{ transformI18n(onlyOneChild.meta.title) }}
|
||||
</ReText>
|
||||
<extraIcon :extraIcon="onlyOneChild.meta.extraIcon" />
|
||||
</div>
|
||||
</template>
|
||||
@@ -264,48 +163,38 @@ function resolvePath(routePath) {
|
||||
<template #title>
|
||||
<div
|
||||
v-if="toRaw(props.item.meta.icon)"
|
||||
:style="getsubMenuIconStyle"
|
||||
:style="getSubMenuIconStyle"
|
||||
class="sub-menu-icon"
|
||||
>
|
||||
<component
|
||||
:is="useRenderIcon(props.item.meta && toRaw(props.item.meta.icon))"
|
||||
/>
|
||||
</div>
|
||||
<span v-if="layout === 'horizontal'">
|
||||
{{ transformI18n(props.item.meta.title) }}
|
||||
</span>
|
||||
<div
|
||||
<ReText
|
||||
v-if="
|
||||
!(
|
||||
layout === 'vertical' &&
|
||||
isCollapse &&
|
||||
toRaw(props.item.meta.icon) &&
|
||||
props.item.parentId === null
|
||||
)
|
||||
"
|
||||
:style="getSubMenuDivStyle(props.item)"
|
||||
:tippyProps="{
|
||||
offset: [0, -10],
|
||||
theme: !isDark ? tooltipEffect : undefined
|
||||
}"
|
||||
:class="{
|
||||
'!text-inherit': true,
|
||||
'!px-4':
|
||||
layout !== 'horizontal' &&
|
||||
isCollapse &&
|
||||
!toRaw(props.item.meta.icon) &&
|
||||
props.item.parentId === null
|
||||
}"
|
||||
>
|
||||
<el-tooltip
|
||||
v-if="layout !== 'horizontal'"
|
||||
placement="top"
|
||||
:effect="tooltipEffect"
|
||||
:offset="-10"
|
||||
:disabled="!props.item.showTooltip"
|
||||
>
|
||||
<template #content>
|
||||
{{ transformI18n(props.item.meta.title) }}
|
||||
</template>
|
||||
<span
|
||||
ref="menuTextRef"
|
||||
:style="getSubTextStyle"
|
||||
@mouseover="hoverMenu(props.item)"
|
||||
>
|
||||
{{
|
||||
overflowSlice(transformI18n(props.item.meta.title), props.item)
|
||||
}}
|
||||
</span>
|
||||
</el-tooltip>
|
||||
<extraIcon v-if="!isCollapse" :extraIcon="props.item.meta.extraIcon" />
|
||||
</div>
|
||||
{{ transformI18n(props.item.meta.title) }}
|
||||
</ReText>
|
||||
<extraIcon v-if="!isCollapse" :extraIcon="props.item.meta.extraIcon" />
|
||||
</template>
|
||||
|
||||
<sidebar-item
|
||||
|
||||
Reference in New Issue
Block a user