diff --git a/packages/amis-core/src/schema.ts b/packages/amis-core/src/schema.ts index 95ca4643d8f..a1a04325397 100644 --- a/packages/amis-core/src/schema.ts +++ b/packages/amis-core/src/schema.ts @@ -1553,9 +1553,24 @@ export interface AMISTrackConfig { * AMIS 加载效果配置 */ export interface AMISSpinnerConfig { + /** + * 是否显示加载状态 + */ + loading?: boolean | AMISSchema; + + /** + * 加载效果配置 + */ loadingConfig?: { root?: string; show?: boolean; + icon?: string; + tip?: string; + tipPlacement?: 'top' | 'right' | 'bottom' | 'left'; + delay?: number; + size?: 'sm' | 'lg' | ''; + className?: string; + spinnerClassName?: string; }; } diff --git a/packages/amis-ui/scss/components/_spinner.scss b/packages/amis-ui/scss/components/_spinner.scss index 3ba70018b84..6738084201f 100644 --- a/packages/amis-ui/scss/components/_spinner.scss +++ b/packages/amis-ui/scss/components/_spinner.scss @@ -23,6 +23,7 @@ flex-direction: column; align-items: center; justify-content: center; + color: var(--Spinner-color); opacity: 0; transition: ease-out opacity var(--animation-duration); @@ -53,14 +54,14 @@ .icon { width: 100%; height: 100%; - color: var(--Spinner-color); + color: inherit; } svg.icon { top: 0; path { - fill: var(--Spinner-color); + fill: currentColor; } } @@ -116,7 +117,7 @@ word-break: keep-all; white-space: nowrap; font-size: var(--spinner-base-fontSize); - color: var(--Spinner-color); + color: inherit; font-weight: var(--spinner-base-fontWeight); } diff --git a/packages/amis-ui/src/components/Spinner.tsx b/packages/amis-ui/src/components/Spinner.tsx index ef1db54fe2c..4ef851d91e0 100644 --- a/packages/amis-ui/src/components/Spinner.tsx +++ b/packages/amis-ui/src/components/Spinner.tsx @@ -43,6 +43,13 @@ export interface SpinnerExtraProps { loadingConfig?: { root?: string; show?: boolean; + icon?: string; + tip?: string; + tipPlacement?: 'top' | 'right' | 'bottom' | 'left'; + delay?: number; + size?: 'sm' | 'lg' | ''; + className?: string; + spinnerClassName?: string; }; } @@ -110,10 +117,10 @@ export class Spinner extends React.Component< show: true, className: '', spinnerClassName: '', - size: '' as '', + size: '' as const, icon: '', tip: '', - tipPlacement: 'bottom' as 'bottom', + tipPlacement: 'bottom' as const, delay: 0, overlay: false, loadingConfig: {}, @@ -199,17 +206,27 @@ export class Spinner extends React.Component< renderBody() { const { classnames: cx, - className, - spinnerClassName, - size = '', + className: propClassName, + spinnerClassName: propSpinnerClassName, overlay, - delay, - icon: iconConfig, - tip, - tipPlacement = '', loadingConfig, - disabled + disabled, + size: propSize, + tip: propTip, + tipPlacement: propTipPlacement, + delay: propDelay, + icon: propIcon } = this.props; + + const size = propSize || loadingConfig?.size || ''; + const tip = propTip || loadingConfig?.tip || ''; + const tipPlacement = propTipPlacement || loadingConfig?.tipPlacement || ''; + const delay = propDelay ?? loadingConfig?.delay ?? 0; + const iconConfig = propIcon || loadingConfig?.icon || ''; + const className = propClassName || loadingConfig?.className || ''; + const spinnerClassName = + propSpinnerClassName || loadingConfig?.spinnerClassName || ''; + // 定义了挂载位置时只能使用默认icon const icon = loadingConfig?.root ? undefined : iconConfig; const isCustomIcon = icon && React.isValidElement(icon); diff --git a/packages/amis/src/renderers/CRUD.tsx b/packages/amis/src/renderers/CRUD.tsx index 690ec713d23..ce9e874e986 100644 --- a/packages/amis/src/renderers/CRUD.tsx +++ b/packages/amis/src/renderers/CRUD.tsx @@ -3194,7 +3194,11 @@ export default class CRUD extends React.Component { headerToolbarRender: this.renderHeaderToolbar, footerToolbarRender: this.renderFooterToolbar, data: store.mergedData, - loading: store.loading, + loading: this.props.loading === false ? false : store.loading, + loadingConfig: { + ...this.props.loadingConfig, + ...(typeof this.props.loading === 'object' ? this.props.loading : {}) + }, offset: store.offset, host: this, filterItemIndex: this.filterItemIndex, @@ -3220,7 +3224,7 @@ export default class CRUD extends React.Component { return (
extends React.Component< onAction: this.handleAction, dispatchEvent: this.dispatchEvent, data: store.mergedData, - loading: store.loading, + loading: this.props.loading === false ? false : store.loading, + loadingConfig: { + ...this.props.loadingConfig, + ...(typeof this.props.loading === 'object' ? this.props.loading : {}) + }, host: this } ); @@ -1749,7 +1753,7 @@ export default class CRUD2 extends React.Component< return (
extends React.Component< translate={__} onRefresh={this.handlePullRefresh} direction={pullRefresh.gestureDirection ?? 'up'} - loading={store.loading} + loading={this.props.loading === false ? false : store.loading} completed={ !store.loading && store.lastPage > 0 && diff --git a/packages/amis/src/renderers/Table/index.tsx b/packages/amis/src/renderers/Table/index.tsx index 48de66eff91..ffdd2ddb0b0 100644 --- a/packages/amis/src/renderers/Table/index.tsx +++ b/packages/amis/src/renderers/Table/index.tsx @@ -497,7 +497,7 @@ export interface TableProps extends RendererProps, SpinnerExtraProps { canAccessSuperData?: boolean; reUseRow?: boolean; itemBadge?: BadgeObject; - loading?: boolean; + loading?: boolean | any; autoFillHeight?: boolean | AutoFillHeightObject; } @@ -2959,7 +2959,13 @@ export default class Table< translate={translate} dispatchEvent={dispatchEvent} onEvent={onEvent} - loading={store.loading} // store 的同步较慢,所以统一用 store 来下发,否则会出现 props 和 store 变化触发子节点两次 re-rerender + loading={this.props.loading === false ? false : store.loading} + loadingConfig={{ + ...loadingConfig, + ...(typeof this.props.loading === 'object' + ? this.props.loading + : {}) + }} > {renderItemActions({ store, @@ -2969,7 +2975,16 @@ export default class Table< })} - + ); }