feat: PLANNING体系首版(00路线图/02任务总表/03执行协议/I-03/I-04/registry42口径)+M1止血交付
This commit is contained in:
@@ -0,0 +1,234 @@
|
||||
# BDCloudVideoView 视频播放器增强方案
|
||||
|
||||
## 问题描述
|
||||
|
||||
现有视频播放器已支持B站和本地视频,但缺少以下关键功能:
|
||||
- 来源切换UI:用户无法在播放过程中切换B站/本地源
|
||||
- 播放进度记忆:关闭页面后无法从断点继续播放
|
||||
- 高级播放控制:缺少多清晰度、倍速播放、字幕等功能
|
||||
- 学习时长统计:未与任务系统联动记录学习时长
|
||||
|
||||
## 用户选择
|
||||
|
||||
- ✅ 来源切换UI
|
||||
- ✅ 播放进度记忆
|
||||
- ✅ 高级播放控制(多清晰度、倍速播放、字幕)
|
||||
- ✅ 学习时长统计(与任务系统联动)
|
||||
|
||||
## 当前状态分析
|
||||
|
||||
### 现有组件结构
|
||||
```
|
||||
src/components/BDCloudVideoView/
|
||||
├── BDCloudVideoView.tsx # 播放器组件(175行)
|
||||
├── BDCloudVideoView.css # 样式文件(107行)
|
||||
└── BDCloudVideoView.md # 说明文档
|
||||
```
|
||||
|
||||
### 现有功能
|
||||
- B站视频:通过 `<iframe>` 内嵌,自动解析 BV 号
|
||||
- 本地视频:集成百度智能云 SDK,失败回退到 HTML5 `<video>`
|
||||
- 下载/跳转B站按钮
|
||||
|
||||
### 问题根源
|
||||
1. `videoSource` 是外部传入的 prop,组件内部无法切换
|
||||
2. 没有使用 `localStorage` 或后端存储播放进度
|
||||
3. 百度 SDK 初始化时未配置高级选项(清晰度、倍速)
|
||||
4. 没有与任务系统的 `tasks.track` API 联动
|
||||
|
||||
## 实现方案
|
||||
|
||||
### 1. 来源切换UI
|
||||
|
||||
**修改文件**: `BDCloudVideoView.tsx`
|
||||
|
||||
```typescript
|
||||
interface BDCloudVideoViewProps {
|
||||
videoSource: 'bilibili' | 'local';
|
||||
bilibiliUrl?: string;
|
||||
localUrl?: string;
|
||||
posterUrl?: string;
|
||||
title?: string;
|
||||
onDownload?: () => void;
|
||||
// 新增:支持双源配置
|
||||
sources?: {
|
||||
bilibili?: string;
|
||||
local?: string;
|
||||
};
|
||||
// 新增:外部控制来源
|
||||
activeSource?: 'bilibili' | 'local';
|
||||
onSourceChange?: (source: 'bilibili' | 'local') => void;
|
||||
}
|
||||
```
|
||||
|
||||
**新增来源切换器组件**:
|
||||
```tsx
|
||||
const SourceSwitcher: React.FC<{
|
||||
activeSource: 'bilibili' | 'local';
|
||||
hasBilibili: boolean;
|
||||
hasLocal: boolean;
|
||||
onSwitch: (source: 'bilibili' | 'local') => void;
|
||||
}> = ({ activeSource, hasBilibili, hasLocal, onSwitch }) => {
|
||||
if (!hasBilibili || !hasLocal) return null;
|
||||
|
||||
return (
|
||||
<div className="bdcloud-source-switcher">
|
||||
<button
|
||||
className={`bdcloud-source-btn ${activeSource === 'bilibili' ? 'active' : ''}`}
|
||||
onClick={() => onSwitch('bilibili')}
|
||||
>
|
||||
B站
|
||||
</button>
|
||||
<button
|
||||
className={`bdcloud-source-btn ${activeSource === 'local' ? 'active' : ''}`}
|
||||
onClick={() => onSwitch('local')}
|
||||
>
|
||||
本地
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
```
|
||||
|
||||
### 2. 播放进度记忆
|
||||
|
||||
**存储策略**:
|
||||
- 使用 `localStorage` 存储,key 格式: `video_progress_{chapterId}`
|
||||
- 存储内容: `{ currentTime: number, duration: number, timestamp: number }`
|
||||
- 播放时每 5 秒自动保存
|
||||
- 加载时自动恢复到上次位置
|
||||
|
||||
```typescript
|
||||
// 进度存储
|
||||
const saveProgress = (chapterId: string, currentTime: number, duration: number) => {
|
||||
try {
|
||||
localStorage.setItem(`video_progress_${chapterId}`, JSON.stringify({
|
||||
currentTime,
|
||||
duration,
|
||||
timestamp: Date.now(),
|
||||
}));
|
||||
} catch {}
|
||||
};
|
||||
|
||||
// 读取进度
|
||||
const loadProgress = (chapterId: string): number => {
|
||||
try {
|
||||
const data = localStorage.getItem(`video_progress_${chapterId}`);
|
||||
if (data) {
|
||||
const { currentTime, timestamp } = JSON.parse(data);
|
||||
// 只恢复7天内的进度
|
||||
if (Date.now() - timestamp < 7 * 24 * 60 * 60 * 1000) {
|
||||
return currentTime;
|
||||
}
|
||||
}
|
||||
} catch {}
|
||||
return 0;
|
||||
};
|
||||
```
|
||||
|
||||
### 3. 高级播放控制
|
||||
|
||||
**百度 SDK 增强配置**:
|
||||
```typescript
|
||||
const config = {
|
||||
container: playerRef.current,
|
||||
video: {
|
||||
url: localUrl || '',
|
||||
pic: posterUrl || '',
|
||||
// 新增:多清晰度支持
|
||||
qualityList: [
|
||||
{ label: '1080P', url: localUrlHd || localUrl },
|
||||
{ label: '720P', url: localUrlSd || localUrl },
|
||||
{ label: '480P', url: localUrl },
|
||||
],
|
||||
},
|
||||
autoplay: false,
|
||||
controls: true,
|
||||
// 新增:播放速度
|
||||
playbackRate: {
|
||||
defaultValue: 1,
|
||||
options: [0.5, 0.75, 1, 1.25, 1.5, 2],
|
||||
},
|
||||
// 新增:字幕支持
|
||||
subtitleList: subtitleUrl ? [
|
||||
{ label: '中文字幕', url: subtitleUrl },
|
||||
] : [],
|
||||
};
|
||||
```
|
||||
|
||||
**新增控制面板**:
|
||||
- 清晰度切换按钮(播放时显示可选清晰度)
|
||||
- 倍速选择器(0.5x - 2x)
|
||||
- 字幕开关(如有字幕时显示)
|
||||
|
||||
### 4. 学习时长统计
|
||||
|
||||
**新增 props**:
|
||||
```typescript
|
||||
interface BDCloudVideoViewProps {
|
||||
// ... 现有 props
|
||||
chapterId?: number; // 章节ID,用于学习统计
|
||||
onStudyTime?: (seconds: number) => void; // 学习时长回调
|
||||
}
|
||||
```
|
||||
|
||||
**统计逻辑**:
|
||||
```typescript
|
||||
// 累计有效观看时长(排除暂停、拖拽)
|
||||
let studySeconds = 0;
|
||||
let lastPlayTime = 0;
|
||||
let isPlaying = false;
|
||||
|
||||
const handlePlay = () => {
|
||||
isPlaying = true;
|
||||
lastPlayTime = Date.now();
|
||||
};
|
||||
|
||||
const handlePause = () => {
|
||||
if (isPlaying && lastPlayTime > 0) {
|
||||
const elapsed = Math.floor((Date.now() - lastPlayTime) / 1000);
|
||||
studySeconds += elapsed;
|
||||
// 每累计 60 秒上报一次
|
||||
if (studySeconds >= 60) {
|
||||
reportStudyTime(studySeconds);
|
||||
studySeconds = 0;
|
||||
}
|
||||
}
|
||||
isPlaying = false;
|
||||
};
|
||||
|
||||
// 上报到任务系统
|
||||
const reportStudyTime = async (seconds: number) => {
|
||||
try {
|
||||
await api_request.login.tasks.track({
|
||||
action_type: 'learn',
|
||||
count: Math.floor(seconds / 60), // 转换为分钟
|
||||
});
|
||||
} catch {}
|
||||
};
|
||||
```
|
||||
|
||||
## 涉及文件
|
||||
|
||||
| 文件 | 操作 | 说明 |
|
||||
|------|------|------|
|
||||
| `src/components/BDCloudVideoView/BDCloudVideoView.tsx` | 修改 | 添加来源切换、进度记忆、高级控制、学习统计 |
|
||||
| `src/components/BDCloudVideoView/BDCloudVideoView.css` | 修改 | 添加来源切换器、高级控制面板样式 |
|
||||
| `src/pages/CourseLearn/CourseLearn.tsx` | 修改 | 传递 chapterId 和回调函数 |
|
||||
|
||||
## 验证步骤
|
||||
|
||||
1. 打开课程学习页面,播放视频
|
||||
2. 验证来源切换:点击B站/本地按钮切换视频源
|
||||
3. 验证进度记忆:刷新页面后视频从断点继续
|
||||
4. 验证高级控制:清晰度切换、倍速播放、字幕开关
|
||||
5. 验证学习统计:播放后检查任务进度是否更新
|
||||
6. 验证暗色模式下样式正常
|
||||
7. 验证移动端响应式布局
|
||||
|
||||
## 假设与决策
|
||||
|
||||
- **假设**:百度 SDK 支持 qualityList 和 subtitleList 配置(需查阅官方文档确认)
|
||||
- **决策**:播放进度存储在 localStorage 而非后端,减少 API 调用
|
||||
- **决策**:学习时长统计每 60 秒上报一次,避免频繁请求
|
||||
- **决策**:来源切换仅在同时配置了 bilibili 和 local 源时显示
|
||||
Reference in New Issue
Block a user