import './index.less' import { getRender } from '../../utils' import { defaultRenderCollapsedButton, defaultRenderLogo, defaultRenderLogoAndTitle, privateSiderMenuProps } from '../SiderMenu/SiderMenu' import { pureSettingsProps } from '../../defaultSettings' import type { MenuDataItem, WithFalse } from '../../types' import type { PureSettings } from '../../defaultSettings' import type { HeaderViewProps } from '../../Header' import type { CSSProperties, PropType, ExtractPropTypes } from 'vue' import type { SiderMenuProps } from '../SiderMenu/SiderMenu' import type { HeaderContentRender, MenuRender, RightContentRender } from '../../renderTypes' import { VueNodeOrRenderPropType } from '#/types' import type { VueNodeOrRender } from '#/types' import TopNavHeader from '#/layout/components/TopNavHeader' import { clearMenuItem } from '#/layout/utils/utils' export const globalHeaderProps = () => ({ ...privateSiderMenuProps(), ...pureSettingsProps, // 覆盖下默认值 headerTheme: { type: String as PropType, default: 'dark' }, // 自有属性 collapsed: { type: Boolean, default: undefined }, onCollapse: { type: Function as PropType<(collapsed: boolean) => void>, default: undefined }, isMobile: { type: Boolean, default: undefined }, logo: { type: VueNodeOrRenderPropType as PropType, default: () => undefined }, /** * 虽然叫menuRender,但是其实是整个 SiderMenu 面板的渲染函数 * * @example 收起时完成不展示菜单 menuRender={(props,defaultDom)=> props.collapsed ? null : defaultDom} * @example 不展示菜单 menuRender={false} */ menuRender: { type: [Function, Boolean] as PropType>, default: () => undefined }, /** * 右侧顶部操作区域的渲染逻辑,一般会展示一个头像和一些操作 * * @example 展示一个头像: rightRender={(props) => } />} * @example 展示一些操作: rightRender={(props) => [,]} */ rightContentRender: { type: [Function, Boolean] as PropType>, default: () => undefined }, prefixCls: { type: String, default: undefined }, menuData: { type: Array as PropType, default: () => undefined }, onMenuHeaderClick: Function as PropType<(e: MouseEvent) => void>, menuHeaderRender: { type: [Function, Boolean] as PropType, default: undefined }, /** *顶部区域的渲染,包含内部的 menu * * @example headerContentRender={(props) =>
管理控制台
} */ headerContentRender: { type: [Function, Boolean] as PropType>, default: undefined }, collapsedButtonRender: { type: [Function, Boolean] as PropType, default: () => defaultRenderCollapsedButton }, splitMenus: { type: Boolean, default: undefined } }) export type GlobalHeaderProps = Partial>> const renderLogo = ( props: SiderMenuProps, menuHeaderRender: SiderMenuProps['menuHeaderRender'], logoDom: VueNodeOrRender ) => { if (menuHeaderRender === false) { return null } if (menuHeaderRender) { return menuHeaderRender(props, logoDom, null) } return logoDom } export default defineComponent({ name: 'GlobalHeader', props: globalHeaderProps(), setup(props, { slots, attrs }) { // TODO 布局方向支持 const direction = undefined const baseClassName = `${props.prefixCls}-global-header` const className = computed(() => [ attrs.class, baseClassName, { [`${baseClassName}-layout-${props.layout}`]: props.layout && props.headerTheme === 'dark' } ]) return () => { if (props.layout === 'mix' && !props.isMobile && props.splitMenus) { const noChildrenMenuData = (props.menuData || []).map(item => ({ ...item, children: undefined })) const clearMenuData = clearMenuItem(noChildrenMenuData) return ( {slots} ) } const logoClassNames = [ `${baseClassName}-logo`, { [`${baseClassName}-logo-rtl`]: direction === 'rtl' } ] // 添加 slots 支持 const logoRender = getRender(props, slots, 'logo') const logoDom = ( {defaultRenderLogo(logoRender)} ) const rightContentRender = getRender(props, slots, 'rightContentRender') return (
{props.isMobile && renderLogo(props, props.menuHeaderRender, logoDom)} {props.isMobile && props.collapsedButtonRender && ( { if (props.onCollapse) { props.onCollapse(!props.collapsed) } }} > {props.collapsedButtonRender(props.collapsed)} )} {props.layout === 'mix' && !props.isMobile && ( <>
{defaultRenderLogoAndTitle( { ...props, collapsed: false }, slots, 'headerTitleRender' )}
)}
{slots.default?.()}
{rightContentRender && rightContentRender(props as HeaderViewProps)}
) } } })