Commit 5367b895 authored by Sendya's avatar Sendya

feat: add PageContainer

parent 97eec8a4
@import "~ant-design-vue/es/style/themes/default.less";
@pro-layout-page-container: ~'@{ant-prefix}-pro-page-container';
.@{pro-layout-page-container}-children-content {
margin: 24px 24px 0;
}
.@{pro-layout-page-container} {
&-warp {
background-color: @component-background;
.@{ant-prefix}-tabs-nav {
margin: 0;
}
}
&-ghost {
.@{pro-layout-page-container}-warp {
background-color: transparent;
}
}
}
.@{pro-layout-page-container}-main {
.@{pro-layout-page-container}-detail {
display: flex;
}
.@{pro-layout-page-container}-row {
display: flex;
width: 100%;
}
.@{pro-layout-page-container}-title-content {
margin-bottom: 16px;
}
.@{pro-layout-page-container}-title,
.@{pro-layout-page-container}-content {
flex: auto;
}
.@{pro-layout-page-container}-extraContent,
.@{pro-layout-page-container}-main {
flex: 0 1 auto;
}
.@{pro-layout-page-container}-main {
width: 100%;
}
.@{pro-layout-page-container}-title {
margin-bottom: 16px;
}
.@{pro-layout-page-container}-logo {
margin-bottom: 16px;
}
.@{pro-layout-page-container}-extraContent {
min-width: 242px;
margin-left: 88px;
text-align: right;
}
}
@media screen and (max-width: @screen-xl) {
.@{pro-layout-page-container}-main {
.@{pro-layout-page-container}-extraContent {
margin-left: 44px;
}
}
}
@media screen and (max-width: @screen-lg) {
.@{pro-layout-page-container}-main {
.@{pro-layout-page-container}-extraContent {
margin-left: 20px;
}
}
}
@media screen and (max-width: @screen-md) {
.@{pro-layout-page-container}-main {
.@{pro-layout-page-container}-row {
display: block;
}
.@{pro-layout-page-container}-action,
.@{pro-layout-page-container}-extraContent {
margin-left: 0;
text-align: left;
}
}
}
@media screen and (max-width: @screen-sm) {
.@{pro-layout-page-container}-detail {
display: block;
}
.@{pro-layout-page-container}-extraContent {
margin-left: 0;
}
}
import { FunctionalComponent, VNodeChild, ref, computed, toRefs } from 'vue';
import { TabPaneProps } from './interfaces/TabPane';
import { TabBarExtraContent, TabsProps } from './interfaces/Tabs';
import { PageHeaderProps } from './interfaces/PageHeader';
import { AffixProps } from './interfaces/Affix';
import { useRouteContext, RouteContextProps } from '../RouteContext';
import { useProProvider } from '../ProProvider';
import { PageHeader } from 'ant-design-vue';
export interface Tab {
key: string;
tab: string | VNodeChild | JSX.Element;
}
export interface PageHeaderTabConfig {
/**
* @name tabs 的列表
*/
tabList?: TabPaneProps & Tab & { key?: string | VNodeChild };
/**
* @name 当前选中 tab 的 key
*/
tabActiveKey?: string;
/**
* @name tab 修改时触发
*/
onTabChange?: () => void;
/**
* @name tab 上多余的区域
*/
tabBarExtraContent?: TabBarExtraContent;
/**
* @name tabs 的其他配置
*/
tabProps?: TabsProps;
/**
* @name 固定 PageHeader 到页面顶部
* @deprecated 请使用 fixedHeader
*/
fixHeader?: boolean;
/**
* @name 固定 PageHeader 到页面顶部
*/
fixedHeader?: boolean;
}
export interface PageContainerProps extends PageHeaderTabConfig, Omit<PageHeaderProps, 'title'> {
title?: VNodeChild | JSX.Element | false;
content?: VNodeChild | JSX.Element;
extraContent?: VNodeChild | JSX.Element;
prefixCls?: string;
footer?: VNodeChild | VNodeChild[] | JSX.Element;
ghost?: boolean;
header?: PageHeaderProps | VNodeChild;
pageHeaderRender?: (props: PageContainerProps) => VNodeChild | JSX.Element;
affixProps?: AffixProps;
loading?: boolean;
}
const defaultPageHeaderRender = (
props: PageContainerProps,
value: RouteContextProps & { prefixedClassName: string },
): VNodeChild | JSX.Element => {
const {
title,
content,
pageHeaderRender,
header,
extraContent,
style,
prefixCls,
...restProps
} = props;
if (pageHeaderRender) {
return pageHeaderRender({ ...props, ...value });
}
let pageHeaderTitle = title;
if (!title && title !== false) {
pageHeaderTitle = value.title;
}
if
return (
<PageHeader
{...value}
title={pageHeaderTitle}
{...restProps}
footer={renderFooter({
...restProps,
prefixedClassName: value.prefixedClassName,
})}
{...header}
preifxCls={prefixCls}
>
{header ||}
</PageHeader>
);
};
export const PageContainer: FunctionalComponent<PageContainerProps> = (props, { slots }) => {
const { loading, style, footer, affixProps, ghost, fixedHeader } = toRefs(props);
const { getPrefixCls } = useProProvider();
const value = useRouteContext();
const prefixCls = props.prefixCls || getPrefixCls();
const prefixedClassName = `${prefixCls}-page-container`; // computed(() => `${prefixCls}-page-container`);
const classNames = ref({
[prefixedClassName]: true,
[`${prefixCls}-page-container-ghost`]: ghost,
});
const content = slots.default ? (
<div>
<div class={`${prefixedClassName}-children-content`}>{slots.default()}</div>
{value.hasFooterToolbar && (
<div
style={{
height: 48,
marginTop: 24,
}}
/>
)}
</div>
) : null;
const headerDom = <div class={`${prefixedClassName}-warp`}></div>;
};
export interface AffixProps {
offsetBottom: number;
offsetTop: number;
target?: () => HTMLElement;
onChange?: (affixed: boolean) => void;
}
import { VNodeChild, CSSProperties } from 'vue';
export type ShapeType = 'circle' | 'square';
export type Size = 'large' | 'small' | 'default';
export interface AvatarProps {
icon?: VNodeChild | JSX.Element;
shape?: ShapeType;
size?: Size;
src?: string;
srcSet?: string;
alt?: string;
loadError?: () => boolean;
}
export interface PageHeaderProps {
backIcon?: VNodeChild | JSX.Element;
prefixCls?: string;
title: string | VNodeChild | JSX.Element;
subTitle?: string | VNodeChild | JSX.Element;
style?: CSSProperties;
class?: string | string[];
breadcrumb?: Record<string, any>;
tags?: VNodeChild | JSX.Element;
footer?: VNodeChild | JSX.Element;
extra?: VNodeChild | JSX.Element;
avatar?: AvatarProps;
onBack?: (e: MouseEvent) => void;
ghost?: boolean;
}
import { VNodeChild, CSSProperties } from 'vue';
export interface TabPaneProps {
tab?: VNodeChild | JSX.Element;
class?: string | string[];
style?: CSSProperties;
disabled?: boolean;
forceRender?: boolean;
closable?: boolean;
closeIcon?: VNodeChild | JSX.Element;
prefixCls?: string;
tabKey?: string;
id: string;
animated?: boolean;
active?: boolean;
destroyInactiveTabPane?: boolean;
}
import { VNodeChild, CSSProperties } from 'vue';
export interface TabsProps {
prefixCls?: string;
class?: string | string[];
style?: CSSProperties;
id?: string;
activeKey?: string;
}
export type TabBarExtraPosition = 'left' | 'right';
export type TabBarExtraMap = Partial<Record<TabBarExtraPosition, VNodeChild>>;
export type TabBarExtraContent = VNodeChild | TabBarExtraMap;
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment