ChenfengDX
ChenfengDX
发布于 2026-01-28 / 9 阅读
0
0

轻课堂项目研究文档

轻课堂项目研究文档

一、项目概述

1.1 基本信息

  • 项目名称: 轻课堂 (Lite Class)
  • 版本: 1.0.6
  • 描述: 专为NAS用户打造的轻量级、多用户私有云学习管理系统
  • 开发者: 落地长安
  • 默认管理员账号: admin / admin123
  • 技术架构: 前后端分离架构

1.2 核心特性

  • 多用户管理系统(管理员/普通用户)
  • 课程分类与管理
  • 视频播放与学习进度追踪
  • 笔记与资料管理
  • 学习日历与历史记录
  • 视频转码服务(支持HLS流式转码)
  • 硬件加速(GPU/NVENC/VAAPI/QSV)
  • 分片上传支持
  • 课程收藏功能
  • 深色主题支持

二、技术栈

2.1 前端技术栈

- 框架: React 18.2.0
- 路由: React Router Dom 6.14.2
- 构建工具: Vite 4.3.9
- UI样式: Tailwind CSS 3.3.3
- 视频播放: hls.js 1.5.7
- 图标库: lucide-react 0.263.1
- 开发语言: JavaScript + JSX

2.2 后端技术栈

- 运行环境: Node.js v22
- Web框架: Fastify 4.26.1
- 数据库: SQLite 3 (sqlite3 5.1.7)
- 身份认证: JWT (jsonwebtoken 9.0.2)
- 密码加密: bcryptjs 2.4.3
- 视频转码: fluent-ffmpeg 2.1.3
- 文件上传: @fastify/multipart 7.7.3
- 静态文件: @fastify/static 6.12.0
- 文件系统: fs-extra 11.2.0
- MIME类型: mime-types 2.1.35

2.3 关键依赖

  • FFmpeg: 视频转码核心工具(需系统预装)
  • fnOS: 飞牛NAS操作系统支持

三、项目结构

3.1 根目录结构

lite.class_1.0.6/
├── app/                      # 应用主目录
│   ├── server/              # 后端服务
│   │   ├── index.js         # 服务器入口文件 (2264行)
│   │   ├── transcoder.js    # 视频转码模块 (905行)
│   │   ├── package.json     # 后端依赖配置
│   │   ├── public/          # 静态资源目录
│   │   │   └── uploads/     # 上传文件存储
│   │   └── liteclass.db     # SQLite数据库
│   ├── frontend/            # 前端应用
│   │   ├── src/
│   │   │   ├── api/         # API封装
│   │   │   ├── components/  # React组件
│   │   │   ├── hooks/       # 自定义Hook
│   │   │   ├── utils/       # 工具函数
│   │   │   ├── App.jsx      # 应用入口
│   │   │   └── main.jsx     # 渲染入口
│   │   ├── index.html       # HTML模板
│   │   └── package.json     # 前端依赖配置
│   ├── ui/                  # UI界面资源
│   └── config/              # 应用配置
├── cmd/                     # 命令脚本目录
│   ├── main                 # 主控脚本(启动/停止/状态)
│   ├── install_callback     # 安装回调
│   ├── install_init         # 安装初始化
│   ├── uninstall_callback   # 卸载回调
│   ├── uninstall_init       # 卸载初始化
│   ├── upgrade_callback     # 升级回调
│   ├── upgrade_init         # 升级初始化
│   ├── config_callback      # 配置回调
│   └── config_init          # 配置初始化
├── wizard/                  # 安装向导
│   ├── install              # 安装配置(端口/管理员账号)
│   └── uninstall            # 卸载配置
├── config/                  # 系统配置
│   ├── privilege            # 权限配置
│   └── resource             # 资源配置
├── manifest                 # 应用清单文件(元数据)
├── ICON.PNG                 # 应用图标
└── ICON_256.PNG             # 应用大图标

3.2 前端组件结构

components/
├── Login.jsx               # 登录页面
├── Layout.jsx              # 布局组件(底部导航栏)
├── Home.jsx                # 首页(学习日历)
├── Courses.jsx             # 课程列表
├── CourseDetail.jsx        # 课程详情与播放器 (84KB)
├── CourseChapterManager.jsx # 章节管理
├── HlsPlayer.jsx           # HLS播放器组件
├── Profile.jsx             # 个人中心 (74KB)
├── ConfirmModal.jsx        # 确认对话框
└── PreviewModal.jsx        # 文件预览弹窗

四、数据库设计

4.1 数据表结构

4.1.1 users(用户表)

CREATE TABLE users (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    username TEXT UNIQUE NOT NULL,          -- 用户名
    password_hash TEXT NOT NULL,            -- 密码哈希
    role TEXT DEFAULT 'user',               -- 角色: admin/user
    nickname TEXT,                          -- 昵称
    avatar TEXT,                            -- 头像路径
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);

4.1.2 categories(分类表)

CREATE TABLE categories (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    name TEXT UNIQUE NOT NULL                -- 分类名称
);
-- 默认分类: ID=1, name='未分类'

4.1.3 courses(课程表)

CREATE TABLE courses (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    title TEXT NOT NULL,                    -- 课程标题
    description TEXT,                       -- 课程描述
    cover_image TEXT,                       -- 封面图片
    category_id INTEGER,                    -- 所属分类
    type TEXT DEFAULT 'manual',            -- 类型: manual(手动)/uploaded(上传)/mount(挂载)
    folder_path TEXT,                       -- 存储路径
    is_shared BOOLEAN DEFAULT 0,           -- 是否公开(0=隐藏, 1=公开)
    creator_id INTEGER DEFAULT 1,          -- 创建者ID
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);

4.1.4 course_materials(课程素材表)

CREATE TABLE course_materials (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    course_id INTEGER NOT NULL,             -- 所属课程
    chapter_title TEXT,                     -- 章节标题(支持树形结构)
    title TEXT NOT NULL,                    -- 素材标题
    file_path TEXT NOT NULL,                -- 文件路径
    media_type TEXT,                        -- 媒体类型: video/audio/document/attachment
    file_size INTEGER,                      -- 文件大小(字节)
    duration INTEGER,                       -- 时长(秒)
    sort_order INTEGER DEFAULT 0,           -- 排序序号
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);

4.1.5 learning_progress(学习进度表)

CREATE TABLE learning_progress (
    user_id INTEGER,
    course_id INTEGER,
    material_id INTEGER,
    played_seconds INTEGER DEFAULT 0,      -- 播放时长(秒)
    is_finished BOOLEAN DEFAULT 0,          -- 是否完成
    last_updated DATETIME DEFAULT CURRENT_TIMESTAMP,
    PRIMARY KEY (user_id, course_id, material_id)
);

4.1.6 learning_notes(学习笔记表)

CREATE TABLE learning_notes (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    user_id INTEGER,
    material_id INTEGER,
    content TEXT,                           -- 笔记内容
    video_timestamp INTEGER DEFAULT 0,       -- 视频时间戳
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);

4.1.7 system_settings(系统设置表)

CREATE TABLE system_settings (
    key TEXT PRIMARY KEY,
    value TEXT
);
-- 默认设置:
-- allow_registration: false
-- allow_course_creation: true
-- enable_transcoding: false
-- max_material_size: 100 (MB)

4.1.8 favorites(收藏表)

CREATE TABLE favorites (
    user_id INTEGER,
    course_id INTEGER,
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
    PRIMARY KEY (user_id, course_id)
);

4.1.9 user_materials(用户私有资料表)

CREATE TABLE user_materials (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    user_id INTEGER NOT NULL,
    course_id INTEGER NOT NULL,
    title TEXT NOT NULL,
    file_path TEXT NOT NULL,
    file_size INTEGER,
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);

4.2 数据库初始化流程

  1. 创建所有数据表
  2. 插入默认系统设置
  3. 插入默认分类(未分类)
  4. 自动创建管理员账号(如果数据库为空且环境变量提供了凭据)
  5. 执行数据库迁移(自动添加新字段)
  6. 初始化转码服务设置

五、后端API设计

