Skip to content

Commit

Permalink
fix: transfer、transferPicker分页和搜索相关的问题修复和优化 (baidu#9453)
Browse files Browse the repository at this point in the history
* 新增TransferPicker组件支持分页

* 解决transfer组件开启分页时,搜索不支持分页的问题。transferPicker组件临时选中状态关闭页面后缓存需清除

* TabsTransferPicker和TransferPlcker修复支持placeholder

* 修复TabsTransfer多tab下的搜索问题

* Transfer组件及相关的Tabs和Picker,增加tree模式下的initiallyOpen支持

* CRUD组件在loading状态下,所有actions不被执行(因为loading遮罩没有把按钮遮住)

* fix: 修复Transfer组件autoCheckChildren的传参问题

* 修改TransferState的searchResultPage参数为可选

* fix: 修改Transfer的search参数拼错问题

* fix: 修复Transfer和TransferPicker的pagination.enable支持表达式配置

* fix: 修复className的类型为SchemaClassName

---------

Co-authored-by: Daly Huang <Daly.Huang@walmart.com>
  • Loading branch information
weien601 and Daly Huang committed Feb 18, 2024
1 parent c016cce commit 6644273
Show file tree
Hide file tree
Showing 9 changed files with 283 additions and 81 deletions.
11 changes: 10 additions & 1 deletion packages/amis-ui/src/components/TabsTransfer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,10 @@ export interface TabsTransferProps
ctx?: Record<string, any>;
selectMode?: 'table' | 'list' | 'tree' | 'chained' | 'associated';
searchable?: boolean;
/**
* 是否默认都展开
*/
initiallyOpen?: boolean;
}

export interface TabsTransferState {
Expand Down Expand Up @@ -127,7 +131,6 @@ export class TabsTransfer extends React.Component<
if (!Array.isArray(result)) {
throw new Error('onSearch 需要返回数组');
}

this.setState({
searchResult: result
});
Expand Down Expand Up @@ -171,12 +174,15 @@ export class TabsTransfer extends React.Component<
onlyChildren,
selectMode,
loadingConfig,
activeKey,
options: optionsConfig,
valueField = 'value',
labelField = 'label'
} = this.props;
const options = searchResult || [];
const mode = searchResultMode || selectMode; // 没有配置时默认和左侧选项展示形式一致

