diff --git a/src/components/InfiniteScroll/index.css b/src/components/InfiniteScroll/index.css index 2a2a57c..6f0dbcb 100644 --- a/src/components/InfiniteScroll/index.css +++ b/src/components/InfiniteScroll/index.css @@ -3,18 +3,10 @@ width: 100%; } -.loading-indicator { - display: flex; - justify-content: center; - align-items: center; - padding: 16px; - color: #999; -} - .no-more-data { display: flex; justify-content: center; align-items: center; padding: 16px; color: #999; -} \ No newline at end of file +} diff --git a/src/components/InfiniteScroll/index.jsx b/src/components/InfiniteScroll/index.jsx index 96df6ca..f718c1f 100644 --- a/src/components/InfiniteScroll/index.jsx +++ b/src/components/InfiniteScroll/index.jsx @@ -1,8 +1,5 @@ import { useEffect, useRef, useState } from "react"; import { Empty } from "@arco-design/web-react"; -import { useSelector } from "react-redux"; -import { useDispatch } from "react-redux"; -import { setLoadingFalse } from "@/store/slices/loadingSlice"; const InfiniteScroll = ({ loadMore, @@ -11,21 +8,18 @@ const InfiniteScroll = ({ threshold = 50, className = "", }) => { - const dispatch = useDispatch(); const containerRef = useRef(null); - const globalLoading = useSelector((state) => state.loading.value); const [loading, setLoading] = useState(false); const handleScroll = () => { if (loading) return; setLoading(true); - if (!containerRef.current || globalLoading || !hasMore) return; + if (!containerRef.current || !hasMore) return; const { scrollTop, scrollHeight, clientHeight } = containerRef.current; if (scrollTop + clientHeight >= scrollHeight - threshold) { loadMore().finally(() => { - dispatch(setLoadingFalse()); setLoading(false); }); } @@ -44,7 +38,7 @@ const InfiniteScroll = ({ container.removeEventListener("scroll", handleScroll); } }; - }, [loadMore, hasMore, threshold, globalLoading]); + }, [loadMore, hasMore, threshold]); return (
{children} - {!hasMore && !globalLoading && } + {!hasMore && !loading && }
); }; diff --git a/src/components/Layout/index.jsx b/src/components/Layout/index.jsx index dcac0e0..5f87092 100644 --- a/src/components/Layout/index.jsx +++ b/src/components/Layout/index.jsx @@ -1,12 +1,28 @@ -import { useState } from "react"; +import { useState, useEffect } from "react"; import { Spin } from "@arco-design/web-react"; -import { useSelector } from "react-redux"; +import { useSelector, useDispatch } from "react-redux"; +import { getLoginStudentInfo } from "@/services"; +import { setStudentInfo } from "@/store/slices/studentSlice"; import Sidebar from "../Sidebar"; import "./index.css"; const Layout = ({ children }) => { - const loading = useSelector((state) => state.loading.value); + const dispatch = useDispatch(); const [isCollapsed, setIsCollapsed] = useState(true); + const loading = useSelector((state) => state.loading.value); + const studentInfo = useSelector((state) => state.student.studentInfo); + + const queryLoginStudentInfo = async () => { + const res = await getLoginStudentInfo(); + dispatch(setStudentInfo(res)); + }; + + // 初始化项目统一获取登录用户信息 + useEffect(() => { + if (!studentInfo) { + queryLoginStudentInfo(); + } + }, [studentInfo]); return (
diff --git a/src/pages/CompanyJobsPage/index.jsx b/src/pages/CompanyJobsPage/index.jsx index 669c131..c4ff752 100644 --- a/src/pages/CompanyJobsPage/index.jsx +++ b/src/pages/CompanyJobsPage/index.jsx @@ -1,14 +1,16 @@ import { useState } from "react"; +import { useSelector } from "react-redux"; import { useNavigate } from "react-router-dom"; import { mapJobList, mapInterviewList } from "@/utils/dataMapper"; import JobList from "./components/JobList"; -import { getJobsList, getInterviewsList, getCurrentStudent } from "@/services"; +import { getJobsList, getInterviewsList } from "@/services"; import InfiniteScroll from "@/components/InfiniteScroll"; import "./index.css"; const PAGE_SIZE = 10; const CompanyJobsPage = () => { + const studentInfo = useSelector((state) => state.student.studentInfo); const [isExpand, setIsExpand] = useState(false); // 是否展开 const [jobs, setJobs] = useState([]); const [jobsListPage, setJobsListPage] = useState(1); @@ -21,14 +23,11 @@ const CompanyJobsPage = () => { // 获取面试信息 const fetchInterviewsData = async () => { try { - let studentId = null; - const currentStudent = await getCurrentStudent(); - studentId = currentStudent?.id; - if (studentId) { + if (studentInfo?.id) { const res = await getInterviewsList({ page: interviewsPage, pageSize: PAGE_SIZE, - studentId: studentId, + studentId: studentInfo?.id, status: "SCHEDULED", }); if (res.success) { diff --git a/src/pages/Dashboard/index.jsx b/src/pages/Dashboard/index.jsx index b2ee272..1cce0a7 100644 --- a/src/pages/Dashboard/index.jsx +++ b/src/pages/Dashboard/index.jsx @@ -9,8 +9,6 @@ import TaskList from "./components/TaskList"; import "./index.css"; const Dashboard = () => { - const [data, setData] = useState({}); - return (
diff --git a/src/pages/PersonalProfile/components/ProfileCard/index.jsx b/src/pages/PersonalProfile/components/ProfileCard/index.jsx index c58a8fb..8b5f702 100644 --- a/src/pages/PersonalProfile/components/ProfileCard/index.jsx +++ b/src/pages/PersonalProfile/components/ProfileCard/index.jsx @@ -1,60 +1,9 @@ import { Avatar } from "@arco-design/web-react"; -import { useState, useEffect } from "react"; -import { studentAPI } from "@/services/api"; -import { mapProfile } from "@/utils/dataMapper"; +import { useSelector } from "react-redux"; import "./index.css"; const ProfileCard = () => { - const [profile, setProfile] = useState(null); - const [loading, setLoading] = useState(true); - - useEffect(() => { - fetchProfile(); - }, []); - - const fetchProfile = async () => { - try { - setLoading(true); - // Get current logged-in student information - const studentData = await studentAPI.getCurrentStudent(); - - if (studentData) { - const mappedProfile = mapProfile(studentData); - setProfile(mappedProfile); - } else { - throw new Error("Failed to get current student data"); - } - } catch (error) { - console.error("Failed to fetch profile:", error); - // Show error message instead of fake data - setProfile({ - name: "数据加载失败", - studentId: "请检查后端服务", - school: error.message || "后端未运行", - major: "请确保数据库已初始化", - badges: { - credits: 0, - classRank: 0, - mbti: "-" - }, - courses: [] - }); - } finally { - setLoading(false); - } - }; - - if (loading) { - return ( -
-

加载中...

-
- ); - } + const studentInfo = useSelector((state) => state.student.studentInfo); return (
@@ -66,9 +15,11 @@ const ProfileCard = () => { />
- {profile?.name} + + {studentInfo?.realName || "-"} +

- 学号: {profile?.studentId} + 学号: {studentInfo?.studentNo || "-"}

@@ -76,7 +27,7 @@ const ProfileCard = () => {
  • 学分 - {profile?.badges?.credits || 0} + {studentInfo?.totalCredits || 0}
  • @@ -84,13 +35,13 @@ const ProfileCard = () => { 班级排名 - {profile?.badges?.classRank || '-'} + {studentInfo?.badges?.classRank || "-"}
  • MBTI - {profile?.badges?.mbti || '-'} + {studentInfo?.mbtiType || "-"}
  • @@ -99,30 +50,28 @@ const ProfileCard = () => { 学校 - {profile?.school || '-'} + {studentInfo?.school || "-"}
  • 专业 - {profile?.major || '-'} + {studentInfo?.major || "-"}
  • - - 班级 - + 班级 - {profile?.className || '-'} + {studentInfo?.className || "-"}
  • 学习阶段 - {profile?.stageName || '-'} + {studentInfo?.stageName || "-"}
  • diff --git a/src/pages/PersonalProfile/components/StudyStudes/index.jsx b/src/pages/PersonalProfile/components/StudyStudes/index.jsx index e81613e..844b273 100644 --- a/src/pages/PersonalProfile/components/StudyStudes/index.jsx +++ b/src/pages/PersonalProfile/components/StudyStudes/index.jsx @@ -1,7 +1,10 @@ import * as echarts from "echarts"; +import { useState, useEffect } from "react"; +import { useSelector } from "react-redux"; import StudyProgress from "../StudyProgress"; import ScoreRingChart from "../ScoreRingChart"; import AttendanceRingChart from "../AttendanceRingChart"; +import { getLoginStudentProgress } from "@/services"; import "./index.css"; const ringData = [ @@ -49,6 +52,21 @@ const attendanceData = [ ]; const StudyStudes = () => { + const studentInfo = useSelector((state) => state.student.studentInfo); + + const [progressData, setProgressData] = useState({}); + + const queryLoginStudentProgress = async () => { + const res = await getLoginStudentProgress(); + if (res.success) { + setProgressData(res.data); + } + }; + + useEffect(() => { + queryLoginStudentProgress(); + }, []); + return (

    学习情况

    diff --git a/src/services/global.js b/src/services/global.js index 477a82b..f7e056b 100644 --- a/src/services/global.js +++ b/src/services/global.js @@ -1,6 +1,6 @@ import request from "@/utils/request"; -// 获取学生信息 -export async function getCurrentStudent() { +// 获取当前登录学生信息 +export async function getLoginStudentInfo() { return request.get("/api/students/me"); } diff --git a/src/services/index.js b/src/services/index.js index cbe0419..d40f283 100644 --- a/src/services/index.js +++ b/src/services/index.js @@ -5,7 +5,8 @@ import { } from "./dashboard"; import { getProjectsList } from "./projectLibrary"; import { getJobsList, getInterviewsList } from "./companyJobs"; -import { getCurrentStudent } from "./global"; +import { getLoginStudentInfo } from "./global"; +import { getLoginStudentProgress } from "./personalProfile"; export { getDashboardStatistics, @@ -14,5 +15,6 @@ export { getProjectsList, getJobsList, getInterviewsList, - getCurrentStudent, + getLoginStudentInfo, + getLoginStudentProgress, }; diff --git a/src/services/personalProfile.js b/src/services/personalProfile.js new file mode 100644 index 0000000..7fa6bff --- /dev/null +++ b/src/services/personalProfile.js @@ -0,0 +1,6 @@ +import request from "@/utils/request"; + +// 获取当前登录学生学习进度 +export async function getLoginStudentProgress(id) { + return request.get(`/api/students/${id}/progress`); +} diff --git a/src/store/index.js b/src/store/index.js index 564517f..67f54c6 100644 --- a/src/store/index.js +++ b/src/store/index.js @@ -1,10 +1,10 @@ -import { configureStore } from '@reduxjs/toolkit'; -import loadingReducer from './slices/loadingSlice'; -import userReducer from './slices/userSlice'; // 导入新的用户reducer +import { configureStore } from "@reduxjs/toolkit"; +import loadingReducer from "./slices/loadingSlice"; +import studentReducer from "./slices/studentSlice"; export default configureStore({ reducer: { loading: loadingReducer, - user: userReducer // 添加用户reducer到store - } + student: studentReducer, + }, }); diff --git a/src/store/slices/studentSlice.js b/src/store/slices/studentSlice.js new file mode 100644 index 0000000..66a1db0 --- /dev/null +++ b/src/store/slices/studentSlice.js @@ -0,0 +1,39 @@ +import { createSlice } from "@reduxjs/toolkit"; + +// 定义初始状态 +const initialState = { + studentInfo: null, // 用户信息初始为null + isLoggedIn: false, // 登录状态初始为false +}; + +const studentSlice = createSlice({ + name: "student", + initialState, + reducers: { + // 设置用户信息 + setStudentInfo: (state, action) => { + state.studentInfo = action.payload; + state.isLoggedIn = true; + }, + // 清除用户信息 + clearStudentInfo: (state) => { + state.studentInfo = null; + state.isLoggedIn = false; + }, + // 更新用户信息的部分字段 + updateStudentInfo: (state, action) => { + if (state.studentInfo) { + state.studentInfo = { + ...state.studentInfo, + ...action.payload, + }; + } + }, + }, +}); + +// 导出actions +export const { setStudentInfo, clearStudentInfo, updateStudentInfo } = + studentSlice.actions; + +export default studentSlice.reducer; diff --git a/src/store/slices/userSlice.js b/src/store/slices/userSlice.js deleted file mode 100644 index 82f258a..0000000 --- a/src/store/slices/userSlice.js +++ /dev/null @@ -1,38 +0,0 @@ -import { createSlice } from '@reduxjs/toolkit'; - -// 定义初始状态 -const initialState = { - userInfo: null, // 用户信息初始为null - isLoggedIn: false // 登录状态初始为false -}; - -const userSlice = createSlice({ - name: 'user', - initialState, - reducers: { - // 设置用户信息 - setUserInfo: (state, action) => { - state.userInfo = action.payload; - state.isLoggedIn = true; - }, - // 清除用户信息 - clearUserInfo: (state) => { - state.userInfo = null; - state.isLoggedIn = false; - }, - // 更新用户信息的部分字段 - updateUserInfo: (state, action) => { - if (state.userInfo) { - state.userInfo = { - ...state.userInfo, - ...action.payload - }; - } - } - } -}); - -// 导出actions -export const { setUserInfo, clearUserInfo, updateUserInfo } = userSlice.actions; - -export default userSlice.reducer; \ No newline at end of file