feat: first commit

This commit is contained in:
eleanor.mao
2025-03-31 22:34:22 +08:00
commit d25187c9c8
390 changed files with 57031 additions and 0 deletions

View File

@ -0,0 +1,207 @@
import { List, PullRefresh } from '@taroify/core';
import classNames from 'classnames';
import { isEqual } from 'lodash-es';
import { useCallback, useEffect, useRef, useState } from 'react';
import JobCard from '@/components/job-card';
import ListPlaceholder from '@/components/list-placeholder';
import { JobType, EmployType, SortType } from '@/constants/job';
import { JobInfo, GetJobsRequest } from '@/types/job';
import { logWithPrefix } from '@/utils/common';
import { requestJobList as requestData } from '@/utils/job';
import './index.less';
interface IRequestProps extends Partial<GetJobsRequest> {}
export interface IJobListProps extends IRequestProps {
visible?: boolean;
refreshDisabled?: boolean;
listHeight?: number;
className?: string;
onListEmpty?: () => void;
}
const FIRST_PAGE = 0;
const PAGE_SIZE = 40;
const PREFIX = 'job-list';
const log = logWithPrefix(PREFIX);
function JobList(props: IJobListProps) {
const {
className,
listHeight,
refreshDisabled,
visible = true,
cityCode = 'ALL',
category = JobType.All,
employType = EmployType.All,
sortType = SortType.RECOMMEND,
isFollow = false,
isOwner = false,
keyWord,
latitude,
longitude,
minSalary,
maxSalary,
blGroupId,
onListEmpty,
} = props;
const [refreshing, setRefreshing] = useState(false);
const [hasMore, setHasMore] = useState(true);
const [loadingMore, setLoadingMore] = useState(false);
const [loadMoreError, setLoadMoreError] = useState(false);
const [dataList, setDataList] = useState<JobInfo[]>([]);
const currentPage = useRef<number>(FIRST_PAGE);
const requestProps = useRef<IRequestProps>({});
const prevRequestProps = useRef<IRequestProps>({});
const onListEmptyRef = useRef(onListEmpty);
const handleRefresh = useCallback(async () => {
log('start pull refresh');
try {
setRefreshing(true);
setLoadMoreError(false);
const { page, hasMore: more, jobResults } = await requestData({ ...requestProps.current, page: 1 });
setHasMore(more);
setDataList(jobResults);
currentPage.current = page;
!jobResults.length && onListEmptyRef.current?.();
log('pull refresh success');
} catch (e) {
setDataList([]);
setHasMore(false);
setLoadMoreError(true);
currentPage.current = FIRST_PAGE;
log('pull refresh failed');
} finally {
setRefreshing(false);
}
}, []);
const handleLoadMore = useCallback(async () => {
log('start load more', hasMore);
if (!hasMore) {
return;
}
setLoadMoreError(false);
setLoadingMore(true);
try {
const {
page,
hasMore: more,
jobResults,
} = await requestData({ ...requestProps.current, page: currentPage.current + 1 });
setDataList([...dataList, ...jobResults]);
setHasMore(more);
currentPage.current = page;
log('load more success');
} catch (e) {
setLoadMoreError(true);
log('load more failed');
} finally {
setLoadingMore(false);
}
}, [dataList, currentPage, hasMore]);
useEffect(() => {
onListEmptyRef.current = onListEmpty;
}, [onListEmpty]);
useEffect(() => {
log('request params changed');
requestProps.current = {
category,
cityCode,
employType,
sortType,
isFollow,
isOwner,
keyWord,
latitude,
longitude,
minSalary,
maxSalary,
blGroupId,
pageSize: PAGE_SIZE,
};
}, [
category,
cityCode,
employType,
sortType,
isFollow,
isOwner,
keyWord,
latitude,
longitude,
minSalary,
maxSalary,
blGroupId,
]);
// 初始化数据&配置变更后刷新数据
useEffect(() => {
// 相比前一次可见时没有数据变更时,不再重新请求
if (isEqual(prevRequestProps.current, requestProps.current)) {
log('visible/city changed, but request params not change, ignore');
return;
}
// 列表不可见时,先不做处理
if (!visible) {
log('visible/city changed, but is not visible, only clear list');
return;
}
prevRequestProps.current = requestProps.current;
const refresh = async () => {
log('visible/city changed, start refresh list data');
try {
setDataList([]);
setLoadingMore(true);
setLoadMoreError(false);
const { page, hasMore: more, jobResults } = await requestData({ ...requestProps.current, page: 1 });
setHasMore(more);
setDataList(jobResults);
currentPage.current = page;
!jobResults.length && onListEmptyRef.current?.();
} catch (e) {
setDataList([]);
setHasMore(false);
setLoadMoreError(true);
currentPage.current = FIRST_PAGE;
} finally {
log('visible/city changed, refresh list data end');
setLoadingMore(false);
}
};
refresh();
}, [visible, cityCode, employType, sortType, keyWord, minSalary, maxSalary, blGroupId]);
// log('render', `hasMore: ${hasMore}, loadingMore: ${loadingMore}, refreshing: ${refreshing}`);
return (
<PullRefresh
className={classNames(`${PREFIX}__pull-refresh`, className)}
loading={refreshing}
onRefresh={handleRefresh}
disabled={refreshDisabled}
>
<List
hasMore={hasMore}
onLoad={handleLoadMore}
loading={loadingMore || refreshing}
disabled={loadMoreError}
fixedHeight={typeof listHeight !== 'undefined'}
style={listHeight ? { height: `${listHeight}px` } : undefined}
>
{dataList.map(item => (
<JobCard data={item} key={item.id} />
))}
<ListPlaceholder hasMore={hasMore} loadingMore={loadingMore} loadMoreError={loadMoreError} />
</List>
</PullRefresh>
);
}
export default JobList;