夏艳的AI课堂 —— 云端交互学习界面 · 学生端⇄教师端切换
1. 系统组成(现网已验证)
| 文件 | 作用 | 换主题时 |
|---|---|---|
questions.json |
题库(N 题单选,含 kp/ppt_ref 溯源) | 整体替换 |
review_bank.json |
知识点讲义 + 逐题错题复习包(每题 3 变式) | 整体替换 |
student.html |
学生端:闯关地图、5 轮重测、错题复习包、作答实时写云库;顶部常驻切换条可一键跳教师端 | 读取 THEME(标题/题数/关卡图标文案/徽章自动跟随,无补丁) |
teacher.html |
教师端:实时作答/成绩表盘/掌握分析/得分排名 + CSV 导出 + 清空数据;顶部常驻切换条可一键跳学生端 | 读取 THEME(标题自动跟随,无补丁) |
server.py |
零依赖后端:原 /api/questions、/api/key、/api/meta、/api/review、/api/practice_check 等全部保留;五大模块 API(/api/space、/api/profile(s)、/api/perception、/api/warnings、/api/subscribe、/api/push/weekly、/api/sim/list、/api/simulation、/api/library/、/api/analytics2、/api/seed/load);画像模型深化 API(/api/table5、/api/capability、/api/profile/weekly、/api/class/distribution、/api/class/fiveavg、/api/classplan、/api/report/weekly、/api/warnings/email、/api/config/teacher_email);启动时若同目录存在 seed_students.json 自动载入验证数据* | 补丁(课程名) |
sim.py |
本地冒烟测试(模拟 3 轮作答,打服务端 session 接口) | 不动 |
space.html |
新增·学生端学习区间:化名/二维码自动进入、学情档案(六类过程数据)、个人智能预警、邮箱订阅与周推送预览、虚拟仿真演练、会诊/研学/反馈上报。走真实云端(CloudDB + CloudAnalytics,昵称直进;参考元数据由 server.py 的 /api/meta、/api/table5、/api/sim/* 提供) | 读取 THEME(课程名/知识点名自动跟随,无补丁) |
console.html |
新增·教师端增强看板:学情档案总览、预警中心(知识点错误率>50%)、仿真演练看板、题库迭代(一键入库)、订阅统计、导入验证数据、扩展 CSV | 读取 THEME(标题自动跟随,无补丁) |
nav.html |
新增·总导航页 /nav:聚合学生端 /、教师端 /teacher.html、学习区间 /space、增强看板 /console 四个入口,读取 THEME 显示课程名,分享码从 URL 透传;满足"多端进去演练" |
读取 THEME(课程名自动跟随) |
sims.json |
新增·虚拟仿真演练场景(模板内为通用占位示例,每步带 kp 溯源与答案;生成实例时随主题整体替换) | 随课程替换 |
qrcode.min.js |
新增·零依赖二维码库(qrcode-generator,纯 JS 单文件),供教师端"学生入口二维码"模块生成二维码;由 server.py 静态路由 /qrcode.min.js 提供 |
随模板 |
gen_fake.py |
新增·验证工具:生成 60 名虚假学生(覆盖六类过程数据+仿真+邮箱订阅)写入 seed_students.json,用于功能验证 | 不动 |
theme.js |
【主题模块·核心】 所有「内容特定部分」的单一数据源:课程名、副标题、关卡图标/文案、徽章、各端标题、知识点名。四个页面与 server.py 统一从此读取;换主题只重写此文件(由 swap_topic.py 单点注入 THEME_CONFIG 标记区块)。 |
由 swap_topic.py 单点注入(标记区块) |
theme.json |
【可配置传入参数】 主题配置(与 theme.js 同内容,供 server.py 运行时读取 course 等)。由 swap_topic.py 写出到部署目录。 | 自动写出 |
- 现网演示(按主题新生成):技能为「纯模板框架」,不内置任何固定课程;每次输入主题由智能体全量生成并部署为独立云实例(详见第 5 节 模式 C)。换主题不再依赖历史范例,
examples/theme.schema.json是唯一输入模板。 - 部署目录约定:每门新课一个独立目录
quiz_<slug>/,sites工具按目录反查应用,重复部署保持同一链接。 - 云数据库 7 表:
quiz_answers(student_name,round_no,question_id,option,correct,created_at)、quiz_practice(student_name,variant_id,correct)、quiz_perception(student_name,kind,data)、quiz_sim(student_name,sim_id,answers,score,progress)、quiz_subscription(student_name,email,rhythm,enabled)、quiz_config(key,value)、quiz_library(title,type,kp,source,body);RLS 全部FOR ALL USING(true) WITH CHECK(true),GRANTauthenticated, anon - 判分链路:学生端从
/api/key取答案索引本地判 correct → 写quiz_answers;小测经/api/practice_check判分后写quiz_practice;教师端拉云表 +/api/meta在浏览器内聚合 - 双向切换:学生端/教师端顶部均有一个常驻绿色切换条,点击即互跳;学生端切换教师端用
/teacher,教师端切换学生端用/app,两条路径均动态透传、不被边缘缓存。 - 静态缓存陷阱(已缓解):CloudStudio Gateway 会把
/与/student.html当作静态文件长期缓存(响应头含Eo-Cache-Status: HIT、Last-Modified固定),即使 server.py 已返回Cache-Control: no-store仍无法刷新;因此正式入口固定用/app,不要让学生直接访问/或/student.html。换主题不生效的根因:旧版只改了内容却没重生成+重部署,网关继续命中旧theme.js。现swap_topic.py已对<script src="theme.js">追加?v=<主题hash>(缓存击穿),换主题重跑生成+部署后浏览器/网关必定拉取新 theme.js,旧主题不再残留。内部测试如需确认最新版,可访问/student.html?v=2或/app。 - 统一入口
/nav:新增总导航页,聚合学生端/、教师端/teacher.html、学习区间/space、增强看板/console四个入口,自动读取 THEME 课程名、分享码从 URL 透传——把"多端进去演练"收敛到一个链接。
本技能目录:
- template/ —— 与线上部署版逐字一致的模板(server.py / student.html / teacher.html / space.html / console.html / nav.html / theme.js / theme.json / cloud-config.js / cloud-db.js / cloud-analytics.js / sim.py / sims.json / qrcode.min.js)
- scripts/validate_content.py —— 内容硬校验(独立可用)
- scripts/swap_topic.py —— 一键换主题(校验→备份→复制模板→单点注入 theme.js + 写出 theme.json + theme.js 缓存击穿(?v=hash) → 自检)
- scripts/generate.py —— 极速编排:调用 swap_topic 生成实例 + 复制 setup_db.sql 进实例目录 + 打印四端入口;把多步生成压成单条命令
- scripts/setup_db.sql —— 一键建表脚本:7 表 + 启用 RLS + 授权 + 全表开放策略,部署后用 db_exec(migrate) 跑一次即可(替代约 21 次逐表调用)
- examples/ —— 换主题唯一输入模板 theme.schema.json(含字段说明 + 中性占位骨架,复制填写即可驱动全量生成;详见第 5 节 模式 C)。技能不再内置任何固定课程的题库/复习包/主题范例,全部按主题现生成。
1.1 主题配置(内容特定部分统一收口 · 2026-10-21 重构)
> 为何要抽主题:早先课程名、副标题、八关图标「虫玉检药盾雨验成」、徽章文案散落在各页面与 server.py 里,换主题要打多处补丁、易漂移。现把所有「内容特定部分」收口为一个可配置主题:theme.json(传入参数)+ theme.js(前端运行时模块,单一数据源)。
主题如何流动:
老师设定主题 theme.json
│ swap_topic.py 单点注入
▼
template/theme.js (window.THEME:course/sub/stations/badges/kpNames/各端标题…)
│ 四个页面 <script src="theme.js"> 读取
▼
学生端/教师端/学习区间/增强看板 文案与图标随主题自动切换
│ swap_topic.py 同时写出 theme.json
▼
server.py 运行时读 theme.json → /api/info 课程名、教学周报标题、启动打印 同步
theme.json schema(可配置传入参数):
{
"course": "课程名(必填)", // 出现在各端标题、学生端大标题、/api/info
"sub": "单元/副标题(必填)", // 学生端副标题
"rounds": 5, // 闯关轮次机会(可选,默认 5)
"stations":[ // 关卡:每题一个图标+文案;数量须等于题数;最后一关=达成
{"icon":"虫","label":"识虫"}, ... , {"icon":"成","label":"达成"}
], // 缺省:自动用中性通用图标(一二三…/第X题)
"badges":[ // 徽章(基于答题机制,可改名/改图标)
{"name":"全对之星","icon":"满","kind":"perfect"}, // kind: perfect/progress/persist/practice/combo
...(共 5 枚,缺省用标准 5 枚)
],
"kpNames":{"KP1":"知识点一", ...} // 知识点显示名;缺省由 swap_topic.py 从 review_bank.json 自动提取
"zoneName":"学习支持服务区间", // 学生端「学习支持服务区间」名称(可选,默认"学习支持服务区间")
"pushFreqs":["每周","每天","每月"], // 主动服务:知识推送可选频次(可选,默认此三项)
"weakServiceName":"学习薄弱点支持服务", // 主动服务:薄弱点支持服务名称(可选,默认此名)
"tabs":{"profile":"学情档案","ability":"能力画像","warn":"智能预警","service":"主动服务","sim":"仿真演练","report":"过程上报"},
// 学习支持服务区间六大板块名(可选,随主题可改)
"dimNames":{"D1":"知识掌握度","D2":"实践操作力","D3":"协作问诊力","D4":"自主研学力","D5":"反思改进力"}
// 能力画像五维名(可选,与 server.py /api/table5 联动)
"prompts":{"consult":"描述你的疑问,如:智能灌溉该依据什么数据决定浇水?",
"research":"任务内容,如:完成本单元案例调研并提交小结"}
// 学习支持服务区间「过程上报」两处输入框占位词(可选,随主题切换,
// 避免旧主题示例残留);consult=问诊/咨询占位,research=自主研学任务占位
"explainTitle":"可视化精讲", // 学习支持服务区间「可视化精讲」模块名称(可选,默认"可视化精讲")
"kpGroups":[ // 可视化精讲:知识点分组(可选,默认 [] 不分组平铺)。
{"name":"道·原理","kps":["KP1","KP2","KP3","KP4"]}, // 每组 name=组名,kps=该组知识点键(须是 kpNames 中已有键)
{"name":"术·职能","kps":["KP5","KP6","KP7","KP8"]}
] // 空数组 [] 则所有知识点按 KP1..KPN 平铺成网格;分组后按组渲染并支持「道/术」式对照
}
- 图标规范:统一用 CJK 单字 / ASCII 字符(如
虫玉检药盾雨验成、苗土肥剪形病虫成),不依赖 emoji(遵循本技能「emoji 跨环境渲染失败」的清理原则,Windows 部分浏览器下稳定一致)。 - stations 数量约束:
len(stations)必须等于题目数 N;swap_topic.py会强制校验,不齐即报错中止。 - 缺省兜底:仅给
--course/--sub时,关卡用通用图标、徽章用标准 5 枚、kpNames 从题库自动提取——无需手抄。 - rounds/storageKey:
rounds改后学生端副标题与「坚持之星」阈值同步;storageKey默认pd_quiz,改它会导致旧本地预览作答丢失,一般不动。
换主题只动一处 + 必重部署:老师改 theme.json 后跑 swap_topic.py --theme ...(或 generate.py),脚本只重写 theme.js 的 THEME_CONFIG 区块并写出 theme.json,四个页面与 server.py 代码零改动;同时给 theme.js 引用追加 ?v=<主题hash> 缓存击穿。注意:主题只在「重新生成实例 + 重新部署」时才写进线上,改完必须重部署,否则线上还是旧副本(这是"换主题不生效"的唯一原因)。这是本技能「统一维护」的关键。
1.2 纯云端模式与微信内打开(2026-10-21 增强)
纯云端模式(部署后即云端,不丢数据)
- cloud-config.js 默认 forceCloud: true:部署(https)后所有作答/学情实时写入云端 PostgreSQL,教师端看板可立即看到;且不再回退 localStorage(旧逻辑在云端不可用时静默写本地、导致教师端看不到,现已禁止)。
- 若部署后云端客户端未能初始化(如 CDN 被拦截),页面顶部弹红条告警「云端连接未建立,当前作答可能不会保存,请刷新或检查网络」,而不是悄悄丢数据。
- cloud-db.js 的 localStorage 读写已包 try/catch,兼容微信隐私模式等禁用 localStorage 的环境。
微信内直接打开(发链接即可演练)
- 入口:把总导航 /nav?sharecode=AK2NDLDHX2(或学生端 /?sharecode=...)链接发到微信群/好友,微信内点开即进入演练;分享码随 URL 自动透传——theme.js 里的 AppCore 在 DOMContentLoaded 时给所有内部 a[href^="/"] 自动补 ?sharecode=,四端互相跳转不丢码。
- 切换条全量跟随分享码:学生端→学习区间/教师端、教师端→增强看板/学生端、学习区间→闯关、增强看板→教师端,全部带码跳转,不再跳到无码地址触发"链接不完整"网关拦截。
- 学生入口二维码带码:教师端/增强看板的「学生端入口二维码」URL 现在自动拼接当前分享码(buildQREntry 改动),微信扫码进入同样可直接演练(旧版不带码会掉码被拦)。
- 剪贴板兼容:微信禁用 navigator.clipboard,已全部改用 AppCore.copyText(),优先 navigator.clipboard、失败自动回退 document.execCommand('copy')(地址复制、周报复制均可用)。
- 微信内提示:检测到 MicroMessenger 时页面底部轻提示「如需扫码进入或导出文件,请用手机浏览器打开」,导出 CSV / 下载二维码等依赖浏览器能力的操作在微信内会引导用浏览器完成。
- 缓存击穿:server.py 对所有 HTML/JS 发 Cache-Control: no-store,theme.js 另带 ?v=<主题hash> 版本号;换主题重部署后微信/网关必定拉取新文件,旧主题不残留。
- 长期多端演练:部署后实例长期在线,任意时间、任意网络、任意端(学生/教师/学习区间/增强看板)带分享码即可进入。
2. 三种模式
- 模式 A:换内容、同网址 —— 已有实例换成新课主题。替换 JSON + 重部署同一目录,链接不变(适合同一课程迭代内容)。
- 模式 B:新课程、新实例(手动备料) —— 另一门课开独立系统(独立链接、独立云环境)。先开通云服务拿
publicConfig,再生成新目录并部署。 - 模式 C(推荐,默认):只给主题 → 全量生成并部署 —— 用户只需给出「课程名 + 副标题 + 教学考点资料」,智能体据此生成题库/复习包/仿真/主题全套内容,自动开云、建表、换装、部署为独立云实例。换主题不再需要手抄任何 JSON。详见第 5 节。
3. 模式 A 工作流(换内容、同网址)
第 1 步 依料生题(RAG 纪律)
向用户索取:课程主题 + 教学考点资料(教材章节/防治规程/常见误区/往届错题)。据此生成:
- questions.json:建议 8 题(允许 4–12 题),每题 4 选项、答案 0–3、解析回链考点出处;
- review_bank.json:知识点讲义 + 每题 3 道变式(基础/巩固/挑战)。
严禁编造:ppt_ref 只能写用户资料中真实存在的出处(如"教材第3章 第X节");资料没有的内容不入题。
第 2 步 内容落盘
写入工作目录(建议会话目录下 topic_<主题slug>/questions.json 与 review_bank.json)。schema 见第 7 节。
第 3 步 一键换装(自动校验+备份+单点注入主题)
python "C:/Users/夏艳/.workbuddy/skills/xiayan-ai-classroom/scripts/swap_topic.py" \
--theme "C:/路径/theme.我的课程.json" \
--questions <新questions.json> --review <新review_bank.json> [--sims <新sims.json>] \
--in-place "C:/Users/夏艳/WorkBuddy/<会话目录>/quiz_<主题slug>"
脚本自动完成:内容硬校验 → 整目录备份到 quiz_<主题slug>_backup_<时间戳> → 复制模板 → 单点注入 theme.js 的 THEME 区块 + 写出 theme.json(课程名、副标题、关卡图标/文案、徽章、知识点名随主题一次到位)→ 自检。主题文件缺 stations 时按题数自动补通用图标;stations 数量 ≠ 题数会直接报错中止(防错位)。兼容旧用法:--course/--sub [--icons/--labels] 仍可只给课程名,关卡用通用图标。
第 4 步 本地试运行
cd "C:/Users/夏艳/WorkBuddy/<会话目录>/quiz_<主题slug>"
PORT=8765 python server.py # 托管 Python 亦可
curl http://127.0.0.1:8765/api/questions # 首题应为新题
curl http://127.0.0.1:8765/api/info # course 应为新课程名
curl http://127.0.0.1:8765/api/meta # kp/ppt_ref 应为新内容
python "C:/Users/夏艳/.workbuddy/skills/xiayan-ai-classroom/template/sim.py" # 3 轮模拟,SIM OK 即通过
第 5 步 清云端旧作答(必须)
换主题后云表里的旧作答与新题混杂。两种清法任选:
- 教师端页面"清空数据"按钮(内部对 quiz_answers/quiz_practice 全表 delete,并重置 quiz_config);
- MCP:mcp__genie-baas__workbuddy_cloudservice_db_exec_sql(先 workbuddy_cloud_service action="activate" applicationMode="reuse" applicationId="<本实例的 wbapp_id>" 绑定会话),执行 delete from quiz_answers; delete from quiz_practice; delete from quiz_perception; delete from quiz_sim; delete from quiz_subscription; delete from quiz_config;(mode=write,逐条执行)。
第 6 步 重部署(精确参数,勿凭记忆)
由智能体调用 workbuddy_sites_deploy:
directory = C:/Users/夏艳/WorkBuddy/<会话目录>/quiz_<主题slug>
language = python
startCmd = python3 server.py
installCmd = "" ← 空串跳过安装(零依赖)
domainPrefix= quiz-<主题slug> ← ASCII 短横线,每个主题一个全新实例域名
userAskedToPublish = true ← 交付口径:任何主题一律直接生成并部署为【新云实例】,
禁止询问"如何发布/部署/交付";本轮直接部署并交付学生端链接。
红线:绝不能省略 language/startCmd 用 auto——auto 会把"Python 服务 + 静态页"误判为纯静态站,平台用自带静态服务器替代 server.py,/api/* 全部返回 404 HTML,学生端报 Unexpected token '<'。
第 7 步 线上验证
curl https://quiz-<主题slug>.app.workbuddy.host/api/questions # 新题
curl https://quiz-<主题slug>.app.workbuddy.host/api/info # 新课程名
再用手机过一遍学生端(闯关→错题复习包→成绩页→徽章),教师端逐个点击四个页签(实时作答/成绩表盘/掌握分析/得分排名)确认都有内容 + CSV 导出。若案例文本引用了题库描述(课程名/题量/考点),同步更新。
静态页必须做缓存比对(否则会把"边缘缓存旧版"误判成"没部署"):
curl -s "https://<域名>/teacher.html?cb=$(date +%s)" | md5sum # 应等于本地 md5sum teacher.html
不一致才需再部署;一致但用户仍看到旧页面 ⇒ 属边缘缓存,交付带 ?v=N 的链接。
4. 模式 B 工作流(新课程、新实例)
> ⚠️ 红线前置:建表是模式 B 的强制步骤,不可省略、不可与换装/部署调序。
> 新开通的云应用默认没有任何数据表。若漏掉建表直接换装+部署,学生端点击「开始答题」写入作答时会报
> Could not find the table 'public.quiz_answers'(2026-09-28 实踩)。swap_topic.py 只替换前端内容(题库/复习包/课程名),
> 不会创建云端数据表、也不会改云端配置——建表必须单独用 MCP 工具完成(步骤 3),cloud-config.js 由新应用的 publicConfig 手写。
- 新目录先写占位:把
template/全部模板文件复制到新目录(如C:/path/quiz_<slug>/);其中cloud-config.js含本实例专属的 endpoint/publishableKey,新建课程必须换成自己的 publicConfig(见步骤 2),不要复用其他课程的配置,否则作答会写入错误应用的数据库。 - 开云环境(自动开通,不询问):
workbuddy_cloud_serviceaction="activate"directory=<新目录>applicationMode="create"appName="<课名>互动答题"domainPrefix="quiz-<slug>"→ 返回publicConfig{endpoint, publishableKey}。智能体直接调用开通,全程无需向用户提问或等待确认(endpoint/publishableKey/确认均由工具返回后自动写入cloud-config.js)。 - 建表(强制,先于换装与部署):
generate.py已在实例目录写出setup_db.sql(7 表 + 启用 RLS + 授权 + 全表开放策略)。用workbuddy_cloud_serviceaction="activate"applicationMode="reuse"applicationId=<新应用ID>绑定会话,再对setup_db.sql执行一次mcp__genie-baas__workbuddy_cloudservice_db_exec_sql(mode=migrate,整文件作为单条脚本)。建完用db_list_tables核对七表存在且RLSOn: true。
自检(必做):用测试账号对quiz_answers做一次 INSERT → SELECT → DELETE,确认云写入链路通,再进下一步。 - 换装:
swap_topic.py --course ... --sub ... --questions ... --review ... --out <新目录>(替换题库/复习包/课程名;不再改云端配置——cloud-config.js由步骤 2 的 publicConfig 手写,模式 B 每门新课独立)。⚠️ 若swap_topic.py仍含PUBLIC_CONFIG替换锚点,需先移除(新模板已无内联PUBLIC_CONFIG,改为独立cloud-config.js),否则锚点失配报错。 - 部署:
workbuddy_sites_deploydirectory=<新目录>language="python"startCmd="python3 server.py"installCmd=""domainPrefix="quiz-<slug>"appName="<课名>互动答题"。 - 验证:新链接四端点 + 双端走一遍;再测一次学生端真实作答,确认不再报"找不到表"。
交付口径(默认只给「课堂互动系统·学生端」)
- 只交付学生端:生成/部署完成后,默认只把「课堂互动系统·学生端」入口交给用户——即学生端闯关答题链接(正式入口固定用
/app,如https://<域名>/app?sharecode=xxx)。教师端 / 学习区间 / 增强看板 / 总导航等模块虽在后端保留,但不在交付中提及、不主动给出其链接,除非用户显式要求。 - 云端自动开通:步骤 2 的开云动作由智能体直接执行,不向用户询问任何信息、不等待确认;publicConfig 由工具返回后自动写入
cloud-config.js,用户无需参与。 - 链接即交付物(2026-10-22 强化):交付主体是部署后的正式学生端链接(
https://quiz-<slug>.app.workbuddy.host/app?sharecode=<码>),放在回复最顶部;应用卡片只是管理入口,不作为交付主体。交付前必须已完成部署并用 curl 验证线上可用(/app200、/api/questions返回题库 JSON);"仅本地预览、未部署"的状态一律不得交付(见坑 #23)。 - 卡片入口注记:部署后应用卡片(
.genie)默认缺entryHtml字段,点击卡片预览会「Not Found」。需手动补entryHtml: student.html(见坑清单 #17);学生端直达链接https://<域名>/app?sharecode=<码>不受此影响,始终可用。
5. 模式 C(推荐):只给主题 → 全量生成并部署新云实例
> 这是默认推荐路径:用户只需给出「课程名 + 副标题 + 教学考点资料」,智能体据此生成全套内容(题库 / 复习包 / 仿真 / 主题配置)并一键部署为独立云实例。换主题不再需要手抄任何 JSON。
>
> 交付铁律(2026-10-22 起,两次强化):任何主题输入 → 直接生成新课、自动开启云服务(workbuddy_cloud_service activate)并部署为新云实例,全程禁止询问"要怎么部署/发布/交付?""需不需要开启云服务?""能不能用云端数据/存储/登录/统计?"之类的问题——云服务默认必开(数据存储/用户登录/访问统计是课堂答题与学情看板的硬依赖),部署与开云动作由智能体直接执行完毕后交付学生端链接。也不复用任何历史课程实例(技能已彻底清除全部旧课程内容,纯模板框架)。
>
> ⛔ 特别禁令(2026-10-22 用户第三次反馈后追加):禁止在对话中输出"实现课堂答题与学情看板需要开启云服务 → ①开启云服务 可使用云端数据/文件存储、用户登录、访问统计"这类确认卡片或任何形式的"是否开启云服务"提问,也不要停下来等待用户点击确认。正确做法:把"开启云服务"当作与"生成题库"同级的既定步骤静默执行——直接调用云服务开通(activate)→ 拿 publicConfig 写 cloud-config.js → 建表 → 部署 → 交付。用户在需求里说过一次"开启云服务",即视为对所有后续新课程的永久授权,任何新课程运行时都不得再次询问。
>
> 🚫 交付形式铁律(2026-10-22 用户第四/五次反馈,两次强化):所有新课交付的唯一结果 = 一条能打开的正式部署链接。具体口径:
> 1. 回复正文第一条就是完整可点击的 URL(https://quiz-<slug>.app.workbuddy.host/app?sharecode=<码>),域名必须逐字取自 workbuddy_sites_deploy 的返回值,不得自己拼写、改造或省略 sharecode。
> 2. 交付前必须实测这条链接能打开:curl -s -o /dev/null -w "%{http_code}" "<完整链接含sharecode>" 返回 200,且 curl -s "<域名>/api/questions" 返回题库 JSON;任一不满足 = 部署未完成,禁止交付(打不开的链接交出去等于没交付)。
> 3. 禁止用这些当交付结果:应用卡片 / 「查看所有产物」、「前往设置—数据管理—应用」管理入口、"已发布/已部署"一句带过却不给 URL——卡片和管理入口只是后台,用户上课只用链接。
> 4. 出现「本地预览模式:当前未连接云端…localStorage」横幅 = 只生成未部署,同样判定交付失败,补部署后以正式链接重新交付。
> 5. 链接打不开的排查顺序:部署实际是否成功(deploy 返回值里有没有域名)→ 域名是否拼错(必须逐字用返回值)→ auto 误判静态站(必须 language=python + startCmd)→ 边缘缓存(交付带 ?v=N 的链接)。
第 1 步 给主题与资料
向用户索取:课程主题(course + sub)+ 教学考点资料(教材章节 / 规程 / 常见误区 / 往届错题)。
第 2 步 智能体全量生成内容(严禁编造,ppt_ref 与考点必须源自用户资料)
- questions.json:建议 8 题(允许 4–12 题),每题 4 选项、答案 0–3、解析回链考点出处。
- review_bank.json:每个知识点 KP1..KPN 的 learning{summary, points≥3, memory_tip, common_mistake} + 每题 3 道变式(基础/巩固/挑战)。
- sims.json:虚拟仿真演练场景(每步带 kp 溯源与答案)。
- theme.<slug>.json:复制 examples/theme.schema.json,填入 course/sub/stations(或用中性占位)/kpNames/kpGroups 等。关键点:stations 数量 = 题数;kpGroups 用于「可视化精讲」分组(如「道·原理 / 术·职能」),留 [] 则平铺。
第 3 步 智能体开云 + 一键生成
1. 智能体先调 workbuddy_cloud_service action="activate" applicationMode="create" appName="<课名>互动答题" domainPrefix="quiz-<slug>" → 拿回 publicConfig{endpoint, publishableKey}(自动写 cloud-config.js,用户无需参与)。
2. 跑 generate.py(内部调 swap_topic.py 校验+单点注入 theme.js+写 theme.json,并复制 setup_db.sql):
python "C:/Users/夏艳/.workbuddy/skills/xiayan-ai-classroom/scripts/generate.py" \
--theme "C:/路径/theme.<slug>.json" \
--questions <新questions.json> --review <新review_bank.json> [--sims <新sims.json>] \
--out "C:/Users/夏艳/WorkBuddy/<会话目录>/quiz_<slug>" \
--endpoint "<上一步 endpoint>" --publishableKey "<上一步 publishableKey>"
- 建表:
generate.py已把setup_db.sql放进实例目录,用workbuddy_cloud_serviceapplicationMode="reuse"绑定该应用后,db_exec(migrate)运行一次setup_db.sql(7 表 + RLS + 授权 + 策略)。建完用测试账号 INSERT→SELECT→DELETE 自检云写入。 - 部署:
workbuddy_sites_deploydirectory=<实例目录>language="python"startCmd="python3 server.py"installCmd=""domainPrefix="quiz-<slug>"appName="<课名>互动答题"userAskedToPublish=true。
第 4 步 线上验证
新链接四端点(/app、/teacher、/space、/console)+ 双端走一遍;再用真实作答测一次云写入,确认不再报「找不到表」。
> ⚠️ 部署后应用卡片(.genie)默认缺 entryHtml,需补 entryHtml: student.html(坑 #17);学生端直达链接 https://<域名>/app?sharecode=<码> 不受此影响。
交付口径:默认只把「课堂互动系统·学生端」入口(/app?sharecode=)交给用户;教师端 / 学习区间 / 增强看板 / 总导航保留在后端但不主动给出,除非用户显式要求。交付形式:正式链接放回复最顶部,严禁以"本地预览卡片"交付(坑 #23)。
6. 出题与复习包规范(面向基层/成人学员)
- 题干写成真实决策情境("怎么判断/选什么/先做什么"),≤120 字、大白话;干扰项教学化(来自"常见误区"资料,能考出批判性思维)。
- 每题 4 选项为硬约束(教师端选项分布按 4 聚合);
answer为 0–3 整数。 - 知识点
KP1..KPN与题目一一对应:name / ppt_ref / learning{summary, points≥3, memory_tip, common_mistake}。 - 每题复习包:
core_point / error_causes / correct_approach / steps / pitfall+ 3 道变式(id=Qn-V1..V3,level=1/2/3对应 基础/巩固/挑战,选项 2–4 个,带解析)。 - 关卡图标与文案推荐在
theme.json的stations数组里随课程一次性设定(数量=题数);题数≠8 且未给stations时脚本自动换用通用图标与"第X题/达成"标签;也可用--icons/--labels临时自定义(逗号分隔,数量=题数)。
7. JSON Schema(严格)
// questions.json —— 数组
[{
"id": "Q1", // 必须 Q1..QN 顺序编号
"text": "题干(真实决策情境)",
"options": ["A文","B文","C文","D文"], // 恰 4 个
"answer": 1, // 0..3
"explanation": "解析:判断依据 + 回链考点出处",
"kp": "KP1" // 与 knowledge_points 一一对应
}]
// review_bank.json
{
"_schema": "说明文字(可选)",
"knowledge_points": {
"KP1": {
"name": "知识点名",
"ppt_ref": "教材第X章 XX(真实出处)",
"learning": {
"summary": "一句话定义",
"points": ["要点1","要点2","要点3","要点4"],
"memory_tip": "记忆锚点",
"common_mistake": "易错提醒"
}
}
},
"reviews": {
"Q1": {
"core_point": "核心考点",
"error_causes": "常见错因",
"correct_approach": "正确思路",
"steps": "判断步骤",
"pitfall": "易错提醒",
"variants": [
{"id":"Q1-V1","level":1,"text":"…","options":["…","…","…","…"],"answer":0,"explanation":"…"},
{"id":"Q1-V2","level":2,"text":"…","options":["…","…","…","…"],"answer":1,"explanation":"…"},
{"id":"Q1-V3","level":3,"text":"…","options":["…","…","…","…"],"answer":2,"explanation":"…"}
]
}
}
}
8. 坑清单(每条都真实踩过)
- 部署必须显式
language="python" + startCmd="python3 server.py" + installCmd="";auto 误判为纯静态站 →/api/*全 404 HTML → 学生端 JSON 解析报错,且教师端"能打开"更具迷惑性。 - 云 SDK Origin 精确匹配 + 本地预览降级(2026-09-28 新增):部署到 https 域名后走云端(数据跨设备实时同步、教师端看板);
file://双击或本地 http 服务器下自动切本地预览模式(LOCAL_MODE=true,用 localStorage + 内置样例题),页面可直接打开、完整跑通答题流程,但作答只存本浏览器、不同步教师端。判定逻辑:IS_DEPLOYED = (location.protocol === 'https:'),LOCAL_MODE = !IS_DEPLOYED。数据层(dbInsert/dbSelectWhere/revealState)与教师端refresh()均按LOCAL_MODE路由到云端或 localStorage。注意:模板template/student.html、teacher.html已内置SAMPLE_QUESTIONS与本地降级层;swap_topic.py生成的新实例会继承该能力,无需手工改动。 - 换题数必须同步
STATIONS/ICONS/LABELS(脚本已自动处理);漏改会导致进度地图错位/图标 undefined。 - 换主题后必须清云端旧作答,否则教师端学情混入旧题数据。
- server.py 启动时加载 JSON → 换内容不重部署不生效。
userAskedToPublish只在用户本轮明确要求发布时置 true;用户未要求时省略,工具会拒绝覆盖线上并提示确认——这是保护,不是故障。data/目录是服务端 session 落盘(审计用),换主题无需清理;正式作答在云表。- 回滚:模式 A 的备份目录
quiz_<主题slug>_backup_<时间戳>整目录复制回原位再重部署即可。 - 教师端页签切换选择器(模板曾长期带此 bug,2026-09-28 修正):旧模板写
$(t.dataset.t).classList.add("on"),而$=document.querySelector,缺#→querySelector("t2")按标签名查找返回null→ 点击任一页签即抛TypeError;由于代码顺序是"先移除所有面板on,再加目标面板",异常正好发生在中间,导致四个面板全被隐藏、整页空白(首屏"实时作答"正常,一点页签就全白,极像"除了实时作答其他模块都不显示")。现模板已改为document.getElementById(t.dataset.t),并在refresh()里一并渲染 T2/T3/T4(不再依赖点击触发)。验收动作:必须逐个点击四个页签确认内容出现,只看首屏不算通过。 - 成绩表盘角度公式(模板曾反向,2026-09-28 修正):旧模板
ang=Math.PI*(1-score/8)配x2=cx - r*cos(ang)把比例画反——8/8 时端点与起点重合(A58 58 0 0 1 12 70)弧线完全不可见,0/8 反而画出满弧。正确写法:
js const f=Math.max(0,Math.min(1,score/8)); const ang=Math.PI*(1+f); // 180°→360°,左端起经顶部到右端 const x2=cx + r*Math.cos(ang), y2=cy + r*Math.sin(ang); - 静态页边缘缓存(部署后"改了却看不到"的头号原因):重部署后即使源站已更新,
*.app.workbuddy.host的边缘缓存仍可能返回旧teacher.html/student.html,响应头为Eo-Cache-Status: HIT;且带Cache-Control: no-cache/Pragma: no-cache请求也照样 HIT,所以让用户"硬刷新 Ctrl+Shift+R"是无效的(别再让用户白折腾)。- 判定(必做):
curl -s "https://<域名>/teacher.html?cb=$(date +%s)" | md5sum与本地md5sum teacher.html比对。一致 ⇒ 源站已更新,问题纯属边缘缓存;不一致 ⇒ 才是真的没部署上去。 - 交付:直接给用户带版本参数的链接(
https://<域名>/teacher.html?v=2,查询串即新的缓存键,已实测可穿透),裸链接待 TTL 过期后自动恢复。 - 推论:凡"用户反馈某静态页还是旧样子",先做上述比对,不要重复重部署(重复部署不会清掉边缘缓存,只会浪费时间)。
- 判定(必做):
- 模式 B 必须先建云表(2026-09-28 实踩,强制项):新建独立云实例时,应用后端默认没有任何数据表。
swap_topic.py只替换前端内容,不建表也不改云端配置(cloud-config.js由新应用的 publicConfig 手写)。漏掉建表直接部署,学生端点击「开始答题」写入作答会报Could not find the table 'public.quiz_answers'。正确顺序:开云环境(拿 publicConfig 手写cloud-config.js)→ 建七表 + RLS + GRANT + POLICY(用 MCPdb_exec_sql,先于换装/部署)→ 换装 → 部署 → 验证。建完务必用测试账号 INSERT→SELECT→DELETE 自检云写入。详见第 4 节模式 B 步骤 3。 - 入口缺
.html后缀会 404(2026-09-28 实踩,已修复于模板):若有人直接访问/teacher或/student(不带.html),旧server.py会返回 Python http.server 默认 404 页。该问题已在template/server.py中修复(/、/student、/student.html、/index.html→ 学生端;/teacher、/teacher.html→ 教师端)。凡新建/换装的实例,务必基于修复后的模板重新部署,否则仍可能 404。诊断口诀:所有接口(/、/teacher.html、/api/info)都 200,却报 404 → 先问用户地址栏完整 URL 是不是少了.html。 - 教师端"得分排名"空白的排查路线(2026-09-28 实测结论:代码无 bug,先查数据/网络):
renderRank与 t1 的"学生名单"都由computeAll同一个students数组生成——若 t1 能看到学生,t4 排名必然有数据;t4 空白只可能源于ANA.ranking为空(即云端没读到"已完成整轮"的作答)。排查顺序:- ① 看教师端右上角
#clock:若显示"云端读取失败…"或"云服务未初始化" → 是云读取/CDN 网络问题(检查https://cdn.jsdeliviv.net/npm/@tencent-ai/workbuddy-cloud-sdk@dev/...能否加载、cloud-config.js的 endpoint 是否指向本实例域名)。 - ② 若
#clock正常("云端更新于…")但排名仍空 → 多半是云库里还没有"完成整轮"的作答(学生只答了几题没答满 N 题,或还没人作答),属正常空态,不是 bug;让学生端走完一轮即可。 - ③ 真机实测:用相同 SDK+anon key+endpoint 在 Node 里
cloud.database.from('quiz_answers').select('*')能返回全部行(error:null),pg_policies确认七表均有p_all ... USING(true) WITH CHECK(true);computeAll对真实作答必产出非空ranking。故"仅排名空白、其他页有数据"在本模板下不应发生——若用户坚持复现,优先要浏览器控制台截图与右上角#clock文字再定位。
- ① 看教师端右上角
- 名次列 emoji medals 在某些系统/浏览器显示为问号/菱形占位符(2026-09-28 实踩,已修复于模板):旧
renderRank对前三名用'🥇🥈🥉'[s.rank-1]作为名次列内容,Windows 部分浏览器或字体缺失环境下会渲染成"问号图标",用户误以为"没有显示排名"。已改为纯数字排名(s.rank),并通过 CSS 给前三名加金色圆形徽章(.rank-num+.rank-1/.rank-2/.rank-3),既无字体兼容问题,又保留视觉区分。 - 装饰性 emoji 在部分环境渲染失败(2026-09-28 系统性清理):实测用户 Windows 环境对 Miscellaneous Symbols and Pictographs(1F3xx/1F9xx)等 emoji 渲染不可靠(奖牌、👤、🌟、📈、🏅、📚、🔥、🎓、👩🏫、🐛 等均可能变问号/框)。模板已做系统性清理:
- 所有装饰 emoji 改为纯文字 / CJK 单字 / ASCII 符号:切换条(🎓/👩🏫 → "学生端"/"教师端" + "→")、徽章图标(🌟📈🏅📚🔥 → 满/进/久/习/连)、进度地图图标(默认 → 由
theme.json的stations配置,生成时随主题注入theme.js)、连击/复习提示(🔥/✨ → 文字)、对勾(✓/✗ → "回答正确"/"正确答案")、知识点标题(📖/🧩 → 文字)。 - 换装脚本
swap_topic.py已重构为「主题单点注入」:不再用ICONS/LABELS行前缀补丁,改为单点重写theme.js的THEME_CONFIG区块并写出theme.json,模板怎么改都不影响换装,且图标/文案/徽章/知识点名随主题一次到位。 - 原则:本技能生成的前端,一律不依赖 emoji 做关键信息的视觉载体;如确需图标,用 CSS 形状或 CJK 字符,保证跨环境一致。
- 所有装饰 emoji 改为纯文字 / CJK 单字 / ASCII 符号:切换条(🎓/👩🏫 → "学生端"/"教师端" + "→")、徽章图标(🌟📈🏅📚🔥 → 满/进/久/习/连)、进度地图图标(默认 → 由
- 应用卡片「Not Found」(2026-10-21 实踩,已修复于工作流):经
workbuddy_sites_deploy生成的应用卡片(.genie标记文件)默认不含entryHtml字段。WorkBuddy 卡片预览找不到默认入口文件index.html(模板本身无此文件),会显示「Not Found」。线上各路由(/app?sharecode、/space?sharecode 等)本身正常(curl 实测均 200),此坑只影响卡片预览入口。修复:部署后手动在对应的.wbapp_<appId>.genie文件追加一行entryHtml: student.html(学生端口径),指向quiz_<slug>/student.html;重新打开卡片即正常。每次部署/重部署后都必须补(重部署会清掉该字段;历史实例目录与 .genie 标记已于 2026-10-22 清理,今后每个新实例都要走此步)。如卡片仍 404,可改用直达链接https://<域名>/app?sharecode=<码>(不受卡片影响)。 swap_topic.py跨目录读取被沙箱拦截时的兜底(2026-10-21 实踩):在部分会话沙箱下,运行swap_topic.py读取~/.workbuddy/skills/...(技能目录,在 workspace 之外)会被拦截。兜底流程:先cp -r <技能>/template/. <新目录>/复制模板,再用theme.json内容(course/sub/stations/badges/kpNames/tabs/dimNames/prompts/zoneName/pushFreqs/weakServiceName)对齐模板theme.js的THEME_CONFIG区块结构手工写出theme.js,并cp题库/复习包/sims 进新目录、手写cloud-config.js的 endpoint/publishableKey、给 5 个 HTML 的<script src="theme.js">加?v=<主题缩写+序号>缓存击穿参数。结果与swap_topic.py自动生成等价。- 可视化精讲「没图 + 排版挤压」的两次改版(2026-10-22):初版用纯文字图标卡片、网格列宽
minmax(150px,1fr)、卡片内边距 12px,用户反馈"没有图、排版挤压"。改版后 ① 顶部加内联 SVG 知识点精讲图谱(中央课程枢纽→分组节点→知识点圆形节点,连线表达层级;纯 SVG+CJK、自适应宽度、不依赖图片/emoji);② 卡片网格放宽到minmax(220px,1fr)、内边距 16px、要点行高 1.7、组间距加大,要点最多展示 4 条(超出提示"见讲义")。换主题重部署时必须给theme.js加?v=版本参数,否则学生端仍看到旧版卡片/旧图谱。 - 主动推送改为「薄弱点答题精讲」(2026-10-22):原推送是"薄弱知识点强化:讲义出处 + 建议完成自测/会诊"的空泛文案。改版后
build_push_preview(server.py 与 cloud-analytics.js 两处同步)改为针对薄弱点按主题归集的「答题精讲」:逐条给出精讲定义、要点(≤4)、记忆锚点、易错点、讲义出处;无薄弱点时回退为前 3 个知识点的常规答题精讲。注意两处实现必须保持一致(一处改另一处要同步),否则学生端预览与教师端/api/push/weekly内容不一致。 - "是否开启云服务"确认卡片被反复弹出(2026-10-22 用户三次反馈,最高优先级):新课程运行时,若智能体把"开启云服务"当成待确认事项输出(如渲染"实现课堂答题与学情看板需要开启云服务 → ①开启云服务…"卡片,或提问"是否开启云服务?"),用户会认为流程又在询问。规则:云服务对所有新课程永久默认开启、静默执行——用户说过一次"开启云服务"即视为永久授权;后续任何新课程一律直接调 activate → publicConfig → 建表 → 部署,全程零确认、零卡片、零提问。若平台层仍弹出云服务引导卡片,智能体应继续执行开通动作并在交付时说明"云服务已默认开启",而不是等待用户点击。
- 微信内打开被平台网关拦截(2026-10-22 实测,平台行为不可绕过):用微信 UA(MicroMessenger)curl 实测
*.app.workbuddy.host,网关在请求到达 server.py 之前就直接返回"请在浏览器中打开"拦截页(普通浏览器 UA 返回 200 正常)。这是 WorkBuddy 发布平台的 H5 限制,应用代码侧无法绕过。交付时的正确话术:微信内打开会看到"复制链接"提示页 → 点复制 → 粘贴到手机浏览器(Safari/Chrome)打开;或微信内点右上角 ⋯ →「在浏览器中打开」。若用户需要真正的"微信内直接打开",唯一官方路径是发布为微信小程序(WorkBuddy 支持网页应用转小程序:自然语言转换 → 关联云服务 → 分享发布;需用户自己的小程序账号扫码绑定,可先发体验版再提审正式版)。转小程序属大改造,须用户明确提出后再做,且需评估多端页面(学生/教师/学习区间/看板)与邮件订阅等功能的取舍。 - 交付卡片出现「本地预览模式:当前未连接云端…localStorage」横幅(2026-10-22 用户反馈,交付红线):用户截图里交付卡片预览顶部出现黄色横幅「本地预览模式:当前未连接云端,作答数据仅保存在本地浏览器(localStorage),不会同步到教师端。正式上课请访问部署后的链接」⇒ 说明该轮只生成了本地目录、没有完成部署(或部署验证被跳过)就把卡片交了出去。规则:新课程交付 = 部署后的正式链接——流程必须走完 开云 → 建表 → 换装 →
workbuddy_sites_deploy→ curl 验证(/app200 且/api/questions返回 JSON)→ 回复最顶部给出https://quiz-<slug>.app.workbuddy.host/app?sharecode=<码>。应用卡片仅是管理入口;交付结果里出现该横幅即视为本轮交付失败,必须补部署后重新交付,不允许"就这样发给用户"。 - 交付只发了应用卡片/管理入口,没给(或给了打不开的)链接(2026-10-22 用户第五次反馈):用户截图显示交付结果是「土地合规课堂·网站应用」卡片 + 「前往『设置—数据管理—应用』中管理此已发布应用」+「查看所有产物」,正文没有可点击的正式链接,且用户反馈链接打不开。正确口径:① 回复正文第一条 = 完整 URL(域名逐字取自 deploy 返回值,含 sharecode);② 交付前 curl 实测该完整链接返回 200、
/api/questions返回 JSON,实测不过不得交付;③ 卡片/「设置—数据管理—应用」管理入口可以存在但只是后台,不能出现在交付口径里代替链接;④ 链接打不开排查:deploy 是否真成功 → 域名是否拼错 → 是否 auto 误判静态站 → 边缘缓存(?v=N穿透)。
10. 增强模块(五大新增功能 · 2026-10-09)
在保持原有学生端/教师端结构与云端答题流程不变的前提下,新增五大模块,数据由真实云端数据库统一支撑(CloudDB + CloudAnalytics),参考元数据由 server.py 的 /api/meta、/api/table5、/api/sim/* 提供;与原云端答题并存、互不干扰:
| 模块 | 能力 | 关键端点 / 页面 |
|---|---|---|
| 一、自主感知 | 自动采集预习自测 / 会诊对话 / 随堂检测 / 仿真记录 / 研学任务 / 课后反馈六类过程数据,构建学生学情档案 | POST /api/perception、GET /api/profile、/space |
| 二、智能决策 | 基于学情档案诊断;任一知识点错误率>50% 自动触发预警(阈值 WARN_THRESHOLD=50,区别于原薄弱阈值 60) |
GET /api/warnings、/console 预警中心 |
| 三、主动服务 | 由"人找资源"转"资源找人":学生自主开启邮箱订阅、填写邮箱与学习节律,系统按节律生成针对薄弱点的「答题精讲」推送(逐条回扣考点/记忆锚点/易错点,SMTP 配置后真实发信,未配置则生成预览) | POST /api/subscribe、GET /api/push/weekly |
| 四、迭代优化 | 复盘候选(来自错因与课后反馈)一键入库,向 review_bank.json 对应知识点追加变式,题库持续升级 | GET /api/library/candidates、POST /api/library/add |
| 五、虚拟仿真演练 | 学习拓展模块:学生参与仿真演练,教师端看板查看其考核数据与学习进度 | GET /api/sim/list、POST /api/simulation、/console 仿真看板 |
附加要求落实:
1. URL/二维码自动进入:学生访问 https://<域名>/space?sid=<身份> 或扫描该链接二维码,系统自动解析并进入专属学习区间(GET /api/space?token=)。
2. 邮箱提醒选项:学习区间「主动服务」页提供邮箱订阅开关,学生自主选择开启并填写邮箱,学习任务按周推送(节律可设工作日晚上/周末上午等)。
3. 化名登录:登录页明确支持昵称/化名,无需真实身份与注册(POST /api/join 按名建档)。
4. 60 条虚假验证数据:python gen_fake.py 生成 60 名虚假学生(刻意使 KP4/KP7 班级错误率>50% 以验证预警),写入 seed_students.json(部署前改名为 seed_students.json.bak 或设 SEED_DISABLE=1 跳过,避免假学生进入教师看板);server.py 启动时自动载入,教师端「增强看板→导入验证数据(60)」亦可热载入。
学生入口二维码(教师端展示/存放,2026-10-09 新增):原教师端 teacher.html 与增强看板 console.html 均新增「学生入口」页签,展示学生端入口二维码(默认指向 /space 学习区间,可切换 /app 闯关答题)。二维码由 location.origin 自动拼接部署后的公网地址,学生扫码即进入,支持不同网络(无需与教师在同一局域网);提供「复制地址」「下载 PNG」便于投屏或发群。二维码库 qrcode.min.js 经 server.py 静态路由 /qrcode.min.js 加载(file:// 双击时同目录亦可加载)。
跨网络(公网)使用:部署到云端(新实例域名 https://quiz-<主题slug>.app.workbuddy.host)后,/space、/app、/teacher、/console 全部公网可达,学生在任意网络扫码/输网址即进入;swap_topic.py 已把 space.html / console.html / sims.json / qrcode.min.js 纳入拷贝清单,新实例自动带二维码模块。
架构要点:新增模块(space/console 的学习区间、画像、预警、仿真、订阅、会诊/研学/反馈)全部走真实云端数据库(CloudDB + CloudAnalytics),跨网络实时同步、教师端看板立即可见;参考元数据(KMETA/TABLE5/QUESTIONS/SIMS)由部署后的 server.py 的 /api/meta、/api/table5、/api/sim/* 提供。原始学生/教师端答题流程零改动。部署时 swap_topic.py 已把 space.html / console.html / sims.json 纳入拷贝清单;新实例如需仿真模块,确保 sims.json 随模板一并部署。
10.1 画像模型深化(五维诊断 · 2026-10-09 第二轮)
在五大模块之上,进一步把六类过程数据 → 清洗 → 画像模型 → 五类应用贯通,杜绝形式化评价。
数据清洗层(clean_events):六类原始记录归一化为统一事件流,执行 ① 归一化(带时间戳/KP 标签/正确性);② 去重(同一 sid+kind+kp+sub 仅留最新);③ 异常过滤(correct 非布尔、KP 不在课程体系、空反馈文本均丢弃);④ 缺失标注(某类为空 → missing[kind]=True,画像模型据此降级而非编造)。kp_evidence 与 compute_profile 均已改走清洗后事件。
五维诊断指标体系(表5,TABLE5 常量,端点 /api/table5),每一维均有定义·数据来源·计算逻辑·教学应用:
| 维度 | 定义 | 数据来源 | 计算逻辑 | 教学应用 |
|---|---|---|---|---|
| D1 知识掌握度 | 各知识点答题整体正确水平 | 随堂检测·预习自测·仿真记录 | 总体正确率=Σ正确/Σ作答;分级 优≥85/良70-84/中60-69/弱<60 | 定位薄弱点,生成课堂预案+预习包 |
| D2 实践操作力 | 知识转化为实际操作与应用的能力 | 仿真记录·研学任务 | 仿真均分×0.6 + 研学优良率×0.4 | 识别需加强实操者,推送仿真演练 |
| D3 协作问诊力 | 会诊对话活跃度与质量 | 会诊对话(条数/解决率/意图) | 活跃度(min(条数/3,1))×(0.5+0.5×解决率)×100 | 识别沉默学生,主动发起会诊提醒 |
| D4 自主研学力 | 主动完成预习与研学的自律 | 预习自测·研学任务 | 预习完成度(min(预览/5,1))×0.5 + 研学完成率×0.5,×100 | 识别被动学习者,调整推送节律 |
| D5 反思改进力 | 课后反馈与错因复盘的改进度 | 课后反馈(评分/建议占比) | 反馈活跃度(min(反馈/2,1))×0.4 + 反馈质量(0.5×评分+0.5×建议占比)×0.6,×100 | 驱动题库更新+教学周报 |
周画像(/api/profile/weekly):取最近 7 天过程数据生成个体五维诊断画像 + 知识点掌握度;数据不足 5 条时回退累计画像并标注(诚实,不伪造周切片)。
班级知识点掌握度分布(/api/class/distribution):每个 KP 的正确率/等级/薄弱人数/是否触发预警(错误率>50%)。
画像驱动五类应用(端点见上表,前端入口 /console 三个新页签「画像模型 / 能力画像 / 周报·预案·预警」):
1. 研学推送:/api/push/weekly 依薄弱点按主题归集生成「答题精讲」推送——逐条回扣考点、记忆锚点与易错点,替代旧版「预习包+会诊提醒」文案(学生端「主动服务」可见预览)。
2. 课堂预案:/api/classplan 依预警知识点自动生成下周课时长/活动/资源/作业。
3. 能力画像:/api/capability 返回个体五维雷达(学生端「能力画像」页 + 教师端「能力画像」选学生)。
4. 教学周报:/api/report/weekly 由画像与预警按周自动生成 Markdown(教师端「周报·预案·预警」可复制/发送)。
5. 题库更新:/api/library/candidates + /api/library/add,将预警知识点变式与反馈建议一键入库(review_bank.json)。
预警直达教师邮箱:/api/warnings 在错误率>50% 时(已配 SMTP_HOST 且 TEACHER_EMAIL 非空)自动向教师邮箱发送预警(首次越线才发,避免重复);教师端「周报·预案·预警」页可手动「推送预警至教师邮箱」并保存教师邮箱(/api/config/teacher_email)。未配 SMTP 时返回预览文案。
本地验证命令:
cd <目录>
python gen_fake.py # 生成 60 人验证数据
PORT=8780 python server.py # 启动(自动载入 seed_students.json)
curl http://127.0.0.1:8780/api/table5 # 五维指标体系
curl http://127.0.0.1:8780/api/capability # 班级五维均值(不传 student_id)
curl http://127.0.0.1:8780/api/class/distribution # 班级知识点掌握度分布
curl http://127.0.0.1:8780/api/report/weekly # 教学周报
curl http://127.0.0.1:8780/api/classplan # 课堂预案
curl -X POST http://127.0.0.1:8780/api/warnings/email -H "Content-Type: application/json" -d '{"email":"teacher@x.com"}' # 预警邮件(预览/发送)
# 浏览器访问 /space(能力画像页)、/console(画像模型/能力画像/周报·预案·预警 三个新页签)
10.2 可视化精讲模块(2026-10-21 新增 · 2026-10-22 改版:加图谱 + 宽松排版 · 位于学习支持服务区间)
在学习支持服务区间(/space)新增第七个板块「可视化精讲」,对主题的知识点做系统化梳理 + 图谱化呈现 + 图标卡片:
- 数据来源:
server.py端点/api/explain,读取review_bank.json的knowledge_points与theme.json的stations(图标按题序对齐到 KP)、kpGroups(分组)、explainTitle(模块名),一次性返回全部知识点精讲数据(名称 / 出处 / 图标 / 一句话定义 / 要点列表 / 记忆锚点 / 易错提醒)。 - 呈现形态(两层):
- ① 知识点精讲图谱(SVG,2026-10-22 新增·解决"没有图"):模块顶部用一张内联 SVG 结构图,中央课程枢纽 → 分组节点(道/术等,按组着色)→ 各知识点圆形节点(复用
stations图标),连线表达主题层级。纯 SVG + CJK 字符,不依赖 emoji、不依赖外部图片,自适应宽度(viewBox+preserveAspectRatio,移动端不溢出)。分组模式按列排布分组与节点;平铺模式按网格排布所有 KP。 - ② 结构说明横幅 + 图标卡片:横幅给出课程名 · 副标题 · 知识点总数 · 分组数;其下按「分组 / 平铺」渲染图标卡片网格(见下)。
- 分组模式(
kpGroups非空):按组渲染对照(如「道 / 术」两栏),每组标题带色点,组内知识点以图标卡片网格排列;未归入任何组的知识点归入「其他」。 - 平铺模式(
kpGroups: []):所有知识点按 KP1..KPN 直接排成自适应图标卡片网格(适合线性/无层级主题)。 - 每张知识点卡片:圆形 CJK 图标(复用
stations图标,不依赖 emoji)+ 知识点名 + 出处 + 一句话定义 + 要点列表(最多 4 条,超出提示"见讲义") + 记忆锚点(金色块)+ 易错提醒(橙色块)。 - 排版改版(2026-10-22·解决"排版挤压"):卡片网格列宽由
minmax(150px,1fr)放宽到minmax(220px,1fr)、卡片内边距 12→16px、要点行高 1.5→1.7、组标题与卡片间距加大;图谱区独立卡片容器,与横幅/卡片之间留足留白。 - 主题联动:模块名(默认"可视化精讲")、分组、图标与图谱配色全部来自
theme.json,换主题只改theme.json即自动切换;严禁在space.html写死知识点文案或图标。 - 前端入口:
space.html的dashNav()增加第七个 tab(读THEME.explainTitle),dashboard()调用renderExplain()(内含buildExplainGraph()生成 SVG),/space登录后可见。 - 缓存击穿:
space.html中<script src="theme.js">须带?v=<主题缩写+序号>版本参数(如?v=mgp2),换主题重部署后浏览器/网关必拉新文件。
theme.json 相关字段(详见第 1.1 节 schema):explainTitle(模块名,可选默认"可视化精讲")、kpGroups(分组数组,可选默认 [])。
示例(二元结构主题):如「原理/方法」类主题可设 kpGroups 为 [{name:"原理篇",kps:["KP1","KP2","KP3","KP4"]},{name:"方法篇",kps:["KP5","KP6","KP7","KP8"]}],学生端学习区间即呈现「原理 / 方法」两栏对照的知识点精讲图谱(顶部 SVG)。
11. 相关技能
quiz-interface-generator:离线单文件版(一个 HTML、localStorage 聚合、无云)。只需要本地演示/单设备课堂用那个;要跨网络多端实时聚合、教师端看板、CSV 导出用本技能。