提交 88f4a3f0 编写于 作者: V vben

perf: perf menu

上级 74e62cbc
......@@ -8,10 +8,10 @@
:dropMenuList="localeList"
:selectedKeys="selectedKeys"
@menuEvent="handleMenuEvent"
overlayClassName="app-locale-picker-overlay"
:overlayClassName="`${prefixCls}-overlay`"
>
<span class="app-local-picker">
<GlobalOutlined class="app-local-picker__icon" />
<span :class="prefixCls">
<GlobalOutlined :class="`${prefixCls}__icon`" />
<span v-if="showText">{{ getLangText }}</span>
</span>
</Dropdown>
......@@ -28,6 +28,7 @@
import { LocaleType } from '/@/locales/types';
import { propTypes } from '/@/utils/propTypes';
import { useDesign } from '/@/hooks/web/useDesign';
export default defineComponent({
name: 'AppLocalPicker',
......@@ -39,9 +40,12 @@
reload: propTypes.bool,
},
setup(props) {
const { localeList } = useLocaleSetting();
const selectedKeys = ref<string[]>([]);
const { prefixCls } = useDesign('app-locale-picker');
const { localeList } = useLocaleSetting();
const { changeLocale, getLang } = useLocale();
const getLangText = computed(() => {
......@@ -64,19 +68,22 @@
toggleLocale(menu.event as string);
}
return { localeList, handleMenuEvent, selectedKeys, getLangText };
return { localeList, handleMenuEvent, selectedKeys, getLangText, prefixCls };
},
});
</script>
<style lang="less" scoped>
:global(.app-locale-picker-overlay) {
@import (reference) '../../../design/index.less';
@prefix-cls: ~'@{namespace}-app-locale-picker';
:global(.@{prefix-cls}-overlay) {
.ant-dropdown-menu-item {
min-width: 160px;
}
}
.app-local-picker {
.@{prefix-cls} {
display: flex;
align-items: center;
cursor: pointer;
......
......@@ -20,15 +20,17 @@
expand: propTypes.bool,
top: propTypes.bool,
bottom: propTypes.bool,
inset: propTypes.bool,
},
setup(props) {
const getClass = computed(() => {
const { expand, top, bottom } = props;
const { expand, top, bottom, inset } = props;
return [
'base-arrow',
{
'base-arrow__active': expand,
top,
inset,
bottom,
},
];
......@@ -47,6 +49,10 @@
transition: all 0.3s ease 0.1s;
transform-origin: center center;
&.inset {
line-height: 0px;
}
&__active {
transform: rotate(90deg);
}
......
......@@ -9,14 +9,15 @@ import {
unref,
reactive,
watch,
onMounted,
ref,
toRefs,
ComputedRef,
ref,
CSSProperties,
} from 'vue';
import { Menu } from 'ant-design-vue';
import MenuContent from './MenuContent';
// import { ScrollContainer } from '/@/components/Container';
// import { BasicArrow } from '/@/components/Basic';
import { MenuModeEnum, MenuTypeEnum } from '/@/enums/menuEnum';
import { ThemeEnum } from '/@/enums/appEnum';
......@@ -29,18 +30,20 @@ import { useRouter } from 'vue-router';
import { isFunction } from '/@/utils/is';
import { getSlot } from '/@/utils/helper/tsxHelper';
import { menuHasChildren } from './helper';
import { getCurrentParentPath } from '/@/router/menus';
import { basicProps } from './props';
import { useMenuSetting } from '/@/hooks/setting/useMenuSetting';
import { REDIRECT_NAME } from '/@/router/constant';
import { tabStore } from '/@/store/modules/tab';
import { useDesign } from '/@/hooks/web/useDesign';
export default defineComponent({
name: 'BasicMenu',
props: basicProps,
emits: ['menuClick'],
setup(props, { slots, emit }) {
const currentParentPath = ref('');
const isClickGo = ref(false);
const menuState = reactive<MenuState>({
defaultSelectedKeys: [],
......@@ -51,170 +54,184 @@ export default defineComponent({
collapsedOpenKeys: [],
});
const { getCollapsed } = useMenuSetting();
const { prefixCls } = useDesign('basic-menu');
const { currentRoute } = useRouter();
const { items, mode, accordion } = toRefs(props);
const { getCollapsed, getIsHorizontal, getTopMenuAlign, getSplit } = useMenuSetting();
const { items, flatItems, mode, accordion } = toRefs(props);
const { currentRoute } = useRouter();
const { handleOpenChange, resetKeys, setOpenKeys } = useOpenKeys(
const { handleOpenChange, setOpenKeys, getOpenKeys } = useOpenKeys(
menuState,
items,
flatItems,
mode,
accordion
);
const getOpenKeys = computed(() => {
return unref(getCollapsed) ? menuState.collapsedOpenKeys : menuState.openKeys;
const getMenuClass = computed(() => {
const { type } = props;
const { mode } = menuState;
return [
prefixCls,
`justify-${unref(getTopMenuAlign)}`,
{
[`${prefixCls}--hide-title`]: !unref(showTitle),
[`${prefixCls}--collapsed-show-title`]: props.collapsedShowTitle,
[`${prefixCls}__second`]:
!props.isHorizontal && appStore.getProjectConfig.menuSetting.split,
[`${prefixCls}__sidebar-hor`]:
type === MenuTypeEnum.TOP_MENU && mode === MenuModeEnum.HORIZONTAL,
},
];
});
// menu外层样式
const getMenuWrapStyle = computed((): any => {
const { showLogo } = props;
let offset = 0;
if (showLogo) {
offset += 46;
}
return {
height: `calc(100% - ${offset}px)`,
position: 'relative',
overflowY: 'auto',
};
});
const showTitle = computed(() => props.collapsedShowTitle && unref(getCollapsed));
// 是否透明化左侧一级菜单
const transparentMenuClass = computed(() => {
const { type } = props;
const { mode } = menuState;
const cls: string[] = [];
if (
(type === MenuTypeEnum.TOP_MENU && mode === MenuModeEnum.HORIZONTAL) ||
props.appendClass
) {
cls.push('basic-menu__sidebar-hor');
}
const getInlineCollapseOptions = computed(() => {
const isInline = props.mode === MenuModeEnum.INLINE;
if (!props.isHorizontal && appStore.getProjectConfig.menuSetting.split) {
cls.push('basic-menu__second');
const inlineCollapseOptions: { inlineCollapsed?: boolean } = {};
if (isInline) {
inlineCollapseOptions.inlineCollapsed = unref(getCollapsed);
}
return cls;
return inlineCollapseOptions;
});
const showTitle = computed(() => props.collapsedShowTitle && unref(getCollapsed));
const getWrapperStyle = computed(
(): CSSProperties => {
const isHorizontal = unref(getIsHorizontal);
return {
height: isHorizontal
? `calc(100% + 1px)`
: `calc(100% - ${props.showLogo ? '48px' : '0'})`,
overflowY: isHorizontal ? 'hidden' : 'auto',
};
}
);
watch(
() => currentRoute.value.name,
(name: string) => {
if (name === REDIRECT_NAME) return;
() => tabStore.getCurrentTab,
() => {
if (unref(currentRoute).name === REDIRECT_NAME) return;
handleMenuChange();
props.isHorizontal && appStore.getProjectConfig.menuSetting.split && getParentPath();
unref(getSplit) && getParentPath();
}
);
watch(
() => props.items,
() => {
if (props.items) {
handleMenuChange();
}
handleMenuChange();
},
{
immediate: true,
}
);
getParentPath();
async function getParentPath() {
const { appendClass } = props;
if (!appendClass) return '';
const parentPath = await getCurrentParentPath(unref(currentRoute).path);
currentParentPath.value = parentPath;
}
async function handleMenuClick(menu: MenuType) {
async function handleMenuClick({ key, keyPath }: { key: string; keyPath: string[] }) {
const { beforeClickFn } = props;
if (beforeClickFn && isFunction(beforeClickFn)) {
const flag = await beforeClickFn(menu);
const flag = await beforeClickFn(key);
if (!flag) return;
}
emit('menuClick', menu);
const { path } = menu;
menuState.selectedKeys = [path];
emit('menuClick', key);
isClickGo.value = true;
menuState.openKeys = keyPath;
menuState.selectedKeys = [key];
}
function handleMenuChange() {
const { flatItems } = props;
if (!unref(flatItems) || flatItems.length === 0) return;
const findMenu = flatItems.find((menu) => menu.path === unref(currentRoute).path);
if (findMenu) {
if (menuState.mode !== MenuModeEnum.HORIZONTAL) {
setOpenKeys(findMenu);
}
menuState.selectedKeys = [findMenu.path];
} else {
resetKeys();
if (unref(isClickGo)) {
isClickGo.value = false;
return;
}
const path = unref(currentRoute).path;
if (menuState.mode !== MenuModeEnum.HORIZONTAL) {
setOpenKeys(path);
}
menuState.selectedKeys = [path];
}
// render menu item
function renderMenuItem(menuList?: MenuType[], index = 1) {
if (!menuList) return;
// function renderExpandIcon({ key }: { key: string }) {
// const isOpen = getOpenKeys.value.includes(key);
// const collapsed = unref(getCollapsed);
// return (
// <BasicArrow
// expand={isOpen}
// bottom
// inset
// class={[
// `${prefixCls}__expand-icon`,
// {
// [`${prefixCls}__expand-icon--collapsed`]: collapsed,
// },
// ]}
// />
// );
// }
function renderItem(menu: MenuType, level = 1) {
return !menuHasChildren(menu) ? renderMenuItem(menu, level) : renderSubMenu(menu, level);
}
function renderMenuItem(menu: MenuType, level: number) {
const { appendClass } = props;
const levelCls = `basic-menu-item__level${index} ${menuState.theme} `;
return menuList.map((menu) => {
if (!menu) {
return null;
}
const isAppendActiveCls =
appendClass && index === 1 && menu.path === unref(currentParentPath);
// 没有子节点
if (!menuHasChildren(menu)) {
return (
<Menu.Item
key={menu.path}
class={`${levelCls}${isAppendActiveCls ? ' top-active-menu ' : ''}`}
onClick={handleMenuClick.bind(null, menu)}
>
{() => [
<MenuContent
item={menu}
level={index}
isHorizontal={props.isHorizontal}
showTitle={unref(showTitle)}
/>,
]}
</Menu.Item>
);
}
return (
<Menu.SubMenu key={menu.path} class={levelCls}>
{{
title: () => [
<MenuContent
showTitle={unref(showTitle)}
item={menu}
level={index}
isHorizontal={props.isHorizontal}
/>,
],
default: () => renderMenuItem(menu.children, index + 1),
}}
</Menu.SubMenu>
);
});
const isAppendActiveCls =
appendClass && level === 1 && menu.path === unref(currentParentPath);
const levelCls = [
`${prefixCls}-item__level${level}`,
` ${menuState.theme} `,
{
'top-active-menu': isAppendActiveCls,
},
];
return (
<Menu.Item key={menu.path} class={levelCls}>
{() => [
<MenuContent
item={menu}
showTitle={unref(showTitle)}
isHorizontal={props.isHorizontal}
/>,
]}
</Menu.Item>
);
}
function renderSubMenu(menu: MenuType, level: number) {
const levelCls = `${prefixCls}-item__level${level} ${menuState.theme} `;
return (
<Menu.SubMenu key={menu.path} class={levelCls}>
{{
title: () => [
<MenuContent
showTitle={unref(showTitle)}
item={menu}
isHorizontal={props.isHorizontal}
/>,
],
// expandIcon: renderExpandIcon,
default: () => (menu.children || []).map((item) => renderItem(item, level + 1)),
}}
</Menu.SubMenu>
);
}
function renderMenu() {
const isInline = props.mode === MenuModeEnum.INLINE;
const { selectedKeys, defaultSelectedKeys, mode, theme } = menuState;
const inlineCollapsedObj = isInline
? {
inlineCollapsed: unref(getCollapsed),
}
: {};
return (
<Menu
selectedKeys={selectedKeys}
......@@ -224,36 +241,25 @@ export default defineComponent({
inlineIndent={props.inlineIndent}
theme={unref(theme)}
onOpenChange={handleOpenChange}
class={[
'basic-menu',
props.collapsedShowTitle && 'collapsed-show-title',
...unref(transparentMenuClass),
]}
{...inlineCollapsedObj}
class={unref(getMenuClass)}
onClick={handleMenuClick}
{...unref(getInlineCollapseOptions)}
>
{{
default: () => renderMenuItem(props.items, 1),
default: () => unref(items).map((item) => renderItem(item)),
}}
</Menu>
);
}
onMounted(async () => {
getParentPath();
});
return () => {
const { mode } = props;
return mode === MenuModeEnum.HORIZONTAL ? (
renderMenu()
) : (
<section class={[`basic-menu-wrap`, !unref(showTitle) && 'hide-title']}>
{getSlot(slots, 'header')}
<section style={unref(getMenuWrapStyle)} class="basic-menu__content">
return (
<>
{!unref(getIsHorizontal) && getSlot(slots, 'header')}
<div class={`${prefixCls}-wrapper`} style={unref(getWrapperStyle)}>
{renderMenu()}
</section>
</section>
</div>
</>
);
};
},
......
<template>
<div> </div>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
export default defineComponent({
setup() {
return {};
},
});
</script>
import type { Menu as MenuType } from '/@/router/types';
import { computed, PropType, unref } from 'vue';
import type { PropType } from 'vue';
import { computed, unref } from 'vue';
import { defineComponent } from 'vue';
import Icon from '/@/components/Icon/index';
import { useI18n } from '/@/hooks/web/useI18n';
import { useDesign } from '/@/hooks/web/useDesign';
const { t } = useI18n();
export default defineComponent({
name: 'MenuContent',
......@@ -12,12 +16,10 @@ export default defineComponent({
type: Object as PropType<MenuType>,
default: null,
},
showTitle: {
type: Boolean as PropType<boolean>,
default: true,
},
level: {
type: Number as PropType<number>,
default: 0,
......@@ -28,13 +30,32 @@ export default defineComponent({
},
},
setup(props) {
const { t } = useI18n();
const { prefixCls } = useDesign('basic-menu');
const getI18nName = computed(() => t(props.item?.name));
const getTagClass = computed(() => {
const { item } = props;
const { tag = {} } = item || {};
const { dot, type = 'error' } = tag;
return [
`${prefixCls}__tag`,
type,
{
dot,
},
];
});
const getNameClass = computed(() => {
const { showTitle } = props;
return { [`${prefixCls}--show-title`]: showTitle, [`${prefixCls}__name`]: !showTitle };
});
/**
* @description: 渲染图标
*/
function renderIcon(icon: string) {
function renderIcon(icon?: string) {
return icon ? <Icon icon={icon} size={18} class="menu-item-icon" /> : null;
}
......@@ -45,36 +66,30 @@ export default defineComponent({
const { tag } = item;
if (!tag) return null;
const { dot, content, type = 'error' } = tag;
const { dot, content } = tag;
if (!dot && !content) return null;
const cls = ['basic-menu__tag'];
dot && cls.push('dot');
type && cls.push(type);
return <span class={cls}>{dot ? '' : content}</span>;
return <span class={unref(getTagClass)}>{dot ? '' : content}</span>;
}
return () => {
if (!props.item) {
const { item } = props;
if (!item) {
return null;
}
const { showTitle } = props;
const { icon } = props.item;
const { icon } = item;
const name = unref(getI18nName);
const cls = showTitle ? ['show-title'] : ['basic-menu__name'];
return (
<>
{renderIcon(icon!)}
<span class={`${prefixCls}__content-wrapper`}>
{renderIcon(icon)}
{
<span class={[cls]}>
<span class={unref(getNameClass)}>
{name}
{renderTag()}
</span>
}
</>
</span>
);
};
},
......
@import (reference) '../../../design/index.less';
@basic-menu-prefix-cls: ~'@{namespace}-basic-menu';
.active-style() {
color: @white;
background: linear-gradient(
......@@ -16,21 +18,48 @@
}
}
.basic-menu {
.@{basic-menu-prefix-cls} {
width: 100%;
&-wrap {
height: 100%;
}
// &__expand-icon {
// position: absolute;
// top: calc(50% - 6px);
// right: 16px;
// width: 10px;
// transform-origin: none;
// span[role='img'] {
// margin-right: 0;
// font-size: 11px;
// }
// &--collapsed {
// opacity: 0;
// }
// }
// collapsed show title start
.show-title {
&--show-title {
max-width: unset !important;
opacity: 1 !important;
}
&.collapsed-show-title.ant-menu-inline-collapsed {
.basic-menu-item__level1 {
&--hide-title {
&.ant-menu-inline-collapsed > .ant-menu-item,
&.ant-menu-inline-collapsed > .ant-menu-item-group > .ant-menu-item-group-list > .ant-menu-item,
&.ant-menu-inline-collapsed
> .ant-menu-item-group
> .ant-menu-item-group-list
> .ant-menu-submenu
> .ant-menu-submenu-title,
&.ant-menu-inline-collapsed > .ant-menu-submenu > .ant-menu-submenu-title {
padding-right: 20px !important;
padding-left: 20px !important;
}
}
&--collapsed-show-title.ant-menu-inline-collapsed {
.@{basic-menu-prefix-cls}-item__level1 {
padding: 2px 0;
}
......@@ -47,14 +76,23 @@
& > li > .ant-menu-submenu-title {
line-height: 24px;
}
.@{basic-menu-prefix-cls}__content-wrapper {
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
.@{basic-menu-prefix-cls}--show-title {
line-height: 30px;
}
}
}
.ant-menu-item {
transition: unset;
}
// .ant-menu-item {
// transition: unset;
// }
// scrollbar -s tart
&__content {
&-wrapper {
/* 滚动槽 */
&::-webkit-scrollbar {
width: 5px;
......@@ -75,8 +113,20 @@
background: @border-color-dark;
}
}
// scrollbar end
&-item__level1.light {
&.top-active-menu {
top: 0 !important;
}
&.top-active-menu:not(.ant-menu-item-selected) {
color: @primary-color;
border-bottom: 3px solid @primary-color;
}
}
&__sidebar-hor {
// overflow: hidden;
......@@ -85,20 +135,13 @@
border: 0;
align-items: center;
.basic-menu-item__level1 {
.@{basic-menu-prefix-cls}-item__level1 {
margin-right: 2px;
}
&.ant-menu-light {
.basic-menu-item__level1 {
&.top-active-menu {
color: @primary-color;
border-bottom: 3px solid @primary-color;
}
}
.ant-menu-item {
&.basic-menu-item__level1 {
&.@{basic-menu-prefix-cls}-item__level1 {
height: @header-height;
line-height: @header-height;
}
......@@ -155,7 +198,7 @@
background: @top-menu-active-bg-color;
}
.basic-menu-item__level1 {
.@{basic-menu-prefix-cls}-item__level1 {
background: transparent;
&.top-active-menu {
......@@ -172,7 +215,7 @@
.ant-menu-item,
.ant-menu-submenu {
&.basic-menu-item__level1,
&.@{basic-menu-prefix-cls}-item__level1,
.ant-menu-submenu-title {
height: @header-height;
line-height: @header-height;
......@@ -182,17 +225,17 @@
}
}
&:not(.basic-menu__sidebar-hor).ant-menu-inline-collapsed {
.basic-menu-item__level1 {
&:not(.@{basic-menu-prefix-cls}__sidebar-hor).ant-menu-inline-collapsed {
.@{basic-menu-prefix-cls}-item__level1 {
> div {
align-items: center;
}
}
}
&.ant-menu-dark:not(.basic-menu__sidebar-hor):not(.basic-menu__second) {
&.ant-menu-dark:not(.@{basic-menu-prefix-cls}__sidebar-hor):not(.@{basic-menu-prefix-cls}__second) {
// Reset menu item row height
.ant-menu-item:not(.basic-menu-item__level1),
.ant-menu-item:not(.@{basic-menu-prefix-cls}-item__level1),
.ant-menu-sub.ant-menu-inline > .ant-menu-item,
.ant-menu-sub.ant-menu-inline > .ant-menu-submenu > .ant-menu-submenu-title {
height: @app-menu-item-height;
......@@ -200,28 +243,28 @@
line-height: @app-menu-item-height;
}
.ant-menu-item.basic-menu-item__level1 {
.ant-menu-item.@{basic-menu-prefix-cls}-item__level1 {
height: @app-menu-item-height;
line-height: @app-menu-item-height;
}
}
// 层级样式
&.ant-menu-dark:not(.basic-menu__sidebar-hor) {
overflow-x: hidden;
&.ant-menu-dark:not(.@{basic-menu-prefix-cls}__sidebar-hor) {
overflow: hidden;
background: @sider-dark-bg-color;
.active-menu-style();
.menu-item-icon.app-iconify {
display: inline-block !important;
}
// .menu-item-icon.app-iconify {
// display: inline-block !important;
// }
.ant-menu-item.ant-menu-item-selected.basic-menu-menu-item__level1,
.ant-menu-submenu-selected.basic-menu-menu-item__level1 {
.ant-menu-item.ant-menu-item-selected.@{basic-menu-prefix-cls}-menu-item__level1,
.ant-menu-submenu-selected.@{basic-menu-prefix-cls}-menu-item__level1 {
color: @white;
}
.basic-menu-item__level1 {
.@{basic-menu-prefix-cls}-item__level1 {
background-color: @sider-dark-bg-color;
> .ant-menu-sub > li {
......@@ -229,12 +272,12 @@
}
}
.basic-menu-item__level2:not(.ant-menu-item-selected),
.@{basic-menu-prefix-cls}-item__level2:not(.ant-menu-item-selected),
.ant-menu-sub {
background-color: @sider-dark-lighten-1-bg-color;
}
.basic-menu-item__level3:not(.ant-menu-item-selected) {
.@{basic-menu-prefix-cls}-item__level3:not(.ant-menu-item-selected) {
background-color: @sider-dark-lighten-2-bg-color;
.ant-menu-item {
......@@ -257,35 +300,26 @@
}
}
&.ant-menu-light:not(.basic-menu__sidebar-hor) {
overflow-x: hidden;
&.ant-menu-light:not(.@{basic-menu-prefix-cls}__sidebar-hor) {
overflow: hidden;
border-right: none;
.menu-item-icon.app-iconify {
display: inline-block !important;
}
// .ant-menu-item-selected {
// background: fade(@primary-color, 18%);
// .menu-item-icon.app-iconify {
// display: inline-block !important;
// }
.ant-menu-item.ant-menu-item-selected.basic-menu-menu-item__level1,
.ant-menu-submenu-selected.basic-menu-menu-item__level1 {
.ant-menu-item.ant-menu-item-selected.@{basic-menu-prefix-cls}-menu-item__level1,
.ant-menu-submenu-selected.@{basic-menu-prefix-cls}-menu-item__level1 {
color: @primary-color;
}
}
// 关键字的颜色
&__keyword {
color: lighten(@primary-color, 20%);
}
// 激活的子菜单样式
.ant-menu-item.ant-menu-item-selected {
position: relative;
}
&.basic-menu__second.ant-menu-inline-collapsed:not(.basic-menu__sidebar-hor) {
&.@{basic-menu-prefix-cls}__second.ant-menu-inline-collapsed:not(.@{basic-menu-prefix-cls}__sidebar-hor) {
// Reset menu item row height
.ant-menu-item,
.ant-menu-sub.ant-menu-inline > .ant-menu-item,
......@@ -298,26 +332,40 @@
align-items: center;
}
}
}
.@{basic-menu-prefix-cls}__tag {
position: absolute;
top: calc(50% - 8px);
right: 30px;
display: inline-block;
padding: 2px 4px;
margin-right: 4px;
font-size: 12px;
line-height: 14px;
color: #fff;
border-radius: 2px;
&.dot {
top: calc(50% - 4px);
width: 8px;
height: 8px;
padding: 0;
border-radius: 50%;
}
// 触发器样式
.ant-layout-sider {
&-dark {
.ant-layout-sider-trigger {
color: darken(@white, 25%);
background: @trigger-dark-bg-color;
&.primary {
background: @primary-color;
}
&:hover {
color: @white;
background: @trigger-dark-hover-bg-color;
}
&.error {
background: @error-color;
}
&.success {
background: @success-color;
}
}
&-light {
.ant-layout-sider-trigger {
color: @text-color-base;
border-top: 1px solid @border-color-light;
&.warn {
background: @warning-color;
}
}
}
......@@ -332,71 +380,16 @@
}
}
.hide-title {
.ant-menu-inline-collapsed > .ant-menu-item,
.ant-menu-inline-collapsed > .ant-menu-item-group > .ant-menu-item-group-list > .ant-menu-item,
.ant-menu-inline-collapsed
> .ant-menu-item-group
> .ant-menu-item-group-list
> .ant-menu-submenu
> .ant-menu-submenu-title,
.ant-menu-inline-collapsed > .ant-menu-submenu > .ant-menu-submenu-title {
padding-right: 20px !important;
padding-left: 20px !important;
}
.ant-menu-inline-collapsed {
.basic-menu-item__level1 {
display: flex;
justify-content: center;
}
}
}
// collapsed show title end
.ant-menu-item,
.ant-menu-submenu-title {
> .basic-menu__name {
> .@{basic-menu-prefix-cls}__name {
width: 100%;
.basic-menu__tag {
.@{basic-menu-prefix-cls}__tag {
float: right;
margin-top: @app-menu-item-height / 2;
transform: translate(0%, -50%);
}
}
}
.basic-menu__tag {
display: inline-block;
padding: 2px 4px;
margin-right: 4px;
font-size: 12px;
line-height: 14px;
color: #fff;
border-radius: 2px;
&.dot {
width: 8px;
height: 8px;
padding: 0;
margin-top: 21px !important;
margin-bottom: 2px;
border-radius: 50%;
}
&.primary {
background: @primary-color;
}
&.error {
background: @error-color;
}
&.success {
background: @success-color;
}
&.warn {
background: @warning-color;
}
}
......@@ -8,14 +8,11 @@ export const basicProps = {
type: Array as PropType<Menu[]>,
default: () => [],
},
flatItems: {
type: Array as PropType<Menu[]>,
default: () => [],
},
appendClass: {
type: Boolean as PropType<boolean>,
default: false,
},
collapsedShowTitle: {
type: Boolean as PropType<boolean>,
default: false,
......@@ -31,6 +28,10 @@ export const basicProps = {
type: String as PropType<MenuModeEnum>,
default: MenuModeEnum.INLINE,
},
showLogo: {
type: Boolean as PropType<boolean>,
default: false,
},
type: {
type: String as PropType<MenuTypeEnum>,
default: MenuTypeEnum.MIX,
......@@ -39,10 +40,6 @@ export const basicProps = {
type: String as PropType<string>,
default: ThemeEnum.DARK,
},
showLogo: {
type: Boolean as PropType<boolean>,
default: false,
},
inlineCollapsed: {
type: Boolean as PropType<boolean>,
default: false,
......@@ -57,7 +54,6 @@ export const basicProps = {
default: true,
},
beforeClickFn: {
type: Function as PropType<Fn>,
default: null,
type: Function as PropType<(key: string) => Promise<boolean>>,
},
};
import { MenuModeEnum } from '/@/enums/menuEnum';
import type { Menu as MenuType } from '/@/router/types';
import type { MenuState } from './types';
import type { Ref } from 'vue';
import { computed, Ref, toRaw } from 'vue';
import { unref } from 'vue';
import { getAllParentPath } from '/@/router/helper/menuHelper';
import { es6Unique } from '/@/utils';
import { useMenuSetting } from '/@/hooks/setting/useMenuSetting';
import { getAllParentPath } from '/@/router/helper/menuHelper';
export function useOpenKeys(
menuState: MenuState,
menus: Ref<MenuType[]>,
flatMenusRef: Ref<MenuType[]>,
mode: Ref<MenuModeEnum>,
accordion: Ref<boolean>
) {
const { getCollapsed } = useMenuSetting();
function setOpenKeys(menu: MenuType) {
const flatMenus = unref(flatMenusRef);
function setOpenKeys(path: string) {
const menuList = toRaw(menus.value);
if (!unref(accordion)) {
menuState.openKeys = es6Unique([
...menuState.openKeys,
...getAllParentPath(flatMenus, menu.path),
]);
menuState.openKeys = es6Unique([...menuState.openKeys, ...getAllParentPath(menuList, path)]);
} else {
menuState.openKeys = getAllParentPath(flatMenus, menu.path);
menuState.openKeys = getAllParentPath(menuList, path);
}
}
const getOpenKeys = computed(() => {
return unref(getCollapsed) ? menuState.collapsedOpenKeys : menuState.openKeys;
});
/**
* @description: 重置值
*/
......@@ -59,5 +60,5 @@ export function useOpenKeys(
}
}
}
return { setOpenKeys, resetKeys, handleOpenChange };
return { setOpenKeys, resetKeys, getOpenKeys, handleOpenChange };
}
......@@ -11,76 +11,76 @@ import { useFullContent } from '/@/hooks/web/useFullContent';
import { MenuModeEnum } from '/@/enums/menuEnum';
export function useHeaderSetting() {
const { getFullContent } = useFullContent();
const { getShowMultipleTab } = useMultipleTabSetting();
const {
getMenuMode,
getSplit,
getShowHeaderTrigger,
getIsSidebarType,
getIsTopMenu,
} = useMenuSetting();
const { getShowBreadCrumb, getShowLogo } = useRootSetting();
const { getFullContent } = useFullContent();
const { getShowMultipleTab } = useMultipleTabSetting();
const {
getMenuMode,
getSplit,
getShowHeaderTrigger,
getIsSidebarType,
getIsTopMenu,
} = useMenuSetting();
const { getShowBreadCrumb, getShowLogo } = useRootSetting();
const getShowMixHeaderRef = computed(() => !unref(getIsSidebarType) && unref(getShowHeader));
const getShowMixHeaderRef = computed(() => !unref(getIsSidebarType) && unref(getShowHeader));
const getShowFullHeaderRef = computed(() => {
return (
!unref(getFullContent) &&
unref(getShowMixHeaderRef) &&
unref(getShowHeader) &&
!unref(getIsTopMenu)
);
});
const getShowFullHeaderRef = computed(() => {
return (
!unref(getFullContent) &&
unref(getShowMixHeaderRef) &&
unref(getShowHeader) &&
!unref(getIsTopMenu)
);
});
const getShowInsetHeaderRef = computed(() => {
const need = !unref(getFullContent) && unref(getShowHeader);
return (need && !unref(getShowMixHeaderRef)) || (need && unref(getIsTopMenu));
});
const getShowInsetHeaderRef = computed(() => {
const need = !unref(getFullContent) && unref(getShowHeader);
return (need && !unref(getShowMixHeaderRef)) || (need && unref(getIsTopMenu));
});
// Get header configuration
const getHeaderSetting = computed(() => appStore.getProjectConfig.headerSetting);
// Get header configuration
const getHeaderSetting = computed(() => appStore.getProjectConfig.headerSetting);
const getShowDoc = computed(() => unref(getHeaderSetting).showDoc);
const getShowDoc = computed(() => unref(getHeaderSetting).showDoc);
const getHeaderTheme = computed(() => unref(getHeaderSetting).theme);
const getHeaderTheme = computed(() => unref(getHeaderSetting).theme);
const getShowHeader = computed(() => unref(getHeaderSetting).show);
const getShowHeader = computed(() => unref(getHeaderSetting).show);
const getFixed = computed(() => unref(getHeaderSetting).fixed);
const getFixed = computed(() => unref(getHeaderSetting).fixed);
const getHeaderBgColor = computed(() => unref(getHeaderSetting).bgColor);
const getHeaderBgColor = computed(() => unref(getHeaderSetting).bgColor);
const getShowRedo = computed(() => unref(getHeaderSetting).showRedo && unref(getShowMultipleTab));
const getShowRedo = computed(() => unref(getHeaderSetting).showRedo && unref(getShowMultipleTab));
const getUseLockPage = computed(() => unref(getHeaderSetting).useLockPage);
const getUseLockPage = computed(() => unref(getHeaderSetting).useLockPage);
const getShowFullScreen = computed(() => unref(getHeaderSetting).showFullScreen);
const getShowFullScreen = computed(() => unref(getHeaderSetting).showFullScreen);
const getShowNotice = computed(() => unref(getHeaderSetting).showNotice);
const getShowNotice = computed(() => unref(getHeaderSetting).showNotice);
const getUnFixedAndFull = computed(() => !unref(getFixed) && !unref(getShowFullHeaderRef));
const getUnFixedAndFull = computed(() => !unref(getFixed) && !unref(getShowFullHeaderRef));
const getShowBread = computed(() => {
return (
unref(getMenuMode) !== MenuModeEnum.HORIZONTAL && unref(getShowBreadCrumb) && !unref(getSplit)
);
});
const getShowBread = computed(() => {
return (
unref(getMenuMode) !== MenuModeEnum.HORIZONTAL && unref(getShowBreadCrumb) && !unref(getSplit)
);
});
const getShowHeaderLogo = computed(() => {
return unref(getShowLogo) && !unref(getIsSidebarType);
});
const getShowHeaderLogo = computed(() => {
return unref(getShowLogo) && !unref(getIsSidebarType);
});
const getShowContent = computed(() => {
return unref(getShowBread) || unref(getShowHeaderTrigger);
});
const getShowContent = computed(() => {
return unref(getShowBread) || unref(getShowHeaderTrigger);
});
// Set header configuration
function setHeaderSetting(headerSetting: Partial<HeaderSetting>): void {
appStore.commitProjectConfigState({ headerSetting });
}
// Set header configuration
function setHeaderSetting(headerSetting: Partial<HeaderSetting>): void {
appStore.commitProjectConfigState({ headerSetting });
}
export function useHeaderSetting() {
return {
setHeaderSetting,
......
......@@ -6,26 +6,26 @@ import { appStore } from '/@/store/modules/app';
import getProjectSetting from '/@/settings/projectSetting';
import { localeList } from '/@/locales';
export function useLocaleSetting() {
// Get locale configuration
const getLocale = computed(() => appStore.getProjectConfig.locale || getProjectSetting.locale);
// Get locale configuration
const getLocale = computed(() => appStore.getProjectConfig.locale || getProjectSetting.locale);
// get current language
const getLang = computed(() => unref(getLocale).lang);
// get current language
const getLang = computed(() => unref(getLocale).lang);
// get Available Locales
const getAvailableLocales = computed((): string[] => unref(getLocale).availableLocales);
// get Available Locales
const getAvailableLocales = computed((): string[] => unref(getLocale).availableLocales);
// get Fallback Locales
const getFallbackLocale = computed((): string => unref(getLocale).fallback);
// get Fallback Locales
const getFallbackLocale = computed((): string => unref(getLocale).fallback);
const getShowLocale = computed(() => unref(getLocale).show);
const getShowLocale = computed(() => unref(getLocale).show);
// Set locale configuration
function setLocale(locale: Partial<LocaleSetting>): void {
appStore.commitProjectConfigState({ locale });
}
// Set locale configuration
function setLocale(locale: Partial<LocaleSetting>): void {
appStore.commitProjectConfigState({ locale });
}
export function useLocaleSetting() {
return {
getLocale,
getLang,
......
......@@ -7,89 +7,89 @@ import { appStore } from '/@/store/modules/app';
import { SIDE_BAR_MINI_WIDTH, SIDE_BAR_SHOW_TIT_MINI_WIDTH } from '/@/enums/appEnum';
import { MenuModeEnum, MenuTypeEnum, TriggerEnum } from '/@/enums/menuEnum';
export function useMenuSetting() {
// Get menu configuration
const getMenuSetting = computed(() => appStore.getProjectConfig.menuSetting);
// Get menu configuration
const getMenuSetting = computed(() => appStore.getProjectConfig.menuSetting);
const getCollapsed = computed(() => unref(getMenuSetting).collapsed);
const getCollapsed = computed(() => unref(getMenuSetting).collapsed);
const getMenuType = computed(() => unref(getMenuSetting).type);
const getMenuType = computed(() => unref(getMenuSetting).type);
const getMenuMode = computed(() => unref(getMenuSetting).mode);
const getMenuMode = computed(() => unref(getMenuSetting).mode);
const getMenuFixed = computed(() => unref(getMenuSetting).fixed);
const getMenuFixed = computed(() => unref(getMenuSetting).fixed);
const getShowMenu = computed(() => unref(getMenuSetting).show);
const getShowMenu = computed(() => unref(getMenuSetting).show);
const getMenuHidden = computed(() => unref(getMenuSetting).hidden);
const getMenuHidden = computed(() => unref(getMenuSetting).hidden);
const getMenuWidth = computed(() => unref(getMenuSetting).menuWidth);
const getMenuWidth = computed(() => unref(getMenuSetting).menuWidth);
const getTrigger = computed(() => unref(getMenuSetting).trigger);
const getTrigger = computed(() => unref(getMenuSetting).trigger);
const getMenuTheme = computed(() => unref(getMenuSetting).theme);
const getMenuTheme = computed(() => unref(getMenuSetting).theme);
const getSplit = computed(() => unref(getMenuSetting).split);
const getSplit = computed(() => unref(getMenuSetting).split);
const getMenuBgColor = computed(() => unref(getMenuSetting).bgColor);
const getMenuBgColor = computed(() => unref(getMenuSetting).bgColor);
const getCanDrag = computed(() => unref(getMenuSetting).canDrag);
const getCanDrag = computed(() => unref(getMenuSetting).canDrag);
const getAccordion = computed(() => unref(getMenuSetting).accordion);
const getAccordion = computed(() => unref(getMenuSetting).accordion);
const getCollapsedShowTitle = computed(() => unref(getMenuSetting).collapsedShowTitle);
const getCollapsedShowTitle = computed(() => unref(getMenuSetting).collapsedShowTitle);
const getTopMenuAlign = computed(() => unref(getMenuSetting).topMenuAlign);
const getTopMenuAlign = computed(() => unref(getMenuSetting).topMenuAlign);
const getIsSidebarType = computed(() => unref(getMenuType) === MenuTypeEnum.SIDEBAR);
const getIsSidebarType = computed(() => unref(getMenuType) === MenuTypeEnum.SIDEBAR);
const getIsTopMenu = computed(() => unref(getMenuType) === MenuTypeEnum.TOP_MENU);
const getIsTopMenu = computed(() => unref(getMenuType) === MenuTypeEnum.TOP_MENU);
const getShowTopMenu = computed(() => {
return unref(getMenuMode) === MenuModeEnum.HORIZONTAL || unref(getSplit);
});
const getShowTopMenu = computed(() => {
return unref(getMenuMode) === MenuModeEnum.HORIZONTAL || unref(getSplit);
});
const getShowHeaderTrigger = computed(() => {
if (
unref(getMenuType) === MenuTypeEnum.TOP_MENU ||
!unref(getShowMenu) ||
!unref(getMenuHidden)
) {
return false;
}
const getShowHeaderTrigger = computed(() => {
if (
unref(getMenuType) === MenuTypeEnum.TOP_MENU ||
!unref(getShowMenu) ||
!unref(getMenuHidden)
) {
return false;
}
return unref(getTrigger) === TriggerEnum.HEADER;
});
return unref(getTrigger) === TriggerEnum.HEADER;
});
const getIsHorizontal = computed(() => {
return unref(getMenuMode) === MenuModeEnum.HORIZONTAL;
});
const getIsHorizontal = computed(() => {
return unref(getMenuMode) === MenuModeEnum.HORIZONTAL;
});
const getRealWidth = computed(() => {
return unref(getCollapsed) ? unref(getMiniWidthNumber) : unref(getMenuWidth);
});
const getRealWidth = computed(() => {
return unref(getCollapsed) ? unref(getMiniWidthNumber) : unref(getMenuWidth);
});
const getMiniWidthNumber = computed(() => {
const { collapsedShowTitle } = unref(getMenuSetting);
return collapsedShowTitle ? SIDE_BAR_SHOW_TIT_MINI_WIDTH : SIDE_BAR_MINI_WIDTH;
});
const getMiniWidthNumber = computed(() => {
const { collapsedShowTitle } = unref(getMenuSetting);
return collapsedShowTitle ? SIDE_BAR_SHOW_TIT_MINI_WIDTH : SIDE_BAR_MINI_WIDTH;
});
const getCalcContentWidth = computed(() => {
const width = unref(getIsTopMenu) || !unref(getShowMenu) ? 0 : unref(getRealWidth);
return `calc(100% - ${unref(width)}px)`;
});
const getCalcContentWidth = computed(() => {
const width = unref(getIsTopMenu) || !unref(getShowMenu) ? 0 : unref(getRealWidth);
return `calc(100% - ${unref(width)}px)`;
});
// Set menu configuration
function setMenuSetting(menuSetting: Partial<MenuSetting>): void {
appStore.commitProjectConfigState({ menuSetting });
}
// Set menu configuration
function setMenuSetting(menuSetting: Partial<MenuSetting>): void {
appStore.commitProjectConfigState({ menuSetting });
}
function toggleCollapsed() {
setMenuSetting({
collapsed: !unref(getCollapsed),
});
}
function toggleCollapsed() {
setMenuSetting({
collapsed: !unref(getCollapsed),
});
}
export function useMenuSetting() {
return {
setMenuSetting,
......
......@@ -4,17 +4,17 @@ import { computed, unref } from 'vue';
import { appStore } from '/@/store/modules/app';
export function useMultipleTabSetting() {
const getMultipleTabSetting = computed(() => appStore.getProjectConfig.multiTabsSetting);
const getMultipleTabSetting = computed(() => appStore.getProjectConfig.multiTabsSetting);
const getShowMultipleTab = computed(() => unref(getMultipleTabSetting).show);
const getShowMultipleTab = computed(() => unref(getMultipleTabSetting).show);
const getShowQuick = computed(() => unref(getMultipleTabSetting).showQuick);
const getShowQuick = computed(() => unref(getMultipleTabSetting).showQuick);
function setMultipleTabSetting(multiTabsSetting: Partial<MultiTabsSetting>) {
appStore.commitProjectConfigState({ multiTabsSetting });
}
function setMultipleTabSetting(multiTabsSetting: Partial<MultiTabsSetting>) {
appStore.commitProjectConfigState({ multiTabsSetting });
}
export function useMultipleTabSetting() {
return {
setMultipleTabSetting,
......
......@@ -9,47 +9,48 @@ type RootSetting = Omit<
ProjectConfig,
'locale' | 'headerSetting' | 'menuSetting' | 'multiTabsSetting'
>;
export function useRootSetting() {
const getRootSetting = computed((): RootSetting => appStore.getProjectConfig);
const getPageLoading = computed(() => appStore.getPageLoading);
const getRootSetting = computed((): RootSetting => appStore.getProjectConfig);
const getPageLoading = computed(() => appStore.getPageLoading);
const getOpenKeepAlive = computed(() => unref(getRootSetting).openKeepAlive);
const getOpenKeepAlive = computed(() => unref(getRootSetting).openKeepAlive);
const getCanEmbedIFramePage = computed(() => unref(getRootSetting).canEmbedIFramePage);
const getCanEmbedIFramePage = computed(() => unref(getRootSetting).canEmbedIFramePage);
const getPermissionMode = computed(() => unref(getRootSetting).permissionMode);
const getPermissionMode = computed(() => unref(getRootSetting).permissionMode);
const getShowLogo = computed(() => unref(getRootSetting).showLogo);
const getShowLogo = computed(() => unref(getRootSetting).showLogo);
const getContentMode = computed(() => unref(getRootSetting).contentMode);
const getContentMode = computed(() => unref(getRootSetting).contentMode);
const getUseOpenBackTop = computed(() => unref(getRootSetting).useOpenBackTop);
const getUseOpenBackTop = computed(() => unref(getRootSetting).useOpenBackTop);
const getShowSettingButton = computed(() => unref(getRootSetting).showSettingButton);
const getShowSettingButton = computed(() => unref(getRootSetting).showSettingButton);
const getUseErrorHandle = computed(() => unref(getRootSetting).useErrorHandle);
const getUseErrorHandle = computed(() => unref(getRootSetting).useErrorHandle);
const getShowFooter = computed(() => unref(getRootSetting).showFooter);
const getShowFooter = computed(() => unref(getRootSetting).showFooter);
const getShowBreadCrumb = computed(() => unref(getRootSetting).showBreadCrumb);
const getShowBreadCrumb = computed(() => unref(getRootSetting).showBreadCrumb);
const getShowBreadCrumbIcon = computed(() => unref(getRootSetting).showBreadCrumbIcon);
const getShowBreadCrumbIcon = computed(() => unref(getRootSetting).showBreadCrumbIcon);
const getFullContent = computed(() => unref(getRootSetting).fullContent);
const getFullContent = computed(() => unref(getRootSetting).fullContent);
const getColorWeak = computed(() => unref(getRootSetting).colorWeak);
const getColorWeak = computed(() => unref(getRootSetting).colorWeak);
const getGrayMode = computed(() => unref(getRootSetting).grayMode);
const getGrayMode = computed(() => unref(getRootSetting).grayMode);
const getLayoutContentMode = computed(() =>
unref(getRootSetting).contentMode === ContentEnum.FULL ? ContentEnum.FULL : ContentEnum.FIXED
);
const getLayoutContentMode = computed(() =>
unref(getRootSetting).contentMode === ContentEnum.FULL ? ContentEnum.FULL : ContentEnum.FIXED
);
function setRootSetting(setting: Partial<RootSetting>) {
appStore.commitProjectConfigState(setting);
}
function setRootSetting(setting: Partial<RootSetting>) {
appStore.commitProjectConfigState(setting);
}
export function useRootSetting() {
return {
setRootSetting,
......
......@@ -4,23 +4,23 @@ import { computed, unref } from 'vue';
import { appStore } from '/@/store/modules/app';
export function useTransitionSetting() {
const getTransitionSetting = computed(() => appStore.getProjectConfig.transitionSetting);
const getTransitionSetting = computed(() => appStore.getProjectConfig.transitionSetting);
const getEnableTransition = computed(() => unref(getTransitionSetting)?.enable);
const getEnableTransition = computed(() => unref(getTransitionSetting)?.enable);
const getOpenNProgress = computed(() => unref(getTransitionSetting)?.openNProgress);
const getOpenNProgress = computed(() => unref(getTransitionSetting)?.openNProgress);
const getOpenPageLoading = computed((): boolean => {
return !!unref(getTransitionSetting)?.openPageLoading;
});
const getOpenPageLoading = computed((): boolean => {
return !!unref(getTransitionSetting)?.openPageLoading;
});
const getBasicTransition = computed(() => unref(getTransitionSetting)?.basicTransition);
const getBasicTransition = computed(() => unref(getTransitionSetting)?.basicTransition);
function setTransitionSetting(transitionSetting: Partial<TransitionSetting>) {
appStore.commitProjectConfigState({ transitionSetting });
}
function setTransitionSetting(transitionSetting: Partial<TransitionSetting>) {
appStore.commitProjectConfigState({ transitionSetting });
}
export function useTransitionSetting() {
return {
setTransitionSetting,
......
import { useAppProviderContext } from '/@/components/Application';
import { computed } from 'vue';
// import { useCssModule, reactive } from 'vue';
// import { computed } from 'vue';
// import { lowerFirst } from 'lodash-es';
export function useDesign(scope: string) {
const values = useAppProviderContext();
// const style = cssModule ? useCssModule() : {};
// const $style = cssModule ? useCssModule() : {};
// const style: Record<string, string> = {};
// if (cssModule) {
// Object.keys(style).forEach((key) => {
// const moduleCls = style[key];
// style[key] = `${cls}-${moduleCls}`;
// Object.keys($style).forEach((key) => {
// // const moduleCls = $style[key];
// const k = key.replace(new RegExp(`^${values.prefixCls}-?`, 'ig'), '');
// style[lowerFirst(k)] = $style[key];
// });
// }
return {
prefixCls: computed(() => `${values.prefixCls}-${scope}`),
// prefixCls: computed(() => `${values.prefixCls}-${scope}`),
prefixCls: `${values.prefixCls}-${scope}`,
prefixVar: values.prefixCls,
// style,
};
......
......@@ -2,12 +2,12 @@ import { computed, unref } from 'vue';
import { appStore } from '/@/store/modules/app';
import { useRouter } from 'vue-router';
import router from '/@/router';
/**
* @description: Full screen display content
*/
export const useFullContent = () => {
const { currentRoute } = useRouter();
const { currentRoute } = router;
// Whether to display the content in full screen without displaying the menu
const getFullContent = computed(() => {
......
import { appStore } from '/@/store/modules/app';
import type { RouteLocationRaw } from 'vue-router';
import { PageEnum } from '/@/enums/pageEnum';
......@@ -11,7 +10,6 @@ export type RouteLocationRawEx = Omit<RouteLocationRaw, 'path'> & { path: PageEn
function handleError(e: Error) {
console.error(e);
appStore.commitPageLoadingState(false);
}
// page switch
......
......@@ -80,13 +80,7 @@ export default defineComponent({
const { refreshPage } = useTabs();
const { t } = useI18n();
const {
getShowTopMenu,
getShowHeaderTrigger,
getSplit,
getTopMenuAlign,
getIsHorizontal,
} = useMenuSetting();
const { getShowTopMenu, getShowHeaderTrigger, getSplit, getIsHorizontal } = useMenuSetting();
const { getShowLocale } = useLocaleSetting();
const { getUseErrorHandle, getShowBreadCrumbIcon } = useRootSetting();
......@@ -184,7 +178,7 @@ export default defineComponent({
{/* <div class={[`layout-header__menu `]}> */}
<LayoutMenu
isHorizontal={true}
class={`justify-${unref(getTopMenuAlign)}`}
// class={`justify-${unref(getTopMenuAlign)}`}
theme={unref(getHeaderTheme)}
splitType={unref(getSplitType)}
menuMode={unref(getMenuMode)}
......
......@@ -21,7 +21,7 @@ export default defineComponent({
const injectValue = useLayoutContext();
const { getCalcContentWidth } = useMenuSetting();
const { getCalcContentWidth, getSplit } = useMenuSetting();
const {
getFixed,
......@@ -56,7 +56,8 @@ export default defineComponent({
(): CSSProperties => {
const style: CSSProperties = {};
if (unref(getFixed)) {
style.width = unref(injectValue.isMobile) ? '100%' : unref(getCalcContentWidth);
style.width =
unref(injectValue.isMobile) || unref(getSplit) ? '100%' : unref(getCalcContentWidth);
}
if (unref(getShowFullHeaderRef)) {
style.top = `${unref(fullHeaderHeightRef)}px`;
......
import './index.less';
import { PropType, toRef } from 'vue';
import type { Menu } from '/@/router/types';
import { computed, defineComponent, unref } from 'vue';
import { BasicMenu } from '/@/components/Menu/index';
import { BasicMenu } from '/@/components/Menu';
import { AppLogo } from '/@/components/Application';
import { MenuModeEnum, MenuSplitTyeEnum } from '/@/enums/menuEnum';
import { useMenuSetting } from '/@/hooks/setting/useMenuSetting';
import { useRootSetting } from '/@/hooks/setting/useRootSetting';
import { useGo } from '/@/hooks/web/usePage';
import { useSplitMenu } from './useLayoutMenu';
import { openWindow } from '/@/utils';
import { propTypes } from '/@/utils/propTypes';
import { isUrl } from '/@/utils/is';
import { useRootSetting } from '/@/hooks/setting/useRootSetting';
export default defineComponent({
name: 'LayoutMenu',
......@@ -38,56 +38,46 @@ export default defineComponent({
const go = useGo();
const {
setMenuSetting,
getMenuMode,
getMenuType,
getCollapsedShowTitle,
getIsSidebarType,
getMenuTheme,
getCollapsed,
getAccordion,
getIsSidebarType,
} = useMenuSetting();
const { getShowLogo } = useRootSetting();
const { flatMenusRef, menusRef } = useSplitMenu(toRef(props, 'splitType'));
const showLogo = computed(() => unref(getShowLogo) && unref(getIsSidebarType));
const { menusRef } = useSplitMenu(toRef(props, 'splitType'));
const getComputedMenuMode = computed(() => props.menuMode || unref(getMenuMode));
const getComputedMenuTheme = computed(() => props.theme || unref(getMenuTheme));
const showLogo = computed(() => unref(getShowLogo) && unref(getIsSidebarType));
const appendClass = computed(() => props.splitType === MenuSplitTyeEnum.TOP);
/**
* click menu
* @param menu
*/
function handleMenuClick(menu: Menu) {
go(menu.path);
function handleMenuClick(path: string) {
go(path);
}
/**
* before click menu
* @param menu
*/
async function beforeMenuClickFn(menu: Menu) {
const { meta: { externalLink } = {} } = menu;
if (externalLink) {
openWindow(externalLink);
return false;
async function beforeMenuClickFn(path: string) {
if (!isUrl(path)) {
return true;
}
return true;
}
function handleClickSearchInput() {
unref(getCollapsed) && setMenuSetting({ collapsed: false });
openWindow(path);
return false;
}
function renderHeader() {
if (!unref(showLogo)) return null;
return (
<AppLogo
showTitle={!unref(getCollapsed)}
......@@ -100,20 +90,17 @@ export default defineComponent({
return () => {
return (
<BasicMenu
class="layout-menu"
beforeClickFn={beforeMenuClickFn}
isHorizontal={props.isHorizontal}
appendClass={unref(appendClass)}
type={unref(getMenuType)}
mode={unref(getComputedMenuMode)}
collapsedShowTitle={unref(getCollapsedShowTitle)}
theme={unref(getComputedMenuTheme)}
showLogo={unref(showLogo)}
items={unref(menusRef)}
flatItems={unref(flatMenusRef)}
accordion={unref(getAccordion)}
onMenuClick={handleMenuClick}
onClickSearchInput={handleClickSearchInput}
appendClass={unref(appendClass)}
showLogo={unref(showLogo)}
>
{{
header: () => renderHeader(),
......
......@@ -8,24 +8,12 @@ import { MenuSplitTyeEnum } from '/@/enums/menuEnum';
import { useThrottle } from '/@/hooks/core/useThrottle';
import { useMenuSetting } from '/@/hooks/setting/useMenuSetting';
import {
getChildrenMenus,
getCurrentParentPath,
getFlatChildrenMenus,
getFlatMenus,
getMenus,
getShallowMenus,
} from '/@/router/menus';
import { getChildrenMenus, getCurrentParentPath, getMenus, getShallowMenus } from '/@/router/menus';
import { permissionStore } from '/@/store/modules/permission';
// import { useI18n } from '/@/hooks/web/useI18n';
// import { cloneDeep } from 'lodash-es';
// const { t } = useI18n();
export function useSplitMenu(splitType: Ref<MenuSplitTyeEnum>) {
// Menu array
const menusRef = ref<Menu[]>([]);
// flat menu array
const flatMenusRef = ref<Menu[]>([]);
const { currentRoute } = useRouter();
......@@ -45,14 +33,6 @@ export function useSplitMenu(splitType: Ref<MenuSplitTyeEnum>) {
return unref(splitType) === MenuSplitTyeEnum.NONE || !unref(getSplit);
});
// const getI18nFlatMenus = computed(() => {
// return setI18nName(flatMenusRef.value, true, false);
// });
// const getI18nMenus = computed(() => {
// return setI18nName(menusRef.value, true, true);
// });
watch(
[() => unref(currentRoute).path, () => unref(splitType)],
async ([path]: [string, MenuSplitTyeEnum]) => {
......@@ -83,20 +63,6 @@ export function useSplitMenu(splitType: Ref<MenuSplitTyeEnum>) {
genMenus();
});
// function setI18nName(list: Menu[], clone = false, deep = true) {
// const menus = clone ? cloneDeep(list) : list;
// const arr: Menu[] = [];
// menus.forEach((item) => {
// if (!item.name.includes('.')) return;
// item.name = t(item.name);
// if (item.children && deep) {
// setI18nName(item.children, false, deep);
// }
// });
// return menus;
// }
// Handle left menu split
async function handleSplitLeftMenu(parentPath: string) {
if (unref(splitLeft)) return;
......@@ -105,14 +71,11 @@ export function useSplitMenu(splitType: Ref<MenuSplitTyeEnum>) {
const children = await getChildrenMenus(parentPath);
if (!children) {
setMenuSetting({ hidden: false });
flatMenusRef.value = [];
menusRef.value = [];
return;
}
const flatChildren = await getFlatChildrenMenus(children);
setMenuSetting({ hidden: true });
flatMenusRef.value = flatChildren;
menusRef.value = children;
}
......@@ -120,7 +83,6 @@ export function useSplitMenu(splitType: Ref<MenuSplitTyeEnum>) {
async function genMenus() {
// normal mode
if (unref(normalType)) {
flatMenusRef.value = await getFlatMenus();
menusRef.value = await getMenus();
return;
}
......@@ -129,11 +91,10 @@ export function useSplitMenu(splitType: Ref<MenuSplitTyeEnum>) {
if (unref(spiltTop)) {
const shallowMenus = await getShallowMenus();
flatMenusRef.value = shallowMenus;
menusRef.value = shallowMenus;
return;
}
}
return { flatMenusRef, menusRef };
return { menusRef };
}
......@@ -12,10 +12,25 @@
&.ant-layout-sider-dark {
background: @sider-dark-bg-color;
.ant-layout-sider-trigger {
color: darken(@white, 25%);
background: @trigger-dark-bg-color;
&:hover {
color: @white;
background: @trigger-dark-hover-bg-color;
}
}
}
&:not(.ant-layout-sider-dark) {
box-shadow: 2px 0 8px 0 rgba(29, 35, 41, 0.05);
.ant-layout-sider-trigger {
color: @text-color-base;
border-top: 1px solid @border-color-light;
}
}
.ant-layout-sider-zero-width-trigger {
......@@ -43,9 +58,9 @@
box-shadow: 0 0 4px 0 rgba(28, 36, 56, 0.15);
}
}
}
.ant-layout-sider-trigger {
height: 36px;
line-height: 36px;
& .ant-layout-sider-trigger {
height: 36px;
line-height: 36px;
}
}
......@@ -100,7 +100,7 @@ export default defineComponent({
flex: `0 0 ${width}`,
maxWidth: width,
minWidth: width,
transition: 'all 0.2s',
transition: 'all 0.15s',
};
}
);
......@@ -126,7 +126,7 @@ export default defineComponent({
)}
<Layout.Sider
ref={sideRef}
breakpoint="md"
breakpoint="lg"
collapsible
class={unref(getSiderClass)}
style={unref(getSiderStyle)}
......
......@@ -79,3 +79,8 @@ export const isMobile = (): boolean => {
/(phone|pad|pod|iPhone|iPod|ios|iPad|Android|Mobile|BlackBerry|IEMobile|MQQBrowser|JUC|Fennec|wOSBrowser|BrowserNG|WebOS|Symbian|Windows Phone)/i
);
};
export const isUrl = (path: string): boolean => {
const reg = /(((^https?:(?:\/\/)?)(?:[-;:&=\+\$,\w]+@)?[A-Za-z0-9.-]+(?::\d+)?|(?:www.|[-;:&=\+\$,\w]+@)[A-Za-z0-9.-]+)((?:\/[\+~%\/.\w-_]*)?\??(?:[-\+=&;%@.\w_]*)#?(?:[\w]*))?)$/;
return reg.test(path);
};
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册