主要更新: - 更新所有12个产业的教务系统数据和功能 - 删除所有 node_modules 文件夹(节省3.7GB) - 删除所有 .yoyo 缓存文件夹(节省1.2GB) - 删除所有 dist 构建文件(节省55MB) 项目优化: - 项目大小从 8.1GB 减少到 3.2GB(节省60%空间) - 保留完整的源代码和配置文件 - .gitignore 已配置,防止再次提交大文件 启动脚本: - start-industry.sh/bat/ps1 脚本会自动检测并安装依赖 - 首次启动时自动运行 npm install - 支持单个或批量启动产业系统 🤖 Generated with Claude Code Co-Authored-By: Claude <noreply@anthropic.com>
248 lines
9.0 KiB
JavaScript
248 lines
9.0 KiB
JavaScript
import { useEffect, useRef, useState } from "react";
|
||
import { Tooltip } from "@arco-design/web-react";
|
||
import { IconArrowLeft } from "@arco-design/web-react/icon";
|
||
import { mockData } from "@/data/mockData";
|
||
import ICON1 from "@/assets/images/HomeworkPage/homework_page_icon1.png";
|
||
import ICON2 from "@/assets/images/HomeworkPage/homework_page_icon2.png";
|
||
import "./index.css";
|
||
|
||
const HomeworkPage = () => {
|
||
const { homework } = mockData;
|
||
const scrollContainerRef = useRef(null);
|
||
const verticalScrollContainerRef = useRef(null);
|
||
const unitNavRefs = useRef({});
|
||
const [showIframe, setShowIframe] = useState(false);
|
||
const [selectedHomework, setSelectedHomework] = useState(null);
|
||
const [selectedUnits, setSelectedUnits] = useState({
|
||
1: "全部", // 复合能力课的选中单元
|
||
2: "全部" // 垂直能力课的选中单元
|
||
});
|
||
|
||
// 调试:打印课程数量
|
||
console.log('作业数据:', homework);
|
||
if (homework && homework[0]) {
|
||
console.log('复合能力培养课程数量:', homework[0].list.length);
|
||
}
|
||
|
||
// 添加鼠标滚轮横向滚动支持(更丝滑的滚动)
|
||
useEffect(() => {
|
||
// 如果显示iframe,不初始化滚动
|
||
if (showIframe) return;
|
||
|
||
// 收集所有需要横向滚动的容器
|
||
const unitNavContainers = Object.values(unitNavRefs.current).filter(Boolean);
|
||
const containers = [scrollContainerRef.current, verticalScrollContainerRef.current, ...unitNavContainers].filter(Boolean);
|
||
if (containers.length === 0) return;
|
||
|
||
const animationIds = new Map();
|
||
const targetScrollLefts = new Map();
|
||
const handlers = new Map();
|
||
|
||
containers.forEach(container => {
|
||
targetScrollLefts.set(container, container.scrollLeft);
|
||
|
||
// 平滑滚动动画
|
||
const smoothScroll = () => {
|
||
const currentScrollLeft = container.scrollLeft;
|
||
const targetScrollLeft = targetScrollLefts.get(container);
|
||
const diff = targetScrollLeft - currentScrollLeft;
|
||
|
||
if (Math.abs(diff) > 0.5) {
|
||
container.scrollLeft = currentScrollLeft + diff * 0.15; // 缓动系数
|
||
const animId = requestAnimationFrame(smoothScroll);
|
||
animationIds.set(container, animId);
|
||
} else {
|
||
container.scrollLeft = targetScrollLeft;
|
||
const animId = animationIds.get(container);
|
||
if (animId) {
|
||
cancelAnimationFrame(animId);
|
||
animationIds.delete(container);
|
||
}
|
||
}
|
||
};
|
||
|
||
// 鼠标滚轮横向滚动
|
||
const handleWheel = (e) => {
|
||
e.preventDefault();
|
||
|
||
// 计算滚动距离,使用较小的值让滚动更平滑
|
||
const scrollAmount = e.deltaY * 0.8;
|
||
let newTargetScrollLeft = targetScrollLefts.get(container) + scrollAmount;
|
||
|
||
// 限制滚动范围
|
||
newTargetScrollLeft = Math.max(0, Math.min(newTargetScrollLeft, container.scrollWidth - container.clientWidth));
|
||
targetScrollLefts.set(container, newTargetScrollLeft);
|
||
|
||
// 如果没有正在进行的动画,启动平滑滚动
|
||
if (!animationIds.has(container)) {
|
||
const animId = requestAnimationFrame(smoothScroll);
|
||
animationIds.set(container, animId);
|
||
}
|
||
};
|
||
|
||
handlers.set(container, handleWheel);
|
||
container.addEventListener('wheel', handleWheel, { passive: false });
|
||
});
|
||
|
||
return () => {
|
||
containers.forEach(container => {
|
||
const handleWheel = handlers.get(container);
|
||
if (handleWheel) {
|
||
container.removeEventListener('wheel', handleWheel);
|
||
}
|
||
const animId = animationIds.get(container);
|
||
if (animId) {
|
||
cancelAnimationFrame(animId);
|
||
}
|
||
});
|
||
};
|
||
}, [showIframe]);
|
||
|
||
const handleClickBtn = (sectionId, item) => {
|
||
// 垂直能力课中标记为isShowCase的课程可以点击
|
||
if (sectionId === 2 && item.isShowCase) {
|
||
setSelectedHomework(item);
|
||
setShowIframe(true);
|
||
}
|
||
};
|
||
|
||
// 判断是否应该显示灰色图片和禁用按钮
|
||
const isDisabled = (sectionId, item) => {
|
||
// 垂直能力课中标记为isShowCase的课程是启用状态
|
||
if (sectionId === 2 && item.isShowCase) {
|
||
return false;
|
||
}
|
||
return true;
|
||
};
|
||
|
||
// 如果显示iframe,渲染全页面的iframe
|
||
if (showIframe) {
|
||
return (
|
||
<div className="homework-page-iframe-wrapper">
|
||
<div className="homework-page-iframe-header">
|
||
<button
|
||
className="homework-page-return-btn"
|
||
onClick={() => setShowIframe(false)}
|
||
>
|
||
<IconArrowLeft style={{ marginRight: '8px' }} />
|
||
返回课后作业
|
||
</button>
|
||
<span className="homework-page-iframe-title">{selectedHomework?.name}</span>
|
||
</div>
|
||
<iframe
|
||
src={selectedHomework?.previewUrl}
|
||
className="homework-page-iframe-content"
|
||
title={selectedHomework?.name}
|
||
style={{ zoom: 0.8 }}
|
||
/>
|
||
</div>
|
||
);
|
||
}
|
||
|
||
// 获取筛选后的课程列表
|
||
const getFilteredCourses = (sectionId) => {
|
||
const section = homework.find(h => h.id === sectionId);
|
||
if (!section) return [];
|
||
|
||
const selectedUnit = selectedUnits[sectionId];
|
||
|
||
// 如果有units结构,使用新结构
|
||
if (section.units) {
|
||
if (selectedUnit === "全部") {
|
||
// 将所有单元的课程合并
|
||
const allCourses = section.units.flatMap(unit => unit.courses);
|
||
|
||
// 将可试看的课程排在前面
|
||
const previewCourses = allCourses.filter(course => course.isShowCase);
|
||
const otherCourses = allCourses.filter(course => !course.isShowCase);
|
||
return [...previewCourses, ...otherCourses];
|
||
} else {
|
||
// 返回选中单元的课程
|
||
const unit = section.units.find(u => u.name === selectedUnit);
|
||
if (!unit) return [];
|
||
|
||
// 将可试看的课程排在前面
|
||
const previewCourses = unit.courses.filter(course => course.isShowCase);
|
||
const otherCourses = unit.courses.filter(course => !course.isShowCase);
|
||
return [...previewCourses, ...otherCourses];
|
||
}
|
||
}
|
||
|
||
// 兼容旧结构
|
||
return section.list || [];
|
||
};
|
||
|
||
// 正常渲染作业列表
|
||
return (
|
||
<div className="homework-page-wrapper">
|
||
<ul className="homework-page-content">
|
||
{homework.map((item) => (
|
||
<li key={item.id} className="homework-page-content-list">
|
||
<div className="homework-page-content-list-header">
|
||
<p className="homework-page-content-list-title">{item.name}</p>
|
||
</div>
|
||
{item.units && (
|
||
<div
|
||
className="homework-page-unit-nav"
|
||
ref={el => unitNavRefs.current[item.id] = el}
|
||
>
|
||
<span
|
||
className={`unit-nav-item ${selectedUnits[item.id] === "全部" ? "active" : ""}`}
|
||
onClick={() => setSelectedUnits({...selectedUnits, [item.id]: "全部"})}
|
||
>
|
||
全部
|
||
</span>
|
||
{item.units.map((unit, index) => (
|
||
<span
|
||
key={index}
|
||
className={`unit-nav-item ${selectedUnits[item.id] === unit.name ? "active" : ""}`}
|
||
onClick={() => setSelectedUnits({...selectedUnits, [item.id]: unit.name})}
|
||
>
|
||
{unit.name}
|
||
</span>
|
||
))}
|
||
</div>
|
||
)}
|
||
<ul
|
||
className="homework-page-content-list-class"
|
||
ref={item.id === 1 ? scrollContainerRef : item.id === 2 ? verticalScrollContainerRef : null}
|
||
>
|
||
{getFilteredCourses(item.id).map((contentItem) => (
|
||
<li
|
||
key={contentItem.id}
|
||
className="homework-page-content-list-content-item"
|
||
>
|
||
<img
|
||
alt="icon"
|
||
src={ICON1}
|
||
className="homework-page-content-list-content-item-icon"
|
||
/>
|
||
<Tooltip content={contentItem.name} position="top">
|
||
<p className="homework-page-content-list-content-item-name">
|
||
{contentItem.name}
|
||
</p>
|
||
</Tooltip>
|
||
<div className="homework-page-content-list-content-item-action">
|
||
<div
|
||
className={`homework-page-content-list-content-item-btn ${
|
||
isDisabled(item.id, contentItem) ? "disabled" : "completed"
|
||
}`}
|
||
onClick={() => !isDisabled(item.id, contentItem) && handleClickBtn(item.id, contentItem)}
|
||
>
|
||
已完成
|
||
</div>
|
||
{contentItem.isShowCase && (
|
||
<span className="homework-page-preview-tag">可试看</span>
|
||
)}
|
||
</div>
|
||
</li>
|
||
))}
|
||
</ul>
|
||
</li>
|
||
))}
|
||
</ul>
|
||
</div>
|
||
);
|
||
};
|
||
|
||
export default HomeworkPage; |