const activeTab = optionsConfig[activeKey];
return mode === 'table' ? (
<TableCheckboxes
placeholder={noResultsText}
Expand Down Expand Up @@ -204,6 +210,7 @@ export class TabsTransfer extends React.Component<
showIcon={false}
multiple={true}
cascade={true}
autoCheckChildren={activeTab.autoCheckChildren}
itemRender={
optionItemRender
? (item: Option, states: ItemRenderStates) =>
Expand Down Expand Up @@ -349,6 +356,7 @@ export class TabsTransfer extends React.Component<
virtualThreshold,
onlyChildren,
loadingConfig,
initiallyOpen = true,
valueField = 'value',
labelField = 'label',
deferField = 'defer'
Expand Down Expand Up @@ -400,6 +408,7 @@ export class TabsTransfer extends React.Component<
virtualThreshold={virtualThreshold}
valueField={valueField}
labelField={labelField}
initiallyOpen={initiallyOpen}
/>
) : selectMode === 'chained' ? (
<ChainedCheckboxes
Expand Down
3 changes: 2 additions & 1 deletion packages/amis-ui/src/components/TabsTransferPicker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ export class TransferPicker extends React.Component<TabsTransferPickerProps> {
popOverContainer,
maxTagCount,
overflowTagPopover,
placeholder,
...rest
} = this.props;

Expand Down Expand Up @@ -100,7 +101,7 @@ export class TransferPicker extends React.Component<TabsTransferPickerProps> {
result={value}
onResultChange={onChange}
onResultClick={onClick}
placeholder={__('Select.placeholder')}
placeholder={placeholder ?? __('Select.placeholder')}
disabled={disabled}
itemRender={option => (
<span>{(option && option[labelField]) || 'undefiend'}</span>
Expand Down
129 changes: 98 additions & 31 deletions packages/amis-ui/src/components/Transfer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -79,8 +79,14 @@ export interface TransferProps
onChange?: (value: Array<Option>, optionModified?: boolean) => void;
onSearch?: (
term: string,
setCancel: (cancel: () => void) => void
) => Promise<Options | void>;
setCancel: (cancel: () => void) => void,
targetPage?: {page: number; perPage?: number}
) => Promise<{
items: Options;
page?: number;
perPage?: number;
total?: number;
} | void>;

// 自定义选择框相关
selectRender?: (
Expand Down Expand Up @@ -151,12 +157,21 @@ export interface TransferProps
perPage?: number,
direction?: 'forward' | 'backward'
) => void;
/**
* 是否默认都展开
*/
initiallyOpen?: boolean;
/**
* ui级联关系,true代表级联选中,false代表不级联,默认为true
*/
autoCheckChildren?: boolean;
}

export interface TransferState {
tempValue?: Array<Option> | Option;
inputValue: string;
searchResult: Options | null;
searchResultPage?: {page?: number; perPage?: number; total?: number} | null;
isTreeDeferLoad: boolean;
resultSelectMode: 'list' | 'tree' | 'table';
}
Expand Down Expand Up @@ -188,6 +203,7 @@ export class Transfer<
state: TransferState = {
inputValue: '',
searchResult: null,
searchResultPage: null,
isTreeDeferLoad: false,
resultSelectMode: 'list'
};
Expand Down Expand Up @@ -376,37 +392,50 @@ export class Transfer<
handleSeachCancel() {
this.setState({
inputValue: '',
searchResult: null
searchResult: null,
searchResultPage: null
});
}

lazySearch = debounce(
async () => {
const {inputValue} = this.state;
if (!inputValue) {
return;
}
const onSearch = this.props.onSearch!;
let result = await onSearch(
inputValue,
(cancelExecutor: () => void) => (this.cancelSearch = cancelExecutor)
);
lazySearch = debounce(this.searchRequest, 250, {
trailing: true,
leading: false
});

if (this.unmounted) {
return;
}
@autobind
async searchRequest(page?: number, perPage?: number) {
const {pagination} = this.props;
const {inputValue} = this.state;
if (!inputValue) {
return;
}

if (!Array.isArray(result)) {
const onSearch = this.props.onSearch!;
let result = await onSearch(
inputValue,
(cancelExecutor: () => void) => (this.cancelSearch = cancelExecutor),
this.props.pagination?.enable
? {page: page || 1, perPage: perPage || pagination?.perPage || 10}
: undefined
);

if (this.unmounted) {
return;
}

if (result) {
const {items, ...currentPage} = result;

if (!Array.isArray(items)) {
throw new Error('onSearch 需要返回数组');
}

this.setState({
searchResult: result
searchResult: items,
searchResultPage: {...currentPage}
});
},
250,
{trailing: true, leading: false}
);
}
}

getFlattenArr(options: Array<Option>) {
const {valueField = 'value'} = this.props;
Expand Down Expand Up @@ -478,6 +507,22 @@ export class Transfer<
});
}

@autobind
onPageChangeHandle(
page: number,
perPage?: number,
direction?: 'forward' | 'backward'
) {
const {onPageChange, onSearch} = this.props;
const {searchResult, inputValue} = this.state;

if (searchResult) {
this.searchRequest(page, perPage);
} else if (onPageChange) {
onPageChange(page, perPage, direction);
}
}

renderSelect(
props: TransferProps & {
onToggleAll?: () => void;
Expand Down Expand Up @@ -597,24 +642,42 @@ export class Transfer<
}

renderFooter() {
const {classnames: cx, pagination, onPageChange} = this.props;
const {classnames: cx, pagination} = this.props;
const {searchResult, searchResultPage} = this.state;

if (!pagination || !pagination?.enable) {
return null;
}

const currentPage =
searchResult && searchResultPage
? {
page: searchResultPage.page,
perPage: searchResultPage.perPage,
total: searchResultPage.total
}
: {
page: pagination.page,
perPage: pagination.perPage,
total: pagination.total
};

return pagination?.enable ? (
return (
<div className={cx('Transfer-footer')}>
<Pagination
className={cx('Transfer-footer-pagination', pagination.className)}
activePage={pagination.page}
perPage={pagination.perPage}
total={pagination.total}
activePage={currentPage.page}
perPage={currentPage.perPage}
total={currentPage.total}
layout={pagination.layout}
maxButtons={pagination.maxButtons}
perPageAvailable={pagination.perPageAvailable}
popOverContainer={pagination.popOverContainer}
popOverContainerSelector={pagination.popOverContainerSelector}
onPageChange={onPageChange}
onPageChange={this.onPageChangeHandle}
/>
</div>
) : null;
);
}

renderSearchResult(props: TransferProps) {
Expand Down Expand Up @@ -761,7 +824,9 @@ export class Transfer<
loadingConfig,
checkAll,
checkAllLabel,
onlyChildren
onlyChildren,
autoCheckChildren = true,
initiallyOpen = true
} = props;

return selectMode === 'table' ? (
Expand Down Expand Up @@ -804,6 +869,8 @@ export class Transfer<
loadingConfig={loadingConfig}
checkAllLabel={checkAllLabel}
checkAll={checkAll}
initiallyOpen={initiallyOpen}
autoCheckChildren={autoCheckChildren}
/>
) : selectMode === 'chained' ? (
<ChainedSelection
Expand Down
34 changes: 30 additions & 4 deletions packages/amis-ui/src/components/TransferPicker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,23 @@ export interface TransferPickerProps extends Omit<TransferProps, 'itemRender'> {
popOverContainer?: any;
}

export class TransferPicker extends React.Component<TransferPickerProps> {
export interface TransferPickerState {
tempValue?: any;
}

export class TransferPicker extends React.Component<
TransferPickerProps,
TransferPickerState
> {
state: TransferPickerState = {
tempValue: null
};
optionModified = false;
@autobind
handleConfirm(value: any) {
this.setState({
tempValue: null
});
this.props.onChange?.(value, this.optionModified);
this.optionModified = false;
}
Expand All @@ -38,6 +51,9 @@ export class TransferPicker extends React.Component<TransferPickerProps> {

@autobind
onBlur() {
this.setState({
tempValue: null
});
this.props.onBlur?.();
}

Expand All @@ -56,9 +72,19 @@ export class TransferPicker extends React.Component<TransferPickerProps> {
popOverContainer,
maxTagCount,
overflowTagPopover,
placeholder,
...rest
} = this.props;

const tp = {
value: this.state.tempValue || value,
onChange: (value: any) => {
this.setState({
tempValue: value
});
}
};

return (
<PickerContainer
title={__('Select.placeholder')}
Expand All @@ -84,13 +110,13 @@ export class TransferPicker extends React.Component<TransferPickerProps> {
this.optionModified = true;
setState({options, value});
} else {
onChange(value);
tp.onChange(value);
}
}}
/>
);
}}
value={value}
value={tp.value}
onConfirm={this.handleConfirm}
size={size}
>
Expand All @@ -105,7 +131,7 @@ export class TransferPicker extends React.Component<TransferPickerProps> {
result={value}
onResultChange={onChange}
onResultClick={onClick}
placeholder={__('Select.placeholder')}
placeholder={placeholder ?? __('Select.placeholder')}
disabled={disabled}
borderMode={borderMode}
itemRender={option => (
Expand Down
5 changes: 5 additions & 0 deletions packages/amis/src/renderers/CRUD.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -760,6 +760,11 @@ export default class CRUD extends React.Component<CRUDProps, any> {
stopAutoRefreshWhenModalIsOpen
} = this.props;

if (store.loading) {
//由于curd的loading样式未遮罩按钮部分,如果处于加载中时不处理操作
return;
}

if (action.actionType === 'dialog') {
store.setCurrentAction(action);
const idx: number = (ctx as any).index;
Expand Down

0 comments on commit 6644273

Please sign in to comment.