Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: transfer、transferPicker分页和搜索相关的问题修复和优化 #9453

Merged
merged 11 commits into from
Feb 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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