import React, { useState, useMemo, useRef, useEffect } from 'react';
import { Select, Spin } from 'antd';
import debounce from 'lodash/debounce';
import request from '@/utils/request';
function calcPageNum(count, pageSize) {
const num = count / pageSize;
return num > parseInt(num) ? parseInt(num) + 1 : parseInt(num);
}
function DebounceSelect({ fetchOptions, debounceTimeout = 800, ...props }) {
const [fetching, setFetching] = useState(false);
const [options, setOptions] = useState();
const [totalPage, setTotalPage] = useState(1);
const fetchRef = useRef(0);
const [params, setParams] = useState({
page: 1,
per_page: 20,
q: '',
});
const debounceFetcher = useMemo(() => {
const loadOptions = (value) => {
fetchRef.current += 1;
const fetchId = fetchRef.current;
setOptions([]);
setFetching(true);
fetchOptions({
...params,
q: value,
}).then(({ count, opts }) => {
if (fetchId !== fetchRef.current) {
console.log('哈哈哈搜索');
return;
}
if (count === 0) {
setFetching(true);
setTotalPage(1);
setOptions(opts);
return;
}
setTotalPage(calcPageNum(count, params.per_page));
setOptions(opts);
setFetching(false);
});
};
return debounce(loadOptions, debounceTimeout);
}, [fetchOptions, debounceTimeout]);
useEffect(() => {
fetchOptions(params).then(({ count, opts }) => {
setTotalPage(calcPageNum(count, params.per_page));
setOptions(opts);
setFetching(false);
props.onChange(opts[0]);
});
}, []);
const onScroll = (e) => {
const { scrollHeight, clientHeight, scrollTop } = e.target;
if (totalPage > params.page) {
if (clientHeight + scrollTop === scrollHeight) {
setParams({
...params,
page: params.page + 1,
});
fetchOptions({ ...params, page: params.page + 1 }).then(({ count, opts }) => {
setTotalPage(calcPageNum(count, params.per_page));
setOptions([...options, ...opts]);
setFetching(false);
});
}
}
};
return (
<Select
labelInValue
allowClear
filterOption={false}
onSearch={debounceFetcher}
notFoundContent={
fetching ? (
<div>
<Spin size="small" />
当前搜索无结果,请输入有效关键词
</div>
) : null
}
onPopupScroll={onScroll}
{...props}
options={options}
/>
);
}
const getNovelsApi = '/novel/novels/searchForPromLink';
const SelectLay = (props) => {
const [value, setValue] = useState({
label: '',
value: '',
});
const getNovels = async (params) => {
return request(`${getNovelsApi}?display=json`, {
method: 'GET',
params: { ...params },
}).then((res) => {
if (res.data.count === 0) {
return {
count: res.data.count,
opts: [],
};
} else {
return {
count: res.data.count,
opts: res.data.novel_list.map((item) => ({
value: item.novel_id,
label: item.title,
})),
};
}
});
};
const changeVal = (val) => {
setValue(val);
props.onChange('int', '=', val);
};
return (
<>
<label style={{ marginRight: '10px' }}>{props.label}</label>
<DebounceSelect
mode="multiple"
showSearch={true}
value={value}
placeholder="请选择"
fetchOptions={getNovels}
onChange={changeVal}
style={{
width: '360px',
}}
/>
</>
);
};
export default SelectLay;