feat: 优化菜单名称右侧的额外图标,使其支持更多图标渲染模式

This commit is contained in:
xiaoxian521 2023-02-09 20:04:57 +08:00
parent e323411d1c
commit b455b2da89
8 changed files with 95 additions and 70 deletions

View File

@ -0,0 +1,20 @@
<script setup lang="ts">
import { toRaw } from "vue";
import { useRenderIcon } from "@/components/ReIcon/src/hooks";
const props = defineProps({
extraIcon: {
type: String,
default: ""
}
});
</script>
<template>
<div v-if="props.extraIcon" class="flex justify-center items-center">
<component
:is="useRenderIcon(toRaw(props.extraIcon))"
class="w-[30px] h-[30px]"
/>
</div>
</template>

View File

@ -1,4 +1,5 @@
<script setup lang="ts"> <script setup lang="ts">
import extraIcon from "./extraIcon.vue";
import Search from "../search/index.vue"; import Search from "../search/index.vue";
import Notice from "../notice/index.vue"; import Notice from "../notice/index.vue";
import { useNav } from "@/layout/hooks/useNav"; import { useNav } from "@/layout/hooks/useNav";
@ -26,6 +27,7 @@ const {
menuSelect, menuSelect,
resolvePath, resolvePath,
username, username,
getDivStyle,
avatarsStyle, avatarsStyle,
getDropdownItemStyle, getDropdownItemStyle,
getDropdownItemClass getDropdownItemClass
@ -85,15 +87,12 @@ watch(
:is="useRenderIcon(route.meta && toRaw(route.meta.icon))" :is="useRenderIcon(route.meta && toRaw(route.meta.icon))"
/> />
</div> </div>
<span class="select-none">{{ transformI18n(route.meta.title) }}</span> <div :style="getDivStyle">
<FontIcon <span class="select-none">
v-if="route.meta.extraIcon" {{ transformI18n(route.meta.title) }}
width="30px" </span>
height="30px" <extraIcon :extraIcon="route.meta.extraIcon" />
style="position: absolute; right: 10px" </div>
:icon="route.meta.extraIcon.name"
:svg="route.meta.extraIcon.svg ? true : false"
/>
</template> </template>
</el-menu-item> </el-menu-item>
</el-menu> </el-menu>

View File

@ -1,6 +1,7 @@
<script setup lang="ts"> <script setup lang="ts">
import path from "path"; import path from "path";
import { getConfig } from "@/config"; import { getConfig } from "@/config";
import extraIcon from "./extraIcon.vue";
import { childrenType } from "../../types"; import { childrenType } from "../../types";
import { useNav } from "@/layout/hooks/useNav"; import { useNav } from "@/layout/hooks/useNav";
import { transformI18n } from "@/plugins/i18n"; import { transformI18n } from "@/plugins/i18n";
@ -12,7 +13,7 @@ import EpArrowDown from "@iconify-icons/ep/arrow-down";
import ArrowLeft from "@iconify-icons/ep/arrow-left"; import ArrowLeft from "@iconify-icons/ep/arrow-left";
import ArrowRight from "@iconify-icons/ep/arrow-right"; import ArrowRight from "@iconify-icons/ep/arrow-right";
const { layout, isCollapse, tooltipEffect } = useNav(); const { layout, isCollapse, tooltipEffect, getDivStyle } = useNav();
const props = defineProps({ const props = defineProps({
item: { item: {
@ -50,16 +51,6 @@ const getMenuTextStyle = computed(() => {
}; };
}); });
const getDivStyle = computed((): CSSProperties => {
return {
width: "100%",
display: "flex",
alignItems: "center",
justifyContent: "space-between",
overflow: "hidden"
};
});
const getsubMenuIconStyle = computed((): CSSProperties => { const getsubMenuIconStyle = computed((): CSSProperties => {
return { return {
display: "flex", display: "flex",
@ -89,6 +80,28 @@ const getSubTextStyle = computed((): CSSProperties => {
} }
}); });
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(() => { const expandCloseIcon = computed(() => {
if (!getConfig()?.MenuArrowIconNoTransition) return ""; if (!getConfig()?.MenuArrowIconNoTransition) return "";
return { return {
@ -240,13 +253,7 @@ function resolvePath(routePath) {
{{ transformI18n(onlyOneChild.meta.title) }} {{ transformI18n(onlyOneChild.meta.title) }}
</span> </span>
</el-tooltip> </el-tooltip>
<FontIcon <extraIcon :extraIcon="onlyOneChild.meta.extraIcon" />
v-if="onlyOneChild.meta.extraIcon"
width="30px"
height="30px"
:icon="onlyOneChild.meta.extraIcon.name"
:svg="onlyOneChild.meta.extraIcon.svg ? true : false"
/>
</div> </div>
</template> </template>
</el-menu-item> </el-menu-item>
@ -267,41 +274,41 @@ function resolvePath(routePath) {
:is="useRenderIcon(props.item.meta && toRaw(props.item.meta.icon))" :is="useRenderIcon(props.item.meta && toRaw(props.item.meta.icon))"
/> />
</div> </div>
<span v-if="layout === 'horizontal'"> <div
{{ transformI18n(props.item.meta.title) }} :style="getSubMenuDivStyle(props.item)"
</span>
<el-tooltip
v-if=" v-if="
layout !== 'horizontal' &&
!( !(
isCollapse && isCollapse &&
toRaw(props.item.meta.icon) && toRaw(props.item.meta.icon) &&
props.item.parentId === null props.item.parentId === null
) )
" "
placement="top"
:effect="tooltipEffect"
:offset="-10"
:disabled="!props.item.showTooltip"
> >
<template #content> <span v-if="layout === 'horizontal'">
{{ transformI18n(props.item.meta.title) }} {{ transformI18n(props.item.meta.title) }}
</template>
<span
ref="menuTextRef"
:style="getSubTextStyle"
@mouseover="hoverMenu(props.item)"
>
{{ overflowSlice(transformI18n(props.item.meta.title), props.item) }}
</span> </span>
</el-tooltip> <el-tooltip
<FontIcon v-if="layout !== 'horizontal'"
v-if="props.item.meta.extraIcon" placement="top"
width="30px" :effect="tooltipEffect"
height="30px" :offset="-10"
:icon="props.item.meta.extraIcon.name" :disabled="!props.item.showTooltip"
:svg="props.item.meta.extraIcon.svg ? true : false" >
/> <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>
</template> </template>
<sidebar-item <sidebar-item
v-for="child in props.item.children" v-for="child in props.item.children"

View File

@ -1,4 +1,3 @@
import { computed } from "vue";
import { storeToRefs } from "pinia"; import { storeToRefs } from "pinia";
import { getConfig } from "@/config"; import { getConfig } from "@/config";
import { useRouter } from "vue-router"; import { useRouter } from "vue-router";
@ -7,6 +6,7 @@ import { routeMetaType } from "../types";
import { useGlobal } from "@pureadmin/utils"; import { useGlobal } from "@pureadmin/utils";
import { transformI18n } from "@/plugins/i18n"; import { transformI18n } from "@/plugins/i18n";
import { router, remainingPaths } from "@/router"; import { router, remainingPaths } from "@/router";
import { computed, type CSSProperties } from "vue";
import { useAppStoreHook } from "@/store/modules/app"; import { useAppStoreHook } from "@/store/modules/app";
import { useUserStoreHook } from "@/store/modules/user"; import { useUserStoreHook } from "@/store/modules/user";
import { useEpThemeStoreHook } from "@/store/modules/epTheme"; import { useEpThemeStoreHook } from "@/store/modules/epTheme";
@ -21,6 +21,16 @@ export function useNav() {
/** 平台`layout`中所有`el-tooltip`的`effect`配置,默认`light` */ /** 平台`layout`中所有`el-tooltip`的`effect`配置,默认`light` */
const tooltipEffect = getConfig()?.TooltipEffect ?? "light"; const tooltipEffect = getConfig()?.TooltipEffect ?? "light";
const getDivStyle = computed((): CSSProperties => {
return {
width: "100%",
display: "flex",
alignItems: "center",
justifyContent: "space-between",
overflow: "hidden"
};
});
/** 用户名 */ /** 用户名 */
const username = computed(() => { const username = computed(() => {
return useUserStoreHook()?.username; return useUserStoreHook()?.username;
@ -146,6 +156,7 @@ export function useNav() {
$storage, $storage,
backHome, backHome,
onPanel, onPanel,
getDivStyle,
changeTitle, changeTitle,
toggleSideBar, toggleSideBar,
menuSelect, menuSelect,

View File

@ -67,10 +67,7 @@ export type childrenType = {
icon?: string; icon?: string;
title?: string; title?: string;
showParent?: boolean; showParent?: boolean;
extraIcon?: { extraIcon?: string;
svg?: boolean;
name?: string;
};
}; };
showTooltip?: boolean; showTooltip?: boolean;
parentId?: number; parentId?: number;

View File

@ -16,10 +16,7 @@ export default {
component: () => import("@/views/components/message/index.vue"), component: () => import("@/views/components/message/index.vue"),
meta: { meta: {
title: $t("menus.hsmessage"), title: $t("menus.hsmessage"),
extraIcon: { extraIcon: "IF-pure-iconfont-new svg",
svg: true,
name: "pure-iconfont-new"
},
transition: { transition: {
enterTransition: "animate__fadeInLeft", enterTransition: "animate__fadeInLeft",
leaveTransition: "animate__fadeOutRight" leaveTransition: "animate__fadeOutRight"

View File

@ -53,10 +53,7 @@ export default {
meta: { meta: {
title: $t("menus.hsmenu1-2-2"), title: $t("menus.hsmenu1-2-2"),
keepAlive: true, keepAlive: true,
extraIcon: { extraIcon: "IF-pure-iconfont-new svg"
svg: true,
name: "pure-iconfont-new"
}
} }
} }
] ]

7
types/global.d.ts vendored
View File

@ -192,11 +192,8 @@ declare global {
title: string; title: string;
/** 菜单图标 `可选` */ /** 菜单图标 `可选` */
icon?: string | FunctionalComponent | IconifyIcon; icon?: string | FunctionalComponent | IconifyIcon;
/** 菜单名称右侧的额外图标,支持`fontawesome`、`iconfont`、`element-plus-icon` `可选` */ /** 菜单名称右侧的额外图标 */
extraIcon?: { extraIcon?: string | FunctionalComponent | IconifyIcon;
svg?: boolean;
name?: string;
};
/** 是否在菜单中显示(默认`true``可选` */ /** 是否在菜单中显示(默认`true``可选` */
showLink?: boolean; showLink?: boolean;
/** 是否显示父级菜单 `可选` */ /** 是否显示父级菜单 `可选` */