更新12个教务系统并优化项目大小

主要更新:
- 更新所有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>
This commit is contained in:
KQL
2025-10-17 14:36:25 +08:00
parent 60921dbfb9
commit 38350dca36
792 changed files with 470498 additions and 11589 deletions

View File

@@ -0,0 +1,806 @@
# 课程可试看功能完整指南
**文档版本**: v2.0
**最后更新**: 2025-10-14
**适用项目**: 环保产业教务系统前端
---
## 📋 目录
1. [功能概述](#功能概述)
2. [iframe嵌入升级历史](#iframe嵌入升级历史)
3. [快速开始](#快速开始)
4. [详细配置步骤](#详细配置步骤)
5. [完整示例](#完整示例)
6. [技术实现说明](#技术实现说明)
7. [常见问题](#常见问题)
8. [验证清单](#验证清单)
---
## 功能概述
### 什么是"可试看"功能?
- 允许特定课程显示"可试看"标签
- 点击课程后通过**iframe嵌入**展示课程内容(**不是新建页面跳转**
- 非可试看课程显示锁定状态
- 可试看课程会自动排在课程列表最前面
### ⚡ 重要说明iframe嵌入功能已升级
**本项目已升级为iframe嵌入方式完全复用了文旅项目的实现**
#### 原始实现(已废弃)
- ❌ 点击可试看课程后打开**新的浏览器窗口**(使用 `window.open`
- ❌ 用户离开教务系统页面
- ❌ 需要手动切换标签页返回
- ❌ 用户体验不连贯
#### 当前实现(已升级)
- ✅ 点击可试看课程后在**当前页面内通过iframe嵌入**显示
- ✅ 用户始终停留在教务系统内
- ✅ 有专门的返回按钮或全屏功能
- ✅ 与文旅项目完全一致的交互体验
#### 当前功能特性
**课程直播间**
- 点击可试看课程后课程内容会在视频播放区域通过iframe嵌入显示
- 支持全屏功能(右上角有全屏按钮)
- iframe自动缩放zoom: 0.5
- 非可试看课程显示模糊背景+锁定图标
- **不再打开新窗口**
**课程作业页面**
- 点击"已完成"按钮后作业页面会全屏通过iframe嵌入显示
- 顶部有"返回课后作业"按钮
- 显示课程标题
- iframe自动缩放zoom: 0.8
- **不再打开新窗口**
### 您只需要做什么?
**只需修改一个文件**`src/data/mockData.js`
**配置两个字段**
- `canPreview`: 设置为 `true`
- `previewUrl`: 设置iframe要显示的URL
**其余功能iframe嵌入、全屏、返回按钮等已全部自动实现**
---
## iframe嵌入升级历史
### 升级信息
**升级日期**2025-10-14
**升级目的**将原始的新窗口跳转方式改为iframe嵌入提升用户体验
**参考项目**:文旅产业教务系统
### 原始版本的问题
**课程直播间**
```javascript
// 原始代码(已移除)
window.open(course.previewUrl, '_blank');
```
**课程作业**
```javascript
// 原始代码(已移除)
setShowIframe(true); // 使用固定URL
// 硬编码标题和URL
```
**存在的问题**
- ❌ 打开新的浏览器窗口
- ❌ 用户离开教务系统页面
- ❌ 需要手动切换标签页
- ❌ 用户体验割裂
### 当前版本的改进
**改进的文件**
1. `src/components/CoursesVideoPlayer/index.jsx` - 课程直播间iframe嵌入
2. `src/pages/HomeworkPage/index.jsx` - 课程作业动态iframe
3. `src/components/CourseList/index.jsx` - 移除window.open代码
**新增功能**
- ✅ 完整的Fullscreen API支持课程直播间
- ✅ 跨浏览器兼容Chrome、Firefox、Safari、Edge
- ✅ 动态iframe数据管理课程作业
- ✅ 可试看课程自动排序
- ✅ 与文旅项目完全一致的交互体验
### 升级效果对比
| 功能 | 原始版本 | 当前版本 |
|------|---------|---------|
| **课程直播间** | | |
| 展示方式 | window.open新窗口 | iframe嵌入 |
| 全屏功能 | ❌ 无 | ✅ 右上角全屏按钮 |
| 缩放适配 | ❌ 无 | ✅ zoom: 0.5全屏1.0 |
| 浏览器兼容 | ❌ 不完善 | ✅ 全浏览器支持 |
| **课程作业** | | |
| URL来源 | 硬编码 | 动态获取 |
| 课程标题 | 固定文本 | 动态显示 |
| 支持课程数 | 1个 | 无限 |
| 状态管理 | boolean | 数据对象 |
| **用户体验** | | |
| 页面跳转 | ✅ 打开新窗口 | ❌ 无跳转 |
| 用户留存 | ❌ 离开系统 | ✅ 停留系统内 |
| 交互流畅度 | ⭐⭐ | ⭐⭐⭐⭐⭐ |
---
## 快速开始
### 配置位置速查
只需修改 **一个文件**`src/data/mockData.js`
**位置1: 课程直播间约第680行**
```javascript
// 搜索这段注释找到位置
// 为"水质样品的采样与保存"课程添加试看标签和链接
```
**位置2: 课程作业约第5325行**
```javascript
// 搜索这段注释找到位置
// 为水质样品的采样与保存课程添加可试看标记
```
### 配置模板
#### 课程直播间配置
```javascript
// 为"您的课程名称"添加试看标签和链接
if (event.title === "课程名称" && unitName === "单元名称") {
courseObj.canPreview = true;
courseObj.previewUrl = "课程iframe嵌入URL";
}
```
#### 课程作业配置
```javascript
// 为"您的课程名称"作业添加可试看标记
if (course.courseName === "课程名称" && unit.unitName === "单元名称") {
homeworkItem.canPreview = true;
homeworkItem.previewUrl = "作业iframe嵌入URL";
}
```
### 配置参数说明
| 字段 | 类型 | 说明 | 示例 |
|------|------|------|------|
| `event.title` / `course.courseName` | string | 课程名称(必须完全匹配) | `"水质样品的采样与保存"` |
| `unitName` / `unit.unitName` | string | 单元名称(必须完全匹配) | `"检验检测实用取样方法"` |
| `canPreview` | boolean | 是否可试看(固定值) | `true` |
| `previewUrl` | string | 预览URLiframe地址 | `"https://example.com/course"` |
### ⚠️ 重要注意事项
1. **课程名称和单元名称必须完全匹配**
- 包括中英文标点符号、空格等
- 大小写必须一致
- 如果名称不匹配,可试看功能不会生效
2. **URL必须支持iframe嵌入**
- 某些网站设置了X-Frame-Options禁止iframe嵌入
- 确保URL可以在浏览器中正常访问
3. **课程作业的URL通常与课程直播间的URL不同**
- 课程直播间课程内容的URL
- 课程作业作业页面的URL
---
## 详细配置步骤
### 步骤1: 找到课程名称和单元名称
#### 方法1查看页面显示
直接在课程列表中查看显示的课程名称和单元名称
#### 方法2使用浏览器控制台
```javascript
// 在浏览器控制台执行
console.log(mockData.courseLiveData.vertical);
console.log(mockData.homework);
```
#### 方法3在代码中搜索
`src/data/mockData.js` 中搜索课程相关的关键词
### 步骤2: 配置课程直播间
`src/data/mockData.js` 文件中找到 `generateVerticalCourseLiveList` 函数。
找到这个位置大约在第680行左右
```javascript
// 为"水质样品的采样与保存"课程添加试看标签和链接
if (event.title === "水质样品的采样与保存" && unitName === "检验检测实用取样方法") {
courseObj.canPreview = true;
courseObj.previewUrl = "https://du9uay.github.io/environment-education-web/";
}
```
在上述代码**之后**,添加新的判断条件:
```javascript
// 为"您的课程名称"添加试看标签和链接
if (event.title === "您的课程名称" && unitName === "单元名称") {
courseObj.canPreview = true;
courseObj.previewUrl = "您的iframe嵌入URL";
}
```
### 步骤3: 配置课程作业
`src/data/mockData.js` 文件中,搜索这段注释:
```javascript
// 为水质样品的采样与保存课程添加可试看标记
```
找到这个位置大约在第5325行左右
```javascript
// 为水质样品的采样与保存课程添加可试看标记
if (course.courseName === "水质样品的采样与保存" && unit.unitName === "检验检测实用取样方法") {
homeworkItem.canPreview = true;
homeworkItem.previewUrl = "https://du9uay.github.io/environment-education-web/#/course-test";
}
```
在上述代码**之后**,添加新的判断条件:
```javascript
// 为"您的课程名称"作业添加可试看标记
if (course.courseName === "您的课程名称" && unit.unitName === "单元名称") {
homeworkItem.canPreview = true;
homeworkItem.previewUrl = "您的作业iframe嵌入URL";
}
```
### 步骤4: 保存并验证
1. 保存 `mockData.js` 文件
2. 刷新浏览器页面Vite会自动热更新
3. 使用验证清单检查功能是否正常
---
## 完整示例
### 示例1为"环境监测技术"课程添加可试看功能
假设要添加的课程信息:
- 课程名称:`环境监测技术`
- 单元名称:`环境监测基础`
- 课程直播URL`https://example.com/course/monitor`
- 作业页面URL`https://example.com/homework/monitor`
#### 配置课程直播间
`src/data/mockData.js` 的约第680行位置添加
```javascript
// 为"水质样品的采样与保存"课程添加试看标签和链接
if (event.title === "水质样品的采样与保存" && unitName === "检验检测实用取样方法") {
courseObj.canPreview = true;
courseObj.previewUrl = "https://du9uay.github.io/environment-education-web/";
}
// 为"环境监测技术"课程添加试看标签和链接
if (event.title === "环境监测技术" && unitName === "环境监测基础") {
courseObj.canPreview = true;
courseObj.previewUrl = "https://example.com/course/monitor";
}
```
#### 配置课程作业
`src/data/mockData.js` 的约第5325行位置添加
```javascript
// 为水质样品的采样与保存课程添加可试看标记
if (course.courseName === "水质样品的采样与保存" && unit.unitName === "检验检测实用取样方法") {
homeworkItem.canPreview = true;
homeworkItem.previewUrl = "https://du9uay.github.io/environment-education-web/#/course-test";
}
// 为"环境监测技术"课程作业添加可试看标记
if (course.courseName === "环境监测技术" && unit.unitName === "环境监测基础") {
homeworkItem.canPreview = true;
homeworkItem.previewUrl = "https://example.com/homework/monitor";
}
```
#### 验证配置
1. 保存文件
2. 刷新浏览器
3. 检查:
- ✅ 课程列表中"环境监测技术"显示在最前面
- ✅ 课程右侧显示"可试看"蓝色标签
- ✅ 点击课程后在视频区域显示iframe不打开新窗口
- ✅ 课程作业页面也显示"可试看"标签
- ✅ 点击作业后全屏显示iframe不打开新窗口
### 示例2批量添加多个可试看课程
如果要为多个课程添加可试看功能,只需要重复添加判断条件:
```javascript
// 课程直播间 - 批量添加
if (event.title === "水质样品的采样与保存" && unitName === "检验检测实用取样方法") {
courseObj.canPreview = true;
courseObj.previewUrl = "https://du9uay.github.io/environment-education-web/";
}
if (event.title === "环境监测技术" && unitName === "环境监测基础") {
courseObj.canPreview = true;
courseObj.previewUrl = "https://example.com/course/monitor";
}
if (event.title === "大气污染控制" && unitName === "污染控制技术") {
courseObj.canPreview = true;
courseObj.previewUrl = "https://example.com/course/air";
}
```
```javascript
// 课程作业 - 批量添加
if (course.courseName === "水质样品的采样与保存" && unit.unitName === "检验检测实用取样方法") {
homeworkItem.canPreview = true;
homeworkItem.previewUrl = "https://du9uay.github.io/environment-education-web/#/course-test";
}
if (course.courseName === "环境监测技术" && unit.unitName === "环境监测基础") {
homeworkItem.canPreview = true;
homeworkItem.previewUrl = "https://example.com/homework/monitor";
}
if (course.courseName === "大气污染控制" && unit.unitName === "污染控制技术") {
homeworkItem.canPreview = true;
homeworkItem.previewUrl = "https://example.com/homework/air";
}
```
---
## 技术实现说明
### iframe嵌入与新窗口跳转的区别
#### 新窗口跳转(原始方式 - 已废弃)
```javascript
// 原始代码(已移除)
window.open(url, '_blank');
```
**表现**
- 点击课程后打开新的浏览器标签页
- 用户离开当前教务系统页面
- 需要手动切换标签页返回
- 用户体验不连贯
#### iframe嵌入当前实现
```javascript
// 当前实现
<iframe src={url} />
```
**表现**
- 点击课程后在当前页面内显示课程内容
- 用户始终停留在教务系统内
- 有明确的返回按钮或关闭方式
- 用户体验流畅连贯
### 实现细节
#### 1. 课程直播间iframe嵌入
**实现位置**`src/components/CoursesVideoPlayer/index.jsx`
**核心代码**
```jsx
// 状态管理
const [isFullscreen, setIsFullscreen] = useState(false);
const iframeContainerRef = useRef(null);
// 全屏处理
const handleFullscreen = () => {
const container = iframeContainerRef.current;
if (!container) return;
if (!isFullscreen) {
// 进入全屏 - 支持多浏览器
if (container.requestFullscreen) {
container.requestFullscreen();
} else if (container.webkitRequestFullscreen) {
container.webkitRequestFullscreen();
}
// ... 其他浏览器前缀
} else {
// 退出全屏
if (document.exitFullscreen) {
document.exitFullscreen();
}
// ... 其他浏览器前缀
}
};
// 渲染逻辑
{selectedCourse.canPreview && selectedCourse.previewUrl ? (
<div ref={iframeContainerRef}>
<iframe
src={selectedCourse.previewUrl}
style={{
width: '100%',
height: '100%',
zoom: isFullscreen ? 1 : 0.5
}}
allowFullScreen
/>
<button onClick={handleFullscreen}>
{isFullscreen ? '退出全屏' : '全屏'}
</button>
</div>
) : (
<Locked /> // 锁定状态
)}
```
**功能特点**
- ✅ 自动检测 `canPreview``previewUrl`
- ✅ 在视频区域嵌入iframe
- ✅ 支持全屏使用Fullscreen API
- ✅ 跨浏览器兼容
- ✅ 自动缩放适配zoom: 0.5全屏时1.0
- ✅ 右上角全屏按钮带SVG图标
#### 2. 课程作业页面iframe嵌入
**实现位置**`src/pages/HomeworkPage/index.jsx`
**核心代码**
```jsx
// 状态管理
const [showIframe, setShowIframe] = useState(false);
const [iframeData, setIframeData] = useState(null);
// 点击处理
const handleClickBtn = (sectionId, item) => {
if (sectionId === 2 && (item.isShowCase || item.canPreview)) {
setIframeData({
url: item.previewUrl || "默认URL",
title: item.name
});
setShowIframe(true);
}
};
// 渲染逻辑
if (showIframe && iframeData) {
return (
<div className="homework-page-iframe-wrapper">
<div className="homework-page-iframe-header">
<button onClick={() => {
setShowIframe(false);
setIframeData(null);
}}>
<IconArrowLeft />
返回课后作业
</button>
<span>{iframeData.title}</span>
</div>
<iframe
src={iframeData.url}
style={{ zoom: 0.8 }}
/>
</div>
);
}
```
**功能特点**
- ✅ 自动检测 `canPreview``isShowCase`
- ✅ 全屏显示iframe
- ✅ 动态课程标题和URL
- ✅ 返回按钮(自动清理状态)
- ✅ 自动缩放zoom: 0.8
#### 3. 课程自动排序
**实现位置**`src/pages/HomeworkPage/index.jsx` - `getFilteredCourses` 函数
**核心代码**
```javascript
// 将可试看的课程排在最前面
const previewCourses = allCourses.filter(course => course.canPreview || course.isShowCase);
const otherCourses = allCourses.filter(course => !course.canPreview && !course.isShowCase);
return [...previewCourses, ...otherCourses];
```
**效果**
- ✅ 可试看课程自动排在最前面
- ✅ 无论"全部"还是"特定单元"视图都生效
- ✅ 提升用户体验
### 自动实现的功能
以下功能**无需手动配置**,系统已自动实现:
1. ✅ 可试看课程自动排在最前面
2. ✅ "可试看"标签自动显示
3.**iframe嵌入功能课程直播间和作业页面**
4.**全屏功能(课程直播间有全屏按钮)**
5.**返回按钮和导航功能(作业页面)**
6. ✅ 锁定状态自动判断
7. ✅ 按钮状态自动切换(蓝色/灰色)
### 您只需要做的事情
**只需在 `mockData.js` 中配置两处:**
1. 课程直播间:添加 `canPreview``previewUrl`
2. 课程作业:添加 `canPreview``previewUrl`
**系统会自动:**
- 在视频区域嵌入iframe而不是打开新窗口
- 在作业页面全屏嵌入iframe而不是打开新窗口
- 添加全屏按钮和返回按钮
- 处理所有交互逻辑
**就这么简单!** 🎉
---
## 常见问题
### Q1: 为什么添加了配置但没有显示"可试看"标签?
**可能原因:**
1. **课程名称不匹配**
- 检查 `event.title``course.courseName` 是否与数据中的课程名称完全一致
- 注意中英文标点符号、空格等
2. **单元名称不匹配**
- 检查 `unitName``unit.unitName` 是否与数据中的单元名称完全一致
3. **代码位置错误**
- 确保代码添加在正确的函数内部
- 课程直播间:`generateVerticalCourseLiveList` 函数内
- 课程作业:在生成 `homeworkItem` 的循环内
**解决方法:**
在浏览器控制台查看课程数据,确认实际的课程名称和单元名称:
```javascript
// 在浏览器控制台执行
console.log(mockData.courseLiveData.vertical);
console.log(mockData.homework);
```
### Q2: iframe显示空白或无法加载
**可能原因:**
1. **URL不支持iframe嵌入**
- 某些网站设置了X-Frame-Options禁止iframe嵌入
2. **URL地址错误**
- 检查URL是否可以直接在浏览器中访问
3. **跨域问题**
- 确保目标网站允许跨域访问
**解决方法:**
1. 先在浏览器中直接访问URL确认页面可以正常打开
2. 使用浏览器开发者工具的Network标签检查是否有加载错误
3. 查看Console是否有跨域相关的错误信息
### Q3: 点击课程后显示锁定状态而非iframe
**可能原因:**
`canPreview` 字段没有正确设置为 `true`
**解决方法:**
1. 检查配置代码中的 `canPreview` 是否拼写正确
2. 确认 `if` 条件判断确实被执行(添加 `console.log` 调试)
```javascript
if (event.title === "您的课程名称" && unitName === "单元名称") {
console.log("匹配到可试看课程:", event.title); // 添加调试日志
courseObj.canPreview = true;
courseObj.previewUrl = "您的URL";
}
```
### Q4: 可试看课程没有排在最前面
**可能原因:**
页面缓存或数据未刷新
**解决方法:**
1. 硬刷新浏览器Cmd+Shift+R 或 Ctrl+Shift+R
2. 清除浏览器缓存后重新加载
3. 检查开发服务器是否正常运行
### Q5: 配置后会打开新窗口吗?
**不会!**
本项目已完全移除 `window.open` 代码所有可试看课程都通过iframe嵌入显示。
### Q6: 如何验证iframe嵌入是否生效
**验证方法:**
1. 打开课程直播间或作业页面
2. 点击可试看课程
3. 检查浏览器地址栏URL是否改变
**结果判断**
-**URL没有改变** = iframe嵌入成功正确
-**URL改变或打开新标签页** = 配置有误(需要检查)
### Q7: 修改后需要重启服务器吗?
**不需要!**
- Vite开发服务器支持热更新
- 保存 `mockData.js` 后,页面会自动刷新
- 如果没有自动刷新,手动刷新浏览器即可
### Q8: 如何快速找到课程名称和单元名称?
**方法1查看页面显示**
直接在课程列表中查看显示的课程名称和单元名称
**方法2在代码中搜索**
`src/data/mockData.js` 中搜索课程相关的关键词
**方法3使用浏览器控制台**
```javascript
// 查看所有垂直课程数据
console.log(mockData.courseLiveData.vertical);
// 查看所有作业数据
console.log(mockData.homework);
```
---
## 验证清单
配置完成后,使用此清单验证功能:
### 课程直播间页面(/live
- [ ] 可试看课程显示在课程列表最前面
- [ ] 课程右侧显示"可试看"蓝色标签
- [ ] 点击可试看课程后视频区域显示iframe内容**不是新窗口**
- [ ] iframe右上角有全屏按钮
- [ ] 点击全屏按钮可以正常全屏显示
- [ ] iframe内容可以正常交互
- [ ] 非可试看课程显示锁定状态(模糊背景+锁图标)
- [ ] 浏览器地址栏URL未改变
### 课程作业页面(/homework
- [ ] 可试看课程作业显示在列表最前面
- [ ] 课程作业卡片显示"可试看"标签
- [ ] "已完成"按钮是蓝色(非灰色)
- [ ] 点击"已完成"按钮后全屏显示iframe**不是新窗口**
- [ ] 顶部显示"返回课后作业"按钮和课程标题
- [ ] 点击返回按钮可以正常返回列表
- [ ] iframe内容正常显示zoom: 0.8
- [ ] 浏览器地址栏URL未改变
---
## 快速参考卡片
### 配置位置
| 位置 | 文件 | 行号 | 搜索关键词 |
|------|------|------|-----------|
| 课程直播间 | `src/data/mockData.js` | 约680行 | `为"水质样品的采样与保存"课程添加试看标签` |
| 课程作业 | `src/data/mockData.js` | 约5325行 | `为水质样品的采样与保存课程添加可试看标记` |
### 配置模板
```javascript
// 课程直播间
if (event.title === "课程名称" && unitName === "单元名称") {
courseObj.canPreview = true;
courseObj.previewUrl = "URL";
}
// 课程作业
if (course.courseName === "课程名称" && unit.unitName === "单元名称") {
homeworkItem.canPreview = true;
homeworkItem.previewUrl = "URL";
}
```
### 常见错误
| 问题 | 原因 | 解决方法 |
|------|------|----------|
| 没有显示标签 | 名称不匹配 | 检查课程/单元名称是否完全一致 |
| iframe空白 | URL不支持嵌入 | 换一个支持iframe的URL |
| 显示锁定状态 | canPreview未生效 | 检查if条件是否匹配 |
| 打开新窗口 | 配置错误 | 不会出现已移除window.open |
---
## 项目信息
**项目名称**:环保产业教务系统前端
**项目路径**`/Users/apple/Documents/cursor/教务系统/frontend_环保`
**开发服务器**http://localhost:5161
**相关页面**
- 课程直播间http://localhost:5161/live
- 课程作业http://localhost:5161/homework
---
## 总结
### 核心要点
1. ✅ iframe嵌入功能已完全实现2025-10-14升级
2. ✅ 原始版本使用window.open已废弃
3. ✅ 当前版本完全复用文旅项目实现
4. ✅ 您只需配置 `canPreview``previewUrl`
5. ✅ 不需要修改任何组件代码
6. ✅ 不会打开新窗口,始终在当前页面显示
7. ✅ 支持全屏、返回按钮等所有交互功能
### 配置三步走
1. **找到课程名称和单元名称**
2. **在mockData.js的两个位置添加配置**
3. **保存文件并验证效果**
### 自动实现的功能
- iframe嵌入课程直播间和作业页面
- 全屏功能(课程直播间)
- 返回按钮(作业页面)
- 可试看课程自动排序
- "可试看"标签显示
- 锁定状态判断
- 按钮状态切换
**配置简单,功能强大!** 🎉
---
**文档结束**