Merge branch 'main' of 123.60.55.248:web_boss/frontend
This commit is contained in:
@@ -6,41 +6,61 @@ const InfiniteScroll = ({
|
|||||||
loadMore,
|
loadMore,
|
||||||
hasMore,
|
hasMore,
|
||||||
children,
|
children,
|
||||||
threshold = 50,
|
threshold = 0.1, // 触发阈值,元素可见比例
|
||||||
className = "",
|
className = "",
|
||||||
empty = false,
|
empty = false,
|
||||||
}) => {
|
}) => {
|
||||||
const containerRef = useRef(null);
|
const containerRef = useRef(null);
|
||||||
|
const sentinelRef = useRef(null);
|
||||||
|
const observerRef = useRef(null);
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
|
const [hasInitialized, setHasInitialized] = useState(false); // 首次挂载
|
||||||
|
|
||||||
|
// 加载更多数据的处理函数
|
||||||
|
const handleLoadMore = () => {
|
||||||
|
if (loading || !hasMore) return;
|
||||||
|
|
||||||
const handleScroll = () => {
|
|
||||||
if (loading) return;
|
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
if (!containerRef.current || !hasMore) return;
|
loadMore().finally(() => {
|
||||||
|
setLoading(false);
|
||||||
const { scrollTop, scrollHeight, clientHeight } = containerRef.current;
|
});
|
||||||
|
|
||||||
if (scrollTop + clientHeight >= scrollHeight - threshold) {
|
|
||||||
loadMore().finally(() => {
|
|
||||||
setLoading(false);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 设置IntersectionObserver
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const container = containerRef.current;
|
// 初始化观察器
|
||||||
if (container) {
|
const options = {
|
||||||
container.addEventListener("scroll", handleScroll);
|
root: containerRef.current,
|
||||||
// 初始加载时检查是否需要加载更多
|
rootMargin: "0px 0px 50px 0px", // 减少提前触发距离
|
||||||
handleScroll();
|
threshold,
|
||||||
|
};
|
||||||
|
|
||||||
|
// 创建观察器实例
|
||||||
|
observerRef.current = new IntersectionObserver((entries) => {
|
||||||
|
const [entry] = entries;
|
||||||
|
if (entry.isIntersecting) {
|
||||||
|
handleLoadMore();
|
||||||
|
}
|
||||||
|
}, options);
|
||||||
|
|
||||||
|
// 开始观察哨兵元素
|
||||||
|
if (sentinelRef.current) {
|
||||||
|
observerRef.current.observe(sentinelRef.current);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 初始加载检查 - 仅在组件首次挂载时执行
|
||||||
|
if (hasMore && !loading && !hasInitialized) {
|
||||||
|
setHasInitialized(true);
|
||||||
|
handleLoadMore();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 清理函数
|
||||||
return () => {
|
return () => {
|
||||||
if (container) {
|
if (observerRef.current) {
|
||||||
container.removeEventListener("scroll", handleScroll);
|
observerRef.current.disconnect();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}, [loadMore, hasMore, threshold]);
|
}, [loadMore, hasMore, threshold, loading]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
@@ -49,6 +69,9 @@ const InfiniteScroll = ({
|
|||||||
>
|
>
|
||||||
{children}
|
{children}
|
||||||
|
|
||||||
|
{/* 哨兵元素 - 用于触发加载更多 */}
|
||||||
|
<div ref={sentinelRef} className="sentinel-element"></div>
|
||||||
|
|
||||||
{!hasMore && empty && (
|
{!hasMore && empty && (
|
||||||
<Empty description="暂无数据" className="empty-data" />
|
<Empty description="暂无数据" className="empty-data" />
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { useState, useEffect } from "react";
|
import { useState, useEffect } from "react";
|
||||||
import { useNavigate } from "react-router-dom";
|
import { useNavigate } from "react-router-dom";
|
||||||
import { jobAPI } from "@/services/api";
|
import { getJobsList } from "@/services";
|
||||||
import { mapJobList } from "@/utils/dataMapper";
|
import { mapJobList } from "@/utils/dataMapper";
|
||||||
import JobList from "@/pages/CompanyJobsPage/components/JobList";
|
import JobList from "@/pages/CompanyJobsPage/components/JobList";
|
||||||
|
|
||||||
@@ -20,10 +20,10 @@ const CompanyJobsListPage = () => {
|
|||||||
const fetchJobs = async () => {
|
const fetchJobs = async () => {
|
||||||
try {
|
try {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
const response = await jobAPI.getList({
|
const response = await getJobsList({
|
||||||
page,
|
page,
|
||||||
pageSize: 20,
|
pageSize: 20,
|
||||||
isActive: true
|
isActive: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
const mappedJobs = mapJobList(response.data || response);
|
const mappedJobs = mapJobList(response.data || response);
|
||||||
@@ -39,12 +39,15 @@ const CompanyJobsListPage = () => {
|
|||||||
|
|
||||||
if (loading && jobs.length === 0) {
|
if (loading && jobs.length === 0) {
|
||||||
return (
|
return (
|
||||||
<div className="company-jobs-list-page-wrapper" style={{
|
<div
|
||||||
display: 'flex',
|
className="company-jobs-list-page-wrapper"
|
||||||
justifyContent: 'center',
|
style={{
|
||||||
alignItems: 'center',
|
display: "flex",
|
||||||
minHeight: '400px'
|
justifyContent: "center",
|
||||||
}}>
|
alignItems: "center",
|
||||||
|
minHeight: "400px",
|
||||||
|
}}
|
||||||
|
>
|
||||||
<p>加载中...</p>
|
<p>加载中...</p>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
@@ -54,11 +57,13 @@ const CompanyJobsListPage = () => {
|
|||||||
<ul className="company-jobs-list-page-wrapper">
|
<ul className="company-jobs-list-page-wrapper">
|
||||||
<JobList data={jobs} />
|
<JobList data={jobs} />
|
||||||
{jobs.length === 0 && !loading && (
|
{jobs.length === 0 && !loading && (
|
||||||
<div style={{
|
<div
|
||||||
textAlign: 'center',
|
style={{
|
||||||
padding: '40px',
|
textAlign: "center",
|
||||||
color: '#999'
|
padding: "40px",
|
||||||
}}>
|
color: "#999",
|
||||||
|
}}
|
||||||
|
>
|
||||||
暂无岗位信息
|
暂无岗位信息
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -72,7 +72,6 @@ const ProjectLibrary = () => {
|
|||||||
<InfiniteScroll
|
<InfiniteScroll
|
||||||
loadMore={fetchProjects}
|
loadMore={fetchProjects}
|
||||||
hasMore={hasMore}
|
hasMore={hasMore}
|
||||||
threshold={100}
|
|
||||||
empty={projectList.length === 0}
|
empty={projectList.length === 0}
|
||||||
className="user-portfolio-list"
|
className="user-portfolio-list"
|
||||||
>
|
>
|
||||||
|
|||||||
Reference in New Issue
Block a user