refactor: result

pull/4134/head
tanjinzhou 2021-05-26 18:55:32 +08:00
parent 42916f50f5
commit 3b89f59094
4 changed files with 74 additions and 37 deletions

View File

@ -1,8 +1,6 @@
import { App, defineComponent, inject, VNodeTypes, Plugin } from 'vue';
import { App, defineComponent, VNodeTypes, Plugin, ExtractPropTypes, computed } from 'vue';
import PropTypes from '../_util/vue-types';
import { tuple } from '../_util/type';
import { getComponent } from '../_util/props-util';
import { defaultConfigProvider } from '../config-provider';
import CheckCircleFilled from '@ant-design/icons-vue/CheckCircleFilled';
import CloseCircleFilled from '@ant-design/icons-vue/CloseCircleFilled';
import ExclamationCircleFilled from '@ant-design/icons-vue/ExclamationCircleFilled';
@ -10,6 +8,8 @@ import WarningFilled from '@ant-design/icons-vue/WarningFilled';
import noFound from './noFound';
import serverError from './serverError';
import unauthorized from './unauthorized';
import useConfigInject from '../_util/hooks/useConfigInject';
import classNames from '../_util/classNames';
export const IconMap = {
success: CheckCircleFilled,
@ -27,7 +27,7 @@ export const ExceptionMap = {
// ExceptionImageMap keys
const ExceptionStatus = Object.keys(ExceptionMap);
export const ResultProps = {
export const resultProps = {
prefixCls: PropTypes.string,
icon: PropTypes.any,
status: PropTypes.oneOf(tuple('success', 'error', 'info', 'warning', '404', '403', '500')).def(
@ -38,6 +38,8 @@ export const ResultProps = {
extra: PropTypes.any,
};
export type ResultProps = Partial<ExtractPropTypes<typeof resultProps>>;
const renderIcon = (prefixCls: string, { status, icon }) => {
if (ExceptionStatus.includes(`${status}`)) {
const SVGComponent = ExceptionMap[status];
@ -57,31 +59,31 @@ const renderExtra = (prefixCls: string, extra: VNodeTypes) =>
const Result = defineComponent({
name: 'AResult',
props: ResultProps,
setup() {
return {
configProvider: inject('configProvider', defaultConfigProvider),
};
},
render() {
const { prefixCls: customizePrefixCls, status } = this;
const getPrefixCls = this.configProvider.getPrefixCls;
const prefixCls = getPrefixCls('result', customizePrefixCls);
const title = getComponent(this, 'title');
const subTitle = getComponent(this, 'subTitle');
const icon = getComponent(this, 'icon');
const extra = getComponent(this, 'extra');
return (
<div class={`${prefixCls} ${prefixCls}-${status}`}>
{renderIcon(prefixCls, { status, icon })}
<div class={`${prefixCls}-title`}>{title}</div>
{subTitle && <div class={`${prefixCls}-subtitle`}>{subTitle}</div>}
{this.$slots.default && <div class={`${prefixCls}-content`}>{this.$slots.default()}</div>}
{renderExtra(prefixCls, extra)}
</div>
props: resultProps,
slots: ['title', 'subTitle', 'icon', 'extra'],
setup(props, { slots }) {
const { prefixCls, direction } = useConfigInject('result', props);
const className = computed(() =>
classNames(prefixCls.value, `${prefixCls.value}-${props.status}`, {
[`${prefixCls.value}-rtl`]: direction.value === 'rtl',
}),
);
return () => {
const title = props.title ?? slots.title?.();
const subTitle = props.subTitle ?? slots.subTitle?.();
const icon = props.icon ?? slots.icon?.();
const extra = props.extra ?? slots.extra?.();
const pre = prefixCls.value;
return (
<div class={className.value}>
{renderIcon(pre, { status: props.status, icon })}
<div class={`${pre}-title`}>{title}</div>
{subTitle && <div class={`${pre}-subtitle`}>{subTitle}</div>}
{renderExtra(pre, extra)}
{slots.default && <div class={`${pre}-content`}>{slots.default()}</div>}
</div>
);
};
},
});

View File

@ -6,19 +6,19 @@
.@{result-prefix-cls} {
padding: 48px 32px;
// status color
&-success &-icon > .anticon {
&-success &-icon > .@{iconfont-css-prefix} {
color: @success-color;
}
&-error &-icon > .anticon {
&-error &-icon > .@{iconfont-css-prefix} {
color: @error-color;
}
&-info &-icon > .anticon {
&-info &-icon > .@{iconfont-css-prefix} {
color: @info-color;
}
&-warning &-icon > .anticon {
&-warning &-icon > .@{iconfont-css-prefix} {
color: @warning-color;
}
@ -33,30 +33,31 @@
margin-bottom: 24px;
text-align: center;
> .anticon {
font-size: 72px;
> .@{iconfont-css-prefix} {
font-size: @result-icon-font-size;
}
}
&-title {
color: @heading-color;
font-size: 24px;
font-size: @result-title-font-size;
line-height: 1.8;
text-align: center;
}
&-subtitle {
color: @text-color-secondary;
font-size: 14px;
font-size: @result-subtitle-font-size;
line-height: 1.6;
text-align: center;
}
&-extra {
margin-top: 32px;
margin: @result-extra-margin;
text-align: center;
> * {
margin-right: 8px;
&:last-child {
margin-right: 0;
}
@ -69,3 +70,5 @@
background-color: @background-color-light;
}
}
@import './rtl';

View File

@ -0,0 +1,25 @@
@import '../../style/themes/default';
@import '../../style/mixins/index';
@result-prefix-cls: ~'@{ant-prefix}-result';
.@{result-prefix-cls} {
&-rtl {
direction: rtl;
}
&-extra {
> * {
.@{result-prefix-cls}-rtl & {
margin-right: 0;
margin-left: 8px;
}
&:last-child {
.@{result-prefix-cls}-rtl & {
margin-left: 0;
}
}
}
}
}

View File

@ -835,3 +835,10 @@
@notification-bg: @component-background;
@notification-padding-vertical: 16px;
@notification-padding-horizontal: 24px;
// Result
// ---
@result-title-font-size: 24px;
@result-subtitle-font-size: @font-size-base;
@result-icon-font-size: 72px;
@result-extra-margin: 24px 0 0 0;