5.1 认证相关 API

POST /api/auth/register - 用户注册

权限: 根据系统设置决定
请求体:

{
  "username": "string",
  "password": "string",
  "nickname": "string"
}

响应: { success: true, role: "admin"|"user" }

POST /api/auth/login - 用户登录

请求体:

{
  "username": "string",
  "password": "string"
}

响应:

{
  "token": "jwt_token",
  "user": {
    "id": 1,
    "username": "admin",
    "nickname": "管理员",
    "role": "admin",
    "avatar": "/avatars/xxx.png"
  }
}

5.2 系统设置 API

GET /api/settings/public - 获取公开设置(无需认证)

响应:

{
  "allow_registration": false,
  "allow_course_creation": true,
  "max_material_size": 100,
  "enable_transcoding": false,
  "appName": "轻课堂",
  "version": "1.0.6",
  "transcode": {
    "enabled": false
  }
}

GET /api/settings - 获取所有设置(管理员)

POST /api/settings - 更新设置(管理员)

请求体: { key: "string", value: "any" }

5.3 课程管理 API

GET /api/courses - 获取课程列表

查询参数:

  • q: 搜索关键词
  • filter: 过滤类型 (all|favorites|uploads)

响应: 返回课程列表,包含进度统计和收藏状态

POST /api/courses - 创建课程

请求体:

{
  "title": "课程标题",
  "description": "课程描述",
  "cover_image": "封面路径",
  "category_id": 1,
  "folder_path": "存储路径(可选)"
}

GET /api/courses/:id - 获取课程详情

响应: 包含课程信息和所有章节(素材)

PUT /api/courses/:id - 更新课程

权限: 课程创建者或管理员

DELETE /api/courses/:id - 删除课程

权限: 课程创建者或管理员
注意: 仅删除课程记录,保留学习记录和笔记

PUT /api/courses/:id/visibility - 切换课程可见性

响应: { is_hidden: boolean, is_shared: boolean }

POST /api/courses/:id/scan - 重新扫描课程目录

适用: 挂载类型课程

5.4 分类管理 API(管理员)

GET /api/categories - 获取分类列表

POST /api/categories - 创建分类

PUT /api/categories/:id - 更新分类

DELETE /api/categories/:id - 删除分类

5.5 文件上传 API

POST /api/upload - 单文件上传

支持: 分片上传和断点续传
限制: 最大5GB
权限: 课程创建者或管理员

GET /api/upload/check - 检查已上传分片

POST /api/upload/chunk - 上传分片

POST /api/upload/merge - 合并分片

POST /api/upload/cover - 上传课程封面

POST /api/upload/avatar - 上传用户头像

POST /api/upload/note-image - 上传笔记图片

5.6 视频流播放 API

GET /api/stream/:materialId - 获取视频流

功能:

  • 原生格式直接流式传输(支持Range请求)
  • 需要转码格式返回HLS信息
  • 缓存MP4直接播放

查询参数:

  • token: JWT认证令牌
  • quality: 画质选择 (original|1080p|720p|480p)

GET /api/stream/:materialId/hls/playlist.m3u8 - HLS播放列表

GET /api/stream/:materialId/hls/:segment - HLS分片流

GET /api/transcode/status/:materialId - 获取转码状态

GET /api/transcode/qualities - 获取可用画质列表

5.7 学习进度与笔记 API

GET /api/notes/:materialId - 获取笔记列表

POST /api/notes - 创建笔记

PUT /api/notes/:id - 更新笔记

DELETE /api/notes/:id - 删除笔记

POST /api/progress - 保存学习进度

请求体:

{
  "course_id": 1,
  "material_id": 10,
  "played_seconds": 120,
  "is_finished": false
}

5.8 历史记录 API

GET /api/history - 获取最近观看记录(最多10条)

GET /api/history/dates - 获取有活动的日期列表

GET /api/history/calendar - 获取月度日历(按月查询)

GET /api/history/by-date - 获取指定日期的记录

DELETE /api/history/by-date - 清除指定日期的记录

DELETE /api/history/item - 删除单条记录

5.9 用户资料 API

