dsh-cet6 · 六级训练台
非官方项目:与全国大学英语四六级考试的主办机构、命题方、出版方均无隶属、合作或授权关系。
装完就能用:包里带一份完全原创的示例题库(345 个自编核心词 + 1 套原创模拟卷,听力由系统语音朗读), 打开就能背词、做题、交卷。示例不是真题,也不含任何真题文字、真题录音或真题答案。
真题要自己准备:把自己合法取得的资料按分类放进项目里的
data-pack/(内容不进公开仓库)构建一次, 示例会自动让位,版权归原权利人,请仅用于个人学习。只给答案,不给解析:客观题交卷后只标对错与正确选项;翻译、作文只提供作答区,不内置参考译文与范文。 理由见 为什么不提供解析——答案册里没有的东西,程序不编。
DeepSeek Harness 插件。把词汇、听力、真题、翻译、写作放在同一个左侧栏面板里,进度只存本机。
功能
| 模块 | 做什么 |
|---|---|
| 核心词(约 2500) | 六级高频词,每 100 词一个单元;背单词 / 记单词 / 默写三种模式。示例题库带 345 词 |
| 大纲词(约 6500) | 完整大纲词表(六级第六版口径实测收 5939 词,首页索引按 500 取整显示「大纲 6000」),同样是每 100 词一个单元、同样三种模式。示例题库没有这一套,卡片会自动隐藏 |
| 听力 | 按考期选套,25 题作答(长对话 8 / 篇章 7 / 讲座 10),交卷对答案。有分段表时可按节跳听;示例卷用系统语音朗读,交卷后才给原文 |
| 随机题测试 | 选词填空 / 长篇阅读 / 仔细阅读,随机抽卷,计时、交卷、退出自动保存 |
| 片段翻译 | 部分翻译(句子)与全篇翻译(整段)两种模式,只提供作答区与计时 |
| 作文书写 | 随机抽写作题,30 分钟倒计时,实时词数 / 句数统计 |
| 生词本 | 练习时点 ☆ 收词,复习、搜索、导入导出 |
| 错词 / 错题本 | 默写错词与交卷错题自动归档,可单独重练或回原卷重做 |
| 今日复习 | 学过但隔天没再碰过的词,用默写过一遍刷新记忆时间 |
词表数量取决于你手上的词表文件,界面统一写「约」。
几个刻意的设计:
- 一个页面只出现一个单词。 三种模式共享同一个位置游标,切换模式不会把你打回第 1 个词。
- 默写按词长给提示。 长度 > 5 给 3 个首字母,4–5 给 2 个,≤ 3 给 1 个。
- 只给答案,不给解析。 见 为什么不提供解析。
安装
# 1) 在 DSH 的 profile 目录里装包
npm install dsh-cet6
- 把包登记进 profile 的 bundle 列表,否则装完左侧栏不会出现图标。编辑
<profile>/package.json(Windows 一般在C:\Users\<你>\.dsh\profiles\desktop\package.json):
{
"dependencies": {
"dsh-cet6": "^1.0.0"
},
"dsh": {
"profile": {
"bundles": [
"@deepseek-ai/dsh-base",
"@deepseek-ai/dsh-web-app",
"dsh-cet6"
]
}
}
}
- 重启 DSH,左侧栏出现「CET-6 训练台」。打开就能用:首屏是内置示例内容(右上角有「示例」徽标), 背词、做听力、选词、阅读、翻译、作文都能走完整流程。要换成自己的真题,见 准备题库。
插件通过 cordis.patch.yml 插进 profile 的层级栈,客户端通过 lib/client.js 在左侧栏注册图标,
面板本体是 iframe,指向宿主托管的 /cet6/app/index.html。
宿主侧只做两件事:用 webServer 把本插件的 app/ 与题库目录挂在 /cet6 前缀下,
并在 /cet6/media/<track> 上按 HTTP Range 推流录音文件(不复制、不转码)。
内置示例内容(装完即用)
包里 starter/ 是一份原创示例题库,作用只是让你装完立刻能上手,不冒充真题:
| 内容 | 说明 |
|---|---|
| 345 个核心词 | 词形 + 音标 + 中文释义 + 例句;释义、例句与译文都是本项目自写 |
| 1 套原创模拟卷 | 听力 25 题(Section A 长对话 8 / B 篇章 7 / C 讲座 10)、选词 10、长篇阅读 10、仔细阅读 10、翻译、作文 |
| 听力 | 没有音频文件:用浏览器语音合成(Web Speech API)在本机实时朗读,可按节单读、可暂停、可调语速;原文在交卷后才出现 |
三点要说明白:
- 不是真题,也不从真题改写。
NOTICE.md第 3 节逐文件写了来源与许可。 - 想换成自己的就换:把自备题库构建到数据目录,示例自动让位;想换回示例,删掉数据目录里的
index.json即可。 - 音色取决于你的电脑:Windows 一般自带英文语音;万一环境没有语音合成,听力页会明说听不了,其余模块照常。
数据目录的解析顺序(lib/data-dir.js):
CET6_DATA → ~/.dsh/dsh-cet6/data → 插件内 data/(仅开发) → 插件内 starter/
准备题库
示例只是兜底。要用自己的真题,从首页的「换成我的真题」或设置里的「准备我自己的真题」进入引导页, 它是一份可照着做的三步流程,而不是一句报错:
- 画出资料目录该长的样子(
01–05五个目录,前两位是识别的依据)。 - 选一次你自己的资料目录,页面在本地核一遍结构:缺哪个目录、一共多少套卷、答案 CSV 表头对不对、 多少份原文与录音。只读文件名与前 512 字节,不上传任何内容。
- 按你填的路径拼出构建命令,一键复制。这一步在自检通过(或只有“可选资料缺失”)之后才解锁; 自检没通过时,它会告诉你还差哪一项。
资料放哪都行;最省事的是放进本项目的 data-pack/——按 01–05 分好类之后,
npm run check:pack 先体检、npm run build:data 直接构建,都不用再写 --src。
目录长什么样、以后怎么加新卷 / 新录音 / 新词表,见 data-pack/README.md。
下面是把这三步写下来的版本。
题库放在哪
分清两个目录:资料目录(你的 docx / mp3 / csv,源)与题库目录(构建产物 JSON)。
资料默认放本项目的 data-pack/;题库默认写 ~/.dsh/dsh-cet6/data
(Windows:C:\Users\<你>\.dsh\dsh-cet6\data)。
题库放在插件目录外是刻意的:插件实际安装在 <profile>/node_modules/dsh-cet6/,
npm update 或重装会整目录替换,写在那里会连题库一起丢掉;往 node_modules 里写文件也不合规矩。
想把资料放别处,构建时用 --src 指过去;想换题库位置就设环境变量 CET6_DATA(指向 data 目录本身),
宿主与构建脚本都认它:
CET6_DATA=D:/cet6-data npm run build:data -- --src "D:/CET-6"
解析顺序:CET6_DATA → ~/.dsh/dsh-cet6/data → 插件目录内的 data/(只用于本项目开发)。
资料目录长得什么样
<资料目录>/
01 真题试卷…/2023年6月/第1套/…整卷.docx 整卷(优先读 docx,其次 pdf;含听力、阅读、翻译、作文题)
02 答案(客观题)/YYYY年M月第N套_答案.txt 一套一份:听力 1–25、选词 26–35(带原词)、长篇 36–45、阅读 46–55
03 听力原文/YYYY年M月第N套_听力原文.txt 按 Section A/B/C 分节
04 听力音频(MP3)/YYYY年M月第N套_听力音频.mp3
05 词汇/六级核心2500…csv、六级6000词汇…csv
目录名前缀(01…05)是识别的依据,后面的名字随便改。然后:
npm run check:pack # 先体检目录(几秒,不解析卷面):谁缺答案、谁没原文、词表列名对不对
npm run build:data # 构建题库:默认读 data-pack/,写到 ~/.dsh/dsh-cet6/data
npm run build:data -- --src "D:/CET-6" # 资料在别处时才带 --src
npm run build:data -- --out ./data # 想换产物位置
npm run check:data # 体检产物:答案数、选项、音轨是否齐全
npm run pack:data # 给构建好的题库打一份带清单的快照(本机备份用)
04/05 的编号不用管:构建按内容认目录——有 *.csv 词表的是词汇目录,有音频文件的是音频目录,谁在前谁在后都行。
构建优先读整卷 .docx,读不到才退回 PDF。原因很实际:六级卷的 PDF 把选词填空的空号(26–35)印在页边,
抽成文本后段落里只剩下空白,无法还原空位;docx 里是行内的 __26__,段落也一段一行,还不会混进站点水印。
要读 PDF 时有下面几条路:
装了
workbuddy-pdf(DSH 自带的那份在~/.workbuddy/external-packages/pdf-cli/)——构建会自动找到,什么都不用配。换一个抽取器:
CET6_PDF_CLI=/path/to/pdftotext-wrapper,调用约定与workbuddy-pdf一致:<cli> <input.pdf> <output.txt> --format txt。完全不用抽取器:把 PDF 的文本存成同名
.txt,放在 PDF 旁边(xxx.pdf↔xxx.txt)。 有同名.txt时构建直接读它,连 PDF 都不打开;也可以只放.txt、不放 PDF —— 这种「纯文本卷」 会被当成一份正常的卷解析。.txt的排版要和抽取结果一致:一行一段、四个选项各占一行、空行分段 (拿一份现成的.txt对照着排最稳)。构建开头会检查这台机器上有没有抽取器,没有就在
notes里提示"将改用同名 .txt", 不会等到跑到一半才报错。
产物:
| 文件 | 内容 |
|---|---|
index.json |
卷宗清单、词表规模、录音统计、生成时间与来源路径 |
papers/<id>.json |
每套卷的听力(3 节 / 25 题 / 原文)、选词、长篇、阅读、翻译、作文、答案 |
vocab-2500.json |
核心词表(释义、音标、例句、考频) |
vocab-6500.json |
大纲词表,例句从核心表里能对上的词借过来 |
media.json |
音轨 → 源音频文件的相对路径,供宿主按 Range 推流 |
build-report.json |
构建统计、notes(可解释的特殊处理)、warnings(已自动降级)、problems(必须修的问题) |
构建完请确认 problems 为空。当前资料(2023.6–2026.6,21 套)的实测结果是:
21 套卷 · 2500 + 5939 词 · 14 份录音(覆盖 21 套)· 21 套都有听力原文
可听 21 套 = 14 份录音 + 7 套的第 3 套沿用同考期另一套(卷面写明「本部分与…共用」);录音归属全部经原文比对确认
原文 14 份 = 7 个考期各覆盖第 1、2 套;第 3 套沿用同考期那一套的原文
notes:逐条写明特殊处理(例如「听力借用 2023年6月第 1 套(卷面注明本部分共用)」)
录音与试卷怎么对应
这是最容易出错的地方,所以构建时做了三道处理:
文件名不可信时按内容归属。 把听力原文里的实词和每套卷的听力选项做关键词重合度比对, 正确配对重合度 53–64%,错误配对只有 19–28%,据此确定某份录音属于哪一套(这套资料 14 份录音全部 53% 以上对上)。
没有原文时按文件名推定,并标记出来。 这类卷宗
audioVerified: false,听力菜单里会显示 「录音按套号推定」,提示你自己听一遍确认。分段表(
audio-tracks.json)不随包发布,并且会被音频时长校验。 它记的是「某份录音第 N 节从第几秒到 第几秒」,只对特定的音源成立。换了录音还沿用旧表,跳节就会落到错误位置 —— 所以构建时按 MP3 帧头算出 音频真实时长,任何一段的end超出时长就整份作废(退回整段播放,不显示跳转按钮),并在build-report.json的warnings里记一条。分段表的查找顺序:--tracks <file> → CET6_TRACKS → <资料目录>/audio-tracks.json → <05 听力音频>/audio-tracks.json → ~/.dsh/dsh-cet6/audio-tracks.json这套资料没有分段表,所以听力是整段播放,页面按 Section A/B/C 分三节显示题目与原文,不提供按节跳听。 想要跳听,可以自己生成一份 3 段的分段表放进上面任一位置(格式:
{"<年>-<月>-<套>": [{"start":0,"end":520}, …]}, 数组长度必须是 3,构建会用音频时长校验,越界就整份作废)。
另外,真题第 3 套常在卷面注明「本部分与 2023年12月第1套 共用」,构建时整段借用(选项、录音、原文),
答案仍用本套答案表,并在 build-report.json 的 notes 里记一条。
音频与题目在数据层是绑定的(papers/<id>.json 的 listening.track + 每节的 start / end):
有 start 时前端点节头按 start 定位、播到 end 自动暂停;没有就只显示音频条。
为什么不提供解析
答案册里只有答案。译文、范文、逐题解析都不在其中,所以插件不生成、也不收录它们 —— 与其编一段 看起来很像的解析让使用者当标准答案背,不如老实只给对错。
同理,翻译与作文两个模块只提供作答区、计时和词数统计,不给参考译文与范文。作答内容保存在本机, 可以自己拿去对照纸质资料或别的工具。
安全与隐私
- 只服务本机。
/cet6下所有路由都会检查remoteAddress,非回环请求直接 403。 如果确实需要在远程访问 DSH 时用,设CET6_ALLOW_REMOTE=1—— 但那等于把你自己的录音对外提供, 后果自负。注意:如果 DSH 自己在前面做了反向代理,转发到插件的连接看起来仍是本机,这道校验就失效了, 此时请靠 DSH 自身的端口暴露范围来兜底。 - 只暴露两个目录。
/cet6/app/*与/cet6/data/*,路径越界一律 404;源码、构建脚本、.cache/都不会被访问到。 - 录音只按白名单取。 只有
media.json里登记过的音轨 id 能取文件,解析后还要校验仍在资料目录之内。 - 学习记录只在浏览器。 localStorage 键
cet6.state.v4,不上传任何服务器。 - 静态资源带 CSP(
default-src 'self'),只能被宿主 GUI 自己嵌。
目录结构
dsh-cet6/
index.js 宿主:/cet6 静态托管 + /cet6/media Range 推流 + 回环校验
lib/client.js 客户端:左侧栏图标 + iframe 面板
lib/data-dir.js 题库目录解析(宿主与构建脚本共用)
lib/docx.js 极简 .docx 读取(zip + document.xml,不引第三方库)
locale/{zh,en}.json 面板标题与描述
cordis.patch.yml bundle 补丁
app/
index.html
styles.css
js/store.js 状态与 localStorage(键 cet6.state.v4)
js/ui.js toast / confirm / 弹层 / 选项渲染
js/setup.js 「准备题库」引导页 + 资料目录结构自检
js/app.js 首页九张卡、设置、主题
js/vocab.js 词表单元、三种模式、默写判分
js/listening.js 听力菜单、音频播放、25 题作答与交卷
js/quiz.js 随机题(选词 / 长篇 / 阅读)、计时、交卷
js/translate.js 片段翻译
js/writing.js 作文
js/notebook.js 生词本
js/wrong.js 错词 / 错题本
starter/ 内置原创示例题库(随包分发:无真题、无音频)
index.json 索引,kind=starter
vocab-2500.json 345 个自编核心词
papers/mock-01.json 1 套原创模拟卷(听力走语音合成)
media.json 空音轨表
data-pack/ 你自己资料的分类落点(内容被 .gitignore 挡住,只有骨架进 Git)
README.md 分类、命名规则、怎么加新内容
pack.json 资料包版本与来源记录(构建不读)
01 真题试卷/ … 05 词汇/ 五个分类目录(各留一个 .gitkeep 占位)
docs/data-pack.md 数据包的完整规范
build/
build.mjs 题库构建(默认读 data-pack/)
check-pack.mjs 构建前体检:目录分类、别名、覆盖情况
validate-data.mjs 构建后体检:答案数 / 选项 / 音轨 / 统计口径
check-starter.mjs 示例题库发版护栏(无音频 / kind / 词数自洽)
pack-data.mjs 给构建好的题库打带清单的快照
serve-plugin.mjs 不开 DSH,单独跑一遍宿主路由
e2e.mjs 无头浏览器回归
test-client.mjs 客户端外壳静态检查
data-pack/ 里你自己的资料与 ~/.dsh/dsh-cet6/ 里的构建产物都不在上面的发布物里。
只有 starter/ 随包走,因为它是原创内容,可以公开分发。
维护
npm run check:pack # 资料目录体检(加新卷 / 新录音 / 新词表之后先跑它)
npm run build:data # 重抽 docx 生成题库(默认读 data-pack/)
npm run check:data # 数据体检
npm run pack:data # 题库快照:~/.dsh/dsh-cet6/packs/<名>-<时间>.tgz + 清单
npm run check:starter # 示例题库护栏(改动 starter/ 后跑)
npm run preview:plugin # 起一个假宿主,浏览器开 http://127.0.0.1:8788/cet6/app/index.html
CET6_DATA=./starter node build/serve-plugin.mjs 8790 # 另起一个用内置示例数据的实例(避开 8788)
npm run test # 客户端静态检查 + 示例护栏 + 数据体检
npm run test:e2e # 无头浏览器跑一遍主要流程(需本机 Chrome/Edge)
npm run check:data 会拦下这些「看不出来但一定会坑人」的问题:答案数量不对、选词字母不在词库里、
长篇阅读答案指向不存在的段落、选项数不是 4、以及选项里混进了下一段的说明文字
(PDF 抽文本时最常见的粘连,比如 D 选项尾巴上挂着 “Questions 3 and 4 are based on…”)。
它还比对 index.json 里的录音统计与卷宗是否一致,避免前端显示“14 份录音 / 21 套可听”这种口径错乱。
npm run test:e2e 需要 puppeteer-core(不随包安装)。可以用 PUPPETEER_DIR 指向已有的安装目录,
用 CHROME_PATH 指定浏览器。
「准备题库」引导页那一条不用另起实例:脚本会把 data/index.json 拦成 404,直接复现
「还没生成题库」的那条路径(包内带了 starter/ 之后,空目录会被示例顶上,靠真实空目录已经测不到了)。
e2e 是开发自测,不是随插件交付的功能。 期望值(卷数、词数、单元数、录音份数)都从
index.json读;只有一套词表时「大纲词」相关的几条会自动跳过;kind: "starter"的示例题库走语音合成分支, 断言换成「有.tts-bar、没有<audio>、交卷后才给原文」。作者的两套数据(真题 / 示例)跑同一份脚本都是 32/32。 换成纯文本卷、既没录音也没原文的题库,听力相关的几条会失败,这属于预期。
改了 PDF 想强制重抽文本,加 --force:npm run build:data -- --force。
抽取结果缓存在 ~/.dsh/dsh-cet6/.cache/extract/,删掉即可重来。
已知限制
- 内置示例只有 345 词 + 1 套卷,够走完流程,不够当复习资料;真复习还是得导入自己的题库。
- 示例卷的听力是语音合成,不是真人录音:音色、语速取决于系统语音引擎;没有英语语音包时会禁用播放并提示, 只能交卷后看原文。它也读不出真实的考场感觉(没有停顿、没有连读)。
- 听力按 Section A/B/C 三节组织,不再细分到每篇:六级的听力原文只有三节的分界,硬拆「第几篇」只能靠猜, 宁可不拆也不拆错。所以页面上是「长对话 / 篇章 / 讲座」三个入口,不是八个。
- 大纲词表本身不带例句:只能从核心词表里借到约三分之一,其余词的例句位置会显示「这个词表没收录例句」。
- 没有分段表时听力只能整段播放(不给按节跳转)——这是刻意的,宁可不跳也不跳错。
- 录音是
.mp3,各浏览器原生支持;用 Range 请求边下边播,不会把整段录音读进内存。 - 学习记录在 localStorage,换浏览器或清缓存就没了,建议用生词本的导出功能定期备份。
- 只在
node >= 20上测过。
仓库与数据分仓
仓库分成两块,边界写死在 .gitignore 里:
| 进 Git | 不进 Git |
|---|---|
代码、文档、构建脚本、原创示例 starter/、data-pack/ 的分类骨架(README / pack.json / 各目录 .gitkeep) |
data-pack/ 里的 docx / pdf / mp3 / csv / txt,以及构建产物 data/ |
所以你的资料就放在项目里的 data-pack/,按 01–05 分好类,npm run build:data 直接读它;
但 git push 与 npm publish 都不会带上它们——.gitignore 挡住提交,package.json 的 files
白名单挡住发版。想核对可以随时跑:
git status --short # data-pack/ 里只有 README、pack.json 与 .gitkeep
npm pack --dry-run # 包内文件清单:没有 data/、没有 data-pack/ 的内容
为什么内容不公开:试题、听力原文、录音、词表的著作权归原权利人(考试主办机构与出版方),
把它们放进公开仓库等于向公众提供复制件,不属于「个人学习研究」的合理使用;本 README 也就不放真题截图
——演示图同样属于对试题内容的复制。仓库里能公开的,只有本项目自写的代码与 starter/ 里的原创示例。
想给资料做版本管理,两条路:
- 本机为主:
data-pack/就在项目里,npm run pack:data给构建好的题库打一份带 sha256 的快照 (默认写到~/.dsh/dsh-cet6/packs/); - 私有仓:把这个仓库设为 Private,或另开一个
mount9527/dsh-cet6-data,克隆到data-pack/后构建。 私有仓不受公开分发限制,但要记得它一旦转公开,资料就跟着公开了。
分类、命名规则、以后怎么加新卷 / 新录音 / 新词表,见 data-pack/README.md
与 docs/data-pack.md。
发布
三处发布,各自独立:
- GitHub:代码仓公开,
main分支。推代码前先跑一遍npm run test:client && npm run check:starter(不依赖题库,CI 里也只跑这两步)。 - npm:
npm publish(或打v*tag 走 .github/workflows/release.yml, 仓库 Secrets 里放NPM_TOKEN)。包内容由package.json的files白名单决定:只有代码、 内置示例(starter/)与文档,data/、data-pack/、.cache/都不会进包。 发版前用npm pack --dry-run自己看一眼清单。 - 插件市场:awesome-dsh-plugin
是 dsh 插件市场的目录源,上架方式是去那个仓库提 PR(不是往 market 仓库提,也不是往某个后台传包)。
硬性条件:
package.json里有dsh.bundle、仓库创建满 1 天、仓库 topics 带dsh-plugin。 条目放在data/plugins/mount9527__dsh-cet6.yml,文案按「内置原创示例 + 可导入自备真题」写, 不要写成「提供真题」。合并后站点与市场通常一天内自动收录。
发布物、README 与市场条目都不放图片演示(截图会变成对试题内容的复制;示例页的图也能省则省)。 功能用文字说清楚就够了。
许可
代码与 starter/ 里的原创示例内容均为 MIT(见 LICENSE)。许可不覆盖你自己准备的题库:
真题、录音、词汇资料的版权归原权利人,插件不附带也不分发这些内容,你的构建产物请自用。
详见 NOTICE.md。
No comments yet. Be the first to write one.