import type { App, VNodeTypes, Plugin, ExtractPropTypes, PropType } from 'vue'; import { defineComponent, computed } from 'vue'; import PropTypes from '../_util/vue-types'; import CheckCircleFilled from '@ant-design/icons-vue/CheckCircleFilled'; import CloseCircleFilled from '@ant-design/icons-vue/CloseCircleFilled'; import ExclamationCircleFilled from '@ant-design/icons-vue/ExclamationCircleFilled'; import WarningFilled from '@ant-design/icons-vue/WarningFilled'; import noFound from './noFound'; import serverError from './serverError'; import unauthorized from './unauthorized'; import useConfigInject from '../config-provider/hooks/useConfigInject'; import classNames from '../_util/classNames'; import type { CustomSlotsType } from '../_util/type'; import useStyle from './style'; export const IconMap = { success: CheckCircleFilled, error: CloseCircleFilled, info: ExclamationCircleFilled, warning: WarningFilled, }; export const ExceptionMap = { '404': noFound, '500': serverError, '403': unauthorized, }; export type ExceptionStatusType = 403 | 404 | 500 | '403' | '404' | '500'; export type ResultStatusType = ExceptionStatusType | keyof typeof IconMap; // ExceptionImageMap keys const ExceptionStatus = Object.keys(ExceptionMap); export const resultProps = () => ({ prefixCls: String, icon: PropTypes.any, status: { type: [Number, String] as PropType, default: 'info' }, title: PropTypes.any, subTitle: PropTypes.any, extra: PropTypes.any, }); export type ResultProps = Partial>>; const renderIcon = (prefixCls: string, { status, icon }) => { if (ExceptionStatus.includes(`${status}`)) { const SVGComponent = ExceptionMap[status]; return (
); } const IconComponent = IconMap[status]; const iconNode = icon || ; return
{iconNode}
; }; const renderExtra = (prefixCls: string, extra: VNodeTypes) => extra &&
{extra}
; const Result = defineComponent({ compatConfig: { MODE: 3 }, name: 'AResult', inheritAttrs: false, props: resultProps(), slots: Object as CustomSlotsType<{ title?: any; subTitle?: any; icon?: any; extra?: any; default?: any; }>, setup(props, { slots, attrs }) { const { prefixCls, direction } = useConfigInject('result', props); const [wrapSSR, hashId] = useStyle(prefixCls); const className = computed(() => classNames(prefixCls.value, hashId.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 wrapSSR(
{renderIcon(pre, { status: props.status, icon })}
{title}
{subTitle &&
{subTitle}
} {renderExtra(pre, extra)} {slots.default &&
{slots.default()}
}
, ); }; }, }); /* add resource */ Result.PRESENTED_IMAGE_403 = ExceptionMap[403]; Result.PRESENTED_IMAGE_404 = ExceptionMap[404]; Result.PRESENTED_IMAGE_500 = ExceptionMap[500]; /* istanbul ignore next */ Result.install = function (app: App) { app.component(Result.name, Result); return app; }; export default Result as typeof Result & Plugin & { readonly PRESENTED_IMAGE_403: typeof unauthorized; readonly PRESENTED_IMAGE_404: typeof noFound; readonly PRESENTED_IMAGE_500: typeof serverError; };