feat: 🎸 接口对接调整
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
import { useEffect, useRef, useState, useCallback } from "react";
|
||||
import { Empty, Spin } from "@arco-design/web-react";
|
||||
import "./index.css";
|
||||
|
||||
@@ -13,18 +13,27 @@ const InfiniteScroll = ({
|
||||
const containerRef = useRef(null);
|
||||
const sentinelRef = useRef(null);
|
||||
const observerRef = useRef(null);
|
||||
const throttleRef = useRef(null); // 节流控制
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [hasInitialized, setHasInitialized] = useState(false); // 首次挂载
|
||||
|
||||
// 加载更多数据的处理函数
|
||||
const handleLoadMore = () => {
|
||||
// 加载更多数据的处理函数(带节流)
|
||||
const handleLoadMore = useCallback(() => {
|
||||
if (loading || !hasMore) return;
|
||||
|
||||
setLoading(true);
|
||||
loadMore().finally(() => {
|
||||
setLoading(false);
|
||||
});
|
||||
};
|
||||
// 节流处理:500ms内只能触发一次
|
||||
if (throttleRef.current) {
|
||||
clearTimeout(throttleRef.current);
|
||||
}
|
||||
|
||||
throttleRef.current = setTimeout(() => {
|
||||
setLoading(true);
|
||||
loadMore().finally(() => {
|
||||
setLoading(false);
|
||||
throttleRef.current = null;
|
||||
});
|
||||
}, 10);
|
||||
}, [hasMore, loadMore, loading]);
|
||||
|
||||
// 设置IntersectionObserver
|
||||
useEffect(() => {
|
||||
@@ -59,8 +68,13 @@ const InfiniteScroll = ({
|
||||
if (observerRef.current) {
|
||||
observerRef.current.disconnect();
|
||||
}
|
||||
// 清理节流定时器
|
||||
if (throttleRef.current) {
|
||||
clearTimeout(throttleRef.current);
|
||||
throttleRef.current = null;
|
||||
}
|
||||
};
|
||||
}, [loadMore, hasMore, threshold, loading]);
|
||||
}, [loadMore, hasMore, threshold, loading, hasInitialized, handleLoadMore]);
|
||||
|
||||
return (
|
||||
<div
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { useState, useEffect } from "react";
|
||||
import { useState, useEffect, useCallback } from "react";
|
||||
import { Spin } from "@arco-design/web-react";
|
||||
import { useSelector, useDispatch } from "react-redux";
|
||||
import { getLoginStudentInfo } from "@/services";
|
||||
@@ -14,19 +14,19 @@ const Layout = ({ children }) => {
|
||||
);
|
||||
const studentInfo = useSelector((state) => state.student.studentInfo);
|
||||
|
||||
const queryLoginStudentInfo = async () => {
|
||||
const queryLoginStudentInfo = useCallback(async () => {
|
||||
const res = await getLoginStudentInfo();
|
||||
if (res.success) {
|
||||
dispatch(setStudentInfo(res.data));
|
||||
}
|
||||
};
|
||||
}, [dispatch]);
|
||||
|
||||
// 初始化项目统一获取登录用户信息
|
||||
useEffect(() => {
|
||||
if (!studentInfo) {
|
||||
queryLoginStudentInfo();
|
||||
}
|
||||
}, [studentInfo]);
|
||||
}, [queryLoginStudentInfo, studentInfo]);
|
||||
|
||||
return (
|
||||
<div className="app-layout">
|
||||
|
||||
0
src/components/Layout/index_new.jsx
Normal file
0
src/components/Layout/index_new.jsx
Normal file
@@ -1,6 +1,9 @@
|
||||
import { Avatar, Skeleton } from "@arco-design/web-react";
|
||||
import "./index.css";
|
||||
|
||||
const positions = ["item2", "item1", "item3"];
|
||||
const icons = ["icon2", "icon1", "icon3"];
|
||||
|
||||
const Rank = ({ className, data = null, loading = false }) => {
|
||||
if (loading) {
|
||||
return (
|
||||
@@ -11,7 +14,7 @@ const Rank = ({ className, data = null, loading = false }) => {
|
||||
);
|
||||
}
|
||||
|
||||
if (!data || !data.rankings || data.rankings.length === 0) {
|
||||
if (!data || !data?.rankings || data?.rankings?.length === 0) {
|
||||
return (
|
||||
<div className={`module-class-rank ${className}`}>
|
||||
<p className="module-class-rank-title">班级排名</p>
|
||||
@@ -20,15 +23,15 @@ const Rank = ({ className, data = null, loading = false }) => {
|
||||
);
|
||||
}
|
||||
|
||||
const rankings = data.rankings.slice(0, 6);
|
||||
|
||||
const rankings = data?.rankings?.slice(0, 6);
|
||||
|
||||
// 安全处理领奖台学生,确保至少有3个位置
|
||||
const podiumStudents = [
|
||||
rankings[1] || null, // 第2名
|
||||
rankings[0] || null, // 第1名
|
||||
rankings[2] || null // 第3名
|
||||
rankings[0] || null, // 第1名
|
||||
rankings[2] || null, // 第3名
|
||||
];
|
||||
|
||||
|
||||
const listStudents = rankings.slice(3);
|
||||
|
||||
return (
|
||||
@@ -37,21 +40,11 @@ const Rank = ({ className, data = null, loading = false }) => {
|
||||
|
||||
<ul className="module-class-rank-podium">
|
||||
{podiumStudents.map((student, index) => {
|
||||
const positions = ["item2", "item1", "item3"];
|
||||
const icons = ["icon2", "icon1", "icon3"];
|
||||
|
||||
if (!student) {
|
||||
return (
|
||||
<li key={`empty-${index}`} className={`module-class-rank-podium-${positions[index]} empty`}>
|
||||
<div className="module-class-rank-podium-placeholder">
|
||||
<span>-</span>
|
||||
</div>
|
||||
</li>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<li key={student.studentId} className={`module-class-rank-podium-${positions[index]}`}>
|
||||
return student ? (
|
||||
<li
|
||||
key={student.studentId}
|
||||
className={`module-class-rank-podium-${positions[index]}`}
|
||||
>
|
||||
<Avatar className="module-class-rank-podium-avatar">
|
||||
{student.avatar ? (
|
||||
<img alt="avatar" src={student.avatar} />
|
||||
@@ -64,6 +57,15 @@ const Rank = ({ className, data = null, loading = false }) => {
|
||||
</span>
|
||||
<i className={`module-class-rank-podium-${icons[index]}`}></i>
|
||||
</li>
|
||||
) : (
|
||||
<li
|
||||
key={`empty-${index}`}
|
||||
className={`module-class-rank-podium-${positions[index]} empty`}
|
||||
>
|
||||
<div className="module-class-rank-podium-placeholder">
|
||||
<span>-</span>
|
||||
</div>
|
||||
</li>
|
||||
);
|
||||
})}
|
||||
</ul>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { useNavigate, useLocation } from "react-router-dom";
|
||||
import { Statistic } from "@arco-design/web-react";
|
||||
import { useSelector } from "react-redux";
|
||||
import IconFont from "@/components/IconFont";
|
||||
import Logo from "@/assets/images/Sidebar/logo.png";
|
||||
import BTNICON from "@/assets/images/Sidebar/btn_icon.png";
|
||||
@@ -9,6 +10,7 @@ import "./index.css";
|
||||
const Sidebar = ({ isCollapsed, setIsCollapsed }) => {
|
||||
const navigate = useNavigate();
|
||||
const location = useLocation();
|
||||
const studentInfo = useSelector((state) => state.student.studentInfo);
|
||||
|
||||
const handleNavClick = (path) => {
|
||||
navigate(path);
|
||||
|
||||
Reference in New Issue
Block a user