Initial commit

This commit is contained in:
Z User
2026-06-06 05:21:10 +00:00
Unverified
commit 6664758a6d
493 changed files with 135653 additions and 0 deletions

191
skills/quiz-html/SKILL.md Executable file
View File

@@ -0,0 +1,191 @@
---
name: quiz-html
description: 把题目数组生成一个**可独立运行的网页练习页**HTML 文件)。当用户完成 quiz-mastery 的「从资料出题」或「从文件提取题目」流程后,应主动询问是否需要"在网页里练习",确认后调用本 skill 把题目注入模板,生成 HTML 给用户。也支持用户直接说"把这些题做成网页/HTML/练习页"时触发。**不处理**:出题(→ quiz-mastery、评分→ quiz-mastery、长期复习计划→ study-buddy
---
# 网页题库生成器 (Quiz HTML Builder)
把一组题目 JSON → 一个**单文件 HTML 练习网页**,包含:
- 📂 分类筛选(学科 / 子模块)+ 学习状态筛选(已掌握 / 未做 / 错题)
- 🎯 4 种题型支持:选择 / 判断 / 填空 / 简答
- 🤖 答题自动标记,错题自动归入错题本(首次错误给一次重试机会)
- ⌨️ 完整键盘快捷键A/B/C/D · Enter · 方向键 · Space
- 📝 模拟考模式(限时 + 一次性提交 + 成绩页)
- 🌓 明暗主题切换 · localStorage 持久化 · 移动端适配
## 核心触发场景
### 场景 1quiz-mastery 出题/导入完成后主动询问 ⭐
这是本 skill 的**主要入口**。当 `quiz-mastery` 完成以下任一流程:
- 「从资料出题」:`generate_from_material.py` → 生成题目 JSON → `service.import_questions()` 入库
- 「从题目文件提取」:`import_quiz.py` → 解析出题目 JSON → 入库
quiz-mastery 出题完成、向用户展示题目前,**主动问一句**
> "题目准备好啦~ 要不要我把它们生成一个网页练习页?你可以在浏览器里慢慢做,错题会自动记下来,还能切换主题、模拟考试 🎯"
用户说"要 / 好 / 生成网页 / 来一个 / 嗯"任一肯定意思 → 调用本 skill。
用户说"不用 / 算了 / 直接在这里做" → 走原本的对话练习流程。
### 场景 2用户直接要求生成网页
触发关键词:
- "把这些题做成网页"、"做个 HTML 练习页"、"生成一个题库网页"
- "我想在浏览器里练"、"做个网页版"
- "把题目导出成 HTML"
## 调用方式
### 一句话总结
```bash
python3 scripts/build_quiz_html.py <题目JSON文件> [--title "..." --open]
```
### 标准流程
1. **拿到题目 JSON**(数组,每项是一道题)
- 来源 Aquiz-mastery 出题后的 LLM 输出(系统已是标准格式)
- 来源 B用户直接粘贴的题目数组
- 来源 C从数据库读取的题目quiz-mastery 的 `data/sessions/<sid>/questions.json`
2. **写到临时 JSON 文件**
```python
import json, tempfile
from pathlib import Path
tmp = Path(tempfile.mkdtemp()) / "questions.json"
tmp.write_text(json.dumps(questions, ensure_ascii=False), encoding="utf-8")
```
3. **调用脚本**
```bash
python3 ~/Desktop/studybuddy_4.0/skills/quiz-html/scripts/build_quiz_html.py \
/tmp/xxx/questions.json \
--title "📚 物理 · 热学练习" \
--output ~/Desktop/quiz_物理热学_20260518.html \
--open
```
4. **解析返回 JSON**
```json
{
"success": true,
"output_path": "/Users/.../quiz_xxx.html",
"question_count": 8,
"title": "📚 物理 · 热学练习",
"subtitle": "共 8 题 · 选择×5 · 判断×2 · 填空×1 · 物理",
"id": "q_1779091201",
"size_bytes": 63752
}
```
5. **告诉用户**:把 HTML 路径报给用户,提示「已经在浏览器打开了,可以开始练啦 ✨」
## 题目 JSON 字段标准
完全兼容 quiz-mastery 输出格式,**新增可选字段** `category` / `memory_tip`
| 字段 | 必填 | 说明 |
|---|---|---|
| `type` | ✅ | `single_choice` / `true_false` / `fill_blank` / `short_answer` |
| `prompt` | ✅ | 题干。也兼容 `question` 字段(自动转换) |
| `options` | 选择题必填 | `["A. xxx", "B. yyy", ...]` |
| `answer` | ✅ | 选择题填字母;判断题填 `"True"`/`"False"`;填空/简答填文本 |
| `explanation` | 推荐 | 解析强烈建议填K12 学生需要) |
| `knowledge_point` | 推荐 | 知识点名(侧边栏二级分组用) |
| `category` | 推荐 | 分类路径,**用"学科 / 子模块"格式**`"物理 / 电学"`、`"数学 / 分数"` |
| `level` | 可选 | 难度 1-3 |
| `memory_tip` | 可选 | 记忆口诀会用橙色卡片高亮显示K12 神器) |
### 示例
```json
[
{
"type": "single_choice",
"prompt": "下列关于并联电路电流规律的说法,正确的是( )。",
"options": [
"A. 干路电流等于各支路电流之差",
"B. 干路电流等于各支路电流之和",
"C. 各支路电流相等",
"D. 干路电流大于任一支路电流的两倍"
],
"answer": "B",
"explanation": "并联电路中,**干路电流等于各支路电流之和**I = I₁ + I₂ + ...",
"knowledge_point": "并联电路电流规律",
"category": "物理 / 电学",
"level": 1,
"memory_tip": "🧠 并联看路口:进多少、出多少,电流不会消失"
}
]
```
## 设计原则
### 1. 自动 category让筛选有意义
如果题目缺 `category` 字段,最好补上(哪怕基于学科推断)。否则所有题都堆到"通用"分类下,分类筛选就废了。
### 2. category 用"学科 / 子模块"
- ✅ `"物理 / 电学"`、`"物理 / 热学"` → 顶部出 4 个细分类 chip
- ❌ `"物理"` → 只出 1 个,子模块在侧栏体现,但筛选粒度变粗
### 3. 知识点和分类不是同一层
- `category` = 横向分类(哪个学科/章节),用于**顶部 chips 筛选**
- `knowledge_point` = 细粒度知识点,用于**左侧栏二级分组**
### 4. 输出文件命名
默认输出到题目 JSON 同目录,文件名 `quiz_<title_slug>_<时间戳>.html`。
**建议显式传 `--output`**,放到 `~/Desktop/` 或一个固定目录方便用户找。
## 工作示例quiz-mastery 衔接全流程)
```python
# 1. quiz-mastery 已完成出题,拿到题目数组
questions = [
{"type": "single_choice", "prompt": "...", "options": [...], "answer": "A",
"explanation": "...", "knowledge_point": "...", "category": "物理 / 电学"},
# ...
]
# 2. agent 问用户:"要不要做成网页版?"
# 3. 用户:"要"
# 4. agent 写临时文件 + 调用 skill
import json, subprocess, tempfile
from pathlib import Path
tmp_dir = Path(tempfile.mkdtemp(prefix="quiz_"))
qjson = tmp_dir / "questions.json"
qjson.write_text(json.dumps(questions, ensure_ascii=False), encoding="utf-8")
output = Path.home() / "Desktop" / "quiz_物理电学.html"
result = subprocess.run([
"python3",
str(Path.home() / "Desktop/studybuddy_4.0/skills/quiz-html/scripts/build_quiz_html.py"),
str(qjson),
"--title", "📚 物理 · 电学练习",
"--output", str(output),
"--open",
], capture_output=True, text=True)
info = json.loads(result.stdout)
# info["output_path"] = "/Users/.../Desktop/quiz_物理电学.html"
```
然后告诉用户:
> 「已经做好啦~ 网页已自动打开 ✨
> 路径:`~/Desktop/quiz_物理电学.html`
> 慢慢做,做完会自动记录错题,下次可以筛"错题"专门攻克 💪」
## 与其他 skill 的边界
| 任务 | 用谁 |
|---|---|
| 从资料出题 | **quiz-mastery** |
| 从文件提取题目 | **quiz-mastery** |
| 评分、掌握度追踪、艾宾浩斯安排 | **quiz-mastery** |
| 把题目做成网页给用户在浏览器练 | **quiz-html**(本 skill |
| 学习计划、长期跟进 | **study-buddy** |
## 失败处理
- `exit 1`:参数错误 / 文件不存在 / 模板缺失 → 报错给用户,让用户检查路径
- `exit 2`JSON 格式问题 / 题目数据非法 → 告诉用户哪几题被跳过,提示检查字段
- 部分题被 skip 但有合法题:仍会成功生成,但 stderr 会列出被跳过的题,需要在回复里告知用户「跳过了 N 题,原因 XXX」