GET /api/user/materials/:courseId - 获取用户私有资料

POST /api/user/materials - 上传用户资料

DELETE /api/user/materials/:id - 删除用户资料

GET /api/user/materials/:id/download - 下载用户资料

5.10 历史课程 API

GET /api/user/history-courses - 获取已删除课程(但有笔记/资料)

GET /api/user/history-courses/:courseId/notes - 获取历史课程笔记

DELETE /api/user/history-courses/:courseId - 永久删除历史课程数据

5.11 收藏 API

POST /api/courses/:id/favorite - 切换收藏状态

GET /api/favorites - 获取收藏列表

POST /api/favorites - 添加收藏

DELETE /api/favorites/:courseId - 取消收藏

GET /api/favorites/check/:courseId - 检查收藏状态

5.12 用户管理 API(管理员)

GET /api/admin/users - 获取用户列表

PUT /api/admin/users/:id - 更新用户信息

PUT /api/admin/users/:id/password - 修改用户密码

DELETE /api/admin/users/:id - 删除用户

5.13 课程统计 API(管理员)

GET /api/admin/courses/:id/members - 获取课程成员统计

5.14 素材管理 API

DELETE /api/materials/:id - 删除素材

PUT /api/materials/:id/rename - 重命名素材

PUT /api/courses/:id/materials/sort - 更新排序

DELETE /api/courses/:id/materials/batch - 批量删除素材

5.15 个人中心 API

PUT /api/user/profile - 更新个人资料

请求体: { nickname: "string", password: "string" }


六、视频转码服务

6.1 转码架构

6.1.1 支持的视频格式

原生支持(无需转码):

  • MP4 (H.264视频 + AAC音频)
  • WebM
  • MP3, WAV, AAC

需要转码:

  • MKV, AVI, MOV, FLV, WMV, M4V, 3GP, RMVB, RM

6.1.2 转码策略

  1. 实时HLS转码:

    • 首次播放时启动
    • 按需生成TS分片
    • 60秒无请求自动停止
    • 支持多画质选择
  2. 后台MP4缓存:

    • 后台异步生成
    • 队列机制管理
    • 缓存有效期30天
    • 二次播放直接使用缓存
  3. 智能编码策略:

    • 原画质: 尝试流复制(容器转换)
    • 非原画质: 重新编码
    • 音频始终转AAC(保证兼容性)

6.2 GPU硬件加速

6.2.1 支持的编码器

编码器硬件平台加速类型
h264_nvencNVIDIACUDA
h264_vaapiIntel/AMDVAAPI
h264_qsvIntelQSV
h264_amfAMDAMF

