wip: use kingdee style header
This commit is contained in:
parent
0ed5dd9d06
commit
11908d5812
@ -1,3 +1,4 @@
|
||||
import BasicMenu from './src/BasicMenu.vue'
|
||||
import KingdeeBaseMenu from './src/KingdeeBasicMenu.vue'
|
||||
|
||||
export { BasicMenu }
|
||||
export { BasicMenu, KingdeeBaseMenu }
|
||||
|
147
src/components/Menu/src/KingdeeBasicMenu.vue
Normal file
147
src/components/Menu/src/KingdeeBasicMenu.vue
Normal file
@ -0,0 +1,147 @@
|
||||
<script lang="ts" setup>
|
||||
import { computed, reactive, ref, toRefs, unref, watch } from 'vue'
|
||||
import type { MenuProps } from 'ant-design-vue'
|
||||
import { Menu } from 'ant-design-vue'
|
||||
import type { RouteLocationNormalizedLoaded } from 'vue-router'
|
||||
import { useRouter } from 'vue-router'
|
||||
import type { MenuState } from './types'
|
||||
import KingdeeBasicSubMenuItem from './components/KingdeeBasicSubMenuItem.vue'
|
||||
import { useOpenKeys } from './useOpenKeys'
|
||||
import { basicProps } from './props'
|
||||
import { MenuModeEnum, MenuTypeEnum } from '@/enums/menuEnum'
|
||||
import { isFunction } from '@/utils/is'
|
||||
import { useMenuSetting } from '@/hooks/setting/useMenuSetting'
|
||||
import { REDIRECT_NAME } from '@/router/constant'
|
||||
import { useDesign } from '@/hooks/web/useDesign'
|
||||
import { getCurrentParentPath } from '@/router/menus'
|
||||
import { listenerRouteChange } from '@/logics/mitt/routeChange'
|
||||
import { getAllParentPath } from '@/router/helper/menuHelper'
|
||||
|
||||
defineOptions({ name: 'BasicMenu' })
|
||||
|
||||
const props = defineProps(basicProps)
|
||||
const emit = defineEmits(['menuClick'])
|
||||
|
||||
const isClickGo = ref(false)
|
||||
const currentActiveMenu = ref('')
|
||||
|
||||
const menuState = reactive<MenuState>({
|
||||
defaultSelectedKeys: [],
|
||||
openKeys: [],
|
||||
selectedKeys: [],
|
||||
collapsedOpenKeys: [],
|
||||
})
|
||||
|
||||
const { prefixCls } = useDesign('basic-menu')
|
||||
const { items, mode, accordion } = toRefs(props)
|
||||
|
||||
const { getCollapsed, getTopMenuAlign, getSplit } = useMenuSetting()
|
||||
|
||||
const { currentRoute } = useRouter()
|
||||
|
||||
const { handleOpenChange, setOpenKeys, getOpenKeys } = useOpenKeys(menuState, items, mode as any, accordion)
|
||||
|
||||
const getIsTopMenu = computed(() => {
|
||||
const { type, mode } = props
|
||||
|
||||
return (type === MenuTypeEnum.TOP_MENU && mode === MenuModeEnum.HORIZONTAL) || (props.isHorizontal && unref(getSplit))
|
||||
})
|
||||
|
||||
const getMenuClass = computed(() => {
|
||||
const align = props.isHorizontal && unref(getSplit) ? 'start' : unref(getTopMenuAlign)
|
||||
return [
|
||||
prefixCls,
|
||||
`justify-${align}`,
|
||||
{
|
||||
[`${prefixCls}__second`]: !props.isHorizontal && unref(getSplit),
|
||||
[`${prefixCls}__sidebar-hor`]: unref(getIsTopMenu),
|
||||
},
|
||||
]
|
||||
})
|
||||
|
||||
const getInlineCollapseOptions = computed(() => {
|
||||
const isInline = props.mode === MenuModeEnum.INLINE
|
||||
|
||||
const inlineCollapseOptions: { inlineCollapsed?: boolean } = {}
|
||||
if (isInline)
|
||||
inlineCollapseOptions.inlineCollapsed = props.mixSider ? false : unref(getCollapsed)
|
||||
|
||||
return inlineCollapseOptions
|
||||
})
|
||||
|
||||
listenerRouteChange((route) => {
|
||||
if (route.name === REDIRECT_NAME)
|
||||
return
|
||||
handleMenuChange(route)
|
||||
currentActiveMenu.value = route.meta?.currentActiveMenu as string
|
||||
|
||||
if (unref(currentActiveMenu)) {
|
||||
menuState.selectedKeys = [unref(currentActiveMenu)]
|
||||
setOpenKeys(unref(currentActiveMenu))
|
||||
}
|
||||
})
|
||||
|
||||
!props.mixSider
|
||||
&& watch(
|
||||
() => props.items,
|
||||
() => {
|
||||
handleMenuChange()
|
||||
},
|
||||
)
|
||||
|
||||
const handleMenuClick: MenuProps['onClick'] = async ({ key }) => {
|
||||
const { beforeClickFn } = props
|
||||
if (beforeClickFn && isFunction(beforeClickFn)) {
|
||||
const flag = await beforeClickFn(key)
|
||||
if (!flag)
|
||||
return
|
||||
}
|
||||
emit('menuClick', key)
|
||||
|
||||
isClickGo.value = true
|
||||
menuState.selectedKeys = [key]
|
||||
}
|
||||
|
||||
async function handleMenuChange(route?: RouteLocationNormalizedLoaded) {
|
||||
if (unref(isClickGo)) {
|
||||
isClickGo.value = false
|
||||
return
|
||||
}
|
||||
const path = (route || unref(currentRoute)).meta?.currentActiveMenu || (route || unref(currentRoute)).path
|
||||
setOpenKeys(path)
|
||||
if (unref(currentActiveMenu))
|
||||
return
|
||||
if (props.isHorizontal && unref(getSplit)) {
|
||||
const parentPath = await getCurrentParentPath(path)
|
||||
menuState.selectedKeys = [parentPath]
|
||||
}
|
||||
else {
|
||||
const parentPaths = await getAllParentPath(props.items, path)
|
||||
menuState.selectedKeys = parentPaths
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Menu
|
||||
:selected-keys="menuState.selectedKeys"
|
||||
:default-selected-keys="menuState.defaultSelectedKeys"
|
||||
:mode="mode"
|
||||
:open-keys="getOpenKeys"
|
||||
:inline-indent="inlineIndent"
|
||||
:theme="theme"
|
||||
:class="getMenuClass"
|
||||
:sub-menu-open-delay="0.2"
|
||||
v-bind="getInlineCollapseOptions"
|
||||
@open-change="handleOpenChange"
|
||||
@click="handleMenuClick"
|
||||
>
|
||||
<template v-for="item in items" :key="item.path">
|
||||
<KingdeeBasicSubMenuItem :item="item" :theme="theme" :is-horizontal="isHorizontal" />
|
||||
</template>
|
||||
</Menu>
|
||||
</template>
|
||||
|
||||
<style lang="less">
|
||||
@import './index.less';
|
||||
</style>
|
@ -0,0 +1,56 @@
|
||||
<script lang="ts" setup>
|
||||
import { computed } from 'vue'
|
||||
import { Menu } from 'ant-design-vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { itemProps } from '../props'
|
||||
import BasicMenuItem from './BasicMenuItem.vue'
|
||||
import MenuItemContent from './MenuItemContent.vue'
|
||||
import { useDesign } from '@/hooks/web/useDesign'
|
||||
import type { Menu as MenuType } from '@/router/types'
|
||||
|
||||
defineOptions({ name: 'BasicSubMenuItem' })
|
||||
|
||||
const props = defineProps(itemProps)
|
||||
|
||||
const SubMenu = Menu.SubMenu
|
||||
|
||||
const { prefixCls } = useDesign('basic-menu-item')
|
||||
|
||||
const getShowMenu = computed(() => !props.item.meta?.hideMenu)
|
||||
function menuHasChildren(menuTreeItem: MenuType): boolean {
|
||||
return (
|
||||
!menuTreeItem.meta?.hideChildrenInMenu
|
||||
&& Reflect.has(menuTreeItem, 'children')
|
||||
&& !!menuTreeItem.children
|
||||
&& menuTreeItem.children.length > 0
|
||||
)
|
||||
}
|
||||
|
||||
const router = useRouter()
|
||||
|
||||
function handleSwitchCloud(item: MenuType) {
|
||||
router.push(getFirstPathOfLastChild(item))
|
||||
}
|
||||
|
||||
function getFirstPathOfLastChild(item: MenuType): string {
|
||||
// 如果当前菜单没有子菜单,直接返回当前菜单的 path
|
||||
if (!item.children || item.children.length === 0)
|
||||
return item.path
|
||||
|
||||
// 递归找到最后一个子菜单的第一个 path
|
||||
return getFirstPathOfLastChild(item.children[0])
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<BasicMenuItem v-if="!menuHasChildren(item) && getShowMenu" v-bind="$props" :class="prefixCls" />
|
||||
<SubMenu v-if="menuHasChildren(item) && getShowMenu" :key="`submenu-${item.path}`" :class="[theme]" popup-class-name="app-top-menu-popup">
|
||||
<template #title>
|
||||
<MenuItemContent v-bind="$props" :item="item" @click="handleSwitchCloud(item)" />
|
||||
</template>
|
||||
|
||||
<!-- <template v-for="childrenItem in item.children || []" :key="childrenItem.path"> -->
|
||||
<!-- <BasicSubMenuItem v-bind="$props" :item="childrenItem" /> -->
|
||||
<!-- </template> -->
|
||||
</SubMenu>
|
||||
</template>
|
@ -16,6 +16,10 @@ import { useMultipleTabStore } from '@/store/modules/multipleTab'
|
||||
|
||||
defineOptions({ name: 'LayoutMultipleHeader' })
|
||||
|
||||
defineProps<{
|
||||
scoped: boolean
|
||||
}>()
|
||||
|
||||
const HEADER_HEIGHT = 48
|
||||
|
||||
const TABS_HEIGHT = 32
|
||||
@ -90,7 +94,7 @@ const getClass = computed(() => {
|
||||
/>
|
||||
<div :style="getWrapStyle" :class="getClass">
|
||||
<LayoutHeader v-if="getShowInsetHeaderRef" />
|
||||
<MultipleTabs v-if="getShowTabs" :key="tabStore.getLastDragEndIndex" />
|
||||
<MultipleTabs v-if="getShowTabs" :key="tabStore.getLastDragEndIndex" :scoped="scoped" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
@ -2,8 +2,9 @@
|
||||
import { computed, unref } from 'vue'
|
||||
|
||||
import { Layout } from 'ant-design-vue'
|
||||
import { ErrorAction, FullScreen, LayoutBreadcrumb, Notify, UserDropDown } from '../../components'
|
||||
import { ErrorAction, FullScreen, Notify, UserDropDown } from '../../components'
|
||||
import LayoutTrigger from '../../../trigger/index.vue'
|
||||
import KingdeeTopMenu from './KingdeeTopMenu.vue'
|
||||
import { propTypes } from '@/utils/propTypes'
|
||||
|
||||
// import { AppLocalePicker, AppLogo, AppSearch, AppSizePicker } from '@/components/Application'
|
||||
@ -19,7 +20,7 @@ import { useHeaderSetting } from '@/hooks/setting/useHeaderSetting'
|
||||
import { useMenuSetting } from '@/hooks/setting/useMenuSetting'
|
||||
import { useRootSetting } from '@/hooks/setting/useRootSetting'
|
||||
|
||||
// import { MenuModeEnum, MenuSplitTyeEnum } from '@/enums/menuEnum'
|
||||
import { MenuModeEnum, MenuSplitTyeEnum } from '@/enums/menuEnum'
|
||||
import { SettingButtonPositionEnum } from '@/enums/appEnum'
|
||||
|
||||
import { useAppInject } from '@/hooks/web/useAppInject'
|
||||
@ -41,7 +42,7 @@ const { getShowHeaderTrigger, getSplit, getIsMixMode, getMenuWidth, getIsMixSide
|
||||
// const { getIsMixMode, getMenuWidth } = useMenuSetting()
|
||||
const { getUseErrorHandle, getShowSettingButton, getSettingButtonPosition } = useRootSetting()
|
||||
|
||||
const { getHeaderTheme, getShowFullScreen, getShowNotice, getShowContent, getShowBread, getShowHeaderLogo, getShowHeader, getShowSearch }
|
||||
const { getHeaderTheme, getShowFullScreen, getShowNotice, getShowContent, getShowHeaderLogo, getShowHeader, getShowSearch }
|
||||
= useHeaderSetting()
|
||||
|
||||
const { getShowLocalePicker } = useLocale()
|
||||
@ -80,10 +81,10 @@ const getLogoWidth = computed(() => {
|
||||
return { width: `${width}px` }
|
||||
})
|
||||
|
||||
// const getSplitType = computed(() => {
|
||||
// return unref(getSplit) ? MenuSplitTyeEnum.TOP : MenuSplitTyeEnum.NONE
|
||||
// })
|
||||
//
|
||||
const getSplitType = computed(() => {
|
||||
return unref(getSplit) ? MenuSplitTyeEnum.TOP : MenuSplitTyeEnum.NONE
|
||||
})
|
||||
|
||||
// const getMenuMode = computed(() => {
|
||||
// return unref(getSplit) ? MenuModeEnum.HORIZONTAL : null
|
||||
// })
|
||||
@ -107,14 +108,14 @@ const getLogoWidth = computed(() => {
|
||||
v-if="(getShowContent && getShowHeaderTrigger && !getSplit && !getIsMixSidebar) || getIsMobile"
|
||||
:theme="getHeaderTheme" :sider="false"
|
||||
/>
|
||||
<LayoutBreadcrumb v-if="getShowContent && getShowBread" :theme="getHeaderTheme" />
|
||||
<!-- <LayoutBreadcrumb v-if="getShowContent && getShowBread" :theme="getHeaderTheme" /> -->
|
||||
</div>
|
||||
<!-- left end -->
|
||||
|
||||
<!-- menu start -->
|
||||
<!-- <div v-if="getShowTopMenu && !getIsMobile" :class="`${prefixCls}-menu`"> -->
|
||||
<!-- <LayoutMenu :is-horizontal="true" :theme="getHeaderTheme" :split-type="getSplitType" :menu-mode="getMenuMode" /> -->
|
||||
<!-- </div> -->
|
||||
<div v-if="!getIsMobile" :class="`${prefixCls}-menu`">
|
||||
<KingdeeTopMenu :is-horizontal="true" :theme="getHeaderTheme" :split-type="getSplitType" :menu-mode="MenuModeEnum.HORIZONTAL" />
|
||||
</div>
|
||||
<!-- menu-end -->
|
||||
|
||||
<!-- action -->
|
||||
|
248
src/layouts/default/header/kingdee/new/KingdeeTopMenu.vue
Normal file
248
src/layouts/default/header/kingdee/new/KingdeeTopMenu.vue
Normal file
@ -0,0 +1,248 @@
|
||||
<script lang="tsx">
|
||||
import type { CSSProperties } from 'vue'
|
||||
|
||||
import { computed, defineComponent, toRef, unref } from 'vue'
|
||||
import { useSplitMenu } from '@/layouts/default/menu/useLayoutMenu'
|
||||
import { KingdeeBaseMenu } from '@/components/Menu'
|
||||
import { SimpleMenu } from '@/components/SimpleMenu'
|
||||
import { AppLogo } from '@/components/Application'
|
||||
|
||||
import { MenuModeEnum, MenuSplitTyeEnum } from '@/enums/menuEnum'
|
||||
|
||||
import { useMenuSetting } from '@/hooks/setting/useMenuSetting'
|
||||
import { ScrollContainer } from '@/components/Container'
|
||||
|
||||
import { useGo } from '@/hooks/web/usePage'
|
||||
import { openWindow } from '@/utils'
|
||||
import { propTypes } from '@/utils/propTypes'
|
||||
import { isHttpUrl } from '@/utils/is'
|
||||
import { useRootSetting } from '@/hooks/setting/useRootSetting'
|
||||
import { useAppInject } from '@/hooks/web/useAppInject'
|
||||
import { useDesign } from '@/hooks/web/useDesign'
|
||||
import type { Menu } from '@/router/types'
|
||||
import { useMultipleTabStore } from '@/store/modules/multipleTab'
|
||||
|
||||
export default defineComponent({
|
||||
name: 'KingdeeTopMenu',
|
||||
props: {
|
||||
theme: propTypes.oneOf(['light', 'dark']),
|
||||
|
||||
splitType: {
|
||||
type: Number as PropType<MenuSplitTyeEnum>,
|
||||
default: MenuSplitTyeEnum.NONE,
|
||||
},
|
||||
|
||||
isHorizontal: propTypes.bool,
|
||||
// menu Mode
|
||||
menuMode: {
|
||||
type: [String] as PropType<Nullable<MenuModeEnum>>,
|
||||
default: '',
|
||||
},
|
||||
isScoped: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
setup(props) {
|
||||
const go = useGo()
|
||||
|
||||
const {
|
||||
getMenuMode,
|
||||
getMenuType,
|
||||
getMenuTheme,
|
||||
getCollapsed,
|
||||
getCollapsedShowTitle,
|
||||
getAccordion,
|
||||
getIsHorizontal,
|
||||
getIsSidebarType,
|
||||
getSplit,
|
||||
} = useMenuSetting()
|
||||
const { getShowLogo } = useRootSetting()
|
||||
|
||||
const { prefixCls } = useDesign('layout-menu')
|
||||
|
||||
const { menusRef } = useSplitMenu(toRef(props, 'splitType'))
|
||||
|
||||
const { getIsMobile } = useAppInject()
|
||||
|
||||
const getComputedMenuMode = computed(() => (unref(getIsMobile) ? MenuModeEnum.INLINE : props.menuMode || unref(getMenuMode)))
|
||||
|
||||
const getComputedMenuTheme = computed(() => props.theme || unref(getMenuTheme))
|
||||
|
||||
const getIsShowLogo = computed(() => unref(getShowLogo) && unref(getIsSidebarType))
|
||||
|
||||
const getUseScroll = computed(() => {
|
||||
return (
|
||||
!unref(getIsHorizontal)
|
||||
&& (unref(getIsSidebarType) || props.splitType === MenuSplitTyeEnum.LEFT || props.splitType === MenuSplitTyeEnum.NONE)
|
||||
)
|
||||
})
|
||||
|
||||
const getWrapperStyle = computed((): CSSProperties => {
|
||||
return {
|
||||
height: `calc(100% - ${unref(getIsShowLogo) ? '48px' : '0px'})`,
|
||||
}
|
||||
})
|
||||
|
||||
const getLogoClass = computed(() => {
|
||||
return [
|
||||
`${prefixCls}-logo`,
|
||||
unref(getComputedMenuTheme),
|
||||
{
|
||||
[`${prefixCls}--mobile`]: unref(getIsMobile),
|
||||
},
|
||||
]
|
||||
})
|
||||
|
||||
const tabStore = useMultipleTabStore()
|
||||
const getTabsState = computed(() => {
|
||||
return tabStore.getTabList.filter(item => !item.meta?.hideTab)
|
||||
})
|
||||
|
||||
/**
|
||||
* 只显示已经打开的一级菜单
|
||||
* @param menus
|
||||
* @param openedFullPath
|
||||
*/
|
||||
function filterMenus(menus: Menu[], openedFullPath: string[]): Menu[] {
|
||||
return menus
|
||||
.map((menu) => {
|
||||
// 如果当前菜单的路径在 openedFullPath 中,直接保留
|
||||
if (openedFullPath.includes(menu.path))
|
||||
return menu
|
||||
|
||||
// 如果当前菜单有子菜单,递归过滤子菜单
|
||||
if (menu.children && menu.children.length > 0) {
|
||||
const filteredChildren = filterMenus(menu.children, openedFullPath)
|
||||
|
||||
// 如果过滤后的子菜单不为空,保留当前菜单并更新子菜单
|
||||
if (filteredChildren.length > 0) {
|
||||
return {
|
||||
...menu,
|
||||
children: filteredChildren,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 如果当前菜单的路径不在 openedFullPath 中,且没有子菜单,则过滤掉
|
||||
return null
|
||||
})
|
||||
.filter(menu => menu !== null) as Menu[]
|
||||
}
|
||||
|
||||
function getFirstPathSegment(path: string): string {
|
||||
const trimmedPath = path.replace(/^\/+/, '/')
|
||||
|
||||
const segments = trimmedPath.split('/')
|
||||
|
||||
const firstSegment = segments.find(segment => segment !== '')
|
||||
|
||||
return firstSegment ? `/${firstSegment}` : '/'
|
||||
}
|
||||
|
||||
const getCommonProps = computed(() => {
|
||||
const openedPath: string[] = []
|
||||
const openedFullPath: string[] = []
|
||||
const tabs = unref(getTabsState)
|
||||
for (let i = 0; i < tabs.length; i++) {
|
||||
openedPath.push(getFirstPathSegment(tabs[i].path))
|
||||
openedFullPath.push(tabs[i].path)
|
||||
}
|
||||
|
||||
const filterMenu = filterMenus(unref(menusRef), openedFullPath)
|
||||
const menus = unref(menusRef)
|
||||
return {
|
||||
menus: filterMenu,
|
||||
beforeClickFn: beforeMenuClickFn,
|
||||
items: menus,
|
||||
theme: unref(getComputedMenuTheme),
|
||||
accordion: unref(getAccordion),
|
||||
collapse: unref(getCollapsed),
|
||||
collapsedShowTitle: unref(getCollapsedShowTitle),
|
||||
onMenuClick: handleMenuClick,
|
||||
}
|
||||
})
|
||||
/**
|
||||
* click menu
|
||||
* @param path
|
||||
*/
|
||||
|
||||
function handleMenuClick(path: string) {
|
||||
go(path)
|
||||
}
|
||||
|
||||
/**
|
||||
* before click menu
|
||||
* @param path
|
||||
*/
|
||||
async function beforeMenuClickFn(path: string) {
|
||||
if (!isHttpUrl(path))
|
||||
return true
|
||||
|
||||
openWindow(path)
|
||||
return false
|
||||
}
|
||||
|
||||
function renderHeader() {
|
||||
if (!unref(getIsShowLogo) && !unref(getIsMobile))
|
||||
return null
|
||||
|
||||
return <AppLogo showTitle={!unref(getCollapsed)} class={unref(getLogoClass)} theme={unref(getComputedMenuTheme)} />
|
||||
}
|
||||
|
||||
function renderMenu() {
|
||||
const { menus, ...menuProps } = unref(getCommonProps)
|
||||
if (!menus || !menus.length)
|
||||
return null
|
||||
return !props.isHorizontal
|
||||
? (
|
||||
<SimpleMenu {...menuProps} isSplitMenu={unref(getSplit)} items={menus} />
|
||||
)
|
||||
: (
|
||||
<KingdeeBaseMenu
|
||||
{...(menuProps as any)}
|
||||
isHorizontal={props.isHorizontal}
|
||||
type={unref(getMenuType)}
|
||||
showLogo={unref(getIsShowLogo)}
|
||||
mode={unref(getComputedMenuMode as any)}
|
||||
items={menus}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
return () => {
|
||||
return (
|
||||
<>
|
||||
{renderHeader()}
|
||||
{unref(getUseScroll) ? <ScrollContainer style={unref(getWrapperStyle)}>{() => renderMenu()}</ScrollContainer> : renderMenu()}
|
||||
</>
|
||||
)
|
||||
}
|
||||
},
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="less">
|
||||
@prefix-cls: ~'@{namespace}-kd-layout-menu';
|
||||
@logo-prefix-cls: ~'@{namespace}-kd-app-logo';
|
||||
|
||||
.@{prefix-cls} {
|
||||
&-logo {
|
||||
height: @header-height;
|
||||
padding: 10px 4px 10px 10px;
|
||||
|
||||
img {
|
||||
width: @logo-width;
|
||||
height: @logo-width;
|
||||
}
|
||||
}
|
||||
|
||||
&--mobile {
|
||||
.@{logo-prefix-cls} {
|
||||
&__title {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
@ -52,7 +52,7 @@ const layoutClass = computed(() => {
|
||||
<Layout :class="[layoutClass, `${prefixCls}-out`]">
|
||||
<LayoutSideBar v-if="(getShowSidebar || getIsMobile)" />
|
||||
<Layout :class="`${prefixCls}-main`">
|
||||
<LayoutMultipleHeader />
|
||||
<LayoutMultipleHeader :scoped="true" />
|
||||
<LayoutContent />
|
||||
<LayoutFooter />
|
||||
</Layout>
|
||||
|
@ -123,8 +123,9 @@ export default defineComponent({
|
||||
const getCommonProps = computed(() => {
|
||||
const current = getFirstPathSegment(currentPath.path)
|
||||
const menus = findChildrenByFirstPathSegment(unref(menusRef), current)
|
||||
const scoped = props.isScoped
|
||||
return {
|
||||
menus,
|
||||
menus: scoped ? menus : unref(menusRef),
|
||||
beforeClickFn: beforeMenuClickFn,
|
||||
items: menus,
|
||||
theme: unref(getComputedMenuTheme),
|
||||
|
@ -6,7 +6,7 @@ import { useMouse } from '@vueuse/core'
|
||||
import { computed, ref, unref } from 'vue'
|
||||
|
||||
import { Tabs } from 'ant-design-vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import TabContent from './components/TabContent.vue'
|
||||
import FoldButton from './components/FoldButton.vue'
|
||||
import TabRedo from './components/TabRedo.vue'
|
||||
@ -26,6 +26,10 @@ import { listenerRouteChange } from '@/logics/mitt/routeChange'
|
||||
|
||||
defineOptions({ name: 'MultipleTabs' })
|
||||
|
||||
const props = defineProps<{
|
||||
scoped: boolean
|
||||
}>()
|
||||
|
||||
const affixTextList = initAffixTabs()
|
||||
const activeKeyRef = ref('')
|
||||
|
||||
@ -33,13 +37,32 @@ useTabsDrag(affixTextList)
|
||||
const tabStore = useMultipleTabStore()
|
||||
const userStore = useUserStore()
|
||||
const router = useRouter()
|
||||
const route = useRoute()
|
||||
|
||||
const { prefixCls } = useDesign('multiple-tabs')
|
||||
const go = useGo()
|
||||
const { getShowQuick, getShowRedo, getShowFold } = useMultipleTabSetting()
|
||||
|
||||
function getFirstPathSegment(path: string): string {
|
||||
if (!path || typeof path !== 'string')
|
||||
return '/'
|
||||
|
||||
const segments = path.split('/').filter(Boolean) // 移除空字符串
|
||||
return segments.length > 0 ? `/${segments[0]}` : '/'
|
||||
}
|
||||
|
||||
const getTabsState = computed(() => {
|
||||
return tabStore.getTabList.filter(item => !item.meta?.hideTab)
|
||||
const currentPath = route.path
|
||||
|
||||
const currentCloud = getFirstPathSegment(currentPath)
|
||||
|
||||
if (props.scoped) {
|
||||
return tabStore.getTabList.filter(item => !item.meta?.hideTab).filter((item) => {
|
||||
const firstPath = getFirstPathSegment(item.path)
|
||||
return firstPath === currentCloud
|
||||
})
|
||||
}
|
||||
else { return tabStore.getTabList.filter(item => !item.meta?.hideTab) }
|
||||
})
|
||||
|
||||
const unClose = computed(() => unref(getTabsState).length === 1)
|
||||
|
Loading…
Reference in New Issue
Block a user