refactor: CustomSelect component update
This commit is contained in:
@@ -1,10 +1,13 @@
|
|||||||
import { useEffect, useState, type FC, type Key } from 'react';
|
import { useEffect, useState, type FC, type Key } from 'react';
|
||||||
import { Select } from 'antd'
|
import { Select } from 'antd';
|
||||||
import type { SelectProps, DefaultOptionType } from 'antd/es/select'
|
import type { SelectProps, DefaultOptionType } from 'antd/es/select';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { request } from '@/utils/request';
|
import { request } from '@/utils/request';
|
||||||
|
|
||||||
// 定义API响应类型
|
interface OptionType {
|
||||||
|
[key: string]: Key | string | number;
|
||||||
|
}
|
||||||
|
|
||||||
interface ApiResponse<T> {
|
interface ApiResponse<T> {
|
||||||
items?: T[];
|
items?: T[];
|
||||||
}
|
}
|
||||||
@@ -20,19 +23,16 @@ interface CustomSelectProps extends Omit<SelectProps, 'filterOption'> {
|
|||||||
format?: (items: OptionType[]) => OptionType[];
|
format?: (items: OptionType[]) => OptionType[];
|
||||||
showSearch?: boolean;
|
showSearch?: boolean;
|
||||||
optionFilterProp?: string;
|
optionFilterProp?: string;
|
||||||
// 其他SelectProps属性
|
|
||||||
onChange?: SelectProps<Key, DefaultOptionType>['onChange'];
|
|
||||||
value?: SelectProps<Key, DefaultOptionType>['value'];
|
|
||||||
disabled?: boolean;
|
|
||||||
style?: React.CSSProperties;
|
|
||||||
className?: string;
|
|
||||||
filterOption?: (inputValue: string, option?: DefaultOptionType) => boolean;
|
filterOption?: (inputValue: string, option?: DefaultOptionType) => boolean;
|
||||||
}
|
}
|
||||||
interface OptionType {
|
|
||||||
[key: string]: Key | string | number;
|
const defaultFilterOption = (inputValue: string, option?: DefaultOptionType): boolean => {
|
||||||
}
|
if (!option || !inputValue) return true;
|
||||||
|
const label = String(option.children || option.label || '');
|
||||||
|
return label.toLowerCase().includes(inputValue.toLowerCase());
|
||||||
|
};
|
||||||
|
|
||||||
const CustomSelect: FC<CustomSelectProps> = ({
|
const CustomSelect: FC<CustomSelectProps> = ({
|
||||||
onChange,
|
|
||||||
url,
|
url,
|
||||||
params,
|
params,
|
||||||
valueKey = 'value',
|
valueKey = 'value',
|
||||||
@@ -42,42 +42,37 @@ const CustomSelect: FC<CustomSelectProps> = ({
|
|||||||
allTitle,
|
allTitle,
|
||||||
format,
|
format,
|
||||||
showSearch = false,
|
showSearch = false,
|
||||||
optionFilterProp = 'label',
|
|
||||||
filterOption,
|
filterOption,
|
||||||
...props
|
...props
|
||||||
}) => {
|
}) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const [options, setOptions] = useState<OptionType[]>([]);
|
const [options, setOptions] = useState<OptionType[]>([]);
|
||||||
|
|
||||||
// 默认模糊搜索函数
|
|
||||||
const defaultFilterOption = (inputValue: string, option?: DefaultOptionType) => {
|
|
||||||
if (!option || !inputValue) return true;
|
|
||||||
const label = String(option.children || option.label || '');
|
|
||||||
return label.toLowerCase().includes(inputValue.toLowerCase());
|
|
||||||
};
|
|
||||||
// 组件挂载时获取初始数据
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
request.get<ApiResponse<OptionType>>(url, params).then((res) => {
|
request.get<ApiResponse<OptionType>>(url, params).then((res) => {
|
||||||
const data = res;
|
const data = Array.isArray(res) ? res : res?.items || [];
|
||||||
setOptions(Array.isArray(data) ? data || [] : Array.isArray(data?.items) ? data.items || [] : []);
|
setOptions(data);
|
||||||
});
|
});
|
||||||
}, []);
|
}, [url, params]);
|
||||||
|
|
||||||
|
const displayOptions = format ? format(options) : options;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Select
|
<Select
|
||||||
placeholder={placeholder ? placeholder : t('common.select')}
|
placeholder={placeholder || t('common.select')}
|
||||||
onChange={onChange}
|
|
||||||
defaultValue={hasAll ? null : undefined}
|
defaultValue={hasAll ? null : undefined}
|
||||||
showSearch={showSearch}
|
showSearch={showSearch}
|
||||||
filterOption={filterOption || defaultFilterOption}
|
filterOption={filterOption || defaultFilterOption}
|
||||||
{...props}
|
{...props}
|
||||||
>
|
>
|
||||||
{hasAll && (<Select.Option>{allTitle || t('common.all')}</Select.Option>)}
|
{hasAll && <Select.Option value={null}>{allTitle || t('common.all')}</Select.Option>}
|
||||||
{(format ? format(options) : options)?.map(option => (
|
{displayOptions.map((option) => (
|
||||||
<Select.Option key={option[valueKey]} value={option[valueKey]}>
|
<Select.Option key={option[valueKey]} value={option[valueKey]}>
|
||||||
{String(option[labelKey])}
|
{String(option[labelKey])}
|
||||||
</Select.Option>
|
</Select.Option>
|
||||||
))}
|
))}
|
||||||
</Select>
|
</Select>
|
||||||
);
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
export default CustomSelect;
|
export default CustomSelect;
|
||||||
Reference in New Issue
Block a user