6.2.2 自动检测流程

  1. 检测系统FFmpeg路径
  2. 检查硬件设备文件(/dev/dri/*)
  3. 检查lspci信息
  4. 检查nvidia-smi(如存在)
  5. 逐个测试编码器可用性
  6. 回退到CPU编码(libx264)

6.3 画质预设

画质分辨率视频码率音频码率
原画原分辨率不限制192kbps
1080p1920x10804000kbps192kbps
720p1280x7202000kbps128kbps
480p854x4801000kbps128kbps

6.4 缓存管理

缓存目录结构

transcode_cache/
├── {materialId}_original.mp4       # 原画质缓存
├── {materialId}_1080p.mp4           # 1080p缓存
├── hls_{materialId}_original/        # HLS临时目录
│   ├── playlist.m3u8
│   ├── segment_000.ts
│   ├── segment_001.ts
│   └── ...

缓存清理策略

  • HLS进程: 60秒无请求自动停止
  • MP4文件: 30天未访问自动删除
  • 定时任务: 每天检查一次

七、前端架构与组件

7.1 路由结构

/
├── /login                           # 登录页(公开)
└── [PrivateRoute]                   # 需要认证
    ├── /                            # 首页(学习日历)
    ├── /courses                     # 课程列表
    ├── /course/:id                  # 课程详情与播放
    ├── /course/:id/manage           # 章节管理
    └── /profile                     # 个人中心

7.2 核心组件说明

7.2.1 Layout组件

  • 提供底部导航栏
  • 渲染子路由
  • 深色主题支持

7.2.2 Home组件(首页)

  • 学习日历:

    • 月度视图
    • 标记有活动的日期
    • 点击查看当日学习记录
  • 观看记录:

    • 显示当日观看的视频
    • 显示播放进度
    • 支持删除单条记录
    • 支持清除当日记录

7.2.3 Courses组件(课程列表)

  • 三个标签页:

    1. 全部课程: 显示所有公开课程
    2. 我的上传: 显示用户创建的课程
    3. 我的收藏: 显示收藏的课程
  • 功能:

    • 搜索课程
    • 切换课程可见性
    • 创建新课程
    • 进入课程详情

7.2.4 CourseDetail组件(课程详情与播放)

  • 视频播放器:

    • 自定义控制条
    • HLS集成
    • 倍速播放(0.5x ~ 3.0x)
    • 画面截图
    • 画中画模式
    • 键盘快捷键
  • 播放模式:

    • 顺序播放
    • 单集循环
    • 全部循环
  • 进度管理:

    • 自动保存播放进度
    • 标记已看完
    • 继续播放(跳转到上次位置)
  • 目录树:

    • 支持树形结构(章节)
    • 智能排序
    • 手动排序
    • 文件预览
  • 笔记功能:

    • 实时笔记
    • 时间戳定位
    • 图片上传
    • 笔记列表
  • 用户资料:

    • 上传私有资料
    • 下载/预览资料
    • 资料管理
  • 历史课程:

    • 查看已删除课程的笔记
    • 永久删除历史数据

7.2.5 CourseChapterManager组件(章节管理)

  • 功能:
    • 文件上传(支持分片)
    • 批量删除
    • 重命名章节
    • 拖拽排序
    • 扫描目录(挂载课程)

7.2.6 Profile组件(个人中心)

  • 个人信息:

    • 昵称修改
    • 密码修改
    • 头像上传
  • 管理员功能:

    • 用户管理
    • 系统设置
    • 转码开关
    • 分类管理
  • 历史课程管理:

    • 查看历史课程
    • 删除历史数据

7.2.7 HlsPlayer组件

  • 基于hls.js
  • 支持多种视频格式
  • 错误处理
  • 加载状态

7.3 自定义Hooks

useTheme

  • 管理深色/浅色主题
  • 响应式颜色方案

useSafeBack

  • 安全返回导航
  • 记录历史路径

八、运行逻辑与流程

8.1 应用启动流程

1. 系统启动
   ↓
2. 执行 cmd/main start
   ↓
3. 读取配置
   - 端口配置 (port.conf)
   - 管理员凭据 (环境变量)
   ↓
4. 环境变量设置
   - DATABASE_URL
   - DATA_DIR
   - UPLOAD_DIR
   - PORT
   - ADMIN_USERNAME
   - ADMIN_PASSWORD
   ↓
5. 创建必要目录
   - 共享目录 (SHARE_DIR)
   - 上传目录 (UPLOAD_DIR)
   ↓
6. 启动Node.js服务
   cd app/server && node index.js
   ↓
7. 服务初始化
   - 连接SQLite数据库
   - 初始化数据表
   - 执行数据库迁移
   - 初始化转码服务
   - 创建管理员账号(如果不存在)
   ↓
8. 监听端口
   默认: 8083 (可通过配置修改)
   ↓
9. 启动完成
   用户可通过浏览器访问

8.2 用户登录流程

1. 用户打开应用
   ↓
2. 前端检查Token
   - 有Token → 验证有效性
   - 无Token → 跳转登录页
   ↓
3. 输入用户名密码
   ↓
4. POST /api/auth/login
   ↓
5. 后端验证
   - 查询用户
   - bcrypt.compare对比密码
   ↓
6. 生成JWT Token
   jwt.sign({id, username, role}, secret, {expiresIn: '7d'})
   ↓
7. 返回Token和用户信息
   ↓
8. 前端存储
   - localStorage.setItem('token', token)
   - localStorage.setItem('user', JSON.stringify(user))
   ↓
9. 跳转到首页

8.3 课程播放流程

1. 用户进入课程详情
   ↓
2. GET /api/courses/:id
   - 获取课程信息
   - 获取章节列表
   ↓
3. 用户点击播放章节
   ↓
4. 检查视频格式
   ↓
5. GET /api/stream/:materialId
   ├─ 原生格式
   │   ├─ 支持Range请求
   │   ├─ 直接流式传输
   │   └─ 前端Video标签播放
   │
   └─ 需要转码格式
       ├─ 检查缓存
       │   └─ 有缓存 → 直接播放缓存MP4
       │
       └─ 无缓存
           ├─ 启动HLS转码 (transcoder.startHlsTranscode)
           │   ├─ 检测GPU编码器
           │   ├─ 构建FFmpeg参数
           │   ├─ 启动FFmpeg进程
           │   ├─ 等待m3u8生成
           │   └─ 同时启动后台缓存 (transcoder.startBackgroundCache)
           │
           ├─ 返回HLS信息
           │   {
           │     needsTranscode: true,
           │     hlsUrl: '/api/stream/:materialId/hls/playlist.m3u8'
           │   }
           │
           └─ 前端HlsPlayer加载m3u8
               ├─ 请求playlist.m3u8
               ├─ 按需请求segment_XXX.ts
               └─ 实时播放
   ↓
6. 播放进度记录
   - 每30秒或暂停时保存
   - POST /api/progress
   - {course_id, material_id, played_seconds, is_finished}

8.4 文件上传流程

1. 用户选择文件
   ↓
2. 前端检查文件大小
   - 超过限制(默认100MB)→ 提示分片上传
   ↓
3. 小文件(单次上传)
   ├─ 构建FormData
   │   {courseId, file}
   ├─ POST /api/upload
   ├─ 保存到课程目录
   ├─ 插入数据库
   └─ 返回成功
   ↓
4. 大文件(分片上传)
   ├─ 文件切片(每片10MB)
   ├─ 逐片上传
   │   POST /api/upload/chunk
   │   {fileId, chunkIndex, totalChunks, courseId}
   │   ↓
   │   保存到临时目录
   │   UPLOAD_DIR/temp/fileId/chunk_0
   │   UPLOAD_DIR/temp/fileId/chunk_1
   │   ...
   ↓
   ├─ 所有分片上传完成
   │   POST /api/upload/merge
   │   {fileId, filename, courseId, totalChunks}
   │   ↓
   │   合并分片
   │   ├─ 读取所有分片
   │   ├─ 按顺序拼接
   │   ├─ 写入最终文件
   │   └─ 清理临时目录
   │
   └─ 插入数据库
   ↓
5. 上传完成
   - 刷新章节列表

8.5 课程扫描流程(挂载类型)

1. 管理员创建挂载课程
   POST /api/courses
   {title, type: 'mount', folder_path: '/shares/course1'}
   ↓
2. 后台启动扫描
   setImmediate(() => scanDirectory(courseId, folderPath))
   ↓
3. 递归扫描目录
   scanDirectoryRecursive(courseId, basePath, relativePath, existingPaths)
   ├─ 遍历所有文件和子目录
   ├─ 识别媒体类型(video/audio/document)
   ├─ 跳过已存在的文件
   ├─ 插入新文件到数据库
   └─ 记录chapter_title(相对路径)
   ↓
4. 清理已删除的文件
   ├─ 对比数据库记录
   ├─ 删除不存在的记录
   ↓
5. 重新排序
   resortCourseMaterials(courseId)
   ├─ 智能排序算法
   ├─ 支持中英文数字
   ├─ 更新sort_order字段
   ↓
6. 自动生成封面
   autoUpdateCourseCover(courseId)
   ├─ 查找第一个视频
   ├─ 使用FFmpeg生成缩略图
   └─ 保存到DATA_DIR/covers/
   ↓
7. 扫描完成
   - 前端刷新课程列表

8.6 笔记管理流程

1. 用户在播放器中打开笔记面板
   ↓
2. GET /api/notes/:materialId
   - 获取该视频的所有笔记
   - 按时间戳排序
   ↓
3. 添加新笔记
   ├─ 输入内容
   ├─ 可选:上传图片
   │   POST /api/upload/note-image
   │   保存到 DATA_DIR/note_images/{userId}/
   ↓
   ├─ POST /api/notes
   │   {
   │     materialId: 10,
   │     content: "笔记内容",
   │     timestamp: 120  // 当前播放时间
   │   }
   │   ↓
   └─ 插入数据库
   ↓
4. 编辑笔记
   ├─ PUT /api/notes/:id
   └─ 更新内容
   ↓
5. 删除笔记
   ├─ DELETE /api/notes/:id
   └─ 从数据库删除
   ↓
6. 笔记关联
   - 笔记永久保存
   - 即使课程被删除,笔记仍可访问
   - 通过"历史课程"查看

8.7 学习进度同步流程

视频播放中
    ↓
每30秒或以下事件触发
- 播放暂停
- 播放结束
- 切换章节
- 页面关闭
    ↓
保存进度
POST /api/progress
{
  course_id: 1,
  material_id: 10,
  played_seconds: 245,
  is_finished: false
}
    ↓
后端UPSERT
INSERT INTO learning_progress ...
ON CONFLICT(...) DO UPDATE SET
  played_seconds = excluded.played_seconds,
  is_finished = excluded.is_finished,
  last_updated = datetime('now')
    ↓
前端更新状态
- 更新进度条
- 更新"已看X分X秒"
- 如果看完,标记为完成

九、部署与配置

9.1 安装配置(向导)

向导配置文件: wizard/install

步骤1: 基本配置

  • 应用端口: 默认8083
  • 可配置其他可用端口

步骤2: 管理员设置

  • 管理员用户名: 默认admin
  • 管理员密码: 默认admin123

9.2 环境变量

启动时自动设置的环境变量:

# 数据库路径
export DATABASE_URL="$SHARE_DIR/liteclass.db"

# 持久化数据目录
export DATA_DIR="$TRIM_PKGVAR"

# 上传目录
export UPLOAD_DIR="$SHARE_DIR/user-uploads"

# 服务端口
export PORT="$APP_PORT"

# 监听地址
export HOST="::"

# 管理员账号
export ADMIN_USERNAME="$admin_username"
export ADMIN_PASSWORD="$admin_password"

9.3 目录权限要求

  • 共享目录: 需要读写权限(用于存储数据库和文件)
  • 上传目录: 需要读写权限
  • 数据目录: 需要读写权限(用于封面、头像、转码缓存)

9.4 FFmpeg安装要求

系统需要预装FFmpeg:

fnOS/Synology:

# fnOS
/var/packages/ffmpeg/target/bin/ffmpeg

# Synology
/usr/bin/ffmpeg

通用Linux:

# Debian/Ubuntu
apt-get install ffmpeg

# CentOS/RHEL
yum install ffmpeg

9.5 端口配置

默认端口: 8083

修改端口方式:

  1. 通过向导安装时指定
  2. 编辑 TRIM_PKGVAR/port.conf
  3. 重启服务

9.6 数据备份

重要数据位置:

  • 数据库: $SHARE_DIR/liteclass.db
  • 上传文件: $SHARE_DIR/user-uploads/
  • 持久化数据: $DATA_DIR/
    • 封面: covers/
    • 头像: avatars/
    • 笔记图片: note_images/
    • 转码缓存: transcode_cache/

十、系统安全

10.1 认证机制

  • JWT Token: 7天有效期
  • 密码加密: bcrypt (10轮哈希)
  • Token存储: localStorage

10.2 权限控制

管理员权限:

  • 所有课程操作
  • 用户管理
  • 系统设置
  • 分类管理
  • 挂载课程(远程目录)

普通用户权限:

  • 创建上传型课程
  • 管理自己的课程
  • 上传/管理自己的资料
  • 查看公开课程

10.3 文件安全

  • 上传文件类型检查
  • 文件大小限制(可配置)
  • 认证Token验证(视频流)
  • 路径遍历防护

10.4 输入验证

  • SQL注入防护(参数化查询)
  • XSS防护(React自动转义)
  • 文件上传类型验证
  • 用户名密码格式验证

十一、性能优化

11.1 前端优化

  • 代码分割: React路由懒加载
  • 静态资源: CDN加速(如使用)
  • 图片优化: 懒加载
  • 缓存策略: LocalStorage

11.2 后端优化

  • 数据库: SQLite连接池
  • 静态文件: Fastify-static
  • 文件流: Range请求支持
  • 转码: GPU硬件加速

11.3 转码优化

  • 缓存机制: HLS + MP4双重缓存
  • 队列管理: 后台任务队列
  • 智能编码: 流复制优先
  • 资源清理: 自动清理过期缓存

11.4 网络优化

  • 分片上传: 大文件断点续传
  • Range请求: 视频按需加载
  • HLS流式: 边转码边播放

十二、故障排查

12.1 常见问题

问题1: 服务无法启动

  • 检查Node.js版本(需要v22)
  • 检查端口是否被占用
  • 查看日志: $TRIM_PKGVAR/info.log

问题2: 视频无法播放

  • 检查FFmpeg是否安装
  • 检查转码服务是否开启
  • 查看浏览器控制台错误

问题3: 转码失败

  • 检查磁盘空间
  • 检查FFmpeg版本
  • 查看转码日志

问题4: 文件上传失败

  • 检查磁盘空间
  • 检查文件大小限制
  • 检查目录权限

12.2 日志查看

服务日志:

tail -f $TRIM_PKGVAR/info.log

系统日志:

  • fnOS: 系统日志 → 应用日志
  • Synology: 控制面板 → 日志中心

12.3 数据库维护

备份数据库:

cp $SHARE_DIR/liteclass.db $SHARE_DIR/liteclass.db.backup

恢复数据库:

cp $SHARE_DIR/liteclass.db.backup $SHARE_DIR/liteclass.db

十三、扩展开发

13.1 添加新API

app/server/index.js 中添加路由:

fastify.get('/api/new-endpoint', { preValidation: [fastify.authenticate] }, async (request, reply) => {
    // 处理逻辑
    return { data: 'response' };
});

13.2 添加新组件

app/frontend/src/components/ 中创建新组件,然后在 App.jsx 中注册路由。

13.3 数据库迁移

// 在initSchema函数的migrations数组中添加
const migrations = [
    // ...现有迁移
    "ALTER TABLE courses ADD COLUMN new_field TEXT",
];

13.4 转码功能扩展

app/server/transcoder.js 中:

  • 添加新的画质预设
  • 添加新的编码器支持
  • 自定义FFmpeg参数

十四、总结

14.1 项目优势

  1. 轻量级: 基于Node.js和SQLite,资源占用低
  2. NAS友好: 专为NAS环境优化
  3. 功能完善: 涵盖学习管理全流程
  4. 技术先进: React + Fastify现代化架构
  5. 易部署: 自动化安装向导
  6. 性能优化: GPU转码、缓存机制

14.2 适用场景

  • 家庭NAS学习平台
  • 企业内部培训系统
  • 在线教育私有部署
  • 视频资源管理

14.3 后续改进方向

  1. 支持更多视频格式
  2. 增加学习统计报表
  3. 支持移动端App
  4. 增加社区功能
  5. 支持更多存储方式(对象存储)
  6. 优化转码性能

附录

A. 键盘快捷键

快捷键功能
Space播放/暂停
快退10秒
快进10秒
音量增加
音量减少
M静音/取消静音
F全屏/退出全屏
P画中画

B. API响应码

状态码说明
200成功
206部分内容(视频流)
400请求参数错误
401未授权/Token过期
403无权限
404资源不存在
416Range请求无效
500服务器内部错误

C. 支持的视频编码

  • H.264 (AVC)
  • H.265 (HEVC) - 需转码
  • VP8/VP9 - 需转码
  • AV1 - 需转码

D. 技术支持

  • 交流QQ群: 1072565705
  • 作者: 落地长安
  • 版本: 1.0.6

文档生成时间: 2026-01-28
项目版本: lite.class 1.0.6


评论