import React, { CSSProperties } from 'react'; import { Select, Spin } from 'antd'; import debounce from 'lodash/debounce'; const { Option } = Select; import { KeyValueObj } from '../interface'; /** * SearchProps properties */ export interface SearchProps { /** fetchOption 搜索方法 */ fetchOption?: (params: any) => Promise<any>; /** getParams 请求参数处理方法 */ getParams?: (params: any) => any; /** getOption 返回结果处理方法,默认展示key value */ getOption?: (params: any) => any; /** onChange 返回选择结果 默认携带key、value */ onChange?: (params: any) => any; /** mode 多选、单选 */ mode?: 'multiple' | 'tags' | undefined; /** select.option 的key字段,默认为key */ optionKey?: string; /** select.option 的value字段,默认为value */ optionValue?: string; /** placeholder 提示信息 */ placeholder?: string; /** itemStyle select样式 */ itemStyle?: CSSProperties; /** defaultKey 默认搜索关键字 */ defaultKey?: string; } /** * UserRemoteSelect */ export default class UserRemoteSelect extends React.Component<SearchProps> { lastFetchId: number; constructor(props: SearchProps) { super(props); this.lastFetchId = 0; this.fetchUser = debounce(this.fetchUser, 800); } state = { options: [], value: [], fetching: false, }; // 初始化加载数据 componentDidMount() { const { defaultKey = '' } = this.props; this.fetchUser(defaultKey || '', true); } /** * * @param value 关键字 * @param updateStateFlag 是否需要更新state中的value */ fetchUser = (value: string, updateStateFlag?: boolean) => { const { fetchOption, getParams, getOption, onChange } = this.props; this.lastFetchId += 1; const fetchId = this.lastFetchId; this.setState({ options: [], fetching: true }); const params = (getParams && getParams(value)) || value; if (fetchOption) { fetchOption(params).then((body: any) => { if (fetchId !== this.lastFetchId) { // for fetch callback order return; } const options = (getOption && getOption(body)) || body; const updateData: any = { options, fetching: false }; if (updateStateFlag) { const item = options.find((itemEach: any) => itemEach.key === value); if (item) { item.label = item.key; updateData.value = item; if (onChange) { onChange(item); } } } this.setState(updateData); }); } }; handleChange = (value: any) => { const { onChange } = this.props; if (onChange) { onChange(value); } this.setState({ value, options: [], fetching: false, }); }; render() { const { fetching, options, value } = this.state; const { mode, placeholder, itemStyle, optionKey = 'key', optionValue = 'value', ...restProps } = this.props; return ( <Select mode={mode} labelInValue value={value} placeholder={placeholder} notFoundContent={fetching ? <Spin size="small" /> : null} filterOption={false} onSearch={this.fetchUser} onChange={this.handleChange} style={itemStyle} showSearch {...restProps} > {options.map((item: KeyValueObj) => ( <Option key={item[optionValue]} value={item[optionValue]}> {item[optionKey]} </Option> ))} </Select> ); } }