feat: 优化教务系统多项功能

主要更新:
1. 项目库功能优化
   - 添加项目效果图点击预览功能,支持图片放大查看和切换
   - 新增ImagePreviewModal组件,提供完整的图片预览体验

2. 企业内推岗位页面改进
   - 右侧岗位面试状态卡片支持点击查看岗位详情
   - 从企业内推岗位库直接导入岗位数据
   - 面试状态查看的岗位详情隐藏投递按钮
   - 岗位要求显示优化,添加数字编号格式

3. 课堂作业板块完善
   - 修复垂直能力课只显示4个单元的问题,现可显示全部12个单元
   - 为"展会主题与品牌定位"课程添加"可试看"标签
   - 调整"可试看"标签位置,避免遮挡课程名称
   - 在全部视图中将"展会主题与品牌定位"课程置顶

4. 课程直播间页面优化
   - 为复合能力课添加文字虚线分割线,与垂直能力课保持一致
   - 删除页面顶部的进度条,简化界面

🤖 Generated with Claude Code

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
KQL
2025-09-08 11:00:54 +08:00
parent 9a14678a12
commit 9198c67caf
13 changed files with 1753 additions and 35 deletions

View File

@@ -13,7 +13,7 @@ import "./index.css";
const InputSearch = Input.Search;
const PAGE_SIZE = 10;
export default ({ visible, onClose, data, directToResume = false }) => {
export default ({ visible, onClose, data, directToResume = false, hideDeliverButton = false }) => {
const studentInfo = useSelector((state) => state.student.studentInfo);
const [resumeModalShow, setResumeModalShow] = useState(directToResume);
const [resumeInfoModalShow, setResumeInfoModalShow] = useState(false);
@@ -260,10 +260,11 @@ export default ({ visible, onClose, data, directToResume = false }) => {
</div>
))
) : (
data?.details?.requirementsText?.split('\n').map((line, index) => (
<p key={index} className="requirement-line">
{line}
</p>
data?.details?.requirementsText?.split(/\d+\.\s*/).filter(item => item.trim()).map((item, index) => (
<div key={index} className="requirements-item">
<span className="requirement-number">{index + 1}.</span>
<span className="requirement-text">{item.trim()}</span>
</div>
))
)}
</div>
@@ -281,13 +282,15 @@ export default ({ visible, onClose, data, directToResume = false }) => {
</div>
</div>
)}
<div
className="job-info-modal-btn"
onClick={handleClickDeliverBtn}
>
<i />
<span>立即投递</span>
</div>
{!hideDeliverButton && (
<div
className="job-info-modal-btn"
onClick={handleClickDeliverBtn}
>
<i />
<span>立即投递</span>
</div>
)}
</>
)}
</div>

View File

@@ -7,11 +7,14 @@ import InfiniteScroll from "@/components/InfiniteScroll";
import toast from "@/components/Toast";
import JobList from "./components/JobList";
import InterviewStatusAnimation from "./components/InterviewStatusAnimation";
import JobInfoModal from "./components/JobInfoModal";
import {
getCompanyJobsPageData,
getJobsList,
getInterviewsList,
getJobsDetail,
} from "@/services";
import { getJobByPosition } from "@/services/companyJobsNew";
import "./index.css";
const PAGE_SIZE = 10;
@@ -27,6 +30,9 @@ const CompanyJobsPage = () => {
const [initialDataLoaded, setInitialDataLoaded] = useState(false);
const [loading, setLoading] = useState(true);
const [expandedItemId, setExpandedItemId] = useState(null);
const [jobDetailVisible, setJobDetailVisible] = useState(false);
const [selectedJob, setSelectedJob] = useState(null);
const [isFromInterview, setIsFromInterview] = useState(false); // 标识是否从面试状态卡片点击
const navigate = useNavigate();
// 初始化页面数据 - 使用聚合接口
@@ -181,6 +187,24 @@ const CompanyJobsPage = () => {
navigate("/company-jobs-list");
};
// 处理岗位卡片点击,显示岗位详情
const handleJobCardClick = async (item) => {
// 直接从企业内推岗位库中查找对应的岗位
if (item.position) {
const jobData = getJobByPosition(item.position);
if (jobData) {
setSelectedJob(jobData);
setIsFromInterview(true); // 标记是从面试状态卡片点击的
setJobDetailVisible(true);
} else {
toast.error("未找到对应的岗位详情");
}
} else {
toast.error("无法获取岗位详情");
}
};
return (
<div className="company-jobs-page-wrapper">
<div className="company-jobs-page">
@@ -245,7 +269,11 @@ const CompanyJobsPage = () => {
>
{interviews.map((item) => (
<div key={item.id} className="interview-item-wrapper">
<li className="company-jobs-page-interview-item">
<li
className="company-jobs-page-interview-item"
onClick={() => handleJobCardClick(item)}
style={{ cursor: 'pointer' }}
>
<div className="company-jobs-page-interview-item-info">
<p className="company-jobs-page-interview-item-info-position">
{item.position}
@@ -293,6 +321,18 @@ const CompanyJobsPage = () => {
)}
</div>
{/* 岗位详情弹窗 */}
<JobInfoModal
visible={jobDetailVisible}
onClose={() => {
setJobDetailVisible(false);
setSelectedJob(null);
setIsFromInterview(false); // 重置标志
}}
data={selectedJob}
directToResume={false}
hideDeliverButton={isFromInterview} // 传递是否隐藏投递按钮的标志
/>
</div>
);
};