提交 0ec1a62e 编写于 作者: V vben

fix(menu): top submenu disappeared problem #214

上级 783e6581
......@@ -15,6 +15,7 @@
- 修复 form 表单初始化值为 0 问题
- 修复表格换行问题
- 修复菜单外链不跳转
- 修复菜单顶部显示问题
## 2.0.0-rc.17 (2020-01-18)
......
/**
* less global variable
*/
const primaryColor = '#018ffb';
const primaryColor = '#0084f4';
// const primaryColor = '#018ffb';
// const primaryColor = '#0065cc';
//{
const modifyVars = {
......
......@@ -13,13 +13,7 @@
v-bind="getInlineCollapseOptions"
>
<template v-for="item in items" :key="item.path">
<BasicSubMenuItem
:item="item"
:theme="theme"
:level="1"
:showTitle="showTitle"
:isHorizontal="isHorizontal"
/>
<BasicSubMenuItem :item="item" :theme="theme" :isHorizontal="isHorizontal" />
</template>
</Menu>
</template>
......@@ -46,6 +40,7 @@
// import { createAsyncComponent } from '/@/utils/factory/createAsyncComponent';
import { listenerLastChangeTab } from '/@/logics/mitt/tabChange';
import { getAllParentPath } from '/@/router/helper/menuHelper';
export default defineComponent({
name: 'BasicMenu',
......@@ -96,16 +91,12 @@
prefixCls,
`justify-${align}`,
{
[`${prefixCls}--hide-title`]: !unref(showTitle),
[`${prefixCls}--collapsed-show-title`]: props.collapsedShowTitle,
[`${prefixCls}__second`]: !props.isHorizontal && unref(getSplit),
[`${prefixCls}__sidebar-hor`]: unref(getIsTopMenu),
},
];
});
const showTitle = computed(() => props.collapsedShowTitle && unref(getCollapsed));
const getInlineCollapseOptions = computed(() => {
const isInline = props.mode === MenuModeEnum.INLINE;
......@@ -135,7 +126,7 @@
}
);
async function handleMenuClick({ key, keyPath }: { key: string; keyPath: string[] }) {
async function handleMenuClick({ key }: { key: string; keyPath: string[] }) {
const { beforeClickFn } = props;
if (beforeClickFn && isFunction(beforeClickFn)) {
const flag = await beforeClickFn(key);
......@@ -144,7 +135,9 @@
emit('menuClick', key);
isClickGo.value = true;
menuState.openKeys = keyPath;
// const parentPath = await getCurrentParentPath(key);
// menuState.openKeys = [parentPath];
menuState.selectedKeys = [key];
}
......@@ -160,7 +153,8 @@
const parentPath = await getCurrentParentPath(path);
menuState.selectedKeys = [parentPath];
} else {
menuState.selectedKeys = [path];
const parentPaths = await getAllParentPath(props.items, path);
menuState.selectedKeys = parentPaths;
}
}
......@@ -172,7 +166,6 @@
getMenuClass,
handleOpenChange,
getOpenKeys,
showTitle,
...toRefs(menuState),
};
},
......
<template>
<MenuItem :class="getLevelClass">
<MenuItem>
<!-- <MenuItem :class="getLevelClass"> -->
<MenuItemContent v-bind="$props" :item="item" />
</MenuItem>
</template>
<script lang="ts">
import { defineComponent, computed } from 'vue';
import { defineComponent } from 'vue';
import { Menu } from 'ant-design-vue';
import { useDesign } from '/@/hooks/web/useDesign';
import { itemProps } from '../props';
......@@ -14,18 +15,19 @@
name: 'BasicMenuItem',
components: { MenuItem: Menu.Item, MenuItemContent },
props: itemProps,
setup(props) {
setup() // props
{
const { prefixCls } = useDesign('basic-menu-item');
const getLevelClass = computed(() => {
const { level, theme } = props;
// const getLevelClass = computed(() => {
// const { level, theme } = props;
const levelCls = [`${prefixCls}__level${level}`, theme];
return levelCls;
});
// const levelCls = [`${prefixCls}__level${level}`, theme];
// return levelCls;
// });
return {
prefixCls,
getLevelClass,
// getLevelClass,
};
},
});
......
......@@ -2,17 +2,15 @@
<BasicMenuItem v-if="!menuHasChildren(item) && getShowMenu" v-bind="$props" />
<SubMenu
v-if="menuHasChildren(item) && getShowMenu"
:class="[`${prefixCls}__level${level}`, theme]"
:class="[theme]"
popupClassName="app-top-menu-popup"
>
<template #title>
<MenuItemContent v-bind="$props" :item="item" />
</template>
<!-- <template #expandIcon="{ key }">
<ExpandIcon :key="key" />
</template> -->
<template v-for="childrenItem in item.children || []" :key="childrenItem.path">
<BasicSubMenuItem v-bind="$props" :item="childrenItem" :level="level + 1" />
<BasicSubMenuItem v-bind="$props" :item="childrenItem" />
</template>
</SubMenu>
</template>
......@@ -26,7 +24,6 @@
import BasicMenuItem from './BasicMenuItem.vue';
import MenuItemContent from './MenuItemContent.vue';
// import { createAsyncComponent } from '/@/utils/factory/createAsyncComponent';
export default defineComponent({
name: 'BasicSubMenuItem',
isSubMenu: true,
......@@ -35,7 +32,6 @@
SubMenu: Menu.SubMenu,
MenuItem: Menu.Item,
MenuItemContent,
// ExpandIcon: createAsyncComponent(() => import('./ExpandIcon.vue')),
},
props: itemProps,
setup(props) {
......
<template>
<span :class="`${prefixCls}-wrapper`">
<Icon v-if="getIcon" :icon="getIcon" :size="18" :class="`${prefixCls}-wrapper__icon`" />
<span :class="getNameClass">
{{ getI18nName }}
<MenuItemTag v-bind="$props" />
</span>
{{ getI18nName }}
</span>
</template>
<script lang="ts">
......@@ -14,25 +11,21 @@
import { useI18n } from '/@/hooks/web/useI18n';
import { useDesign } from '/@/hooks/web/useDesign';
import { contentProps } from '../props';
import { createAsyncComponent } from '/@/utils/factory/createAsyncComponent';
const { t } = useI18n();
export default defineComponent({
name: 'MenuItemContent',
components: { Icon, MenuItemTag: createAsyncComponent(() => import('./MenuItemTag.vue')) },
components: {
Icon,
},
props: contentProps,
setup(props) {
const { prefixCls } = useDesign('basic-menu-item-content');
const getI18nName = computed(() => t(props.item?.name));
const getIcon = computed(() => props.item?.icon);
const getNameClass = computed(() => {
const { showTitle } = props;
return { [`${prefixCls}--show-title`]: showTitle, [`${prefixCls}__name`]: !showTitle };
});
return {
prefixCls,
getNameClass,
getI18nName,
getIcon,
};
......
@basic-menu-prefix-cls: ~'@{namespace}-basic-menu';
@basic-menu-content-prefix-cls: ~'@{namespace}-basic-menu-item-content';
@basic-menu-tag-prefix-cls: ~'@{namespace}-basic-menu-item-tag';
.active-style() {
color: @white;
// background: @primary-color !important;
background: linear-gradient(
118deg,
rgba(@primary-color, 0.8),
rgba(@primary-color, 1)
) !important;
}
.active-menu-style() {
.ant-menu-item-selected,
.ant-menu-submenu-popup.ant-menu-dark .ant-menu-item-selected {
.active-style();
}
.app-top-menu-popup {
min-width: 150px;
}
.@{basic-menu-prefix-cls} {
width: 100%;
// &__expand-icon {
// position: absolute;
// top: calc(50% - 6px);
// right: 16px;
// width: 10px;
// transform-origin: none;
// opacity: 0.45;
// span[role='img'] {
// margin-right: 0;
// font-size: 11px;
// }
// &--collapsed {
// opacity: 0;
// }
// }
// collapsed show title start
.@{basic-menu-content-prefix-cls}--show-title {
max-width: unset !important;
opacity: 1 !important;
}
&--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-title {
padding-right: 16px !important;
padding-left: 16px !important;
}
}
&--collapsed-show-title.ant-menu-inline-collapsed {
.@{basic-menu-prefix-cls}-item__level1 {
padding: 2px 0;
justify-content: center !important;
&.ant-menu-item {
display: flex;
align-items: center;
height: 60px !important;
margin-top: 0 !important;
margin-bottom: 0 !important;
line-height: 60px !important;
> span {
margin-top: 10px;
}
}
}
& > li[role='menuitem']:not(.ant-menu-submenu),
& > li > .ant-menu-submenu-title {
display: flex;
margin-top: 10px;
font-size: 12px;
flex-direction: column;
align-items: center;
line-height: 24px;
}
& > li > .ant-menu-submenu-title {
line-height: 24px;
}
.@{basic-menu-content-prefix-cls}-wrapper {
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
.@{basic-menu-content-prefix-cls}--show-title {
line-height: 30px;
}
}
}
&.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-title {
padding-right: 16px !important;
padding-left: 16px !important;
}
.@{basic-menu-content-prefix-cls}-wrapper {
width: 100%;
margin-top: 4px;
&__icon {
vertical-align: text-top;
}
}
.ant-menu-item {
transition: unset;
}
......@@ -179,117 +62,6 @@
}
}
&.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-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;
margin: 0;
line-height: @app-menu-item-height;
}
.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-prefix-cls}__sidebar-hor) {
overflow: hidden;
background: @sider-dark-bg-color;
.active-menu-style();
.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-prefix-cls}-item__level1 {
background-color: @sider-dark-bg-color;
> .ant-menu-sub > li {
background-color: @sider-dark-lighten-1-bg-color;
}
}
.@{basic-menu-prefix-cls}-item__level2:not(.ant-menu-item-selected),
.ant-menu-sub {
background-color: @sider-dark-lighten-1-bg-color;
}
.@{basic-menu-prefix-cls}-item__level3:not(.ant-menu-item-selected) {
background-color: @sider-dark-lighten-2-bg-color;
.ant-menu-item {
background-color: @sider-dark-lighten-2-bg-color;
}
}
.ant-menu-submenu-title {
display: flex;
height: @app-menu-item-height;
// margin: 0;
align-items: center;
}
&.ant-menu-inline-collapsed {
.ant-menu-submenu-selected,
.ant-menu-item-selected {
position: relative;
font-weight: 500;
color: @white;
background: @sider-dark-darken-bg-color !important;
&::before {
position: absolute;
top: 0;
left: 0;
width: 3px;
height: 100%;
background: @primary-color;
content: '';
}
}
}
}
&.ant-menu-light:not(.@{basic-menu-prefix-cls}__sidebar-hor) {
// overflow: hidden;
border-right: none;
.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;
}
}
&.@{basic-menu-prefix-cls}__second.ant-menu-inline-collapsed:not(.@{basic-menu-prefix-cls}__sidebar-hor) {
// Reset menu item row height
.@{basic-menu-prefix-cls}-item__level1 {
display: flex;
height: @app-menu-item-height * 1.4;
padding: 6px 0 !important;
margin: 0;
font-size: 12px;
line-height: @app-menu-item-height;
align-items: center;
text-align: center;
> div {
padding: 6px 0 !important;
font-size: 12px;
}
.@{basic-menu-content-prefix-cls}__name {
display: inline-block;
width: 50%;
overflow: hidden;
}
}
}
.ant-menu-submenu,
.ant-menu-submenu-inline {
transition: unset;
......@@ -300,63 +72,3 @@
transition: unset;
}
}
.ant-menu-dark {
&.ant-menu-submenu-popup {
> ul {
background: @sider-dark-bg-color;
}
.active-menu-style();
}
}
// collapsed show title end
.ant-menu-item,
.ant-menu-submenu-title {
> .@{basic-menu-content-prefix-cls}__name {
width: 100%;
.@{basic-menu-tag-prefix-cls} {
float: right;
margin-top: @app-menu-item-height / 2;
transform: translate(0%, -50%);
}
}
}
.@{basic-menu-tag-prefix-cls} {
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: 6px;
height: 6px;
padding: 0;
border-radius: 50%;
}
&--primary {
background: @primary-color;
}
&--error {
background: @error-color;
}
&--success {
background: @success-color;
}
&--warn {
background: @warning-color;
}
}
......@@ -72,9 +72,6 @@ export function useSplitMenu(splitType: Ref<MenuSplitTyeEnum>) {
// Handle left menu split
async function handleSplitLeftMenu(parentPath: string) {
console.log('======================');
console.log(unref(getSplitLeft));
console.log('======================');
if (unref(getSplitLeft) || unref(getIsMobile)) return;
// spilt mode left
......
......@@ -19,9 +19,9 @@
appear
>
<keep-alive v-if="openCache" :include="getCaches">
<component :is="Component" :key="route.fullPath" />
<component :is="Component" v-bind="getKey(Component, route)" />
</keep-alive>
<component v-else :is="Component" :key="route.fullPath" />
<component v-else :is="Component" v-bind="getKey(Component, route)" />
</transition>
</template>
</router-view>
......@@ -34,7 +34,7 @@
import { useMultipleTabSetting } from '/@/hooks/setting/useMultipleTabSetting';
import { useTransitionSetting } from '/@/hooks/setting/useTransitionSetting';
import { useCache } from './useCache';
import { useCache, getKey } from './useCache';
import { getTransitionName } from './transition';
export default defineComponent({
......@@ -56,6 +56,7 @@
openCache,
getEnableTransition,
getTransitionName,
getKey,
};
},
});
......
......@@ -27,9 +27,6 @@
</template>
<script lang="ts">
import type { FunctionalComponent } from 'vue';
import type { RouteLocation } from 'vue-router';
import { computed, defineComponent, unref } from 'vue';
import FrameLayout from '/@/layouts/iframe/index.vue';
......@@ -37,7 +34,7 @@
import { useRootSetting } from '/@/hooks/setting/useRootSetting';
import { useTransitionSetting } from '/@/hooks/setting/useTransitionSetting';
import { useCache } from './useCache';
import { useCache, getKey } from './useCache';
import { useMultipleTabSetting } from '/@/hooks/setting/useMultipleTabSetting';
import { getTransitionName } from './transition';
......@@ -54,10 +51,6 @@
const openCache = computed(() => unref(getOpenKeepAlive) && unref(getShowMultipleTab));
function getKey(component: FunctionalComponent & { type: Indexable }, route: RouteLocation) {
return !!component?.type.parentView ? {} : { key: route.fullPath };
}
return {
getTransitionName,
openCache,
......
import type { FunctionalComponent } from 'vue';
import type { RouteLocation } from 'vue-router';
import { computed, ref, unref } from 'vue';
import { useRootSetting } from '/@/hooks/setting/useRootSetting';
import { tryTsxEmit } from '/@/utils/helper/vueHelper';
......@@ -6,6 +8,11 @@ import { tabStore, PAGE_LAYOUT_KEY } from '/@/store/modules/tab';
import { useRouter } from 'vue-router';
const ParentLayoutName = 'ParentLayout';
export function getKey(component: FunctionalComponent & { type: Indexable }, route: RouteLocation) {
return !!component?.type.parentView ? {} : { key: route.fullPath };
}
export function useCache(isPage: boolean) {
const name = ref('');
const { currentRoute } = useRouter();
......
......@@ -1768,10 +1768,10 @@
"@vue/babel-plugin-jsx" "^1.0.1"
hash-sum "^2.0.0"
"@vitejs/plugin-vue@^1.1.2":
version "1.1.2"
resolved "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-1.1.2.tgz#64d1f0e0739675f5717015ffb4d861c53af8fe60"
integrity sha512-a5ORYuPsiAO4Kb2blA/x63mDiBQBxEJkbjhVtiv5IP/I7fGfpwXPPGHx9LHD4MedpXp8icngJYMKO0hOwahtmQ==
"@vitejs/plugin-vue@1.1.0":
version "1.1.0"
resolved "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-1.1.0.tgz#8ae0b11388897b07259c9e5198c0e3fb5e4b37d9"
integrity sha512-ExlAt3nb3PB31jV9AgRZSMoGd+aQRU53fc/seghV8/l0JCzaX2mqlgpG8iytWkRxbBPgtAx4TpCPdiVKnTFT/A==
"@vue/babel-helper-vue-transform-on@^1.0.2":
version "1.0.2"
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册