refactor: React 前端重构,新旧平台合并为莞易学

This commit is contained in:
study-tool
2026-10-29 23:50:46 +08:00
parent 35853891c9
commit e8634a6317
62 changed files with 8923 additions and 4623 deletions
+64 -15
View File
@@ -1,6 +1,6 @@
# 多账号学习控制台
# 莞易学多账号学习控制台
东莞市教师培训平台(jspx.dgjy.net / study.dgjy.net)的多账号挂机控制台。账号、会话、课程缓存、运行日志、系统设置全部存在服务端 SQLite,浏览器只是界面,换电脑、远程打开都在。
莞易学(`jspx.dgjy.net` / `study.dgjy.net`,新旧版课程页自动识别)的多账号挂机控制台。账号、会话、课程缓存、运行日志、系统设置全部存在服务端 SQLite,浏览器只是界面,换电脑、远程打开都在。
## 启动
@@ -63,6 +63,21 @@ docker compose logs -f # 看启动日志
镜像默认装 Chromium(直链视频要真播到结尾)。不需要就用
`docker compose build --build-arg WITH_PLAYWRIGHT=0`,镜像能小一大截。
## 前端开发
页面在 `web/`,技术栈 React 19 + TypeScript + Vite + Tailwind CSS v4。构建产物已提交到
`static/`,只跑 Python 时不需要装 Node:
```bash
cd web
pnpm install
pnpm dev # http://127.0.0.1:5173,/api 代理到 8848
pnpm build # 输出到 ../static/,Python 端直接托管
pnpm typecheck
```
改完前端执行一次 `pnpm build`,刷新页面即可;`static/index.html` 禁止缓存。
## 数据存储(SQLite3)
单文件 `data/study.db`(WAL 模式,读写不互斥)。表:
@@ -127,20 +142,51 @@ docker compose logs -f # 看启动日志
## 目录
```
app.py 服务端:登录链路 / 课程抓取 / 课时上报 / 测验 / 反馈表 / HTTP 接口
store.py SQLite3 存储层:账号 / 设置 / 登录记录 / 运行日志 / 状态 / 缓存 / 快照
static/index.html 前端:账号卡片 + 卡片内「课程日志」折叠面板(无框架,原生 JS)
des.js desenc.js DES 加密(登录表单 rsa 字段,站点原版算法)
start.bat 一键启动(Windows)
Dockerfile Docker 镜像(python:3.12-slim + nodejs + chromium)
docker-compose.yml Docker 编排:端口、数据卷、AUTH_TOKEN、健康检查
.env.example 远程管理用的环境变量样例(复制成 .env)
requirements.txt 依赖
data/study.db SQLite 库(账号/设置/日志/快照)
study_video.py 独立命令行工具:按 trainCourseId 直接刷视频课时(会话也存 study.db)
dgjy-toolkit.user.js 浏览器油猴脚本(独立使用,与网页端无关)
app.py 启动壳:把 src 加进 sys.path,调 study_tool.app.main()
pyproject.toml 打包(src 布局;pip install -e . 后可用 study-tool 命令)
src/study_tool/
app.py 组装:FastAPI、鉴权中间件、页面 / health、启动 main()
webapp.py FastAPI 实例(路由模块从这里注册,避免循环导入)
runtime.py 运行状态 + 统一日志源(控制台 / 内存 / SQLite)
config.py 常量、环境变量、根目录定位(data / static / desenc.js)
store.py SQLite3:账号 / 设置 / 登录记录 / 运行日志 / 状态 / 缓存 / 快照
models.py HTTP 请求模型
settings_store.py 系统设置读写
llm.py 大模型调用
quiz.py 测验解析 / 交卷 / AI 答题
engine.py 学习引擎:发现 → 按平台分发 → worker / 视频 / 提交
capture.py 抓包
platforms/ 平台插件
base.py Platform 契约(id / label / study / entries)
registry.py 注册表:register / get / detect / all
detect.py 页面代际识别(旧版 / 新版 SPA)
guanyixue.py 莞易学:合并 jspx 登录入口与 study 学习入口
jspx.py 莞易学旧版页面实现
study.py 莞易学新版 SPA 实现
routes/ HTTP 接口
accounts.py 账号 / 登录 / 登录记录
misc.py 课程 / 发现 / 学习 / 停止 / 抓包 / 快照 / 平台列表
logs.py /api/log、/api/runs
web/ 前端源码(React 19 + TypeScript + Vite + Tailwind CSS v4)
static/ 前端构建产物(index.html + assets/ + favicon.svg)
des.js desenc.js DES 加密(登录表单 rsa 字段,站点原版算法)
start.bat 一键启动(Windows)
Dockerfile Docker 镜像(python:3.12-slim + nodejs + chromium)
docker-compose.yml Docker 编排:端口、数据卷、AUTH_TOKEN、健康检查
.env.example 远程管理用的环境变量样例(复制成 .env)
requirements.txt 依赖
data/study.db SQLite 库(账号/设置/日志/快照)
docs/architecture.md 分层说明 + 平台插件怎么加
study_video.py 独立命令行工具:按 trainCourseId 直接刷视频课时(会话也存 study.db)
dgjy-toolkit.user.js 浏览器油猴脚本(独立使用,与网页端无关)
```
分层与插件契约见 [docs/architecture.md](docs/architecture.md):引擎只按 `course["platform"]`
从注册表取平台实现;平台用 `entries` 声明登录 / 学习入口,新增平台不用改 engine / 路由 / 前端。
日志统一从 `runtime.log()` 出:控制台、页面卡片「课程日志」(按账号 id)、右上角「系统日志」(key=system)
看到的是同一份;新增日志不要再自己 `print()`。
## 登录链路
```
@@ -156,7 +202,9 @@ GET jspx.dgjy.net/admin/main.action table-results 课程表
`requests` 不执行 JS,中间两跳是手工解析 `scriptLogin.src` 和 `verifyURL` 走完的。
新版平台(慕课)另走一条 OAuth 码换 token 的链,拿到 `study.dgjy.net` 的 `Middle-Token`,见 `ensure_study_session()`。
新版页面(慕课)另走一条 OAuth 码换 token 的链,拿到 `study.dgjy.net` 的 `Middle-Token`,见 `ensure_study_session()`。
`jspx.dgjy.net` 与 `study.dgjy.net` 在注册表里是同一个平台(`guanyixue` / 莞易学),
课程发现时自动判断页面代际(旧版 / 新版),分别走 `jspx.py` / `study.py` 的学习实现。
## 接口
@@ -164,6 +212,7 @@ GET jspx.dgjy.net/admin/main.action table-results 课程表
| --- | --- | --- |
| GET | `/` | 控制台页面 |
| GET | `/api/health` | 存活探测:pid / port / runs / SQLite 路径与行数(不需要 token) |
| GET | `/api/platforms` | 已注册平台(id / label),用于界面展示平台名 |
| GET | `/api/accounts` | 账号列表(会话、课程缓存、勾选,**不含密码**) |
| POST | `/api/accounts` | 新增/更新账号;`password` 不传 = 保留库里原密码 |
| GET | `/api/accounts/{id}` | 单个账号 |