style: lint格式化文件
This commit is contained in:
@ -1,160 +1,142 @@
|
||||
<template>
|
||||
<Menu
|
||||
v-bind="getBindValues"
|
||||
:activeName="activeName"
|
||||
:openNames="getOpenKeys"
|
||||
:class="prefixCls"
|
||||
:activeSubMenuNames="activeSubMenuNames"
|
||||
@select="handleSelect"
|
||||
>
|
||||
<template v-for="item in items" :key="item.path">
|
||||
<SimpleSubMenu
|
||||
:item="item"
|
||||
:parent="true"
|
||||
:collapsedShowTitle="collapsedShowTitle"
|
||||
:collapse="collapse"
|
||||
/>
|
||||
</template>
|
||||
</Menu>
|
||||
<Menu v-bind="getBindValues" :activeName="activeName" :openNames="getOpenKeys" :class="prefixCls" :activeSubMenuNames="activeSubMenuNames" @select="handleSelect">
|
||||
<template v-for="item in items" :key="item.path">
|
||||
<SimpleSubMenu :item="item" :parent="true" :collapsedShowTitle="collapsedShowTitle" :collapse="collapse" />
|
||||
</template>
|
||||
</Menu>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import type { MenuState } from './types';
|
||||
import type { Menu as MenuType } from '/@/router/types';
|
||||
import type { RouteLocationNormalizedLoaded } from 'vue-router';
|
||||
import { defineComponent, computed, ref, unref, reactive, toRefs, watch } from 'vue';
|
||||
import { useDesign } from '/@/hooks/web/useDesign';
|
||||
import Menu from './components/Menu.vue';
|
||||
import SimpleSubMenu from './SimpleSubMenu.vue';
|
||||
import { listenerRouteChange } from '/@/logics/mitt/routeChange';
|
||||
import { propTypes } from '/@/utils/propTypes';
|
||||
import { REDIRECT_NAME } from '/@/router/constant';
|
||||
import { useRouter } from 'vue-router';
|
||||
import { isFunction, isUrl } from '/@/utils/is';
|
||||
import { openWindow } from '/@/utils';
|
||||
import type { MenuState } from './types';
|
||||
import type { Menu as MenuType } from '/@/router/types';
|
||||
import type { RouteLocationNormalizedLoaded } from 'vue-router';
|
||||
import { defineComponent, computed, ref, unref, reactive, toRefs, watch } from 'vue';
|
||||
import { useDesign } from '/@/hooks/web/useDesign';
|
||||
import Menu from './components/Menu.vue';
|
||||
import SimpleSubMenu from './SimpleSubMenu.vue';
|
||||
import { listenerRouteChange } from '/@/logics/mitt/routeChange';
|
||||
import { propTypes } from '/@/utils/propTypes';
|
||||
import { REDIRECT_NAME } from '/@/router/constant';
|
||||
import { useRouter } from 'vue-router';
|
||||
import { isFunction, isUrl } from '/@/utils/is';
|
||||
import { openWindow } from '/@/utils';
|
||||
|
||||
import { useOpenKeys } from './useOpenKeys';
|
||||
export default defineComponent({
|
||||
name: 'SimpleMenu',
|
||||
components: {
|
||||
Menu,
|
||||
SimpleSubMenu,
|
||||
},
|
||||
inheritAttrs: false,
|
||||
props: {
|
||||
items: {
|
||||
type: Array as PropType<MenuType[]>,
|
||||
default: () => [],
|
||||
},
|
||||
collapse: propTypes.bool,
|
||||
mixSider: propTypes.bool,
|
||||
theme: propTypes.string,
|
||||
accordion: propTypes.bool.def(true),
|
||||
collapsedShowTitle: propTypes.bool,
|
||||
beforeClickFn: {
|
||||
type: Function as PropType<(key: string) => Promise<boolean>>,
|
||||
},
|
||||
isSplitMenu: propTypes.bool,
|
||||
},
|
||||
emits: ['menuClick'],
|
||||
setup(props, { attrs, emit }) {
|
||||
const currentActiveMenu = ref('');
|
||||
const isClickGo = ref(false);
|
||||
|
||||
const menuState = reactive<MenuState>({
|
||||
activeName: '',
|
||||
openNames: [],
|
||||
activeSubMenuNames: [],
|
||||
});
|
||||
|
||||
const { currentRoute } = useRouter();
|
||||
const { prefixCls } = useDesign('simple-menu');
|
||||
const { items, accordion, mixSider, collapse } = toRefs(props);
|
||||
|
||||
const { setOpenKeys, getOpenKeys } = useOpenKeys(
|
||||
menuState,
|
||||
items,
|
||||
accordion,
|
||||
mixSider,
|
||||
collapse,
|
||||
);
|
||||
|
||||
const getBindValues = computed(() => ({ ...attrs, ...props }));
|
||||
|
||||
watch(
|
||||
() => props.collapse,
|
||||
(collapse) => {
|
||||
if (collapse) {
|
||||
menuState.openNames = [];
|
||||
} else {
|
||||
setOpenKeys(currentRoute.value.path);
|
||||
}
|
||||
import { useOpenKeys } from './useOpenKeys';
|
||||
export default defineComponent({
|
||||
name: 'SimpleMenu',
|
||||
components: {
|
||||
Menu,
|
||||
SimpleSubMenu
|
||||
},
|
||||
{ immediate: true },
|
||||
);
|
||||
|
||||
watch(
|
||||
() => props.items,
|
||||
() => {
|
||||
if (!props.isSplitMenu) {
|
||||
return;
|
||||
}
|
||||
setOpenKeys(currentRoute.value.path);
|
||||
inheritAttrs: false,
|
||||
props: {
|
||||
items: {
|
||||
type: Array as PropType<MenuType[]>,
|
||||
default: () => []
|
||||
},
|
||||
collapse: propTypes.bool,
|
||||
mixSider: propTypes.bool,
|
||||
theme: propTypes.string,
|
||||
accordion: propTypes.bool.def(true),
|
||||
collapsedShowTitle: propTypes.bool,
|
||||
beforeClickFn: {
|
||||
type: Function as PropType<(key: string) => Promise<boolean>>
|
||||
},
|
||||
isSplitMenu: propTypes.bool
|
||||
},
|
||||
{ flush: 'post' },
|
||||
);
|
||||
emits: ['menuClick'],
|
||||
setup(props, { attrs, emit }) {
|
||||
const currentActiveMenu = ref('');
|
||||
const isClickGo = ref(false);
|
||||
|
||||
listenerRouteChange((route) => {
|
||||
if (route.name === REDIRECT_NAME) return;
|
||||
const menuState = reactive<MenuState>({
|
||||
activeName: '',
|
||||
openNames: [],
|
||||
activeSubMenuNames: []
|
||||
});
|
||||
|
||||
currentActiveMenu.value = route.meta?.currentActiveMenu as string;
|
||||
handleMenuChange(route);
|
||||
const { currentRoute } = useRouter();
|
||||
const { prefixCls } = useDesign('simple-menu');
|
||||
const { items, accordion, mixSider, collapse } = toRefs(props);
|
||||
|
||||
if (unref(currentActiveMenu)) {
|
||||
menuState.activeName = unref(currentActiveMenu);
|
||||
setOpenKeys(unref(currentActiveMenu));
|
||||
const { setOpenKeys, getOpenKeys } = useOpenKeys(menuState, items, accordion, mixSider, collapse);
|
||||
|
||||
const getBindValues = computed(() => ({ ...attrs, ...props }));
|
||||
|
||||
watch(
|
||||
() => props.collapse,
|
||||
(collapse) => {
|
||||
if (collapse) {
|
||||
menuState.openNames = [];
|
||||
} else {
|
||||
setOpenKeys(currentRoute.value.path);
|
||||
}
|
||||
},
|
||||
{ immediate: true }
|
||||
);
|
||||
|
||||
watch(
|
||||
() => props.items,
|
||||
() => {
|
||||
if (!props.isSplitMenu) {
|
||||
return;
|
||||
}
|
||||
setOpenKeys(currentRoute.value.path);
|
||||
},
|
||||
{ flush: 'post' }
|
||||
);
|
||||
|
||||
listenerRouteChange((route) => {
|
||||
if (route.name === REDIRECT_NAME) return;
|
||||
|
||||
currentActiveMenu.value = route.meta?.currentActiveMenu as string;
|
||||
handleMenuChange(route);
|
||||
|
||||
if (unref(currentActiveMenu)) {
|
||||
menuState.activeName = unref(currentActiveMenu);
|
||||
setOpenKeys(unref(currentActiveMenu));
|
||||
}
|
||||
});
|
||||
|
||||
async function handleMenuChange(route?: RouteLocationNormalizedLoaded) {
|
||||
if (unref(isClickGo)) {
|
||||
isClickGo.value = false;
|
||||
return;
|
||||
}
|
||||
const path = (route || unref(currentRoute)).path;
|
||||
|
||||
menuState.activeName = path;
|
||||
|
||||
setOpenKeys(path);
|
||||
}
|
||||
|
||||
async function handleSelect(key: string) {
|
||||
if (isUrl(key)) {
|
||||
openWindow(key);
|
||||
return;
|
||||
}
|
||||
const { beforeClickFn } = props;
|
||||
if (beforeClickFn && isFunction(beforeClickFn)) {
|
||||
const flag = await beforeClickFn(key);
|
||||
if (!flag) return;
|
||||
}
|
||||
|
||||
emit('menuClick', key);
|
||||
|
||||
isClickGo.value = true;
|
||||
setOpenKeys(key);
|
||||
menuState.activeName = key;
|
||||
}
|
||||
|
||||
return {
|
||||
prefixCls,
|
||||
getBindValues,
|
||||
handleSelect,
|
||||
getOpenKeys,
|
||||
...toRefs(menuState)
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
async function handleMenuChange(route?: RouteLocationNormalizedLoaded) {
|
||||
if (unref(isClickGo)) {
|
||||
isClickGo.value = false;
|
||||
return;
|
||||
}
|
||||
const path = (route || unref(currentRoute)).path;
|
||||
|
||||
menuState.activeName = path;
|
||||
|
||||
setOpenKeys(path);
|
||||
}
|
||||
|
||||
async function handleSelect(key: string) {
|
||||
if (isUrl(key)) {
|
||||
openWindow(key);
|
||||
return;
|
||||
}
|
||||
const { beforeClickFn } = props;
|
||||
if (beforeClickFn && isFunction(beforeClickFn)) {
|
||||
const flag = await beforeClickFn(key);
|
||||
if (!flag) return;
|
||||
}
|
||||
|
||||
emit('menuClick', key);
|
||||
|
||||
isClickGo.value = true;
|
||||
setOpenKeys(key);
|
||||
menuState.activeName = key;
|
||||
}
|
||||
|
||||
return {
|
||||
prefixCls,
|
||||
getBindValues,
|
||||
handleSelect,
|
||||
getOpenKeys,
|
||||
...toRefs(menuState),
|
||||
};
|
||||
},
|
||||
});
|
||||
});
|
||||
</script>
|
||||
<style lang="less">
|
||||
@import './index.less';
|
||||
@import './index.less';
|
||||
</style>
|
||||
|
||||
@ -1,68 +1,68 @@
|
||||
<template>
|
||||
<span :class="getTagClass" v-if="getShowTag">{{ getContent }}</span>
|
||||
<span :class="getTagClass" v-if="getShowTag">{{ getContent }}</span>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import type { Menu } from '/@/router/types';
|
||||
import type { Menu } from '/@/router/types';
|
||||
|
||||
import { defineComponent, computed } from 'vue';
|
||||
import { defineComponent, computed } from 'vue';
|
||||
|
||||
import { useDesign } from '/@/hooks/web/useDesign';
|
||||
import { propTypes } from '/@/utils/propTypes';
|
||||
import { useDesign } from '/@/hooks/web/useDesign';
|
||||
import { propTypes } from '/@/utils/propTypes';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'SimpleMenuTag',
|
||||
props: {
|
||||
item: {
|
||||
type: Object as PropType<Menu>,
|
||||
default: () => ({}),
|
||||
},
|
||||
dot: propTypes.bool,
|
||||
collapseParent: propTypes.bool,
|
||||
},
|
||||
setup(props) {
|
||||
const { prefixCls } = useDesign('simple-menu');
|
||||
export default defineComponent({
|
||||
name: 'SimpleMenuTag',
|
||||
props: {
|
||||
item: {
|
||||
type: Object as PropType<Menu>,
|
||||
default: () => ({})
|
||||
},
|
||||
dot: propTypes.bool,
|
||||
collapseParent: propTypes.bool
|
||||
},
|
||||
setup(props) {
|
||||
const { prefixCls } = useDesign('simple-menu');
|
||||
|
||||
const getShowTag = computed(() => {
|
||||
const { item } = props;
|
||||
const getShowTag = computed(() => {
|
||||
const { item } = props;
|
||||
|
||||
if (!item) return false;
|
||||
if (!item) return false;
|
||||
|
||||
const { tag } = item;
|
||||
if (!tag) return false;
|
||||
const { tag } = item;
|
||||
if (!tag) return false;
|
||||
|
||||
const { dot, content } = tag;
|
||||
if (!dot && !content) return false;
|
||||
return true;
|
||||
});
|
||||
const { dot, content } = tag;
|
||||
if (!dot && !content) return false;
|
||||
return true;
|
||||
});
|
||||
|
||||
const getContent = computed(() => {
|
||||
if (!getShowTag.value) return '';
|
||||
const { item, collapseParent } = props;
|
||||
const { tag } = item;
|
||||
const { dot, content } = tag!;
|
||||
return dot || collapseParent ? '' : content;
|
||||
});
|
||||
const getContent = computed(() => {
|
||||
if (!getShowTag.value) return '';
|
||||
const { item, collapseParent } = props;
|
||||
const { tag } = item;
|
||||
const { dot, content } = tag!;
|
||||
return dot || collapseParent ? '' : content;
|
||||
});
|
||||
|
||||
const getTagClass = computed(() => {
|
||||
const { item, collapseParent } = props;
|
||||
const { tag = {} } = item || {};
|
||||
const { dot, type = 'error' } = tag;
|
||||
const tagCls = `${prefixCls}-tag`;
|
||||
return [
|
||||
tagCls,
|
||||
const getTagClass = computed(() => {
|
||||
const { item, collapseParent } = props;
|
||||
const { tag = {} } = item || {};
|
||||
const { dot, type = 'error' } = tag;
|
||||
const tagCls = `${prefixCls}-tag`;
|
||||
return [
|
||||
tagCls,
|
||||
|
||||
[`${tagCls}--${type}`],
|
||||
{
|
||||
[`${tagCls}--collapse`]: collapseParent,
|
||||
[`${tagCls}--dot`]: dot || props.dot,
|
||||
},
|
||||
];
|
||||
});
|
||||
return {
|
||||
getTagClass,
|
||||
getShowTag,
|
||||
getContent,
|
||||
};
|
||||
},
|
||||
});
|
||||
[`${tagCls}--${type}`],
|
||||
{
|
||||
[`${tagCls}--collapse`]: collapseParent,
|
||||
[`${tagCls}--dot`]: dot || props.dot
|
||||
}
|
||||
];
|
||||
});
|
||||
return {
|
||||
getTagClass,
|
||||
getShowTag,
|
||||
getContent
|
||||
};
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
@ -1,114 +1,98 @@
|
||||
<template>
|
||||
<MenuItem
|
||||
:name="item.path"
|
||||
v-if="!menuHasChildren(item) && getShowMenu"
|
||||
v-bind="$props"
|
||||
:class="getLevelClass"
|
||||
>
|
||||
<Icon v-if="getIcon" :icon="getIcon" :size="16" />
|
||||
<div v-if="collapsedShowTitle && getIsCollapseParent" class="mt-1 collapse-title">
|
||||
{{ getI18nName }}
|
||||
</div>
|
||||
<template #title>
|
||||
<span :class="['ml-2', `${prefixCls}-sub-title`]">
|
||||
{{ getI18nName }}
|
||||
</span>
|
||||
<SimpleMenuTag :item="item" :collapseParent="getIsCollapseParent" />
|
||||
</template>
|
||||
</MenuItem>
|
||||
<SubMenu
|
||||
:name="item.path"
|
||||
v-if="menuHasChildren(item) && getShowMenu"
|
||||
:class="[getLevelClass, theme]"
|
||||
:collapsedShowTitle="collapsedShowTitle"
|
||||
>
|
||||
<template #title>
|
||||
<Icon v-if="getIcon" :icon="getIcon" :size="16" />
|
||||
<MenuItem :name="item.path" v-if="!menuHasChildren(item) && getShowMenu" v-bind="$props" :class="getLevelClass">
|
||||
<Icon v-if="getIcon" :icon="getIcon" :size="16" />
|
||||
<div v-if="collapsedShowTitle && getIsCollapseParent" class="mt-1 collapse-title">
|
||||
{{ getI18nName }}
|
||||
</div>
|
||||
<template #title>
|
||||
<span :class="['ml-2', `${prefixCls}-sub-title`]">
|
||||
{{ getI18nName }}
|
||||
</span>
|
||||
<SimpleMenuTag :item="item" :collapseParent="getIsCollapseParent" />
|
||||
</template>
|
||||
</MenuItem>
|
||||
<SubMenu :name="item.path" v-if="menuHasChildren(item) && getShowMenu" :class="[getLevelClass, theme]" :collapsedShowTitle="collapsedShowTitle">
|
||||
<template #title>
|
||||
<Icon v-if="getIcon" :icon="getIcon" :size="16" />
|
||||
|
||||
<div v-if="collapsedShowTitle && getIsCollapseParent" class="mt-2 collapse-title">
|
||||
{{ getI18nName }}
|
||||
</div>
|
||||
<div v-if="collapsedShowTitle && getIsCollapseParent" class="mt-2 collapse-title">
|
||||
{{ getI18nName }}
|
||||
</div>
|
||||
|
||||
<span v-show="getShowSubTitle" :class="['ml-2', `${prefixCls}-sub-title`]">
|
||||
{{ getI18nName }}
|
||||
</span>
|
||||
<SimpleMenuTag :item="item" :collapseParent="!!collapse && !!parent" />
|
||||
</template>
|
||||
<template v-for="childrenItem in item.children || []" :key="childrenItem.path">
|
||||
<SimpleSubMenu v-bind="$props" :item="childrenItem" :parent="false" />
|
||||
</template>
|
||||
</SubMenu>
|
||||
<span v-show="getShowSubTitle" :class="['ml-2', `${prefixCls}-sub-title`]">
|
||||
{{ getI18nName }}
|
||||
</span>
|
||||
<SimpleMenuTag :item="item" :collapseParent="!!collapse && !!parent" />
|
||||
</template>
|
||||
<template v-for="childrenItem in item.children || []" :key="childrenItem.path">
|
||||
<SimpleSubMenu v-bind="$props" :item="childrenItem" :parent="false" />
|
||||
</template>
|
||||
</SubMenu>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import type { PropType } from 'vue';
|
||||
import type { Menu } from '/@/router/types';
|
||||
import type { PropType } from 'vue';
|
||||
import type { Menu } from '/@/router/types';
|
||||
|
||||
import { defineComponent, computed } from 'vue';
|
||||
import { useDesign } from '/@/hooks/web/useDesign';
|
||||
import Icon from '/@/components/Icon/index';
|
||||
import { defineComponent, computed } from 'vue';
|
||||
import { useDesign } from '/@/hooks/web/useDesign';
|
||||
import Icon from '/@/components/Icon/index';
|
||||
|
||||
import MenuItem from './components/MenuItem.vue';
|
||||
import SubMenu from './components/SubMenuItem.vue';
|
||||
import { propTypes } from '/@/utils/propTypes';
|
||||
import { useI18n } from '/@/hooks/web/useI18n';
|
||||
import { createAsyncComponent } from '/@/utils/factory/createAsyncComponent';
|
||||
import MenuItem from './components/MenuItem.vue';
|
||||
import SubMenu from './components/SubMenuItem.vue';
|
||||
import { propTypes } from '/@/utils/propTypes';
|
||||
import { useI18n } from '/@/hooks/web/useI18n';
|
||||
import { createAsyncComponent } from '/@/utils/factory/createAsyncComponent';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'SimpleSubMenu',
|
||||
components: {
|
||||
SubMenu,
|
||||
MenuItem,
|
||||
SimpleMenuTag: createAsyncComponent(() => import('./SimpleMenuTag.vue')),
|
||||
Icon,
|
||||
},
|
||||
props: {
|
||||
item: {
|
||||
type: Object as PropType<Menu>,
|
||||
default: () => ({}),
|
||||
},
|
||||
parent: propTypes.bool,
|
||||
collapsedShowTitle: propTypes.bool,
|
||||
collapse: propTypes.bool,
|
||||
theme: propTypes.oneOf(['dark', 'light']),
|
||||
},
|
||||
setup(props) {
|
||||
const { t } = useI18n();
|
||||
const { prefixCls } = useDesign('simple-menu');
|
||||
export default defineComponent({
|
||||
name: 'SimpleSubMenu',
|
||||
components: {
|
||||
SubMenu,
|
||||
MenuItem,
|
||||
SimpleMenuTag: createAsyncComponent(() => import('./SimpleMenuTag.vue')),
|
||||
Icon
|
||||
},
|
||||
props: {
|
||||
item: {
|
||||
type: Object as PropType<Menu>,
|
||||
default: () => ({})
|
||||
},
|
||||
parent: propTypes.bool,
|
||||
collapsedShowTitle: propTypes.bool,
|
||||
collapse: propTypes.bool,
|
||||
theme: propTypes.oneOf(['dark', 'light'])
|
||||
},
|
||||
setup(props) {
|
||||
const { t } = useI18n();
|
||||
const { prefixCls } = useDesign('simple-menu');
|
||||
|
||||
const getShowMenu = computed(() => !props.item?.meta?.hideMenu);
|
||||
const getIcon = computed(() => props.item?.icon || 'ant-design:menu-outlined');
|
||||
const getI18nName = computed(() => t(props.item?.name));
|
||||
const getShowSubTitle = computed(() => !props.collapse || !props.parent);
|
||||
const getIsCollapseParent = computed(() => !!props.collapse && !!props.parent);
|
||||
const getLevelClass = computed(() => {
|
||||
return [
|
||||
{
|
||||
[`${prefixCls}__parent`]: props.parent,
|
||||
[`${prefixCls}__children`]: !props.parent,
|
||||
},
|
||||
];
|
||||
});
|
||||
const getShowMenu = computed(() => !props.item?.meta?.hideMenu);
|
||||
const getIcon = computed(() => props.item?.icon || 'ant-design:menu-outlined');
|
||||
const getI18nName = computed(() => t(props.item?.name));
|
||||
const getShowSubTitle = computed(() => !props.collapse || !props.parent);
|
||||
const getIsCollapseParent = computed(() => !!props.collapse && !!props.parent);
|
||||
const getLevelClass = computed(() => {
|
||||
return [
|
||||
{
|
||||
[`${prefixCls}__parent`]: props.parent,
|
||||
[`${prefixCls}__children`]: !props.parent
|
||||
}
|
||||
];
|
||||
});
|
||||
|
||||
function menuHasChildren(menuTreeItem: Menu): boolean {
|
||||
return (
|
||||
(!menuTreeItem.meta?.hideChildrenInMenu &&
|
||||
Reflect.has(menuTreeItem, 'children') &&
|
||||
!!menuTreeItem.children &&
|
||||
menuTreeItem.children.length > 0) ||
|
||||
menuTreeItem.meta?.menuType === 0
|
||||
);
|
||||
}
|
||||
function menuHasChildren(menuTreeItem: Menu): boolean {
|
||||
return (!menuTreeItem.meta?.hideChildrenInMenu && Reflect.has(menuTreeItem, 'children') && !!menuTreeItem.children && menuTreeItem.children.length > 0) || menuTreeItem.meta?.menuType === 0;
|
||||
}
|
||||
|
||||
return {
|
||||
prefixCls,
|
||||
menuHasChildren,
|
||||
getShowMenu,
|
||||
getIcon,
|
||||
getI18nName,
|
||||
getShowSubTitle,
|
||||
getLevelClass,
|
||||
getIsCollapseParent,
|
||||
};
|
||||
},
|
||||
});
|
||||
return {
|
||||
prefixCls,
|
||||
menuHasChildren,
|
||||
getShowMenu,
|
||||
getIcon,
|
||||
getI18nName,
|
||||
getShowSubTitle,
|
||||
getLevelClass,
|
||||
getIsCollapseParent
|
||||
};
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
@ -1,158 +1,148 @@
|
||||
<template>
|
||||
<ul :class="getClass">
|
||||
<slot></slot>
|
||||
</ul>
|
||||
<ul :class="getClass">
|
||||
<slot></slot>
|
||||
</ul>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import type { PropType } from 'vue';
|
||||
import type { SubMenuProvider } from './types';
|
||||
import {
|
||||
defineComponent,
|
||||
ref,
|
||||
computed,
|
||||
onMounted,
|
||||
watchEffect,
|
||||
watch,
|
||||
nextTick,
|
||||
getCurrentInstance,
|
||||
provide,
|
||||
} from 'vue';
|
||||
import type { PropType } from 'vue';
|
||||
import type { SubMenuProvider } from './types';
|
||||
import { defineComponent, ref, computed, onMounted, watchEffect, watch, nextTick, getCurrentInstance, provide } from 'vue';
|
||||
|
||||
import { useDesign } from '/@/hooks/web/useDesign';
|
||||
import { propTypes } from '/@/utils/propTypes';
|
||||
import { createSimpleRootMenuContext } from './useSimpleMenuContext';
|
||||
import mitt from '/@/utils/mitt';
|
||||
export default defineComponent({
|
||||
name: 'Menu',
|
||||
props: {
|
||||
theme: propTypes.oneOf(['light', 'dark']).def('light'),
|
||||
activeName: propTypes.oneOfType([propTypes.string, propTypes.number]),
|
||||
openNames: {
|
||||
type: Array as PropType<string[]>,
|
||||
default: () => [],
|
||||
},
|
||||
accordion: propTypes.bool.def(true),
|
||||
width: propTypes.string.def('100%'),
|
||||
collapsedWidth: propTypes.string.def('48px'),
|
||||
indentSize: propTypes.number.def(16),
|
||||
collapse: propTypes.bool.def(true),
|
||||
activeSubMenuNames: {
|
||||
type: Array as PropType<(string | number)[]>,
|
||||
default: () => [],
|
||||
},
|
||||
},
|
||||
emits: ['select', 'open-change'],
|
||||
setup(props, { emit }) {
|
||||
const rootMenuEmitter = mitt();
|
||||
const instance = getCurrentInstance();
|
||||
|
||||
const currentActiveName = ref<string | number>('');
|
||||
const openedNames = ref<string[]>([]);
|
||||
|
||||
const { prefixCls } = useDesign('menu');
|
||||
|
||||
const isRemoveAllPopup = ref(false);
|
||||
|
||||
createSimpleRootMenuContext({
|
||||
rootMenuEmitter: rootMenuEmitter,
|
||||
activeName: currentActiveName,
|
||||
});
|
||||
|
||||
const getClass = computed(() => {
|
||||
const { theme } = props;
|
||||
return [
|
||||
prefixCls,
|
||||
`${prefixCls}-${theme}`,
|
||||
`${prefixCls}-vertical`,
|
||||
{
|
||||
[`${prefixCls}-collapse`]: props.collapse,
|
||||
},
|
||||
];
|
||||
});
|
||||
|
||||
watchEffect(() => {
|
||||
openedNames.value = props.openNames;
|
||||
});
|
||||
|
||||
watchEffect(() => {
|
||||
if (props.activeName) {
|
||||
currentActiveName.value = props.activeName;
|
||||
}
|
||||
});
|
||||
|
||||
watch(
|
||||
() => props.openNames,
|
||||
() => {
|
||||
nextTick(() => {
|
||||
updateOpened();
|
||||
});
|
||||
import { useDesign } from '/@/hooks/web/useDesign';
|
||||
import { propTypes } from '/@/utils/propTypes';
|
||||
import { createSimpleRootMenuContext } from './useSimpleMenuContext';
|
||||
import mitt from '/@/utils/mitt';
|
||||
export default defineComponent({
|
||||
name: 'Menu',
|
||||
props: {
|
||||
theme: propTypes.oneOf(['light', 'dark']).def('light'),
|
||||
activeName: propTypes.oneOfType([propTypes.string, propTypes.number]),
|
||||
openNames: {
|
||||
type: Array as PropType<string[]>,
|
||||
default: () => []
|
||||
},
|
||||
accordion: propTypes.bool.def(true),
|
||||
width: propTypes.string.def('100%'),
|
||||
collapsedWidth: propTypes.string.def('48px'),
|
||||
indentSize: propTypes.number.def(16),
|
||||
collapse: propTypes.bool.def(true),
|
||||
activeSubMenuNames: {
|
||||
type: Array as PropType<(string | number)[]>,
|
||||
default: () => []
|
||||
}
|
||||
},
|
||||
);
|
||||
emits: ['select', 'open-change'],
|
||||
setup(props, { emit }) {
|
||||
const rootMenuEmitter = mitt();
|
||||
const instance = getCurrentInstance();
|
||||
|
||||
function updateOpened() {
|
||||
rootMenuEmitter.emit('on-update-opened', openedNames.value);
|
||||
}
|
||||
const currentActiveName = ref<string | number>('');
|
||||
const openedNames = ref<string[]>([]);
|
||||
|
||||
function addSubMenu(name: string) {
|
||||
if (openedNames.value.includes(name)) return;
|
||||
openedNames.value.push(name);
|
||||
updateOpened();
|
||||
}
|
||||
const { prefixCls } = useDesign('menu');
|
||||
|
||||
function removeSubMenu(name: string) {
|
||||
openedNames.value = openedNames.value.filter((item) => item !== name);
|
||||
updateOpened();
|
||||
}
|
||||
const isRemoveAllPopup = ref(false);
|
||||
|
||||
function removeAll() {
|
||||
openedNames.value = [];
|
||||
updateOpened();
|
||||
}
|
||||
createSimpleRootMenuContext({
|
||||
rootMenuEmitter: rootMenuEmitter,
|
||||
activeName: currentActiveName
|
||||
});
|
||||
|
||||
function sliceIndex(index: number) {
|
||||
if (index === -1) return;
|
||||
openedNames.value = openedNames.value.slice(0, index + 1);
|
||||
updateOpened();
|
||||
}
|
||||
const getClass = computed(() => {
|
||||
const { theme } = props;
|
||||
return [
|
||||
prefixCls,
|
||||
`${prefixCls}-${theme}`,
|
||||
`${prefixCls}-vertical`,
|
||||
{
|
||||
[`${prefixCls}-collapse`]: props.collapse
|
||||
}
|
||||
];
|
||||
});
|
||||
|
||||
provide<SubMenuProvider>(`subMenu:${instance?.uid}`, {
|
||||
addSubMenu,
|
||||
removeSubMenu,
|
||||
getOpenNames: () => openedNames.value,
|
||||
removeAll,
|
||||
isRemoveAllPopup,
|
||||
sliceIndex,
|
||||
level: 0,
|
||||
props: props as any,
|
||||
});
|
||||
watchEffect(() => {
|
||||
openedNames.value = props.openNames;
|
||||
});
|
||||
|
||||
onMounted(() => {
|
||||
openedNames.value = !props.collapse ? [...props.openNames] : [];
|
||||
updateOpened();
|
||||
rootMenuEmitter.on('on-menu-item-select', (name: string) => {
|
||||
currentActiveName.value = name;
|
||||
watchEffect(() => {
|
||||
if (props.activeName) {
|
||||
currentActiveName.value = props.activeName;
|
||||
}
|
||||
});
|
||||
|
||||
nextTick(() => {
|
||||
props.collapse && removeAll();
|
||||
});
|
||||
emit('select', name);
|
||||
});
|
||||
watch(
|
||||
() => props.openNames,
|
||||
() => {
|
||||
nextTick(() => {
|
||||
updateOpened();
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
rootMenuEmitter.on('open-name-change', ({ name, opened }) => {
|
||||
if (opened && !openedNames.value.includes(name)) {
|
||||
openedNames.value.push(name);
|
||||
} else if (!opened) {
|
||||
const index = openedNames.value.findIndex((item) => item === name);
|
||||
index !== -1 && openedNames.value.splice(index, 1);
|
||||
}
|
||||
});
|
||||
});
|
||||
function updateOpened() {
|
||||
rootMenuEmitter.emit('on-update-opened', openedNames.value);
|
||||
}
|
||||
|
||||
return { getClass, openedNames };
|
||||
},
|
||||
});
|
||||
function addSubMenu(name: string) {
|
||||
if (openedNames.value.includes(name)) return;
|
||||
openedNames.value.push(name);
|
||||
updateOpened();
|
||||
}
|
||||
|
||||
function removeSubMenu(name: string) {
|
||||
openedNames.value = openedNames.value.filter((item) => item !== name);
|
||||
updateOpened();
|
||||
}
|
||||
|
||||
function removeAll() {
|
||||
openedNames.value = [];
|
||||
updateOpened();
|
||||
}
|
||||
|
||||
function sliceIndex(index: number) {
|
||||
if (index === -1) return;
|
||||
openedNames.value = openedNames.value.slice(0, index + 1);
|
||||
updateOpened();
|
||||
}
|
||||
|
||||
provide<SubMenuProvider>(`subMenu:${instance?.uid}`, {
|
||||
addSubMenu,
|
||||
removeSubMenu,
|
||||
getOpenNames: () => openedNames.value,
|
||||
removeAll,
|
||||
isRemoveAllPopup,
|
||||
sliceIndex,
|
||||
level: 0,
|
||||
props: props as any
|
||||
});
|
||||
|
||||
onMounted(() => {
|
||||
openedNames.value = !props.collapse ? [...props.openNames] : [];
|
||||
updateOpened();
|
||||
rootMenuEmitter.on('on-menu-item-select', (name: string) => {
|
||||
currentActiveName.value = name;
|
||||
|
||||
nextTick(() => {
|
||||
props.collapse && removeAll();
|
||||
});
|
||||
emit('select', name);
|
||||
});
|
||||
|
||||
rootMenuEmitter.on('open-name-change', ({ name, opened }) => {
|
||||
if (opened && !openedNames.value.includes(name)) {
|
||||
openedNames.value.push(name);
|
||||
} else if (!opened) {
|
||||
const index = openedNames.value.findIndex((item) => item === name);
|
||||
index !== -1 && openedNames.value.splice(index, 1);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
return { getClass, openedNames };
|
||||
}
|
||||
});
|
||||
</script>
|
||||
<style lang="less">
|
||||
@import './menu.less';
|
||||
@import './menu.less';
|
||||
</style>
|
||||
|
||||
@ -1,78 +1,78 @@
|
||||
<template>
|
||||
<transition mode="out-in" v-on="on">
|
||||
<slot></slot>
|
||||
</transition>
|
||||
<transition mode="out-in" v-on="on">
|
||||
<slot></slot>
|
||||
</transition>
|
||||
</template>
|
||||
<script lang="ts">
|
||||
import { defineComponent } from 'vue';
|
||||
import { addClass, removeClass } from '/@/utils/domUtils';
|
||||
import { defineComponent } from 'vue';
|
||||
import { addClass, removeClass } from '/@/utils/domUtils';
|
||||
|
||||
export default defineComponent({
|
||||
name: 'MenuCollapseTransition',
|
||||
setup() {
|
||||
return {
|
||||
on: {
|
||||
beforeEnter(el) {
|
||||
addClass(el, 'collapse-transition');
|
||||
if (!el.dataset) el.dataset = {};
|
||||
export default defineComponent({
|
||||
name: 'MenuCollapseTransition',
|
||||
setup() {
|
||||
return {
|
||||
on: {
|
||||
beforeEnter(el) {
|
||||
addClass(el, 'collapse-transition');
|
||||
if (!el.dataset) el.dataset = {};
|
||||
|
||||
el.dataset.oldPaddingTop = el.style.paddingTop;
|
||||
el.dataset.oldPaddingBottom = el.style.paddingBottom;
|
||||
el.dataset.oldPaddingTop = el.style.paddingTop;
|
||||
el.dataset.oldPaddingBottom = el.style.paddingBottom;
|
||||
|
||||
el.style.height = '0';
|
||||
el.style.paddingTop = 0;
|
||||
el.style.paddingBottom = 0;
|
||||
},
|
||||
el.style.height = '0';
|
||||
el.style.paddingTop = 0;
|
||||
el.style.paddingBottom = 0;
|
||||
},
|
||||
|
||||
enter(el) {
|
||||
el.dataset.oldOverflow = el.style.overflow;
|
||||
if (el.scrollHeight !== 0) {
|
||||
el.style.height = el.scrollHeight + 'px';
|
||||
el.style.paddingTop = el.dataset.oldPaddingTop;
|
||||
el.style.paddingBottom = el.dataset.oldPaddingBottom;
|
||||
} else {
|
||||
el.style.height = '';
|
||||
el.style.paddingTop = el.dataset.oldPaddingTop;
|
||||
el.style.paddingBottom = el.dataset.oldPaddingBottom;
|
||||
}
|
||||
enter(el) {
|
||||
el.dataset.oldOverflow = el.style.overflow;
|
||||
if (el.scrollHeight !== 0) {
|
||||
el.style.height = el.scrollHeight + 'px';
|
||||
el.style.paddingTop = el.dataset.oldPaddingTop;
|
||||
el.style.paddingBottom = el.dataset.oldPaddingBottom;
|
||||
} else {
|
||||
el.style.height = '';
|
||||
el.style.paddingTop = el.dataset.oldPaddingTop;
|
||||
el.style.paddingBottom = el.dataset.oldPaddingBottom;
|
||||
}
|
||||
|
||||
el.style.overflow = 'hidden';
|
||||
},
|
||||
el.style.overflow = 'hidden';
|
||||
},
|
||||
|
||||
afterEnter(el) {
|
||||
removeClass(el, 'collapse-transition');
|
||||
el.style.height = '';
|
||||
el.style.overflow = el.dataset.oldOverflow;
|
||||
},
|
||||
afterEnter(el) {
|
||||
removeClass(el, 'collapse-transition');
|
||||
el.style.height = '';
|
||||
el.style.overflow = el.dataset.oldOverflow;
|
||||
},
|
||||
|
||||
beforeLeave(el) {
|
||||
if (!el.dataset) el.dataset = {};
|
||||
el.dataset.oldPaddingTop = el.style.paddingTop;
|
||||
el.dataset.oldPaddingBottom = el.style.paddingBottom;
|
||||
el.dataset.oldOverflow = el.style.overflow;
|
||||
beforeLeave(el) {
|
||||
if (!el.dataset) el.dataset = {};
|
||||
el.dataset.oldPaddingTop = el.style.paddingTop;
|
||||
el.dataset.oldPaddingBottom = el.style.paddingBottom;
|
||||
el.dataset.oldOverflow = el.style.overflow;
|
||||
|
||||
el.style.height = el.scrollHeight + 'px';
|
||||
el.style.overflow = 'hidden';
|
||||
},
|
||||
el.style.height = el.scrollHeight + 'px';
|
||||
el.style.overflow = 'hidden';
|
||||
},
|
||||
|
||||
leave(el) {
|
||||
if (el.scrollHeight !== 0) {
|
||||
addClass(el, 'collapse-transition');
|
||||
el.style.height = 0;
|
||||
el.style.paddingTop = 0;
|
||||
el.style.paddingBottom = 0;
|
||||
}
|
||||
},
|
||||
leave(el) {
|
||||
if (el.scrollHeight !== 0) {
|
||||
addClass(el, 'collapse-transition');
|
||||
el.style.height = 0;
|
||||
el.style.paddingTop = 0;
|
||||
el.style.paddingBottom = 0;
|
||||
}
|
||||
},
|
||||
|
||||
afterLeave(el) {
|
||||
removeClass(el, 'collapse-transition');
|
||||
el.style.height = '';
|
||||
el.style.overflow = el.dataset.oldOverflow;
|
||||
el.style.paddingTop = el.dataset.oldPaddingTop;
|
||||
el.style.paddingBottom = el.dataset.oldPaddingBottom;
|
||||
},
|
||||
},
|
||||
};
|
||||
},
|
||||
});
|
||||
afterLeave(el) {
|
||||
removeClass(el, 'collapse-transition');
|
||||
el.style.height = '';
|
||||
el.style.overflow = el.dataset.oldOverflow;
|
||||
el.style.paddingTop = el.dataset.oldPaddingTop;
|
||||
el.style.paddingBottom = el.dataset.oldPaddingBottom;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
@ -1,107 +1,106 @@
|
||||
<template>
|
||||
<li :class="getClass" @click.stop="handleClickItem" :style="getCollapse ? {} : getItemStyle">
|
||||
<Tooltip placement="right" v-if="showTooptip">
|
||||
<template #title>
|
||||
<slot name="title"></slot>
|
||||
</template>
|
||||
<div :class="`${prefixCls}-tooltip`">
|
||||
<slot></slot>
|
||||
</div>
|
||||
</Tooltip>
|
||||
<li :class="getClass" @click.stop="handleClickItem" :style="getCollapse ? {} : getItemStyle">
|
||||
<Tooltip placement="right" v-if="showTooptip">
|
||||
<template #title>
|
||||
<slot name="title"></slot>
|
||||
</template>
|
||||
<div :class="`${prefixCls}-tooltip`">
|
||||
<slot></slot>
|
||||
</div>
|
||||
</Tooltip>
|
||||
|
||||
<template v-else>
|
||||
<slot></slot>
|
||||
<slot name="title"></slot>
|
||||
</template>
|
||||
</li>
|
||||
<template v-else>
|
||||
<slot></slot>
|
||||
<slot name="title"></slot>
|
||||
</template>
|
||||
</li>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { PropType } from 'vue';
|
||||
import { defineComponent, ref, computed, unref, getCurrentInstance, watch } from 'vue';
|
||||
import { useDesign } from '/@/hooks/web/useDesign';
|
||||
import { propTypes } from '/@/utils/propTypes';
|
||||
import { useMenuItem } from './useMenu';
|
||||
import { Tooltip } from 'ant-design-vue';
|
||||
import { useSimpleRootMenuContext } from './useSimpleMenuContext';
|
||||
export default defineComponent({
|
||||
name: 'MenuItem',
|
||||
components: { Tooltip },
|
||||
props: {
|
||||
name: {
|
||||
type: [String, Number] as PropType<string | number>,
|
||||
required: true,
|
||||
},
|
||||
disabled: propTypes.bool,
|
||||
},
|
||||
setup(props, { slots }) {
|
||||
const instance = getCurrentInstance();
|
||||
import { PropType } from 'vue';
|
||||
import { defineComponent, ref, computed, unref, getCurrentInstance, watch } from 'vue';
|
||||
import { useDesign } from '/@/hooks/web/useDesign';
|
||||
import { propTypes } from '/@/utils/propTypes';
|
||||
import { useMenuItem } from './useMenu';
|
||||
import { Tooltip } from 'ant-design-vue';
|
||||
import { useSimpleRootMenuContext } from './useSimpleMenuContext';
|
||||
export default defineComponent({
|
||||
name: 'MenuItem',
|
||||
components: { Tooltip },
|
||||
props: {
|
||||
name: {
|
||||
type: [String, Number] as PropType<string | number>,
|
||||
required: true
|
||||
},
|
||||
disabled: propTypes.bool
|
||||
},
|
||||
setup(props, { slots }) {
|
||||
const instance = getCurrentInstance();
|
||||
|
||||
const active = ref(false);
|
||||
const active = ref(false);
|
||||
|
||||
const { getItemStyle, getParentList, getParentMenu, getParentRootMenu } =
|
||||
useMenuItem(instance);
|
||||
const { getItemStyle, getParentList, getParentMenu, getParentRootMenu } = useMenuItem(instance);
|
||||
|
||||
const { prefixCls } = useDesign('menu');
|
||||
const { prefixCls } = useDesign('menu');
|
||||
|
||||
const { rootMenuEmitter, activeName } = useSimpleRootMenuContext();
|
||||
const { rootMenuEmitter, activeName } = useSimpleRootMenuContext();
|
||||
|
||||
const getClass = computed(() => {
|
||||
return [
|
||||
`${prefixCls}-item`,
|
||||
{
|
||||
[`${prefixCls}-item-active`]: unref(active),
|
||||
[`${prefixCls}-item-selected`]: unref(active),
|
||||
[`${prefixCls}-item-disabled`]: !!props.disabled,
|
||||
},
|
||||
];
|
||||
});
|
||||
|
||||
const getCollapse = computed(() => unref(getParentRootMenu)?.props.collapse);
|
||||
|
||||
const showTooptip = computed(() => {
|
||||
return unref(getParentMenu)?.type.name === 'Menu' && unref(getCollapse) && slots.title;
|
||||
});
|
||||
|
||||
function handleClickItem() {
|
||||
const { disabled } = props;
|
||||
if (disabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
rootMenuEmitter.emit('on-menu-item-select', props.name);
|
||||
if (unref(getCollapse)) {
|
||||
return;
|
||||
}
|
||||
const { uidList } = getParentList();
|
||||
|
||||
rootMenuEmitter.emit('on-update-opened', {
|
||||
opend: false,
|
||||
parent: instance?.parent,
|
||||
uidList: uidList,
|
||||
});
|
||||
}
|
||||
watch(
|
||||
() => activeName.value,
|
||||
(name: string) => {
|
||||
if (name === props.name) {
|
||||
const { list, uidList } = getParentList();
|
||||
active.value = true;
|
||||
list.forEach((item) => {
|
||||
if (item.proxy) {
|
||||
(item.proxy as any).active = true;
|
||||
}
|
||||
const getClass = computed(() => {
|
||||
return [
|
||||
`${prefixCls}-item`,
|
||||
{
|
||||
[`${prefixCls}-item-active`]: unref(active),
|
||||
[`${prefixCls}-item-selected`]: unref(active),
|
||||
[`${prefixCls}-item-disabled`]: !!props.disabled
|
||||
}
|
||||
];
|
||||
});
|
||||
|
||||
rootMenuEmitter.emit('on-update-active-name:submenu', uidList);
|
||||
} else {
|
||||
active.value = false;
|
||||
}
|
||||
},
|
||||
{ immediate: true },
|
||||
);
|
||||
const getCollapse = computed(() => unref(getParentRootMenu)?.props.collapse);
|
||||
|
||||
return { getClass, prefixCls, getItemStyle, getCollapse, handleClickItem, showTooptip };
|
||||
},
|
||||
});
|
||||
const showTooptip = computed(() => {
|
||||
return unref(getParentMenu)?.type.name === 'Menu' && unref(getCollapse) && slots.title;
|
||||
});
|
||||
|
||||
function handleClickItem() {
|
||||
const { disabled } = props;
|
||||
if (disabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
rootMenuEmitter.emit('on-menu-item-select', props.name);
|
||||
if (unref(getCollapse)) {
|
||||
return;
|
||||
}
|
||||
const { uidList } = getParentList();
|
||||
|
||||
rootMenuEmitter.emit('on-update-opened', {
|
||||
opend: false,
|
||||
parent: instance?.parent,
|
||||
uidList: uidList
|
||||
});
|
||||
}
|
||||
watch(
|
||||
() => activeName.value,
|
||||
(name: string) => {
|
||||
if (name === props.name) {
|
||||
const { list, uidList } = getParentList();
|
||||
active.value = true;
|
||||
list.forEach((item) => {
|
||||
if (item.proxy) {
|
||||
(item.proxy as any).active = true;
|
||||
}
|
||||
});
|
||||
|
||||
rootMenuEmitter.emit('on-update-active-name:submenu', uidList);
|
||||
} else {
|
||||
active.value = false;
|
||||
}
|
||||
},
|
||||
{ immediate: true }
|
||||
);
|
||||
|
||||
return { getClass, prefixCls, getItemStyle, getCollapse, handleClickItem, showTooptip };
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
@ -1,334 +1,303 @@
|
||||
<template>
|
||||
<li :class="getClass">
|
||||
<template v-if="!getCollapse">
|
||||
<div :class="`${prefixCls}-submenu-title`" @click.stop="handleClick" :style="getItemStyle">
|
||||
<slot name="title"></slot>
|
||||
<Icon
|
||||
icon="eva:arrow-ios-downward-outline"
|
||||
:size="14"
|
||||
:class="`${prefixCls}-submenu-title-icon`"
|
||||
/>
|
||||
</div>
|
||||
<CollapseTransition>
|
||||
<ul :class="prefixCls" v-show="opened">
|
||||
<slot></slot>
|
||||
</ul>
|
||||
</CollapseTransition>
|
||||
</template>
|
||||
<li :class="getClass">
|
||||
<template v-if="!getCollapse">
|
||||
<div :class="`${prefixCls}-submenu-title`" @click.stop="handleClick" :style="getItemStyle">
|
||||
<slot name="title"></slot>
|
||||
<Icon icon="eva:arrow-ios-downward-outline" :size="14" :class="`${prefixCls}-submenu-title-icon`" />
|
||||
</div>
|
||||
<CollapseTransition>
|
||||
<ul :class="prefixCls" v-show="opened">
|
||||
<slot></slot>
|
||||
</ul>
|
||||
</CollapseTransition>
|
||||
</template>
|
||||
|
||||
<Popover
|
||||
placement="right"
|
||||
:overlayClassName="`${prefixCls}-menu-popover`"
|
||||
v-else
|
||||
:visible="getIsOpend"
|
||||
@visible-change="handleVisibleChange"
|
||||
:overlayStyle="getOverlayStyle"
|
||||
:align="{ offset: [0, 0] }"
|
||||
>
|
||||
<div :class="getSubClass" v-bind="getEvents(false)">
|
||||
<div
|
||||
:class="[
|
||||
{
|
||||
[`${prefixCls}-submenu-popup`]: !getParentSubMenu,
|
||||
[`${prefixCls}-submenu-collapsed-show-tit`]: collapsedShowTitle,
|
||||
},
|
||||
]"
|
||||
>
|
||||
<slot name="title"></slot>
|
||||
</div>
|
||||
<Icon
|
||||
v-if="getParentSubMenu"
|
||||
icon="eva:arrow-ios-downward-outline"
|
||||
:size="14"
|
||||
:class="`${prefixCls}-submenu-title-icon`"
|
||||
/>
|
||||
</div>
|
||||
<!-- eslint-disable-next-line -->
|
||||
<template #content v-show="opened">
|
||||
<div v-bind="getEvents(true)">
|
||||
<ul :class="[prefixCls, `${prefixCls}-${getTheme}`, `${prefixCls}-popup`]">
|
||||
<slot></slot>
|
||||
</ul>
|
||||
</div>
|
||||
</template>
|
||||
</Popover>
|
||||
</li>
|
||||
<Popover placement="right" :overlayClassName="`${prefixCls}-menu-popover`" v-else :visible="getIsOpend" @visible-change="handleVisibleChange" :overlayStyle="getOverlayStyle" :align="{ offset: [0, 0] }">
|
||||
<div :class="getSubClass" v-bind="getEvents(false)">
|
||||
<div
|
||||
:class="[
|
||||
{
|
||||
[`${prefixCls}-submenu-popup`]: !getParentSubMenu,
|
||||
[`${prefixCls}-submenu-collapsed-show-tit`]: collapsedShowTitle
|
||||
}
|
||||
]"
|
||||
>
|
||||
<slot name="title"></slot>
|
||||
</div>
|
||||
<Icon v-if="getParentSubMenu" icon="eva:arrow-ios-downward-outline" :size="14" :class="`${prefixCls}-submenu-title-icon`" />
|
||||
</div>
|
||||
<!-- eslint-disable-next-line -->
|
||||
<template #content v-show="opened">
|
||||
<div v-bind="getEvents(true)">
|
||||
<ul :class="[prefixCls, `${prefixCls}-${getTheme}`, `${prefixCls}-popup`]">
|
||||
<slot></slot>
|
||||
</ul>
|
||||
</div>
|
||||
</template>
|
||||
</Popover>
|
||||
</li>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import type { CSSProperties, PropType } from 'vue';
|
||||
import type { SubMenuProvider } from './types';
|
||||
import {
|
||||
defineComponent,
|
||||
computed,
|
||||
unref,
|
||||
getCurrentInstance,
|
||||
toRefs,
|
||||
reactive,
|
||||
provide,
|
||||
onBeforeMount,
|
||||
inject,
|
||||
} from 'vue';
|
||||
import { useDesign } from '/@/hooks/web/useDesign';
|
||||
import { propTypes } from '/@/utils/propTypes';
|
||||
import { useMenuItem } from './useMenu';
|
||||
import { useSimpleRootMenuContext } from './useSimpleMenuContext';
|
||||
import { CollapseTransition } from '/@/components/Transition';
|
||||
import Icon from '/@/components/Icon';
|
||||
import { Popover } from 'ant-design-vue';
|
||||
import { isBoolean, isObject } from '/@/utils/is';
|
||||
import mitt from '/@/utils/mitt';
|
||||
import type { CSSProperties, PropType } from 'vue';
|
||||
import type { SubMenuProvider } from './types';
|
||||
import { defineComponent, computed, unref, getCurrentInstance, toRefs, reactive, provide, onBeforeMount, inject } from 'vue';
|
||||
import { useDesign } from '/@/hooks/web/useDesign';
|
||||
import { propTypes } from '/@/utils/propTypes';
|
||||
import { useMenuItem } from './useMenu';
|
||||
import { useSimpleRootMenuContext } from './useSimpleMenuContext';
|
||||
import { CollapseTransition } from '/@/components/Transition';
|
||||
import Icon from '/@/components/Icon';
|
||||
import { Popover } from 'ant-design-vue';
|
||||
import { isBoolean, isObject } from '/@/utils/is';
|
||||
import mitt from '/@/utils/mitt';
|
||||
|
||||
const DELAY = 200;
|
||||
export default defineComponent({
|
||||
name: 'SubMenu',
|
||||
components: {
|
||||
Icon,
|
||||
CollapseTransition,
|
||||
Popover,
|
||||
},
|
||||
props: {
|
||||
name: {
|
||||
type: [String, Number] as PropType<string | number>,
|
||||
required: true,
|
||||
},
|
||||
disabled: propTypes.bool,
|
||||
collapsedShowTitle: propTypes.bool,
|
||||
},
|
||||
setup(props) {
|
||||
const instance = getCurrentInstance();
|
||||
const DELAY = 200;
|
||||
export default defineComponent({
|
||||
name: 'SubMenu',
|
||||
components: {
|
||||
Icon,
|
||||
CollapseTransition,
|
||||
Popover
|
||||
},
|
||||
props: {
|
||||
name: {
|
||||
type: [String, Number] as PropType<string | number>,
|
||||
required: true
|
||||
},
|
||||
disabled: propTypes.bool,
|
||||
collapsedShowTitle: propTypes.bool
|
||||
},
|
||||
setup(props) {
|
||||
const instance = getCurrentInstance();
|
||||
|
||||
const state = reactive({
|
||||
active: false,
|
||||
opened: false,
|
||||
});
|
||||
const state = reactive({
|
||||
active: false,
|
||||
opened: false
|
||||
});
|
||||
|
||||
const data = reactive({
|
||||
timeout: null as TimeoutHandle | null,
|
||||
mouseInChild: false,
|
||||
isChild: false,
|
||||
});
|
||||
const data = reactive({
|
||||
timeout: null as TimeoutHandle | null,
|
||||
mouseInChild: false,
|
||||
isChild: false
|
||||
});
|
||||
|
||||
const { getParentSubMenu, getItemStyle, getParentMenu, getParentList } =
|
||||
useMenuItem(instance);
|
||||
const { getParentSubMenu, getItemStyle, getParentMenu, getParentList } = useMenuItem(instance);
|
||||
|
||||
const { prefixCls } = useDesign('menu');
|
||||
const { prefixCls } = useDesign('menu');
|
||||
|
||||
const subMenuEmitter = mitt();
|
||||
const subMenuEmitter = mitt();
|
||||
|
||||
const { rootMenuEmitter } = useSimpleRootMenuContext();
|
||||
const { rootMenuEmitter } = useSimpleRootMenuContext();
|
||||
|
||||
const {
|
||||
addSubMenu: parentAddSubmenu,
|
||||
removeSubMenu: parentRemoveSubmenu,
|
||||
removeAll: parentRemoveAll,
|
||||
getOpenNames: parentGetOpenNames,
|
||||
isRemoveAllPopup,
|
||||
sliceIndex,
|
||||
level,
|
||||
props: rootProps,
|
||||
handleMouseleave: parentHandleMouseleave,
|
||||
} = inject<SubMenuProvider>(`subMenu:${getParentMenu.value?.uid}`)!;
|
||||
const {
|
||||
addSubMenu: parentAddSubmenu,
|
||||
removeSubMenu: parentRemoveSubmenu,
|
||||
removeAll: parentRemoveAll,
|
||||
getOpenNames: parentGetOpenNames,
|
||||
isRemoveAllPopup,
|
||||
sliceIndex,
|
||||
level,
|
||||
props: rootProps,
|
||||
handleMouseleave: parentHandleMouseleave
|
||||
} = inject<SubMenuProvider>(`subMenu:${getParentMenu.value?.uid}`)!;
|
||||
|
||||
const getClass = computed(() => {
|
||||
return [
|
||||
`${prefixCls}-submenu`,
|
||||
{
|
||||
[`${prefixCls}-item-active`]: state.active,
|
||||
[`${prefixCls}-opened`]: state.opened,
|
||||
[`${prefixCls}-submenu-disabled`]: props.disabled,
|
||||
[`${prefixCls}-submenu-has-parent-submenu`]: unref(getParentSubMenu),
|
||||
[`${prefixCls}-child-item-active`]: state.active,
|
||||
},
|
||||
];
|
||||
});
|
||||
const getClass = computed(() => {
|
||||
return [
|
||||
`${prefixCls}-submenu`,
|
||||
{
|
||||
[`${prefixCls}-item-active`]: state.active,
|
||||
[`${prefixCls}-opened`]: state.opened,
|
||||
[`${prefixCls}-submenu-disabled`]: props.disabled,
|
||||
[`${prefixCls}-submenu-has-parent-submenu`]: unref(getParentSubMenu),
|
||||
[`${prefixCls}-child-item-active`]: state.active
|
||||
}
|
||||
];
|
||||
});
|
||||
|
||||
const getAccordion = computed(() => rootProps.accordion);
|
||||
const getCollapse = computed(() => rootProps.collapse);
|
||||
const getTheme = computed(() => rootProps.theme);
|
||||
const getAccordion = computed(() => rootProps.accordion);
|
||||
const getCollapse = computed(() => rootProps.collapse);
|
||||
const getTheme = computed(() => rootProps.theme);
|
||||
|
||||
const getOverlayStyle = computed((): CSSProperties => {
|
||||
return {
|
||||
minWidth: '200px',
|
||||
};
|
||||
});
|
||||
const getOverlayStyle = computed((): CSSProperties => {
|
||||
return {
|
||||
minWidth: '200px'
|
||||
};
|
||||
});
|
||||
|
||||
const getIsOpend = computed(() => {
|
||||
const name = props.name;
|
||||
if (unref(getCollapse)) {
|
||||
return parentGetOpenNames().includes(name);
|
||||
}
|
||||
return state.opened;
|
||||
});
|
||||
const getIsOpend = computed(() => {
|
||||
const name = props.name;
|
||||
if (unref(getCollapse)) {
|
||||
return parentGetOpenNames().includes(name);
|
||||
}
|
||||
return state.opened;
|
||||
});
|
||||
|
||||
const getSubClass = computed(() => {
|
||||
const isActive = rootProps.activeSubMenuNames.includes(props.name);
|
||||
return [
|
||||
`${prefixCls}-submenu-title`,
|
||||
{
|
||||
[`${prefixCls}-submenu-active`]: isActive,
|
||||
[`${prefixCls}-submenu-active-border`]: isActive && level === 0,
|
||||
[`${prefixCls}-submenu-collapse`]: unref(getCollapse) && level === 0,
|
||||
},
|
||||
];
|
||||
});
|
||||
const getSubClass = computed(() => {
|
||||
const isActive = rootProps.activeSubMenuNames.includes(props.name);
|
||||
return [
|
||||
`${prefixCls}-submenu-title`,
|
||||
{
|
||||
[`${prefixCls}-submenu-active`]: isActive,
|
||||
[`${prefixCls}-submenu-active-border`]: isActive && level === 0,
|
||||
[`${prefixCls}-submenu-collapse`]: unref(getCollapse) && level === 0
|
||||
}
|
||||
];
|
||||
});
|
||||
|
||||
function getEvents(deep: boolean) {
|
||||
if (!unref(getCollapse)) {
|
||||
return {};
|
||||
}
|
||||
return {
|
||||
onMouseenter: handleMouseenter,
|
||||
onMouseleave: () => handleMouseleave(deep),
|
||||
};
|
||||
}
|
||||
|
||||
function handleClick() {
|
||||
const { disabled } = props;
|
||||
if (disabled || unref(getCollapse)) return;
|
||||
const opened = state.opened;
|
||||
|
||||
if (unref(getAccordion)) {
|
||||
const { uidList } = getParentList();
|
||||
rootMenuEmitter.emit('on-update-opened', {
|
||||
opend: false,
|
||||
parent: instance?.parent,
|
||||
uidList: uidList,
|
||||
});
|
||||
} else {
|
||||
rootMenuEmitter.emit('open-name-change', {
|
||||
name: props.name,
|
||||
opened: !opened,
|
||||
});
|
||||
}
|
||||
state.opened = !opened;
|
||||
}
|
||||
|
||||
function handleMouseenter() {
|
||||
const disabled = props.disabled;
|
||||
if (disabled) return;
|
||||
|
||||
subMenuEmitter.emit('submenu:mouse-enter-child');
|
||||
|
||||
const index = parentGetOpenNames().findIndex((item) => item === props.name);
|
||||
|
||||
sliceIndex(index);
|
||||
|
||||
const isRoot = level === 0 && parentGetOpenNames().length === 2;
|
||||
if (isRoot) {
|
||||
parentRemoveAll();
|
||||
}
|
||||
data.isChild = parentGetOpenNames().includes(props.name);
|
||||
clearTimeout(data.timeout!);
|
||||
data.timeout = setTimeout(() => {
|
||||
parentAddSubmenu(props.name);
|
||||
}, DELAY);
|
||||
}
|
||||
|
||||
function handleMouseleave(deepDispatch = false) {
|
||||
const parentName = getParentMenu.value?.props.name;
|
||||
if (!parentName) {
|
||||
isRemoveAllPopup.value = true;
|
||||
}
|
||||
|
||||
if (parentGetOpenNames().slice(-1)[0] === props.name) {
|
||||
data.isChild = false;
|
||||
}
|
||||
|
||||
subMenuEmitter.emit('submenu:mouse-leave-child');
|
||||
if (data.timeout) {
|
||||
clearTimeout(data.timeout!);
|
||||
data.timeout = setTimeout(() => {
|
||||
if (isRemoveAllPopup.value) {
|
||||
parentRemoveAll();
|
||||
} else if (!data.mouseInChild) {
|
||||
parentRemoveSubmenu(props.name);
|
||||
}
|
||||
}, DELAY);
|
||||
}
|
||||
if (deepDispatch) {
|
||||
if (getParentSubMenu.value) {
|
||||
parentHandleMouseleave?.(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
onBeforeMount(() => {
|
||||
subMenuEmitter.on('submenu:mouse-enter-child', () => {
|
||||
data.mouseInChild = true;
|
||||
isRemoveAllPopup.value = false;
|
||||
clearTimeout(data.timeout!);
|
||||
});
|
||||
subMenuEmitter.on('submenu:mouse-leave-child', () => {
|
||||
if (data.isChild) return;
|
||||
data.mouseInChild = false;
|
||||
clearTimeout(data.timeout!);
|
||||
});
|
||||
|
||||
rootMenuEmitter.on(
|
||||
'on-update-opened',
|
||||
(data: boolean | (string | number)[] | Recordable) => {
|
||||
if (unref(getCollapse)) return;
|
||||
if (isBoolean(data)) {
|
||||
state.opened = data;
|
||||
return;
|
||||
}
|
||||
if (isObject(data) && rootProps.accordion) {
|
||||
const { opend, parent, uidList } = data as Recordable;
|
||||
if (parent === instance?.parent) {
|
||||
state.opened = opend;
|
||||
} else if (!uidList.includes(instance?.uid)) {
|
||||
state.opened = false;
|
||||
}
|
||||
return;
|
||||
function getEvents(deep: boolean) {
|
||||
if (!unref(getCollapse)) {
|
||||
return {};
|
||||
}
|
||||
return {
|
||||
onMouseenter: handleMouseenter,
|
||||
onMouseleave: () => handleMouseleave(deep)
|
||||
};
|
||||
}
|
||||
|
||||
if (props.name && Array.isArray(data)) {
|
||||
state.opened = (data as (string | number)[]).includes(props.name);
|
||||
function handleClick() {
|
||||
const { disabled } = props;
|
||||
if (disabled || unref(getCollapse)) return;
|
||||
const opened = state.opened;
|
||||
|
||||
if (unref(getAccordion)) {
|
||||
const { uidList } = getParentList();
|
||||
rootMenuEmitter.emit('on-update-opened', {
|
||||
opend: false,
|
||||
parent: instance?.parent,
|
||||
uidList: uidList
|
||||
});
|
||||
} else {
|
||||
rootMenuEmitter.emit('open-name-change', {
|
||||
name: props.name,
|
||||
opened: !opened
|
||||
});
|
||||
}
|
||||
state.opened = !opened;
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
rootMenuEmitter.on('on-update-active-name:submenu', (data: number[]) => {
|
||||
if (instance?.uid) {
|
||||
state.active = data.includes(instance?.uid);
|
||||
}
|
||||
});
|
||||
});
|
||||
function handleMouseenter() {
|
||||
const disabled = props.disabled;
|
||||
if (disabled) return;
|
||||
|
||||
function handleVisibleChange(visible: boolean) {
|
||||
state.opened = visible;
|
||||
}
|
||||
subMenuEmitter.emit('submenu:mouse-enter-child');
|
||||
|
||||
// provide
|
||||
provide<SubMenuProvider>(`subMenu:${instance?.uid}`, {
|
||||
addSubMenu: parentAddSubmenu,
|
||||
removeSubMenu: parentRemoveSubmenu,
|
||||
getOpenNames: parentGetOpenNames,
|
||||
removeAll: parentRemoveAll,
|
||||
isRemoveAllPopup,
|
||||
sliceIndex,
|
||||
level: level + 1,
|
||||
handleMouseleave,
|
||||
props: rootProps,
|
||||
});
|
||||
const index = parentGetOpenNames().findIndex((item) => item === props.name);
|
||||
|
||||
return {
|
||||
getClass,
|
||||
prefixCls,
|
||||
getCollapse,
|
||||
getItemStyle,
|
||||
handleClick,
|
||||
handleVisibleChange,
|
||||
getParentSubMenu,
|
||||
getOverlayStyle,
|
||||
getTheme,
|
||||
getIsOpend,
|
||||
getEvents,
|
||||
getSubClass,
|
||||
...toRefs(state),
|
||||
...toRefs(data),
|
||||
};
|
||||
},
|
||||
});
|
||||
sliceIndex(index);
|
||||
|
||||
const isRoot = level === 0 && parentGetOpenNames().length === 2;
|
||||
if (isRoot) {
|
||||
parentRemoveAll();
|
||||
}
|
||||
data.isChild = parentGetOpenNames().includes(props.name);
|
||||
clearTimeout(data.timeout!);
|
||||
data.timeout = setTimeout(() => {
|
||||
parentAddSubmenu(props.name);
|
||||
}, DELAY);
|
||||
}
|
||||
|
||||
function handleMouseleave(deepDispatch = false) {
|
||||
const parentName = getParentMenu.value?.props.name;
|
||||
if (!parentName) {
|
||||
isRemoveAllPopup.value = true;
|
||||
}
|
||||
|
||||
if (parentGetOpenNames().slice(-1)[0] === props.name) {
|
||||
data.isChild = false;
|
||||
}
|
||||
|
||||
subMenuEmitter.emit('submenu:mouse-leave-child');
|
||||
if (data.timeout) {
|
||||
clearTimeout(data.timeout!);
|
||||
data.timeout = setTimeout(() => {
|
||||
if (isRemoveAllPopup.value) {
|
||||
parentRemoveAll();
|
||||
} else if (!data.mouseInChild) {
|
||||
parentRemoveSubmenu(props.name);
|
||||
}
|
||||
}, DELAY);
|
||||
}
|
||||
if (deepDispatch) {
|
||||
if (getParentSubMenu.value) {
|
||||
parentHandleMouseleave?.(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
onBeforeMount(() => {
|
||||
subMenuEmitter.on('submenu:mouse-enter-child', () => {
|
||||
data.mouseInChild = true;
|
||||
isRemoveAllPopup.value = false;
|
||||
clearTimeout(data.timeout!);
|
||||
});
|
||||
subMenuEmitter.on('submenu:mouse-leave-child', () => {
|
||||
if (data.isChild) return;
|
||||
data.mouseInChild = false;
|
||||
clearTimeout(data.timeout!);
|
||||
});
|
||||
|
||||
rootMenuEmitter.on('on-update-opened', (data: boolean | (string | number)[] | Recordable) => {
|
||||
if (unref(getCollapse)) return;
|
||||
if (isBoolean(data)) {
|
||||
state.opened = data;
|
||||
return;
|
||||
}
|
||||
if (isObject(data) && rootProps.accordion) {
|
||||
const { opend, parent, uidList } = data as Recordable;
|
||||
if (parent === instance?.parent) {
|
||||
state.opened = opend;
|
||||
} else if (!uidList.includes(instance?.uid)) {
|
||||
state.opened = false;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (props.name && Array.isArray(data)) {
|
||||
state.opened = (data as (string | number)[]).includes(props.name);
|
||||
}
|
||||
});
|
||||
|
||||
rootMenuEmitter.on('on-update-active-name:submenu', (data: number[]) => {
|
||||
if (instance?.uid) {
|
||||
state.active = data.includes(instance?.uid);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
function handleVisibleChange(visible: boolean) {
|
||||
state.opened = visible;
|
||||
}
|
||||
|
||||
// provide
|
||||
provide<SubMenuProvider>(`subMenu:${instance?.uid}`, {
|
||||
addSubMenu: parentAddSubmenu,
|
||||
removeSubMenu: parentRemoveSubmenu,
|
||||
getOpenNames: parentGetOpenNames,
|
||||
removeAll: parentRemoveAll,
|
||||
isRemoveAllPopup,
|
||||
sliceIndex,
|
||||
level: level + 1,
|
||||
handleMouseleave,
|
||||
props: rootProps
|
||||
});
|
||||
|
||||
return {
|
||||
getClass,
|
||||
prefixCls,
|
||||
getCollapse,
|
||||
getItemStyle,
|
||||
handleClick,
|
||||
handleVisibleChange,
|
||||
getParentSubMenu,
|
||||
getOverlayStyle,
|
||||
getTheme,
|
||||
getIsOpend,
|
||||
getEvents,
|
||||
getSubClass,
|
||||
...toRefs(state),
|
||||
...toRefs(data)
|
||||
};
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
@ -2,76 +2,76 @@
|
||||
@prefix-cls: ~'@{namespace}-menu';
|
||||
|
||||
.@{prefix-cls} {
|
||||
&-dark&-vertical .@{simple-prefix-cls}__parent {
|
||||
background-color: @sider-dark-darken-bg-color;
|
||||
> .@{prefix-cls}-submenu-title {
|
||||
background-color: @sider-dark-darken-bg-color;
|
||||
&-dark&-vertical .@{simple-prefix-cls}__parent {
|
||||
background-color: @sider-dark-darken-bg-color;
|
||||
> .@{prefix-cls}-submenu-title {
|
||||
background-color: @sider-dark-darken-bg-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&-dark&-vertical .@{simple-prefix-cls}__children,
|
||||
&-dark&-popup .@{simple-prefix-cls}__children {
|
||||
// background-color: @sider-dark-lighten-bg-color;
|
||||
> .@{prefix-cls}-submenu-title {
|
||||
background-color: @sider-dark-lighten-bg-color;
|
||||
&-dark&-vertical .@{simple-prefix-cls}__children,
|
||||
&-dark&-popup .@{simple-prefix-cls}__children {
|
||||
// background-color: @sider-dark-lighten-bg-color;
|
||||
> .@{prefix-cls}-submenu-title {
|
||||
background-color: @sider-dark-lighten-bg-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.collapse-title {
|
||||
overflow: hidden;
|
||||
font-size: 12px;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.collapse-title {
|
||||
overflow: hidden;
|
||||
font-size: 12px;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
}
|
||||
|
||||
.@{simple-prefix-cls} {
|
||||
&-sub-title {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
transition: all 0.3s;
|
||||
}
|
||||
|
||||
&-tag {
|
||||
position: absolute;
|
||||
top: calc(50% - 8px);
|
||||
right: 30px;
|
||||
display: inline-block;
|
||||
padding: 2px 3px;
|
||||
margin-right: 4px;
|
||||
font-size: 10px;
|
||||
line-height: 14px;
|
||||
color: #fff;
|
||||
border-radius: 2px;
|
||||
|
||||
&--collapse {
|
||||
top: 6px !important;
|
||||
right: 2px;
|
||||
&-sub-title {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
transition: all 0.3s;
|
||||
}
|
||||
|
||||
&--dot {
|
||||
top: calc(50% - 2px);
|
||||
width: 6px;
|
||||
height: 6px;
|
||||
padding: 0;
|
||||
border-radius: 50%;
|
||||
}
|
||||
&-tag {
|
||||
position: absolute;
|
||||
top: calc(50% - 8px);
|
||||
right: 30px;
|
||||
display: inline-block;
|
||||
padding: 2px 3px;
|
||||
margin-right: 4px;
|
||||
font-size: 10px;
|
||||
line-height: 14px;
|
||||
color: #fff;
|
||||
border-radius: 2px;
|
||||
|
||||
&--primary {
|
||||
background-color: @primary-color;
|
||||
}
|
||||
&--collapse {
|
||||
top: 6px !important;
|
||||
right: 2px;
|
||||
}
|
||||
|
||||
&--error {
|
||||
background-color: @error-color;
|
||||
}
|
||||
&--dot {
|
||||
top: calc(50% - 2px);
|
||||
width: 6px;
|
||||
height: 6px;
|
||||
padding: 0;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
&--success {
|
||||
background-color: @success-color;
|
||||
}
|
||||
&--primary {
|
||||
background-color: @primary-color;
|
||||
}
|
||||
|
||||
&--warn {
|
||||
background-color: @warning-color;
|
||||
&--error {
|
||||
background-color: @error-color;
|
||||
}
|
||||
|
||||
&--success {
|
||||
background-color: @success-color;
|
||||
}
|
||||
|
||||
&--warn {
|
||||
background-color: @warning-color;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user