From 428b88097086e15b061da15abc77f76f3d500e1a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=89=8D=E7=AB=AF=E4=BA=BA=E7=BB=9D=E4=B8=8D=E4=B8=BA?= =?UTF-8?q?=E5=A5=B4?= Date: Tue, 26 Aug 2025 10:54:12 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=F0=9F=8E=B8=20=E6=8E=A5=E5=8F=A3?= =?UTF-8?q?=E5=AF=B9=E6=8E=A5=E8=B0=83=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- eslint.config.js | 3 +- index.html | 4 +- public/vite.svg | 1 - src/components/InfiniteScroll/index.jsx | 32 +++++-- src/components/Layout/index.jsx | 8 +- src/components/Layout/index_new.jsx | 0 src/components/Rank/index.jsx | 44 ++++----- src/components/Sidebar/index.jsx | 2 + src/pages/CompanyJobsListPage/index.jsx | 89 +++++++------------ .../components/JobInfoModal/index.jsx | 12 +-- src/pages/CompanyJobsPage/index.css | 1 + .../components/EchartsProgress/index.jsx | 2 +- .../Dashboard/components/TaskList/index.jsx | 50 ++++++----- src/pages/Dashboard/index.jsx | 28 +++--- .../components/StudyStudes/index.jsx | 54 +++++++---- src/pages/PersonalProfile/index.jsx | 36 ++++---- .../components/ProjectCasesModal/index.jsx | 1 - src/pages/ProjectLibraryPage/index.jsx | 4 +- .../InterviewQuestionsModal/index.jsx | 23 ++--- src/pages/ResumeInterviewPage/index.css | 59 +----------- src/pages/ResumeInterviewPage/index.jsx | 62 ++++--------- 21 files changed, 223 insertions(+), 292 deletions(-) delete mode 100644 public/vite.svg create mode 100644 src/components/Layout/index_new.jsx diff --git a/eslint.config.js b/eslint.config.js index 8aad11f..85655be 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -31,7 +31,7 @@ export default defineConfig([ }, ], "react-hooks/exhaustive-deps": "warn", - "no-console": "warn", + "no-console": 1, "react-hooks/rules-of-hooks": "error", "no-nested-ternary": 0, // 允许嵌套三元表达式 "no-script-url": 0, // 允许javascript:; @@ -47,6 +47,7 @@ export default defineConfig([ "react/no-deprecated": 0, // 关闭react弃用检测 "react/no-string-refs": 0, "no-useless-escape": 0, + "react-refresh/only-export-components": 0, // 允许匿名导出 }, }, ]); diff --git a/index.html b/index.html index 66f3451..ddd83db 100644 --- a/index.html +++ b/index.html @@ -1,8 +1,8 @@ - + - + 多多畅职教育系统 diff --git a/public/vite.svg b/public/vite.svg deleted file mode 100644 index e7b8dfb..0000000 --- a/public/vite.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/src/components/InfiniteScroll/index.jsx b/src/components/InfiniteScroll/index.jsx index bb6d62e..85fd763 100644 --- a/src/components/InfiniteScroll/index.jsx +++ b/src/components/InfiniteScroll/index.jsx @@ -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 (
{ ); 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 (
diff --git a/src/components/Layout/index_new.jsx b/src/components/Layout/index_new.jsx new file mode 100644 index 0000000..e69de29 diff --git a/src/components/Rank/index.jsx b/src/components/Rank/index.jsx index d385c72..12cbfaa 100644 --- a/src/components/Rank/index.jsx +++ b/src/components/Rank/index.jsx @@ -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 (

班级排名

@@ -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 }) => {
    {podiumStudents.map((student, index) => { - const positions = ["item2", "item1", "item3"]; - const icons = ["icon2", "icon1", "icon3"]; - - if (!student) { - return ( -
  • -
    - - -
    -
  • - ); - } - - return ( -
  • + return student ? ( +
  • {student.avatar ? ( avatar @@ -64,6 +57,15 @@ const Rank = ({ className, data = null, loading = false }) => {
  • + ) : ( +
  • +
    + - +
    +
  • ); })}
diff --git a/src/components/Sidebar/index.jsx b/src/components/Sidebar/index.jsx index 88b96bb..e1a1747 100644 --- a/src/components/Sidebar/index.jsx +++ b/src/components/Sidebar/index.jsx @@ -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); diff --git a/src/pages/CompanyJobsListPage/index.jsx b/src/pages/CompanyJobsListPage/index.jsx index e27b5f9..1f0787a 100644 --- a/src/pages/CompanyJobsListPage/index.jsx +++ b/src/pages/CompanyJobsListPage/index.jsx @@ -1,73 +1,46 @@ -import { useState, useEffect } from "react"; -import { useNavigate } from "react-router-dom"; +import { useState, useCallback } from "react"; +import JobList from "@/pages/CompanyJobsPage/components/JobList"; +import InfiniteScroll from "@/components/InfiniteScroll"; import { getJobsList } from "@/services"; import { mapJobList } from "@/utils/dataMapper"; -import JobList from "@/pages/CompanyJobsPage/components/JobList"; - import "./index.css"; +const PAGE_SIZE = 20; + const CompanyJobsListPage = () => { const [jobs, setJobs] = useState([]); - const [loading, setLoading] = useState(true); - const [page, setPage] = useState(1); - const [total, setTotal] = useState(0); - const navigate = useNavigate(); + const [listPage, setListPage] = useState(1); + const [listHasMore, setListHasMore] = useState(true); - useEffect(() => { - fetchJobs(); - }, [page]); - - const fetchJobs = async () => { - try { - setLoading(true); - const response = await getJobsList({ - page, - pageSize: 20, - isActive: true, + const fetchJobs = useCallback(async () => { + const res = await getJobsList({ + page: listPage, + pageSize: PAGE_SIZE, + isActive: true, + }); + if (res.success) { + const mappedJobs = mapJobList(res.data); + setJobs((prevList) => { + const newList = [...prevList, ...mappedJobs]; + if (res.total === newList?.length) { + setListHasMore(false); + } else { + setListPage((prevPage) => prevPage + 1); + } + return newList; }); - - const mappedJobs = mapJobList(response.data || response); - setJobs(mappedJobs); - setTotal(response.total || mappedJobs.length); - } catch (error) { - console.error("Failed to fetch jobs:", error); - setJobs([]); - } finally { - setLoading(false); } - }; - - if (loading && jobs.length === 0) { - return ( -
-

加载中...

-
- ); - } + }, [listPage]); return ( -
    + - {jobs.length === 0 && !loading && ( -
    - 暂无岗位信息 -
    - )} -
+ ); }; diff --git a/src/pages/CompanyJobsPage/components/JobInfoModal/index.jsx b/src/pages/CompanyJobsPage/components/JobInfoModal/index.jsx index a90ed43..9278d5e 100644 --- a/src/pages/CompanyJobsPage/components/JobInfoModal/index.jsx +++ b/src/pages/CompanyJobsPage/components/JobInfoModal/index.jsx @@ -1,10 +1,10 @@ -import { useState } from "react"; +import { useState, useCallback } from "react"; import { useSelector } from "react-redux"; import { Input } from "@arco-design/web-react"; import Modal from "@/components/Modal"; import InfiniteScroll from "@/components/InfiniteScroll"; -import ResumeInfoModal from "@/pages/CompanyJobsPage/components/ResumeInfoModal"; import FILEICON from "@/assets/images/CompanyJobsPage/file_icon.png"; +import ResumeInfoModal from "../ResumeInfoModal"; import { getResumesList } from "@/services"; import "./index.css"; @@ -24,7 +24,7 @@ export default ({ visible, onClose, data }) => { onClose(); }; - const queryResumeList = async () => { + const queryResumeList = useCallback(async () => { const res = await getResumesList({ page: listPage, pageSize: PAGE_SIZE, @@ -41,7 +41,7 @@ export default ({ visible, onClose, data }) => { return newList; }); } - }; + }, [listPage, studentInfo?.id]); // 点击立即投递 const handleClickDeliverBtn = (e) => { @@ -50,18 +50,19 @@ export default ({ visible, onClose, data }) => { }; const onSearch = (value) => { + // todo console.log(value); }; // 选择简历投递 const userResumesClick = (item) => { + // todo console.log(item); }; // 点击简历详情 const userResumesBtnClick = (e, item) => { e.stopPropagation(); - console.log(item); setResumeInfoModalShow(true); }; @@ -185,6 +186,7 @@ export default ({ visible, onClose, data }) => { setResumeInfoModalShow(false)} /> diff --git a/src/pages/CompanyJobsPage/index.css b/src/pages/CompanyJobsPage/index.css index b3f0295..0181d75 100644 --- a/src/pages/CompanyJobsPage/index.css +++ b/src/pages/CompanyJobsPage/index.css @@ -98,6 +98,7 @@ margin-bottom: 20px; box-sizing: border-box; padding: 20px; + list-style: none; .company-jobs-page-interview-item-info { width: 100%; diff --git a/src/pages/Dashboard/components/EchartsProgress/index.jsx b/src/pages/Dashboard/components/EchartsProgress/index.jsx index 2b7c8fe..5acd7a9 100644 --- a/src/pages/Dashboard/components/EchartsProgress/index.jsx +++ b/src/pages/Dashboard/components/EchartsProgress/index.jsx @@ -92,7 +92,7 @@ const EchartsProgress = ({ return () => { window.removeEventListener("resize", resizeHandler); }; - }, [percent, strokeWidth]); + }, [backgroundColor, percent, progressColor, strokeWidth]); return
; }; diff --git a/src/pages/Dashboard/components/TaskList/index.jsx b/src/pages/Dashboard/components/TaskList/index.jsx index a70bea1..42ed918 100644 --- a/src/pages/Dashboard/components/TaskList/index.jsx +++ b/src/pages/Dashboard/components/TaskList/index.jsx @@ -12,41 +12,43 @@ const TaskList = ({ tasks = [], selectedDate, loading }) => { } const formatDate = (date) => { - return date.toLocaleDateString('zh-CN', { - year: 'numeric', - month: 'long', - day: 'numeric' + return date.toLocaleDateString("zh-CN", { + year: "numeric", + month: "long", + day: "numeric", }); }; const getTaskTypeText = (type) => { const typeMap = { - 'HOMEWORK': '作业', - 'PROJECT': '项目', - 'REPORT': '报告', - 'INTERVIEW': '面试', - 'OTHER': '其他' + HOMEWORK: "作业", + PROJECT: "项目", + REPORT: "报告", + INTERVIEW: "面试", + OTHER: "其他", }; return typeMap[type] || type; }; - const getPriorityClass = (priority) => { - const classMap = { - 'URGENT': 'urgent', - 'HIGH': 'high', - 'MEDIUM': 'medium', - 'LOW': 'low' - }; - return classMap[priority] || 'medium'; - }; + // const getPriorityClass = (priority) => { + // const classMap = { + // URGENT: "urgent", + // HIGH: "high", + // MEDIUM: "medium", + // LOW: "low", + // }; + // return classMap[priority] || "medium"; + // }; return (

事项 - {formatDate(selectedDate)} - {tasks.length > 0 && ({tasks.length})} + {tasks.length > 0 && ( + ({tasks.length}) + )}

- + {tasks.length === 0 ? (
@@ -60,11 +62,11 @@ const TaskList = ({ tasks = [], selectedDate, loading }) => { {item?.teacherAvatar ? ( avatar ) : ( - item?.teacherName?.charAt(0) || 'T' + item?.teacherName?.charAt(0) || "T" )} - {item?.teacherName || '未知教师'} + {item?.teacherName || "未知教师"}
{ {item?.duration} - + {/* {item.status === 'PENDING' ? '待完成' : item.status === 'IN_PROGRESS' ? '进行中' : item.status === 'COMPLETED' ? '已完成' : '未知'} - + */}
diff --git a/src/pages/Dashboard/index.jsx b/src/pages/Dashboard/index.jsx index 6700863..e94f4a7 100644 --- a/src/pages/Dashboard/index.jsx +++ b/src/pages/Dashboard/index.jsx @@ -30,7 +30,7 @@ const Dashboard = () => { setDashboardData(response); } } catch (error) { - console.error('Failed to fetch dashboard data:', error); + console.error("Failed to fetch dashboard data:", error); } finally { setLoading(false); } @@ -41,11 +41,11 @@ const Dashboard = () => { if (!dashboardData?.tasks?.allTasks) return []; // Check if date is valid before calling toISOString if (!date || isNaN(date.getTime())) { - console.warn('Invalid date provided to getTasksForDate:', date); + console.warn("Invalid date provided to getTasksForDate:", date); return []; } - const dateStr = date.toISOString().split('T')[0]; - return dashboardData.tasks.allTasks.filter(task => task.date === dateStr); + const dateStr = date.toISOString().split("T")[0]; + return dashboardData.tasks.allTasks.filter((task) => task.date === dateStr); }; return ( @@ -53,29 +53,33 @@ const Dashboard = () => {
- - - - - { +const StudyStudes = ({ + studyStatistics, + learningProgress, + loading = false, +}) => { const studentInfo = useSelector((state) => state.student.studentInfo); - - console.log("StudyStudes props:", { studyStatistics, learningProgress, loading }); // 如果数据还在加载中,显示加载状态 if (loading) { @@ -25,10 +26,14 @@ const StudyStudes = ({ studyStatistics, learningProgress, loading = false }) => const personalStudyHours = studyStatistics?.studyTime?.personal ?? 0; const classAverageStudyHours = studyStatistics?.studyTime?.classAverage ?? 0; const overallProgress = learningProgress?.overallProgress ?? 0; - const personalCourseProgress = studyStatistics?.courseCompletion?.personalProgress ?? 0; - const classAverageCourseProgress = studyStatistics?.courseCompletion?.classAverageProgress ?? 0; - const personalHomeworkProgress = studyStatistics?.homeworkCompletion?.personalProgress ?? 0; - const classAverageHomeworkProgress = studyStatistics?.homeworkCompletion?.classAverageProgress ?? 0; + const personalCourseProgress = + studyStatistics?.courseCompletion?.personalProgress ?? 0; + const classAverageCourseProgress = + studyStatistics?.courseCompletion?.classAverageProgress ?? 0; + const personalHomeworkProgress = + studyStatistics?.homeworkCompletion?.personalProgress ?? 0; + const classAverageHomeworkProgress = + studyStatistics?.homeworkCompletion?.classAverageProgress ?? 0; const attendanceRate = studyStatistics?.attendance?.attendanceRate ?? 0; const absenceRate = studyStatistics?.attendance?.absenceRate ?? 0; @@ -117,7 +122,14 @@ const StudyStudes = ({ studyStatistics, learningProgress, loading = false }) => 个人学习时长(h)

- + {personalStudyHours}

@@ -153,11 +165,15 @@ const StudyStudes = ({ studyStatistics, learningProgress, loading = false }) => />

班级平均进度

- {classAverageCourseProgress}% + + {classAverageCourseProgress}% +

我的进度

- {personalCourseProgress}% + + {personalCourseProgress}% +
{/* 课后作业完成情况 */} @@ -169,11 +185,15 @@ const StudyStudes = ({ studyStatistics, learningProgress, loading = false }) => />

班级平均进度

- {classAverageHomeworkProgress}% + + {classAverageHomeworkProgress}% +

我的进度

- {personalHomeworkProgress}% + + {personalHomeworkProgress}% +
{/* 考勤情况 */} @@ -189,11 +209,15 @@ const StudyStudes = ({ studyStatistics, learningProgress, loading = false }) =>

出勤率

- {attendanceRate}% + + {attendanceRate}% +

缺勤率

- {absenceRate}% + + {absenceRate}% +
diff --git a/src/pages/PersonalProfile/index.jsx b/src/pages/PersonalProfile/index.jsx index 21e3ce9..ba389eb 100644 --- a/src/pages/PersonalProfile/index.jsx +++ b/src/pages/PersonalProfile/index.jsx @@ -1,4 +1,4 @@ -import { useState, useEffect } from "react"; +import { useState, useEffect, useCallback } from "react"; import { useDispatch } from "react-redux"; import ProfileCard from "./components/ProfileCard"; import Rank from "@/components/Rank"; @@ -14,37 +14,33 @@ const PersonalProfile = () => { const [loading, setLoading] = useState(true); // 获取个人档案完整数据 - const queryProfileOverview = async () => { + const queryProfileOverview = useCallback(async () => { try { setLoading(true); - console.log("Fetching profile overview..."); const res = await getProfileOverview(); - console.log("Profile overview response:", res); - if (res.success) { const data = res.data; - + // 更新Redux中的学生信息 const studentInfo = { ...data.studentInfo, myRank: data.ranking.myRank, classInfo: data.ranking.classInfo, }; - + setProfileData(data); dispatch(updateStudentInfo(studentInfo)); - console.log("Profile data set:", data); } } catch (error) { console.error("Failed to fetch profile overview:", error); } finally { setLoading(false); } - }; + }, [dispatch]); useEffect(() => { queryProfileOverview(); - }, []); + }, [queryProfileOverview]); return (
@@ -54,18 +50,22 @@ const PersonalProfile = () => {
-
- { }; const handleProjectClick = (item) => { + console.log(item); setModalData(item); setProjectCasesModalVisible(true); }; @@ -36,13 +36,11 @@ const ProjectLibrary = () => { const fetchProjects = async (searchValue = "", pageNum) => { try { - // 这里使用真实API替换模拟数据 const res = await getProjectsList({ search: searchValue, page: pageNum ?? page, pageSize: PAGE_SIZE, }); - console.log(res); if (res.success) { setProjectList((prevList) => { const newList = [...prevList, ...res.data]; diff --git a/src/pages/ResumeInterviewPage/components/InterviewQuestionsModal/index.jsx b/src/pages/ResumeInterviewPage/components/InterviewQuestionsModal/index.jsx index b8e4069..c3443f6 100644 --- a/src/pages/ResumeInterviewPage/components/InterviewQuestionsModal/index.jsx +++ b/src/pages/ResumeInterviewPage/components/InterviewQuestionsModal/index.jsx @@ -1,4 +1,3 @@ -import { useState } from "react"; import Modal from "@/components/Modal"; import "./index.css"; @@ -7,35 +6,31 @@ export default ({ visible, onClose, data }) => { onClose(); }; - if (!data) return null; - - const { question } = data; - return (
-

{data.name}面试题

+

{data?.name}面试题

在1V1定制求职策略阶段,企业HR会为您讲解面试题

  • - 问题:{question.question} + 问题: + {data?.question?.question}

    解答: - 这是一个{question.difficulty.toLowerCase()}难度的{question.category}相关问题。 - 针对这类问题,建议从以下几个方面来回答: - 1. 理解问题的核心概念和背景 - 2. 结合实际项目经验进行说明 - 3. 展示对相关技术的深入理解 - 4. 提及可能的优化或改进方案 + 这是一个{data?.question?.difficulty?.toLowerCase()}难度的 + {data?.question?.category}相关问题。 + 针对这类问题,建议从以下几个方面来回答: 1. + 理解问题的核心概念和背景 2. 结合实际项目经验进行说明 3. + 展示对相关技术的深入理解 4. 提及可能的优化或改进方案

); -}; \ No newline at end of file +}; diff --git a/src/pages/ResumeInterviewPage/index.css b/src/pages/ResumeInterviewPage/index.css index 43b51c1..2756e3a 100644 --- a/src/pages/ResumeInterviewPage/index.css +++ b/src/pages/ResumeInterviewPage/index.css @@ -41,63 +41,6 @@ font-weight: 600; text-align: center; } - - .search-container { - position: relative; - display: flex; - align-items: center; - } - - .search-input { - width: 200px; - height: 32px; - padding: 0 35px 0 12px; - border: 1px solid #e5e8ed; - border-radius: 16px; - font-size: 14px; - outline: none; - transition: border-color 0.3s; - - &::placeholder { - color: #86909c; - } - - &:focus { - border-color: #2c7aff; - box-shadow: 0 0 0 2px rgba(44, 122, 255, 0.1); - } - } - - .search-icon { - position: absolute; - right: 10px; - width: 16px; - height: 16px; - background-color: #86909c; - mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2'%3E%3Ccircle cx='11' cy='11' r='8'/%3E%3Cpath d='m21 21-4.35-4.35'/%3E%3C/svg%3E") center/contain no-repeat; - pointer-events: none; - } - - .clear-button { - position: absolute; - right: 8px; - width: 20px; - height: 20px; - background: none; - border: none; - cursor: pointer; - display: flex; - align-items: center; - justify-content: center; - color: #86909c; - font-size: 14px; - opacity: 0.7; - transition: opacity 0.3s; - - &:hover { - opacity: 1; - } - } } .resume-interview-content-wrapper { @@ -312,4 +255,4 @@ } } } -} \ No newline at end of file +} diff --git a/src/pages/ResumeInterviewPage/index.jsx b/src/pages/ResumeInterviewPage/index.jsx index 55e6449..325133b 100644 --- a/src/pages/ResumeInterviewPage/index.jsx +++ b/src/pages/ResumeInterviewPage/index.jsx @@ -1,6 +1,7 @@ import { useRef, useState, useEffect } from "react"; +import toast from "@/components/Toast"; import InterviewQuestionsModal from "./components/InterviewQuestionsModal"; -import ResumeModal from "./components/ResumeModal"; +import ResumeInfoModal from "@/pages/CompanyJobsPage/components/ResumeInfoModal"; import { getPageData } from "@/services/resumeInterview"; import "./index.css"; @@ -13,7 +14,6 @@ const ResumeInterviewPage = () => { const [resumeModalData, setResumeModalData] = useState(undefined); const [pageData, setPageData] = useState(null); const [loading, setLoading] = useState(true); - const [searchTerm, setSearchTerm] = useState(""); const sectionsRef = useRef({}); // 导航到指定行业段落 @@ -27,19 +27,24 @@ const ResumeInterviewPage = () => { // 面试题点击处理 const handleQuestionClick = (item) => { - setInterviewModalData(item); - setInterviewModalVisible(true); + if (item) { + setInterviewModalVisible(true); + setInterviewModalData(item); + } else { + toast.error("加载数据失败"); + } }; // 职位点击处理 const handlePositionClick = (position, industry) => { // Find resume templates for this industry const templates = pageData.resumeTemplates[industry.name] || []; - const selectedTemplate = templates.find(t => t.level === position.level) || templates[0]; - + const selectedTemplate = + templates.find((t) => t.level === position.level) || templates[0]; + setResumeModalData({ selectedTemplate, - studentResume: pageData.myResume + studentResume: pageData.myResume, }); setResumeModalVisible(true); }; @@ -54,21 +59,8 @@ const ResumeInterviewPage = () => { setResumeModalData(undefined); }; - // Search functionality - const handleSearchChange = (e) => { - setSearchTerm(e.target.value); - }; - - const handleClearSearch = () => { - setSearchTerm(""); - }; - - // Filter positions based on search term const filterPositions = (positions) => { - if (!searchTerm.trim()) return positions; - return positions.filter(position => - position.name.toLowerCase().includes(searchTerm.toLowerCase()) - ); + return positions.filter((position) => position.name.toLowerCase()); }; // 获取页面数据 @@ -150,21 +142,6 @@ const ResumeInterviewPage = () => { ))}
-
- - {searchTerm && ( - - )} - {!searchTerm &&
} -
    {pageData.industries.map((item) => ( @@ -178,8 +155,8 @@ const ResumeInterviewPage = () => {
      {filterPositions(item.positions).map((position) => ( -
    • handlePositionClick(position, item)} > @@ -190,11 +167,6 @@ const ResumeInterviewPage = () => {
    ))} - {searchTerm && filterPositions(item.positions).length === 0 && ( -
  • -

    未找到匹配的职位

    -
  • - )}
    {item.questions.map((question) => ( @@ -216,7 +188,7 @@ const ResumeInterviewPage = () => { onClose={handleCloseInterviewModal} data={interviewModalData} /> - { ); }; -export default ResumeInterviewPage; \ No newline at end of file +export default ResumeInterviewPage;