import { withInstall } from '../../util/type'; import { TabPaneProps, Affix, Spin, PageHeader, Tabs, Button, } from '../../components'; import type { ExtractPropTypes, FunctionalComponent, PropType, VNodeChild, CSSProperties, } from 'vue'; import { defineComponent, unref, toRefs, computed } from 'vue'; import { pageHeaderProps } from 'ant-design-vue/lib/page-header'; import type { DefaultPropRender, PageHeaderRender } from '../typings'; import type { AffixProps, TabBarExtraContent } from './typings'; import { useRouteContext } from '../RouteContext'; import { getSlotVNode } from '../util'; import { VueNode } from 'ant-design-vue/lib/_util/type'; import './index.less'; export const pageHeaderTabConfig = { /** * @name tabs 的列表 */ tabList: { type: [Object, Function, Array] as PropType< (Omit & { key?: string; class: string })[] >, default: () => undefined, }, /** * @name 当前选中 tab 的 key */ tabActiveKey: String, //PropTypes.string, /** * @name tab 上多余的区域 */ tabBarExtraContent: { type: [Object, Function] as PropType, default: () => undefined, }, /** * @name tabs 的其他配置 */ tabProps: { type: Object, //as PropType, default: () => undefined, }, /** * @name 固定 PageHeader 到页面顶部 */ fixedHeader: Boolean, //PropTypes.looseBool, // events onTabChange: Function, //PropTypes.func, pure: Boolean, }; export type PageHeaderTabConfig = Partial< ExtractPropTypes >; export const pageContainerProps = { ...pageHeaderTabConfig, ...pageHeaderProps, prefixCls: { type: String, default: 'ant-pro', }, //PropTypes.string.def('ant-pro'), title: { type: [ Object, String, Boolean, Function, ] as PropType, default: () => null, }, subTitle: { type: [ Object, String, Boolean, Function, ] as PropType, default: () => null, }, content: { type: [ Object, String, Boolean, Function, ] as PropType, default: () => null, }, extra: { type: [ Object, String, Boolean, Function, ] as PropType, default: () => null, }, extraContent: { type: [ Object, String, Boolean, Function, ] as PropType, default: () => null, }, header: { type: [ Object, String, Boolean, Function, ] as PropType, default: () => null, }, pageHeaderRender: { type: [Object, Function, Boolean] as PropType, default: () => undefined, }, affixProps: { type: [Object, Function] as PropType, }, ghost: { type: Boolean, default: () => false, }, //PropTypes.looseBool, loading: { type: Boolean, default: () => undefined, }, //PropTypes.looseBool, childrenFullHeight: { type: Boolean, default: () => true, }, pure: { type: Boolean, default: false, }, showBack: { type: Boolean, default: false, }, contentStyle: { type: Object, default: () => ({}), }, }; export type PageContainerProps = Partial< ExtractPropTypes >; const renderFooter = ( props: Omit, ): VNodeChild | JSX.Element => { const { tabList, tabActiveKey, onTabChange, tabBarExtraContent, tabProps } = props; const tabPane = (item: any) => { return ( {item.tab} ); }; if (tabList && tabList.length) { return ( { if (onTabChange) { onTabChange(key); } }} tabBarExtraContent={tabBarExtraContent} {...tabProps} > {tabList.map((item) => ( ))} ); } return null; }; const renderPageHeader = ( content: VueNode, extraContent: VueNode, prefixedClassName: string, ): VNodeChild | JSX.Element | null => { if (!content && !extraContent) { return null; } return (
{content && (
{ // @ts-ignore (typeof content === 'function' && content()) || content }
)} {extraContent && (
{ // @ts-ignore (typeof extraContent === 'function' && extraContent()) || extraContent }
)}
); }; const ProPageHeader: FunctionalComponent< PageContainerProps & { prefixedClassName: string } > = (props) => { const { title, tabList, tabActiveKey, content, pageHeaderRender, header, extraContent, prefixedClassName, prefixCls, fixedHeader: _, showBack, ...restProps } = props; const value = useRouteContext(); if (pageHeaderRender === false) { return null; } if (pageHeaderRender) { return pageHeaderRender({ ...props }); } let pageHeaderTitle = title; if (!title && title !== false) { pageHeaderTitle = value.title; } const unrefBreadcrumb = unref(value.breadcrumb || {}); const breadcrumb = (props as any).breadcrumb || { ...unrefBreadcrumb, routes: unrefBreadcrumb.routes, itemRender: unrefBreadcrumb.itemRender, }; const backProps: any = {}; if (showBack) { // @ts-ignore backProps.backIcon = ; backProps.onBack = () => { value.back?.(); }; } return (
{header || renderPageHeader(content, extraContent, prefixedClassName)}
); }; const PageContainer = defineComponent({ name: 'JPageContainer', inheritAttrs: false, props: pageContainerProps, setup(props, { slots, attrs }) { const { loading, affixProps, ghost, childrenFullHeight } = toRefs(props); const value = useRouteContext(); const { getPrefixCls } = value; const prefixCls = props.prefixCls || getPrefixCls(); const prefixedClassName = computed(() => `${prefixCls}-page-container`); const classNames = computed(() => { return { [prefixedClassName.value]: true, [`${prefixCls}-page-container-ghost`]: ghost.value, }; }); const headerDom = computed(() => { // const tags = getSlotVNode(slots, props, 'tags'); const headerContent = getSlotVNode( slots, props, 'content', ); const extra = getSlotVNode( slots, props, 'extra', ); const extraContent = getSlotVNode( slots, props, 'extraContent', ); const subTitle = getSlotVNode( slots, props, 'subTitle', ); const title = getSlotVNode( slots, props, 'title', ); // @ts-ignore return ( ); }); return () => { const { fixedHeader, pure } = props; return ( <> {pure ? (
{slots.default?.()}
) : (
{fixedHeader && headerDom.value ? ( {headerDom.value} ) : ( headerDom.value )}
{loading.value ? ( ) : slots.default ? (
{slots.default()}
{value.hasFooterToolbar && (
)}
) : null}
)} ); }; }, }); export default withInstall(PageContainer, 'JPageContainer');