教师维护手册 《高频电子线路》真实工程任务学习平台 · 不改代码,只改数据
第一节 / 共八节

怎么用这本手册

课程内容和程序是分开的:任务书、技术指标、十三步文案、质量屋、约束、场景、器件、预置电路、自动导览、附页「全班的路」,全写在 app/data/十个 JSON 里。改一个字、存盘、刷新浏览器,页面就变了,不需要打开程序文件,也不用重新构建。其中教师最常改的八个在第二、三节逐个讲;另外两个——tour.json(自动导览十三段的字幕与停留秒数)与 class-paths.json(附页「全班的路」的匿名计数,由 tools/build_class_paths.py 生成)——一般不用手改,位置见本节右边那张表的末两行。

三条规矩

  • 先备份。改之前把那个 JSON 复制一份,例如 indicators.json.bak,出问题换回来就行。
  • 保持是合法的 JSON。逗号、双引号、括号要配对;中文标点不能当语法符号用。存盘后按第八节校验一次。
  • 强制刷新。浏览器里按 Ctrl + F5,否则可能还是旧数据。

我想改这个,改哪个文件

任务书、四个难题卡taskbook.json
技术指标表indicators.json
某一步的标题、引导语、助教开场白steps.json
器件卡的参数与要点parts.json
质量屋的行、列、关系强度qfd.json
六条设计约束constraints.json
四张前后对照图scenarios.json
仿真器里的预置电路circuits.json + app/circuits/*.txt
自动导览的字幕与停留秒数tour.json
附页「全班的路」的匿名计数class-paths.json(脚本生成,不手改)

本手册只讲"教师自己能做的事"。装机、换端口、上服务器、容器与反向代理见仓库里的 deploy/部署说明.md,这里不重复。

第二节 / 共八节

常改的八个(上):内容四件

这四个管的是"页面上写什么字"。改完只影响文字与表格,不会影响任何曲线的算法。

文件管什么关键字段改了以后页面哪里变
taskbook.json 任务书与四个难题 course 课程名、title 任务名、background 背景一句;problems[] 每个难题含 ordinal 序号、title 名称、device 设备、symptom 现象、consequence 后果、requirements[] 要求、chapters[] 对应章节、display_indicators[] 展示型指标、scene 对应的成效图、accent 卡片颜色 第 1 步四张难题卡的全部文字;顶栏课程名与任务名;成果报告封面。id(p1 至 p4)被别的文件引用,不要改
indicators.json 技术指标表(参考版) columns[] 表头;rows[] 每行含 name 指标名、target 目标值、unit 单位、problem_id 属于哪个难题、chapter 对应章节、pending 是否待审定;prompts[] 助教追问用的提示句;pending_label 角标文字 第 2 步的参考指标表;pendingtrue 的行带"教学取值待审定"角标
steps.json 十三步的全部文案 steps[] 每步含 title 标题、lead 引导语、primary 主按钮字、assistant_title 助教面板标题、assistant_opening 助教开场白、evidence 这一步留下什么证据、more 右上角"了解更多"展开层的文字、hook_in 上一段留下的问题、completion 完成卡 对应那一步的标题栏、引导语、按钮、助教面板与展开层。templatevizviz_altnseg 是程序用的挂点名,不要改
parts.json 第 5 步的关键器件 器件[] 每个含 名称英文名副标一句话对应难题章节,以及五个 页签:结构、参数、工程要点、常见故障、位置;页签顺序 决定页签排列 器件卡的文字与参数表。id 与三维模型一一对应,不要改;参数为工程典型值范围,需要教师审定
第三节 / 共八节

常改的八个(下):与计算有关的四件

这四个既有文字也有数值。文字部分改了立刻生效;带 ★ 的数值改动会牵动曲线,改之前请读那一行的提醒。

文件管什么关键字段改了以后页面哪里变
qfd.json 第 7 步质量屋 rows[] 需求行(problem 属于哪个难题、text 需求、indicator 对应指标、importance 重要度);cols[] 设计特性列(textunittarget 目标值、chapter);relations[] 每格的 strength(9 强、3 中、1 弱)与 basis 依据;roof[] 屋顶耦合(sign 取 ++ + − ⁠−−) 质量屋的行列标题、格子符号、悬停时显示的依据、屋顶的正负号
constraints.json 第 8 步六条设计约束 每条含 name 名称、expression 约束式、teachingValue 教学取值、source 教材出处、why 为什么这么定、violation 违反了会怎样、pushes 把参数往哪边推;context ★ 是中频、邻道频偏、各项门限等数值 约束清单的文字与说明立刻变。★ 提醒:改 contextaxes 里的数值,第 8 步图上的东西会跟着重画——六条边界线、可行域阴影、薄荷青「最稳的点」菱形、图下的逐条读数与结论行、左栏「六条约束满足几条」与完成卡文案,存盘刷新即生效(app/js/core/viz-registry.js:191-196 把本文件的 context / axes 注进组件,app/js/viz/constraint-boundary.js:126-127 拿它盖住 app/js/rf/constraints.jsDEFAULT_CONTEXT / AXES:146-153 重算边界与可行域、:308 按同一组取值出读数);第 11 步「方案越界核对」用的是同一个组件,图上也跟着变。★ 但有三处不跟着变,要一并改 app/js/rf/constraints.js 才对得上:① 第 8 步左栏「跳到最稳的点」按钮(app/js/steps/step08.js:104,直接走 DEFAULT_CONTEXT / AXES);② 第 11 步左栏的越界核对与对照方案(app/js/steps/step11.js:106-109、137、143、232-236、243);③ 第 8 步两个滑块写死的上下界(app/js/steps/step08.js:53-54、80、83),把 axes 改小,图的坐标轴会变、滑块仍能拖到老范围。另外 expression / teachingValue / why 这些是给人看的文字,不参与计算(只有 nameteachingValue 印在图例上),所以只改文字线不会动、只改 context 文字也不会自己跟上——两边都要改。数值改动请记在 tasks/ 里交维护者同步
scenarios.json 第 12 步四张前后对照图 每个场景含 titlesubtitlebasis 依据等级(物理公式 / 简化模型 / 示意)、basisNote 算法依据、beforeafter ★ 两组驱动参数、readouts 图下方读数、unit 与色标说明;meta.basisLevels 是三个等级的定义 四张图的标题、右上角依据角标、读数与色标文字。★ before / after 里的数是喂给公式的物理量(例如 Q 值、驻波比、幅相误差),改了图会重算——这正是它的用法,但改完请把 readouts 的文字一起对上
circuits.json 第 9、10 步的预置电路清单 仿真器 段写明名称、入口与许可;电路[] 每个含 编号id文件(对应 app/circuits/ 下的 txt)、标题任务提示难题章节关键取值可调[] 学生能动的量、步骤[] 出现在第几步 仿真页左侧的电路清单、任务提示与关键取值。电路本身的元件值在那个 txt 文件里,用仿真器导出即可
第四节 / 共八节

三个例子:改一处,页面变哪里

照着做一遍,后面所有的改动都是同一个套路:找到那一行 → 改值 → 存盘 → 强制刷新 → 到对应的那一步看一眼。

例一

改技术指标表的一行

  1. 打开 app/data/indicators.json
  2. 找到 "id": "i1" 那一行(中频通道邻道抑制);
  3. "target": "≥ 60" 改成你要的值,单位在 "unit" 里;
  4. 数值若已经审定,把 "pending": true 改成 false,角标就没了;
  5. 存盘,强制刷新,看第 2 步右侧的参考指标表。

连带 同一条要求还写在 taskbook.json 难题一的 requirements 里(第 1 步的卡片),两处要一起改,否则前后对不上。

例二

改一个约束的教学取值

  1. 打开 app/data/constraints.json
  2. 找到 "id": "adjacent_rejection"(邻道抑制);
  3. teachingValue 里的"单级 ≥ 35 dB"改成新值,expression 末尾的数字一起改;
  4. whyviolation 两句是给学生看的理由,一并改成对得上的说法;
  5. 存盘刷新,看第 8 步中栏的约束清单。

提醒 这一步改的都是文字,所以边界线不会动——但原因不是"线由 app/js/rf/constraints.js 的默认取值算出":线的门限读的是同一份 JSON 的 context(邻道抑制这条读 context.rejectionReqDb,见 app/js/rf/constraints.js:50c1AdjacentRejection),teachingValue 只是印在图例上的说法。要让线也动,把 context.rejectionReqDb 一并改成新值,存盘刷新第 8 步的边界、可行域与「最稳的点」菱形就会重画(app/js/core/viz-registry.js:191-196app/js/viz/constraint-boundary.js:126-127、146-153)。只剩左栏「跳到最稳的点」按钮(app/js/steps/step08.js:104)与第 11 步左栏的越界核对(app/js/steps/step11.js:236、243)仍按 app/js/rf/constraints.jsDEFAULT_CONTEXT 算,这两处要跟上得改那个文件——请把改动记下来交维护者同步,别只改一边。

例三

加一个预置电路

  1. 在仿真器里搭好电路,导出电路文本,存成 app/circuits/my-lc.txt
  2. 打开 app/data/circuits.json,在 "电路" 数组末尾加一段(注意上一段末尾要补逗号);
  3. 存盘刷新,第 9 步的清单里就多了一项。
{
  "编号": "C7",
  "id": "my-lc",
  "文件": "my-lc.txt",
  "标题": "我的选频回路",
  "任务提示": "把 C 从 22 pF 调到 47 pF,看谐振点往哪边走。",
  "难题": "难题一 · 北斗终端失锁",
  "章节": "LC 谐振回路",
  "关键取值": "L=10 μH,C=22 pF,f0≈10.7 MHz",
  "可调": ["电容 C_F", "负载电阻 RL_ohm"],
  "步骤": [9]
}
第五节 / 共八节

第 3 步与第 10 步那张双曲线,现在是怎么来的

第 3 步"现场现象"和第 10 步"实测验证"共用同一张双曲线图:蓝线理论、金线实测。 两条线都不是写死的数组,而是由 app/js/viz/dual-curve.js 里的探头加载模型按一组元件值当场算出来的; 这组元件值与第 9 步预置电路 C1(单调谐 LC 并联回路)、C6(示波器探头加载)完全相同, 所以图上的读数与电路仿真器里量到的数对得上。 金线是复现值,不是实验台的原始记录——这句口径就写在那两步图下方的说明行里。

它现在算的是什么

  • 元件值 L = 10 μH、C = 22 pF、线圈损耗 r = 6.74 Ω(空载 Q₀ = 100)、Rs = 100 kΩ、RL = 68 kΩ;探头按 1 MΩ 并联 110 pF。
  • 蓝线(理论回路) f₀ = 10.730 MHz、有载 Q 37.5、通频带 286 kHz、回路电压峰值 1.265 V。
  • 金线(挂上探头之后) f₀ = 4.381 MHz、有载 Q 31.7、通频带 138.3 kHz、峰值 0.436 V。
  • 第 10 步是两步回填加一次核对(不是三次回填):先补探头输入电容 110 pF(回路总电容 22 pF → 132 pF,谐振点掉到 4.381 MHz),再补示波器输入电阻 1 MΩ(有载 Q 从 32.0 压到 31.7、通频带从 137.1 kHz 放到 138.3 kHz),最后把两条线的 3 dB 带宽标在图上逐点核对。每一档在曲线或读数上都有看得见的变化。

这些数全部由 app/js/rf/resonance.js 现算,页面上没有写死的结论。

要改的时候改哪里

  1. 只改页面上的文字与数值(引导语、"了解更多"里的那几行、电路的关键取值):改 app/data/steps.json 第 3 步与第 10 步的 leadmore,以及 app/data/circuits.json 里 C1 与 C6 的关键取值任务提示。这一档是教师自己能做的。
  2. 要换一组元件值,或换成真实实验记录:动的是程序文件——app/js/viz/dual-curve.js 顶部的 PROBE_MODEL(L、C、r、Rs、RL、探头的 R 与 C),以及 app/js/steps/step03.jsstep10.js 里传给组件的那一行 model。两处的数必须一样。
  3. 改完把上一条里的文字一起对上:曲线会跟着新元件值重算,文字不会自己跟着变。
  4. 刷新后两步各看一眼:第 3 步两条线应当明显分开,第 10 步走到最后一档应当基本重合,图下说明行里那句数据口径还在。

实验记录里如果带学生姓名或学号,请先去掉再写进文件。手上有实验台原始记录又不想动程序文件的,把数据交给维护者:把这组参数挪进 app/data/ 已经登记为待改进项。

组件里还留着一份十一点的样例数组(VERIFIER_DATA),那是 app/dev/ 演示页与旧调用方的回退路径,第 3、10 步不走它,照着它改不会影响页面。

第六节 / 共八节

学生报告怎么导出,记录留在哪

报告是学生自己在第 13 步生成的;后端在运行时,服务器上还会留一份,整个目录拷走就是全班的记录。不想翻文件的话,学生会话浏览见 teacher.html:列出所有会话,点一个就能看它走到第几步、每步填了什么,也能直接打开那一份成果报告。想一眼看全班而不是一个一个点,就在同一页右栏顶上切到「全班汇总」页签:十三步在哪一步掉队、四个难题谁被选得最多、设计点落没落进可行域、最常写的指标与 Q 估值散在哪里,每块右上角的「口径」角标写明这些数是怎么数出来的。同一行右边还有一个「导出表格」按钮,把全班压成一张 csv,见下面「全班导成一张表」。

学生这一侧

第 13 步点"生成成果报告",浏览器下载一份 HTML:任务书与技术指标、原因树与证据计划、参数估算与质量屋、设计点与约束核对、仿真与回填记录、四张成效对照图,以及各步与助教的全部对话。

同一页还能下载一份学习记录 JSON(原始输入与事件),交作业时两份都收更完整。

服务器这一侧

后端在跑的时候,学生每次保存追加一行到 backend/data/sessions/<会话号>.jsonl;每生成一次报告,存一份 backend/data/reports/<会话号>-<时间戳>.html

换存放位置:设环境变量 CLASS_AGENT_DATA_DIR 指向一个可写目录(服务化与容器部署都这么配)。

全班导成一张表

teacher.html 右栏切到「全班汇总」页签,标题行右边、「刷新」旁边有一个「导出表格」按钮。点一下,浏览器下载一份 csv,文件名形如 会话汇总-20260915.csv(日期由服务器按下面那个时区给;响应头读不到时按本机日期另拼一个同样式的名字)。导出期间按钮显示「正在导出…」并暂时点不动,完事自己复原。

表里有什么 每行一个会话,一共 28 列:会话编号、最后保存时间、保存版本数、完成步数、走到过的步数、完成到第几步、对话条数、入手难题编号与难题名、设计点 Q、设计点 η、设计点是否可行、违反的约束、第 6 步 Q 估值、指标行数,后面是十三步各自的状态(完成 / 走到过 / 空白)。一次最多导 200 行。服务器上还没有任何记录时,给的是一份只有表头的空表——那是「这一轮还没人保存过」的如实回答,不是故障。

表里没有什么 没有学号,也没有姓名,更没有服务器上的文件路径:第一列的会话编号是浏览器自己发的随机串。时间一律换算到报告时区,默认 Asia/Shanghai,并且写在表头第二格里(「最后保存(Asia/Shanghai)」);要换时区,改环境变量 CLASS_AGENT_REPORT_TZ,表头跟着变。文件是 UTF-8 带字节序标记的,Excel 双击打开中文不乱码。

设了教师令牌时 和这一页的别处一样:令牌在页面第一次打开时问一次,之后放在请求头里带上,不写进地址栏(地址会进浏览器历史和服务器访问日志)。令牌不对,后端回 401,页面再问一次;仍然不对,「全班汇总」那块会写出「表格导不出来 · 需要教师令牌」,并提示先点「刷新」再导一次。整个过程只读,学生记录一个字节都没动。

两件要注意的事

  • 直接打开静态页、后端没启动时,报告在学生本机生成,照样能下载,但服务器上不会留记录。
  • 留痕文件里是学生的原话,按学校规定保管;这个目录不进代码仓库(已排除)。
第七节 / 共八节

本机与服务器怎么启动,密钥放哪

两条命令就够上课用;换端口、局域网访问、容器、服务化、反向代理、离线安装与排错,全在部署说明里,本手册不重复。

启动

本机(Windows) 在仓库根目录打开 PowerShell:

powershell -ExecutionPolicy Bypass -File scripts\run.ps1

服务器(Linux)

bash scripts/run.sh

两个脚本都会自己准备运行环境,然后在 8020 端口启动;浏览器打开 http://127.0.0.1:8020/,页面与接口同源。停止按 Ctrl + C

要让同一间教室的学生访问,见部署说明里的监听地址参数。全部细节在仓库的 deploy/部署说明.md

密钥只放环境变量

  • 模型密钥 OPENROUTER_API_KEY 放在系统环境变量里,或仓库根目录的 .env 文件里(这个文件不进仓库)。
  • 不要把密钥写进任何 JSON、HTML、脚本或文档,也不要贴进对话框和聊天工具。
  • 没有密钥网站照常启动,助教退回本机规则,其余部分不受影响。
  • 想确认有没有读到:打开 http://127.0.0.1:8020/api/health,看 model_configuredtrue 还是 false
  • 已经存在的系统环境变量不会被 .env 覆盖——换密钥时记得改的是同一处。
第八节 / 共八节

改完之后的自查清单

四步,两分钟。第一步是硬的:JSON 写坏了页面会停在"正在装入任务书"。

一、先校验 JSON

在仓库根目录执行(把文件名换成你改的那个):

backend\.venv\Scripts\python.exe -m json.tool app\data\indicators.json

能把整份内容打印出来就是合法的;报 JSONDecodeError 就照它给的行号去补逗号或引号。

二、再看页面

强制刷新,直接跳到改动的那一步(地址栏 #/step/2 直达第 2 步),看文字、角标、按钮是不是你要的样子。

三、看三个连带的地方

  • 上一段完成卡里那句"下一段要解决什么"还对不对;
  • 第 13 步的成果报告里这项内容跟着变了没有;
  • 同一个数字如果在别的文件里也出现(例如指标同时写在任务书里),两处是否一致。

四、机器再走一遍(可选)

装了检查工具的话,在仓库根目录跑:

backend\.venv\Scripts\python.exe tools\page_check.py

它会用无头浏览器把十三步逐一打开,报告写在 tasks/页面检查报告.md

还没审定的数值请保留"教学取值待审定"的角标(indicators.json 里是 pending 字段)。宁可标着待审定,也不要让学生把没核过的数当成结论。