【生活娱乐-亲子教育、社会公益赛道】字帖生成器 — 纯前端 PWA 离线汉字书法练习工具(复赛最终版 v3.0.0)
A Type, A Trace — 一键生成带拼音、组词、笔画分解、动态笔顺演示的描红字帖,支持矢量 PDF 输出,PWA 离线安装。
本文为 TRAE AI 创造力大赛复赛作品说明帖(最终版 v3.0.0)。作品体验入口、源码包等交付物已通过飞书问卷私密提交,仅供评审查看;按大赛规则,社区帖内不放置体验链接、二维码或可下载的源码/安装包。
本帖修订说明(2026-08-07)
本帖于 2026-07-23 发布(v2.9.5 时代)、07-26 更新至 v2.9.7,08-06 整合修订至 v2.9.9。此后项目持续推进至 v3.0.0,本帖下方回复楼层中已沉淀了大量重要内容(字体需求答疑、创作心路长文、笔顺功能"克制—破局"决策、v2.9.8 真离线升级、v2.9.9 AI 组词升级、v3.0.0 双引擎 AI 升级等)。
本次修订(v3.0.0 最终版)依据 《复赛参赛指南》(topic 152171) ,对照项目最新 功能和特点做了深度核对(已按规则隐藏仓库地址,retake 分支),将主贴 + 全部回复楼层整理合并为一份完整的作品说明帖,体现历次迭代的最新进展与当前状态。复赛截止时间为 2026-08-09 23:59,本帖即为最终提交版本。
版本更新记录:
| 时间 | 版本 | 里程碑 |
|---|---|---|
| 2026-07-05 | v1.0 | 初赛 Demo(单 HTML 文件) |
| 2026-07-21 ~ 07-26 | v2.0 ~ v2.9.7 | 复赛:工程化重构 + PWA + 学习闭环 + 界面辅助 |
| 2026-08-05 | — | 补充创作心路长文(“一个普通人的 AI 探索”) |
| 2026-08-06 | v2.9.8 | 真离线动态笔画笔顺演示(9574 字打包)+ 导航 16 步 |
| 2026-08-06 | v2.9.9 | 笔画弹窗加载态 + AI 组词补齐(DeepSeek) + 拼音纠错 + 引导 17 步 |
| 2026-08-07 | v3.0.0 | 双引擎 AI(DeepSeek + 火山引擎豆包)+ 三模式分流 + 超时重试 + 缓存穿透修复 + 级联开关 + 引导 18 步 |
这个动态演示笔画笔顺的功能到2.9.8之后才有,2.9.9之后才初步完善离线和在线功能:
0. 一句话定位(最新)
离线优先的汉字学习闭环平台——从"字帖生成工具"升级为"汉字学习闭环平台":输入汉字,一键生成带拼音、组词、笔画分解、动态笔顺演示的描红字帖,矢量 PDF 三轨输出,PWA 离线安装;配合历史记录、练习反馈、艾宾浩斯复习计划、难度评估、内置模板库、文件导入、双引擎 AI 组词,形成 “生成 → 练习 → 反馈 → 复习” 的完整学习闭环。
当前版本 v3.0.0(2026-08-07 部署上线):在 v2.9.9 实现 AI 组词补齐(DeepSeek)与拼音纠错的基础上,新增 火山引擎豆包双引擎支持(API Key 前缀自动识别)、三模式 AI 分流(fast / single_check / poly_check)、5 分钟硬超时 + 部分成功处理、指数退避重试、缓存穿透修复(pinyinChecked)、级联开关联动、HTTP 状态码中文诊断、4 级健壮 JSON 解析、紧急逃生门(localStorage.ai_model_override),导航引导增强至 18 步,并修复多项健壮性 Bug。
1. 团队介绍
| 项目 | 说明 |
|---|---|
| 参赛身份 | 个人参赛 |
| 社区昵称 | u309409433785034 |
| 编程年限 | 业余爱好 20+ 年,熟悉 Matlab / Mathematica;Html/CSS/JS 素人 |
| 职业背景 | 材料和化学方向工程技术人员,小学生家长,关注教育科技与汉字书写传承 |
| 擅长领域 | 产品需求分析、技术方案设计、AI 辅助开发(全程自己没写一句代码,代码全部由 AI 生成,我扮演的是"目不转睛、吹毛求疵、写代码做测试的 LLM 们见了都怕的产品经理") |
| 为什么做 | 自书法练习者,深感市面字帖工具痛点:内容固定、依赖网络、输出模糊。希望用技术降低练字门槛,服务教师、家长和书法爱好者 |
初赛晋级作品:【学习工作赛道】字帖生成器 — 纯前端离线汉字书法练习工具(另见初赛帖子 71664)
关于"为什么做"的一点私心(补自楼层回复)
孩子上小学后每天要练字,市面字帖要么内容固定、要么依赖网络、要么收费,更头疼的是付费字帖打印出来还是位图,放大就模糊,根本谈不上描红精度。我自己平时爱写毛笔字,同样苦于找不到适合自己进度的字帖——就像背单词不想每次都是 abandon,临字帖抬眼就是"永和九年"。
有一次我开 1.6L 的经济型车接送孩子,被另一个小朋友感慨"哇,这么豪华"。这句话让我瞬间震惊:在有些孩子看来平平常常、甚至还老嫌弃的东西,对别人却可能是遥不可及。还有很多类似的小学生,他们也应该在不付费的情况下享受类似的机会——这是 MIT 协议的初衷,也跟 TRAE 用自身算力缓冲池过剩算力普惠广大未付费用户的初衷类似:用自己有限的余力,借 TRAE 慷慨赞助的东风(2.9.9版本及之前仍是 free 用户,平时实在用不了那么多 token,不过3.0.0之后已经是Lite用户了),取之于免费,还之于 MIT 与普惠。
2. 产品简介(复赛版)
2.1 是什么
字帖生成器是一款纯前端、可 PWA 离线安装的应用,基于 Vite + ES Module 工程化构建。无需服务器、无需安装、无需联网,安装到桌面/手机主屏后完全离线可用。输入汉字后自动生成带拼音标注、组词提示、笔画分解、动态笔顺演示的描红字帖,支持矢量 PDF 输出。
相比初赛 Demo 的"单 HTML 文件",复赛版本已升级为工程化 PWA 应用:完整的构建流程、CI/CD 自动部署、模块化代码结构,并新增了学习闭环(历史记录 / 练习反馈 / 复习计划 / 学习报告)、界面辅助(设置中心 / 新手引导 / 演示模式 / 难度评估)、SVG 矢量字格引擎(5 种网格 × 3 种渲染模式 × 物理级 18mm 精度)、离线动态笔顺演示(9574 字)与 双引擎 AI 组词补齐(DeepSeek + 火山引擎豆包)。
进入复赛之后的早期版本界面(此后持续迭代更新,界面设计以后还可根据反馈调整):



v2.9.3 之后修改的界面(Desktop):

字帖预览(移动端、Desktop 等效果一致性好):


版本更迭2.9.5之后在Matepad上的字帖效果:
2.2 面向谁
- 中小学语文教师 — 快速生成课堂练习字帖,自定义练习内容,支持 txt/md/csv/xlsx/docx 批量导入生字
- 家长 — 为孩子定制课后练字纸,随时打印,保护儿童隐私(全部数据本地处理,不上传)
- 书法爱好者 — 自由切换多款开源书法字体,个性化练习
- 教育资源匮乏地区 — 无网络环境可用,服务教育公平(乡村老师无网教室打开手机即用)
- 任何想写好汉字的人 — 正如作者所说:“自从用了电脑,打字技术增长,但字却越来越丑”
2.3 完整功能清单(按引入版本归类,初赛/复赛对照)
| # | 功能 | 说明 | 初赛 | 复赛 |
|---|---|---|---|---|
| 1 | 智能描红字帖生成 | 输入汉字自动生成田字格描红字帖 | ||
| 2 | 拼音自动标注 | pinyin-pro 引擎,带声调显示 | ||
| 3 | 组词辅助 | 1719 条自定义词典 + cnchar 回退 | ||
| 4 | 笔画分解 | hanzi-writer SVG 笔画渲染(静态参考) | ||
| 5 | 矢量 PDF 导出 | 浏览器打印 + jsPDF/svg2pdf + Puppeteer 三轨方案 | ||
| 6 | 日间/夜间主题 | CSS 变量驱动,Dark 模式范字自动反色 | ||
| 7 | 字体上传 | 用户自定义字体(FontFace API) | ||
| 8 | PWA 离线安装 | Service Worker 缓存,安装到桌面/主屏 | ||
| 9 | 开源字体(版权合规) | 霞鹜文楷/思源宋体/文鼎楷体等 6 款 | ||
| 10 | Vite 工程化构建 | ES Module 模块化,27 个 JS 模块文件 + 19 个 CSS | ||
| 11 | CI/CD 自动部署 | 自动化构建部署(GitHub Actions → Pages) | ||
| 12 | Tailwind CSS v4 | 现代化 UI 框架集成 | ||
| 13 | Lucide Icons | 现代化 SVG 图标库 | ||
| 14 | 单文件构建能力 | vite-plugin-singlefile 生成可离线分发单 HTML | ||
| 15 | 在线访问 | 评审可直接打开体验(链接按规则走飞书问卷) | ||
| 16 | 历史记录 | 自动保存最近 20 条生成记录,支持重新生成/删除/清空 | ||
| 17 | 练习反馈闭环 | 整体反馈(轻松/有点难/需要继续)+ 单字反馈(掌握/复习/错字) | ||
| 18 | 复习计划生成 | 基于艾宾浩斯遗忘曲线(7天/3天/1天规则),本地自动生成复习计划 | ||
| 19 | 内置模板库 | 20 个预设模板(唐诗宋词 8 + 三字经 2 + 千字文 2 + 常用字 3 + 成语 3 + 节日 2) | ||
| 20 | 分级字库 | 3 级 18 分类(初级 1-5 画/中级 6-10 画/高级 10+ 画) | ||
| 21 | 设置中心面板 | 滑块(格子大小/每行字数/每页行数/字体大小)+ 开关(拼音/组词/笔画/笔顺)+ 主题三选 | ||
| 22 | 新手引导 | 3 步聚光灯引导(输入框→生成按钮→打印按钮),首次自动触发,现扩展至 18 步 | ||
| 23 | 演示模式 | 一键加载示例并生成字帖,3 秒操作提示,脉冲动画 | ||
| 24 | 难度评估 | cnchar 笔画数计算,5 级星级 + 初级/中级/高级标签,实时评估 | ||
| 25 | 米字格/回宫格 | 新格子样式(纯 CSS 实现),含打印友好样式 | ||
| 26 | 学习报告样式 | 报告卡片/统计区域/柱状图/进度条样式(v3.0.0 已升级为纯原生 Canvas 学习报告面板:7 天趋势/难度分布/掌握率) | ||
| 27 | SVG 矢量字格引擎 | 参数化 Inline SVG(viewBox 100×100 抽象坐标 + CSS mm 物理尺寸),屏幕/PDF/打印三者一致 | ||
| 28 | 5 种网格类型 | 田字格 / 米字格 / 九宫格 / 回字格 / 拼音田字格(上 30% 四线三格 + 下 70% 田字格),侧栏一键切换 | ||
| 29 | 3 种渲染模式 | stroke-order(首字彩色笔顺示范)/ trace(浅灰描红 0.1–0.4 透明度可调)/ blank(空白自写) | ||
| 30 | 物理级 18mm 精准尺寸 | CSS width:18mm + @page margin + preferCSSPageSize,误差 <0.1mm,绝不跨页断格 | ||
| 31 | 4 色网格颜色预设 | 传统绿(默认)/ 朱砂红 / 靛青蓝 / 墨黑,侧栏快切 | ||
| 32 | 320px 双栏工作台 | 左侧柔光侧栏 + 右侧 A4 沉浸式预览,移动端自动改抽屉 | ||
| 33 | 接口契约层 | contracts/interfaces.js:GridCellProps / GridType / RenderMode / PdfExportOptions 标准 Props,多 Agent 并行开发零冲突 | ||
| 34 | 文件导入 | 支持 txt/md/csv/xlsx/docx 导入生词(xlsx/docx 动态 import 按需加载) | ||
| 35 | 智能推荐 | 离线规则版,按难度/主题/场景三维度推荐 | ||
| 36 | 系统字体自动匹配 | 启动时自动从当前操作系统(Windows/Linux/macOS/Android/HarmonyOS)已安装字体中匹配加载 1-2 种楷体(避免加载问题作了限制),下拉菜单以 ★ 标识 | ||
| 37 | 离线动态笔顺演示 | 点击字格弹窗逐笔演示,9574 个汉字离线数据(11.75MB Gzip 二进制 + Web Worker 解压)+ HanziWriter 双图层 + 播放/暂停 + 速度 1x-5x 可调 + 最多 4 窗并存 + 多窗口 | ||
| 38 | 笔画弹窗加载态 | 首次访问数据未就绪时点击字格立即显示加载动画弹窗 + 就绪徽章 | ||
| 39 | AI 组词补齐 | 大模型补齐默认词库缺失的二字组词,设置中心开关 + API Key 配置,localStorage 缓存 + 中断支持 | ||
| 40 | AI 拼音纠错 | AI 组词时同步注音核对 + 全局拼音校验(多音字修正),显示纠错报告(原拼音→纠正拼音+原因) | ||
| 41 | 双引擎 AI(DeepSeek + 豆包) | API Key 前缀自动识别(sk-→DeepSeek,ark-→火山引擎豆包),无需手动切换引擎;豆包免费入门、DeepSeek 性价比付费,覆盖不同用户群体 | ||
| 42 | 三模式 AI 分流 | fast(仅补齐组词,批次 10 字)/ single_check(单音字校验,批次 10 字)/ poly_check(多音字深度校验,批次 6 字 + 自动升级强模型);多音字本地预判定,大幅降低 token 消耗 | ||
| 43 | 缓存穿透修复 | 缓存条目新增 pinyinChecked 字段:全量检查/拼音纠错对已有组词缓存的字不再误跳过;补齐组词不再覆盖已有拼音纠正记录 | ||
| 44 | 5 分钟硬超时 + 部分成功处理 | HARD_TIMEOUT_MS=300000,超时返回 partialSuccess + 已完成字数 + 诊断建议;兼容旧 WebView 的 AbortSignal.any 缺失 | ||
| 45 | 指数退避重试 | MAX_RETRY=3,500ms×attempt 退避;重试全失败的批次跳过但继续后续批次 | ||
| 46 | 级联开关联动 | 启用总开关 → 默认勾"组词补齐";勾"全量检查" → 自动勾选其余两项并禁用(灰显)+ 黄色耗时预警条;取消恢复可编辑 | ||
| 47 | 错误诊断建议 | 按 HTTP 状态码分类的中文诊断(401/403/404/429/网络错误/超时/JSON 解析失败) | ||
| 48 | 健壮 JSON 解析 | 4 级解析策略(直接解析→剥离代码块→提取首个 {…}→提取首个 […]),适配豆包 lite 等弱模型输出多余文字/代码块场景 | ||
| 49 | 引导 18 步 | 新增"AI 组词补齐"+"AI 调用流程解读"两步;autoOpen 机制联动打开设置面板/侧栏/历史栏 | ||
| 50 | 紧急逃生门 | localStorage.ai_model_override 可免打包切换模型(补丁C) |
2.4 用户使用路径
访问在线地址(评审经飞书问卷获取)
↓
[首次使用] 新手引导 18 步 → 浏览器提示安装 PWA → 点击安装到桌面/主屏
↓
[快速体验] 点击"演示模式"按钮 → 自动加载示例并生成字帖
↓
[自主使用] 在文本框输入要练习的汉字(或从模板库/分级字库/文件导入选字)→ 难度评估实时显示
↓
选择字体(霞鹜文楷/思源宋体/文鼎楷体等开源字体 + 系统楷体自动匹配 ★)
↓
[可选] 选择网格类型(田字格/米字格/九宫格/回字格/拼音田字格)与渲染模式(笔顺示范/描红/空白)
↓
[可选] 打开设置中心调整格子大小/每行字数/显示选项/颜色预设;[可选] 配置 AI 组词(DeepSeek 或豆包 API Key)
↓
点击「生成字帖」→ 实时预览拼音+组词+笔画 → 自动保存到历史记录
↓
[笔顺学习] 点击任意字格 → 弹窗逐笔演示笔顺(速度 1x-5x,最多 4 窗)→ 窗口可最小化/最大化/拖拽
↓
[练习反馈] 标记整体难度(轻松/有点难/需要继续)
↓
[单字反馈] 悬停字帖格子标记单字状态(掌握/复习/错字),状态色环(绿/黄/红)
↓
[AI 组词] 设置中心启用 → 输入 API Key → 点击运行 → 三模式分流批量补齐组词/校验拼音 → 查看统计与纠错报告
↓
点击右下角打印按钮 → 浏览器打印预览(全平台)/ jsPDF 矢量导出 / Puppeteer 命令行(桌面端)
↓
[复习] 次日打开 → 首页显示"今日待复习" → 一键加载复习字帖;学习报告查看 7 天趋势/掌握率
↓
[离线使用] 关闭网络后刷新页面 → 仍可正常使用(含笔顺动态演示、AI 已缓存结果)
2.5 PWA 安装与离线使用
本作品是标准 PWA(Progressive Web App),支持安装到桌面/手机主屏,安装后完全离线可用(Service Worker 预缓存全部核心资源含字体;v2.9.8 起 SW 安装包优化至 3.3MB,笔顺数据与字体按需缓存、长期有效)。
如何安装 PWA 应用(演示视频,含 Node.js 支持与 Puppeteer 矢量 PDF 导出功能的 Desktop 使用方式;Windows 从 bat/powershell 脚本启动,Linux/macOS 用 .sh 脚本启动):
桌面端:
- Microsoft Edge(推荐,开发测试用):打开页面 → 地址栏右侧出现 ⊕ 安装图标 → 点击「安装」→ 桌面生成独立应用图标;备用入口:右上角 ⋯ →「应用」→「将此站点作为应用安装」
- Google Chrome:地址栏右侧 ⊕ 图标 →「安装」;或 ⋮ →「保存和分享」→「将页面作为应用安装」
- Brave / Opera / Vivaldi / 国产浏览器(360/搜狗等):地址栏 ⊕ 图标或菜单中搜索"安装应用"
移动端:
- Android(Chrome/Edge/Firefox):浏览器菜单 ⋮ →「添加到主屏幕」或「安装应用」
- iOS 16.4+(Safari):分享按钮 →「添加到主屏幕」(16.4+ 才支持 PWA 推送和离线)
- Firefox:桌面版不支持 PWA 安装,可正常在线使用;移动版支持「添加到主屏幕」
离线验证:安装后断开网络(关 Wi-Fi 或拔网线)→ F5 刷新 → 页面正常加载,所有功能可用(含字体、拼音、笔画渲染、动态笔顺演示);或 F12 → Network → Online 改 Offline 刷新验证。
2.6 相比初赛 Demo 的升级(详细对比)
| 维度 | 初赛 Demo | 复赛完整作品 | 升级幅度 |
|---|---|---|---|
| 代码结构 | 单 HTML 文件(1.1MB) | Vite 工程化(27 JS 文件 + 19 CSS + 3 数据文件) | |
| 构建工具 | 无(手动管理) | Vite 5.4 + vite-plugin-singlefile + vite-plugin-pwa | |
| 部署方式 | ZIP 下载解压 | 在线访问 + CI/CD 自动部署(体验入口按规则走飞书问卷) | |
| 离线能力 | 双击 HTML 文件 | PWA 安装到桌面/主屏,Service Worker 缓存;v2.9.8 起"真离线" | |
| 字体版权 | 9 款含商业字体(仅演示用) | 6 款开源字体全部合规(OFL/Apache-2.0/GUST) | |
| UI 框架 | 原生 CSS | Tailwind CSS v4 + Lucide Icons | |
| 字格渲染 | CSS Grid 拼凑 | SVG 矢量引擎(viewBox 抽象坐标 + 18mm 物理尺寸 + 行级统一边框) | |
| 依赖管理 | CDN + 内嵌 | npm 统一管理版本(12 运行时 + 5 开发) | |
| 版本控制 | 无 | Git + 备份分支(25+)+ 标签回退策略(28+ tags) | |
| 文档规范 | README + CHANGELOG | README(中英)+ CHANGELOG + 参赛文档 + 方案文档 + TASK_BOARD | |
| 学习闭环 | 无 | 历史记录 + 练习反馈 + 复习计划(艾宾浩斯规则)+ 学习报告 | |
| 内容辅助 | 无 | 模板库 20 个 + 分级字库 3 级 18 分类 + 演示模式 + 难度评估 + 文件导入 + 智能推荐 | |
| 笔顺学习 | 静态笔画分解 | 离线动态笔顺演示(9574 字,Web Worker 解压) | |
| AI 能力 | 无 | 双引擎 AI 组词补齐 + 拼音纠错(DeepSeek + 火山引擎豆包,三模式分流),AI 贯穿开发全程 | |
| 用户体验 | 无引导 | 新手引导 18 步 + 设置中心 + FAB 拖拽 + Dark/触屏/移动端适配 |
2.7 产品边界与免责声明
- 本工具是辅助练字的工具,不替代学校书法课程、专业书法教师指导与教材
- AI 组词/拼音纠错为可选增强功能,默认关闭,需用户自配 API Key;受大模型概率生成特性影响,冷僻字/多音字偶需多次点击;AI 结果仅供参考,以权威教材/字典为准
- 隐私承诺:全部数据本地处理,本工具自身不设任何服务器、不留存任何用户数据;AI 数据仅发往用户自选的模型服务商(DeepSeek/火山引擎豆包)
- 字帖内容与字体均来自开源生态;用户自上传字体/内容的版权与合规责任由用户自行承担
3. 产品演示视频
视频 1(复赛主流程,v2.9.5 时代):演示了包含 Node.js 支持和 Puppeteer 矢量格式 PDF 导出功能的 Desktop 使用方法;使用 Windows,可从 .bat 或 .ps1 脚本启动,Linux/macOS 用 .sh 脚本;电脑比较老旧、天气热、降温只靠风扇,所以视频中反应比较迟钝。
从脚本打开全功能使用视频(约 12MB,曾因论坛 20MB 上限险些传不上)
视频 2(v2.9.8,动态笔顺演示):见楼层 13 回复,演示点击字格呼出离线动态笔顺演示窗口(双窗口截图 + 视频)。
V3.0.0这个双引擎“AI辅助组词”的功能不得不提,以前一直以为豆包Lite免费版总体表现一般,不过这次这个对比说明,在辅导学生方面豆包确有过人之处(含 v3.0.0 双引擎 AI 组词、三模式分流、级联开关演示);因为等待时间要1-2分钟(设置了超过5分钟强行截停),所以我只放操作视频和对比结果。
测试用生字集-人教版五年级下册语文2019版生字
昼耘桑晓蝴蚂蚱嗡樱拔瞎铲锄割尾承拴瓢逛妒忌曹督委鲁遮寨擂呐插冈饥碟斤俺榜杖申兼勿拖悉坠膛截仞岳摩遗涕巫彭拟谋瑞损锻炼眷赴搞殊尊签革庆诊沃龄匪绷审剂施吭崭衷慈祥荣跤搂仗鞭欺挠扳腕剃腮疤监侄喉咙浆傅袱桶障芝圣犯馅轰堪诈傻捏怔矛盾誉吾赢拳擦策荐艘航肆帽桅撕逗唬钩扭咧舱鸥瞄尼斯艇纵艄翘垫帘姆祷雇簇哗码笼仪眺骏驰辽绵凳吆铛罐恢踢牲畜梁诣禽拇搔痒秽轧拧螺纽扣貌仓渺享庸憎
豆包2.0Lite组词结果(没有遗漏,用时76秒):
DeepSeek V4Flash组词结果(有遗漏,用时65秒)
操作视频
字帖自带的开源工具对某些生字无法给出合适的组词,默认就显示“组词”;刚刚导入的时候可以看到,这批生字,有多个仅仅依靠开源的、自带的工具,不能完成组词,这也是2.9.8及之前版本的一个痛点。2.9.9引入deepseek,3.0.0则进一步引入在这方面更擅长的豆包(我辅导功课常常会在技穷的时候倾向于求助豆包和豆包爱学)。——如果有专用微调的大模型,可能会更好。

4. 产品创作历程
4.1 想法诞生
作为一名书法练习者,我在日常练字中遇到几个痛点:
- 市面上的字帖内容固定、无法定制
- 在线字帖工具依赖网络且常收费
- 打印出来的字帖往往是位图、放大后模糊不清
- 缺少拼音、组词、笔画分解等教学辅助信息
于是想到用前端技术,做一个完全离线、自由定制、高清矢量输出的字帖工具。
我自从用了电脑,打字技术增长,但字却越来越丑;自从练习写字之后,用小楷毛笔在 A4 复印纸上都能写出这个水平的字了:
——一个真实用户对"写一手好字"的执念,是这个项目最初的起点。
4.2 初赛 Demo(2026-07-05)
初赛阶段采用"最小可行产品"策略:
- 单 HTML 文件实现核心功能(拼音 + 组词 + 笔画 + PDF)
- 双击即可运行,零安装零依赖
- 9 款字体内置(含商业字体,仅演示用)
- 极光毛玻璃 UI,日间/夜间双主题
- Puppeteer 矢量 PDF 双轨方案
初赛成果:成功晋级复赛。(初赛 7 条 Session ID 见 5.5 节)
4.3 复赛完整作品(2026-07-21 至 2026-08-07)
复赛围绕"从工具到产品"的核心目标,经历了 7 大维度升级(v2.0–v2.9.7)→ 真离线破局(v2.9.8)→ AI 组词扩展(v2.9.9)→ 双引擎 AI + 健壮性加固(v3.0.0) 四个阶段。
阶段一:工程化重构(Vite + ES Module)
将 1.1MB 单 HTML 文件拆分为模块化工程:
- 17 个功能模块(src/modules/)+ 2 个组件 + 1 个工具 + 1 个契约:main.js / fontManager.js / settings.js / gridRenderer.js / pdfExport.js / puppeteerClient.js / zuci.js / strokes.js / history.js / feedback.js / review.js / settingsCenter.js / onboarding.js / demoMode.js / difficulty.js / aiZuci.js / hanziDataStore.js / strokeDemoModal.js / fileImporter.js / recommender.js / reportPanel.js / fabDrag.js / Sidebar.js / GridEngine.js / pdfExport.js(utils)等(v3.0.0 扩展至 27 个 JS 源文件)
- 19 个 CSS 文件:base / components / fab / grid / main / print / tailwind / theme / history / feedback / review / grid-styles / report / settingsCenter / onboarding / demoMode / difficulty / strokeDemoModal / grid-svg 等
- 3 个数据文件:customZuCi.js(1719 条组词)/ templates.js(20 个模板)/ vocabulary.js(3 级 18 分类字库)
- 构建工具:Vite 5.4 + vite-plugin-singlefile(保留单 HTML 分发能力)
- 依赖管理:pinyin-pro / cnchar / hanzi-writer / jspdf / svg2pdf / mammoth / xlsx / fflate 全部 npm 安装
阶段二:PWA 离线支持
- vite-plugin-pwa 0.20.5:Workbox 预缓存策略
- Service Worker:字体与笔顺数据 CacheFirst 策略(v2.9.8 起 SW 安装包优化至 3.3MB,大文件按需缓存)
- manifest.webmanifest:lang=zh-CN,3 个图标含 maskable
- 可安装到桌面/手机主屏,像原生应用一样独立运行
阶段三:开源字体替换(版权合规)
| 初赛字体 | 复赛字体 | 协议 |
|---|---|---|
| 姜浩硬笔楷书 | 霞鹜文楷 Regular + Light | OFL |
| 华文楷体 | 思源宋体 SC Regular | OFL |
| 方正仿宋 GBK | 文鼎楷体(TW-Kai) | Apache 2.0 |
| 田英章楷书 30Light | TW-Kai | OFL |
| 商业字体 ×6 | 开源字体 ×6 |
- 追加能力:个人使用时,可添加电脑上已安装或已有个性化字体;v2.9.x 起启动时自动从操作系统已安装字体中匹配 1-2 种楷体(★ 标识)。
- 字体合规红线(历次升级时多次声明):未嵌入方正楷体_GBK 或其它需特别授权的字体,默认字体文鼎楷体,可选霞鹜文楷/思源宋体/TeX Gyre Adventor/楷体/KaiTi。
阶段四:UI 现代化
- Tailwind CSS v4:渐进集成,保留 CSS 变量主题系统
- Lucide Icons:主题切换(sun/moon)+ 打印(printer)+ 设置(settings)+ 演示(sparkles)
- 响应式适配:@media max-width:680px 移动端适配
阶段五:CI/CD 自动部署
- GitHub Actions:push 到 retake 分支自动触发构建部署(体验入口按规则走飞书问卷)
- deploy.yml 工作流:字体下载 → Vite 构建 → Pages 部署
- download-fonts.sh:CI 环境自动下载开源字体(霞鹜文楷、思源宋体、文鼎楷体 TW-Kai,全开源协议)
- Pages:https 持续可用,无需续费;部署期间修复 4 个 CI 构建阻断问题、通过 gh api CLI 修复部署权限
阶段六:学习闭环(教育化升级)
复赛核心差异化
将"字帖生成工具"升级为"汉字学习闭环平台":
- 历史记录:每次生成字帖自动保存到 localStorage(最多 20 条),右侧可折叠侧边栏,支持重新生成/删除/清空
- 练习反馈闭环:整体反馈三按钮(很轻松/有点难/需要继续)+ 单字反馈悬停图标(已掌握
/需要复习
/总是写错
)+ 状态色环(绿/黄/红),数据保存 localStorage - 复习计划生成:基于艾宾浩斯遗忘曲线本地规则(已掌握→7 天后复习 / 需要复习→3 天后复习 / 总是写错→明天复习),首页顶部"今日待复习"区域,一键加载待复习字并生成字帖,统计信息(已掌握/待复习/错字数)
- 学习报告面板(v3.0.0 完整版):纯原生 JS + Canvas 图表(7 天趋势 / 难度分布 / 掌握率),不引入图表库
阶段七:内容辅助与体验优化
- 内置模板库:20 个预设模板(唐诗宋词 8 + 三字经 2 + 千字文 2 + 常用字 3 + 成语 3 + 节日 2)
- 分级字库:3 级 18 分类(初级 1-5 画 / 中级 6-10 画 / 高级 10+ 画)
- 设置中心面板:滑块 + 开关 + 主题选项,实时更新预览
- 新手引导:3 步聚光灯引导 → 5 步 → 9 步 → 16 步(v2.9.8)→ 17 步(v2.9.9 含 AI 组词补齐步骤)→ 18 步(v3.0.0 新增 AI 调用流程解读)
- 演示模式:一键加载示例并生成字帖,3 秒操作提示
- 难度评估:cnchar 笔画数计算,5 级星级,实时评估
- 米字格/回宫格:新格子样式,含打印友好样式
- 智能推荐:离线规则版,按难度(3 级)/主题(13 类)/场景(6 类)三维度推荐,单字点击追加/模板点击覆盖/一键加载分类全部
阶段八:SVG 矢量字格引擎(v2.4,复赛中期关键架构升级)
复赛版本中期,将 CSS Grid 拼凑渲染升级为参数化 Inline SVG 矢量引擎:
- GridEngine.js:viewBox 100×100 抽象坐标 + CSS mm 物理尺寸,一处修改全局生效
- 5 种网格类型:田字格 / 米字格 / 九宫格 / 回字格 / 拼音田字格(上 30% 四线三格 + 下 70% 田字格)
- 3 种渲染模式:stroke-order(首字彩色笔顺示范)/ trace(浅灰描红,透明度 0.1–0.4 可调)/ blank(空白自写)
- 18mm 精准物理尺寸:CSS width:18mm + @page margin + preferCSSPageSize,误差 < 0.1mm,绝不跨页断格
- 4 色网格颜色预设:传统绿(默认)/ 朱砂红 / 靛青蓝 / 墨黑
- 接口契约层 contracts/interfaces.js(GridCellProps/GridType/RenderMode/PdfExportOptions):模块间标准 Props,多 Agent 并行开发零冲突
- 行级统一边框(v2.4.14):整行外框 + 竖线绘制在同一个 SVG 中,消除多个独立 cell 的亚像素累积误差;改用填充矩形代替 stroke,确保 PDF 中线宽精确(stroke 在 PDF 中可能渲染为 0 宽度)
- currentColor 智能反色(v2.9.7):范字使用 currentColor,dark 模式自动反色,打印时 print.css 强制黑色
- 320px 双栏工作台:左侧柔光侧栏 + 右侧 A4 沉浸式预览,移动端自动改抽屉
阶段九:真离线破局——离线动态笔画笔顺演示(v2.9.8,2026-08-06 凌晨)
这是一个"克制 → 破局"的故事,完整记录见楼层 11–14。
为什么 v2.9.7 之前没有动态笔顺?(楼层 11 详细论证)
- 数据依赖冲突:HanziWriter 每个汉字需独立 JSON 数据文件,原型阶段近万个零碎 JSON 文件,要么请求 CDN(违背离线初衷)、要么全打包(构建体积灾难性膨胀),与"离线普惠"底线冲突;
- 核心场景错位:字帖归宿是"打印出来的纸",静态笔画分解参考(功能 #4)已足够;动态演示是屏幕交互场景,强行嵌入会打断"批量生成、一键打印"心流;
- 做产品要做减法:AI 时代实现炫酷功能前所未有地容易,但技术上摆不平问题就忌讳 Feature Creep;初赛"动态笔顺"作为技术探索更适合独立识字工具。
破局(楼层 12–13):后来发现可以把近万个 JSON 文件自己重新打包、压缩成一个数据文件,编写专门的检索和读取工具,实现完全离线的动态笔顺——“炫酷而耗时,但对字帖基本功能的改良有限(如果有的话,应该是可以离线很彻底)”。于是连夜更新 v2.9.8:
- 内置 9574 个汉字离线数据(11.75MB Gzip 二进制,Web Worker 后台解压,不阻塞主线程)
- 双图层架构:底层 0.25 不透明度轮廓始终显示,顶层逐笔动画覆盖
- 播放/暂停两态切换,速度 1x–5x 可调并持久化到 localStorage
- 最多 4 个演示窗口并存,支持最小化/最大化/关闭/拖拽
- 引导流程 9 步 → 16 步;新增独立笔顺演示介绍页 stroke-demo-guide.html
- 新增 fflate 依赖;hanziDataStore.js 用 import.meta.env.BASE_URL + new URL 修复子路径 404;vite.config.js globIgnores 排除大文件 precache,SW 从 140MB 降至 3.3MB
- 多级降级方案:Web Worker → 主线程 fflate 解压 → .js Base64 降级 → 网络备选;支持自定义数据扩展(冷僻字/新造字),localStorage 持久化
性能取舍:出于对设备性能的考虑,限制最多开 4 个动态演示窗口。
阶段十:AI 组词补齐 + 拼音纠错(v2.9.9,2026-08-06)
“又是一次规划之外的迭代,但极大地弥补了真实使用场景下的体验缺口。”
缘起:v2.9.8 实现"真离线"后才发现,联网加载过程中受网速限制仍会卡顿;笔画演示在低网速/缓冲期容易受影响。v2.9.9 核心任务:解决未完全加载或低网速缓冲过程中依然流畅使用笔画笔顺及动态演示的问题。
核心修复与升级:
- 本地缓存 + 网络同步双轮驱动:动态笔画笔顺即时可用,缓冲期 Bug 彻底修复(修复本地数据缓冲时功能短暂瘫痪的漏洞),Mobile/Desktop 双端压测通过;
- 笔画弹窗加载态:首次访问数据未就绪时,点击字格立即显示加载动画弹窗 + 就绪徽章;
- 重磅:AI 组词接入(DeepSeek API):为解决某些生字组词不完整甚至完全没有组词的痛点,在增加 API Key 的情况下添加"AI 组词":
- 入口深藏、默认关闭,需手动输入用户自己的 DeepSeek API Key;
- 目前定位测试期,暂时只提供 DeepSeek(性价比与口碑兼备);
- 受 LLM 概率生成特性影响,冷僻字/多音字场景有时需多次点击"AI 组词"才得到理想结果;
- AI 拼音纠错增强(同日晚间):AI prompt 升级为"注音核对 + 精准组词 + 全局拼音校验"——角色设定为专业汉语教学与拼音专家,组词前先核对 pinyin-pro 预设拼音、多音字自动修正,杜绝地名/人名专有名词(如"鹤"禁用"鹤壁"),词性多样化,JSON 结构化输出 {chars, fix_count, fixes};新增 getAiPinyin() 仅当 AI 明确修正时返回纠正值,GridEngine 两处拼音生成点优先使用 AI 纠正结果,设置中心显示纠错报告(原拼音→纠正拼音+原因);缓存扩展向后兼容;
- 导航引导 16 步 → 17 步(新增 AI 组词补齐步骤,autoOpen: ‘settings’ 高亮 AI 区域)。
v2.9.9 其他修复:汉字打印无法正常显示(强制 light 主题 + FontFace URL 加引号)、页脚黑色底色、触屏版 Light 主题渲染(内联 color-scheme)、导航按钮显示、localStorage 规则优化、最小化/最大化按钮失效(固定 vw/vh)、速度滑块失效(hanzi-writer 3.7.3 无 updateOptions,直接赋值 _options)。
阶段十一:v3.0.0 双引擎 AI + 健壮性加固(2026-08-07)
“为了把豆包大模型放进去,还花了两个 9.9 元,购买了火山引擎 Lite 和 Trae Work 权限——其实都不是真用得上,只是测试产品调用大模型的很简单的附加功能而已。事实证明:必须从开源社区进一步汲取能量,或者微调出专用小模型,否则原创的要求很高。”
缘起:v2.9.9 的 AI 组词(DeepSeek)上线后收到真实反馈:DeepSeek 需要用户自配 API Key 且为付费接口,部分用户希望有免费入口;同时弱模型/弱网环境下偶发 JSON 解析失败、卡死无响应。v3.0.0 目标:把"单引擎、单一模式"升级为"双引擎、三模式分流"的健壮 AI 管道,并整体加固超时、重试、缓存与诊断。
真实参赛经历(如实记录):为了把豆包大模型放进产品做测试,我分别购买了火山引擎 Lite 权限和 Trae Work 权限用来测试"产品调用大模型"这个很简单的附加功能而已。实测后发现:接入一个全新的大模型,API 格式差异、JSON 输出差异、弱模型能力差异都会带来一连串工程问题;这次迭代让我最深刻的体会是——必须从开源社区进一步汲取能量(比如借鉴社区开源的健壮 JSON 解析、超时重试、请求合并方案),或者微调出专用小模型,否则"原创的要求很高"。这也是为什么我在致谢里强调开源社区的价值:个人开发者单打独斗做 AI 应用,站在巨人肩膀上才是正路。
核心升级(v3.0.0,共 10 项):
- 双引擎 AI 自动识别:API Key 前缀自动路由——
sk-→ DeepSeek(deepseek-v4-flash,支持 response_format: json_object,性价比优),ark-→ 火山引擎豆包(doubao-seed-2-0-lite-260428 快速模式,免费入门);全量检查时豆包自动升级 doubao-seed-2-1-turbo-260628 强模型;紧急逃生门 localStorage.ai_model_override 可免打包切换模型(补丁C) - 三模式分流:AI 处理前用 pinyin-pro multiple 模式判定多音字,将待处理字分为三组——fast(仅补齐组词,批次 10 字,max_tokens 2048)/ single_check(单音字校验已有组词,批次 10 字,max_tokens 4096)/ poly_check(多音字深度校验音义匹配,批次 6 字 + 自动升级强模型);不同提示词 + 不同批次,大幅减少不必要的 AI 调用、降低 token 消耗
- 缓存穿透修复(pinyinChecked 字段):缓存条目结构 {zuci, pinyin, pinyinFixed, pinyinChecked, wordsDetail, ts};pinyinChecked 字段确保全量检查/拼音纠错模式下,已有组词缓存但未经拼音校验的字不再被误跳过;补丁B 修复"仅拼音纠错后的字再次组词补齐时被误跳过"的问题,且补齐组词时不再覆盖已有拼音纠正记录
- 5 分钟硬超时 + 部分成功处理:HARD_TIMEOUT_MS = 300000;combineSignals() 合并外部 signal + 超时 signal(兼容旧 WebView 的 AbortSignal.any 缺失,补丁A);超时后返回 partialSuccess: true + 已完成的字数 + 诊断建议
- 重试机制:MAX_RETRY = 3,指数退避(500ms × attempt);重试全失败的批次跳过但继续下一批
- 健壮 JSON 解析(4 级策略):直接解析 → 剥离 markdown 代码块 → 提取首个 {…} → 提取首个 […];适配豆包 lite 等弱模型可能输出多余文字或代码块的场景
- 级联开关联动:启用总开关 → 默认勾"组词补齐";勾"全量检查" → 自动勾选其余两项并禁用(灰显)+ 显示黄色耗时预警条;取消"全量检查" → 恢复可编辑状态;面板重新打开时自动同步默认勾选状态
- 错误诊断建议:按 HTTP 状态码分类给出中文建议(401/403/404/429/网络错误/超时/JSON 解析失败)
- AI 运行按钮升级:运行中变为"
中断"(AbortController);旋转图标(SMIL animateTransform,无需 CSS keyframes)+ 批次进度(已处理/总数 · 批次 N/M);完成后显示详细统计:✓ DeepSeek:共 X · 默认 X · AI X · 缺失 X(Xms) - 引导 18 步:新增"AI 组词补齐"+"AI 调用流程解读"两个步骤(autoOpen: ‘settings’ 联动);防御性编程——每步前检查 selector 存在且可见,不可见步骤自动跳过;IntersectionObserver 滚动边角提示
实测数据:v3.0.0 提交记录实测 90 字组词一次通过(豆包 JSON mode);双引擎 + 三模式分流后 token 消耗较"全部丢给 AI"方案显著下降。
豆包适配的艰难历程(2026-08-07 楼层 18 追加):接入豆包的过程远没有想象中顺利——豆包 lite 作为弱模型,JSON 输出稳定性、响应格式与 DeepSeek 差异明显,经过多轮调试(提取共用 SYSTEM_PROMPT、四级健壮 JSON 解析、3 次指数退避重试、批次降为 6 字 + 强模型兜底)才终于把豆包也修改得能用了。更深层的反思是:如果只用通用大模型,稍微复杂点的任务,自动生成的提示词效果并不理想,可能需要在大模型微调、提示词改进等方面深入打磨——但这已经超过了我作为个人开发者的能力范畴。这也是为什么我把"从开源社区汲取健壮性方案 / 微调专用小模型"写进体会:普通开发者做 AI 应用,能站在巨人肩膀上把产品体验打磨好,已经是很有价值的事了。
版本迭代节奏说明:从 v1.0.1 到 v3.0.0,更新日志记录了 90+ 次 commits、28+ 个版本标签。这些数字不是用来炫耀的,每一次都对应着真实的使用反馈和功能改进。引导从 5 步到 18 步、Dark 模式优化、移动端首次使用引导、桌面端 FAB 拖拽吸附、双引擎 AI……都是因为我真正在使用它、打磨它。业余时间也足以完成——早年混迹 Stackoverflow/StackExchange 养成的"如何提高提问、追问和回答质量"的肌肉记忆,融入 Prompting 技巧之后,vibe coding 的难度并没有想象中那么高,AI 交互出来的交付物,有时候居然能够出人意外地好。
5. TRAE 实践过程
本项目全程使用 TRAE IDE 完成。以下是开发关键步骤、Session ID 和踩坑经验。
5.1 技术架构
| 技术点 | 方案 | 版本 | 说明 |
|---|---|---|---|
| 构建工具 | Vite | ^5.4.0 | 开发服务器(port 3000)+ 生产构建(outDir: dist) |
| 模块化 | ES Module | — | 27 个 JS 源文件(17 模块 + 2 组件 + 1 工具 + 1 契约)+ 19 个 CSS + 3 数据文件 |
| 单文件打包 | vite-plugin-singlefile | ^2.0.0 | 生成可离线分发单 HTML |
| PWA | vite-plugin-pwa | ^0.20.0 | Workbox 预缓存(3.3MB 核心)+ 大文件运行时缓存 |
| UI 框架 | @tailwindcss/vite + tailwindcss | ^4.3.3 | Tailwind CSS v4 渐进集成 |
| 图标库 | lucide-static | ^1.25.0 | 现代化 SVG 图标 |
| 拼音转换 | pinyin-pro | ^3.0.0 | 自动标注声调 + 多音字判定(multiple 模式,MIT) |
| 组词查询 | cnchar + cnchar-words | ^3.0.0 | 智能组词 + 1719 条自定义词典 + 笔画数计算 |
| 笔画渲染 | hanzi-writer | ^3.5.0 → 3.7.3 | SVG 笔画分解 + 动态笔顺动画(MIT) |
| 笔顺数据 | 自研打包 | — | 9574 汉字离线数据(11.75MB Gzip)+ Web Worker + fflate 解压 |
| AI 引擎 | DeepSeek + 火山引擎豆包 | v3.0.0 | 双引擎自动识别(sk-→DeepSeek,ark-→豆包),三模式分流(fast/single_check/poly_check),默认关闭、用户自配 API Key,localStorage 缓存 |
| AI 健壮性 | 超时重试 + 缓存穿透修复 | v3.0.0 | HARD_TIMEOUT_MS=300000、MAX_RETRY=3 指数退避、pinyinChecked 字段、4 级健壮 JSON 解析、HTTP 状态码中文诊断、级联开关 |
| PDF 导出 | puppeteer | ^23.0.0 | 矢量 PDF 生成(.cjs 脚本)+ jsPDF/svg2pdf 纯前端导出 |
| 客户端 PDF | jspdf + svg2pdf.js | ^2.5.2 / ^2.7.0 | 纯前端矢量导出轨道(拒绝位图化 html2canvas) |
| 文件导入 | mammoth + xlsx | ^1.6.0 / ^0.18.5 | DOCX/Excel 动态 import 按需加载 |
| 字体加载 | FontFace API | — | 动态注册 + document.fonts.check() 验证 + 超时重试(5s + 3s) |
| 主题切换 | CSS 变量 + data-theme | — | 日间/夜间/系统三模式 + Lucide 图标切换 |
| 跨模块通信 | CustomEvent | — | calligraphy:history-updated / char-feedback-updated / settings-updated |
| 数据持久化 | localStorage | — | calligraphy_ 前缀(history / char_feedback / settings / onboarded / strokeSpeed / aiCache / deepseek_api_key 等) |
| CI/CD | GitHub Actions | — | deploy.yml 自动构建部署到 Pages |
| 版本控制 | Git | — | retake 分支(默认)+ backup 备份分支(25+)+ tag 快照(28+,含 v2.9.7 / v2.9.8 / v2.9.9 / v3.0.0) |
| 开发工具 | TRAE IDE | — | AI 辅助编码、调试、部署、多 Agent 并行开发(Trae Work 付费试用辅助验证,主力靠 Trae CN IDE) |
5.2 vite.config.js 关键配置
{
base: './', // 相对路径,支持子目录部署
cssMinify: false, // 保护 @media print 关键规则不被 esbuild 合并/丢弃
target: 'es2020', // 保留 ES2020+ 语法
plugins: [
tailwindcss(), // Tailwind CSS v4
viteSingleFile(), // 单 HTML 打包
VitePWA({
registerType: 'autoUpdate',
manifest: {
name: '字帖生成器',
short_name: '字帖',
lang: 'zh-CN',
theme_color: '#9E2A2B',
display: 'standalone',
icons: [ // 3 个 SVG 图标(含 maskable)
{ src: 'icon-192.svg', purpose: 'any' },
{ src: 'icon-512.svg', purpose: 'any' },
{ src: 'icon-192-maskable.svg', purpose: 'maskable' }
]
},
workbox: {
maximumFileSizeToCacheInBytes: 41943040, // 40MB 上限
globIgnores: [ // v2.9.8 起:大文件排除 precache(SW 140MB → 3.3MB)
'**/hanzi-data.bin', '**/hanzi-data-embedded.js', '**/fonts/**'
],
runtimeCaching: [ // 大文件按需加载(CacheFirst,长期有效)
{ urlPattern: /hanzi-data/, handler: 'CacheFirst',
options: { cacheName: 'hanzi-data', expiration: { maxAgeSeconds: 60*60*24*365*10, maxEntries: 10 } } },
{ urlPattern: /\.(?:woff2?|ttf|otf)$/, handler: 'CacheFirst',
options: { cacheName: 'fonts-cache', expiration: { maxAgeSeconds: 60*60*24*365, maxEntries: 20 } } }
]
}
})
],
build: { outDir: 'dist', emptyOutDir: true },
server: { port: 3000, open: true }
}
5.3 关键开发步骤
步骤一:Vite 工程化重构 — 分析全局变量引用关系生成检查清单 → 划分 10 个迁移模块、制定迁移顺序 → 配置 vite.config.js(singlefile + pwa + tailwind)→ 验证功能完整性
步骤二:PWA 配置与离线策略 — 配置 vite-plugin-pwa 0.20.5 → Workbox 预缓存(字体 CacheFirst,最大 40MB)→ 生成 PWA 图标(SVG → 192/512/maskable)→ 验证 Service Worker 注册和离线可用性
步骤三:开源字体替换与 CI 集成 — 评估 6 款开源字体协议合规性 → 编写 download-fonts.sh → 处理思源宋体 zip 解压路径问题(硬编码 → find 动态查找)→ 修复 pdfExport.js 中 14 处字体引用
步骤四:CI/CD 部署与问题排查 — 配置 GitHub Actions deploy.yml → 排查修复 4 个 CI 构建阻断问题 → gh api CLI 修复部署权限 → 验证 Pages 部署成功(HTTP 200)
步骤五:UI 现代化与图标替换 — 集成 Tailwind CSS v4(@import “tailwindcss”)→ 替换 Lucide sun/moon/printer/settings/sparkles 图标 → 保留 CSS 变量主题系统渐进迁移
步骤六:学习闭环三件套(多 Agent 并行开发)
— Agent A:历史记录 + 练习反馈 + 复习计划(顺序执行,有依赖);Agent B:模板库数据 + 分级字库 + 米字格/回宫格样式 + 学习报告样式(纯新增文件零冲突);Agent C:设置中心 + 新手引导 + 演示模式 + 难度评估。技术亮点:自定义事件跨模块通信;单字反馈 DOM 事件委托不修改 gridRenderer.js;settingsCenter 通过 toggleTheme() 与现有 settings.js 同步;所有新 UI 在 @media print 下隐藏不影响 PDF 导出
步骤七:SVG 矢量字格引擎(v2.4) — GridEngine.js 参数化渲染(viewBox 100×100 + CSS mm)→ 5 网格 × 3 渲染模式 → 18mm 物理精度验证(误差 <0.1mm)→ contracts/interfaces.js 契约层(多 Agent 零冲突基础)→ 行级统一边框(填充矩形代替 stroke)
步骤八:v2.9.8 真离线笔顺(多 Agent 并行) — 9574 字 JSON 打包为单 bin(fflate)→ hanziDataStore.js(BASE_URL + new URL 修复子路径)→ Web Worker 解压 → 双图层 HanziWriter 动画 → 弹窗管理(4 窗 + 最小化/最大化/拖拽)→ SW precache 优化(globIgnores,140MB → 3.3MB)
步骤九:v2.9.9 AI 组词 + 拼音纠错 — callDeepSeekDirect 重写(注音核对 + 精准组词 + 全局校验)→ JSON 结构化输出 → getAiPinyin() 纠错回退 → 缓存扩展(zuci/pinyin/pinyinFixed/wordsDetail/ts,向后兼容)→ 设置中心纠错报告 → 引导第 17 步
步骤十:v3.0.0 双引擎 AI + 健壮性加固 — 双引擎抽象层(detectApiKeyType 前缀路由 + getAiProvider 返回 endpoint/model/label)→ 三模式分流(多音字判定 → fast/single_check/poly_check 分批)→ combineSignals() 超时合并(补丁A)→ MAX_RETRY 指数退避 → extractJsonRobust 4 级解析 → pinyinChecked 缓存穿透修复(补丁B)→ 级联开关联动 + 黄色预警条 → HTTP 状态码中文诊断 → localStorage.ai_model_override 逃生门(补丁C)→ 引导 18 步
5.4 开发踩坑与经验
踩坑 1:思源宋体 zip 解压路径不一致 — CI 环境硬编码路径 /tmp/shs/SourceHanSerifSC-Regular.otf 找不到,实际解压到 /tmp/shs/OTF/SimplifiedChinese/…;解决:find /tmp/shs -name “SourceHanSerifSC-Regular.otf” | head -1 动态查找
踩坑 2:PowerShell 重定向导致 UTF-16 编码 — Git 备份分支恢复 fontManager.js 时 PowerShell > 重定向默认保存 UTF-16 LE(BOM: FF-FE),Vite 报 invalid JS syntax;解决:.NET [IO.File]::WriteAllText + UTF8Encoding($false) 重写为 UTF-8(457,850 → 228,957 bytes)
踩坑 3:部署权限 — CI 构建成功但部署失败 Branch “retake” is not allowed to deploy to github-pages;解决:gh api --method POST …/deployment-branch-policies -f name=retake 添加 retake 到允许列表
踩坑 4:gh api 与 git push 历史不一致 — gh api Contents API 推送的文件创建不同 Git 历史导致 push 被拒;解决:创建备份分支保护本地提交 → git reset --hard origin/retake 同步远程最新
踩坑 5:多 Agent 并行开发的文件冲突 — 多个 Agent 同时改 main.js/index.html 会冲突;解决:Agent B 只新增文件不修改现有代码(零冲突),Agent A/C 顺序执行(C 基于 A 的结果)
踩坑 6:近万个笔顺 JSON 的迁移噩梦 — 原型阶段解压后近万个零碎文件,没用 FastCopy 时在不同硬盘间迁移是噩梦;后来想到合并 JSON、压缩到一个文件并提供检索函数(→ v2.9.8 的 hanzi-data.bin)
踩坑 7:v2.9.8 子路径 404 — 子路径部署下 hanzi-data.bin 404;解决:import.meta.env.BASE_URL + new URL 构建 URL
踩坑 8:SW precache 过大 — 大文件进 precache 导致 SW 安装包 140MB、hanzi-data.bin 加载失败;解决:globIgnores 排除,降至 3.3MB
踩坑 9:部署超时 — v2.9.9 部署两次出现 deployment_queued 超时(平台侧瞬时问题);解决:重跑后成功,构建本身无问题
踩坑 10:豆包 lite 弱模型 JSON 输出不稳定 — doubao-seed-2-0-lite 有时在 JSON 前后输出多余文字或 markdown 代码块,直接 JSON.parse 失败;解决:extractJsonRobust 4 级解析策略(剥离代码块 → 提取首个 {…} → 提取首个 […]),实测 90 字组词一次通过
踩坑 11:旧 WebView 缺失 AbortSignal.any — 部分旧版 WebView 不支持 AbortSignal.any,多信号合并直接报错;解决:combineSignals() 手写合并外部 signal + 超时 signal(补丁A)
踩坑 12:缓存穿透——拼音纠错与组词补齐互相踩 — 已有组词缓存但未校验拼音的字被跳过;仅拼音纠错后的字再次组词补齐时被误跳过;解决:缓存条目新增 pinyinChecked 字段(补丁B),且补齐组词不再覆盖已有拼音纠正记录
踩坑 13(真实参赛经历):测试"产品调用大模型"的附加功能 — 为了把豆包大模型放进产品,买了火山引擎 Lite 和 Trae Work Lite 权限,实测后发现通用大模型解决类似问题在效率和稳健性方面并不总能如期望的好等方面;更深刻的教训是:接入新模型必须从开源社区汲取健壮性方案(JSON 解析/超时重试等)或微调专用小模型,否则原创要求很高——技术选型要多参考开源社区成熟实践,少走弯路
5.5 关键 Session ID(TRAE 开发凭证)
以下 Session ID 用于证明作品由 TRAE 开发完成。获取方法:以 TraeCN IDE 为例,在一段对话开始的地方,双击红圈的 Trae 图标,跳出 “copy success” 一闪即逝,剪贴板就有 session id 了。
复赛阶段(Trae CN 新版格式 {username}:{hash}_{thread_id}.{message_id}.{agent_id}:Trae CN.T({timestamp})):
| # | 任务 | 时间 | Session ID |
|---|---|---|---|
| 1 | Vite 工程化重构 + 模块拆分 | 07-23 | .309409433785034:3987398260dd2c55f46e45830d638dbc_6a60feb9103e2f9262702768.6a611202103e2f9262702b26.6a611202add19038c350563e:Trae CN.T(7/23/2026, 2:54:58 AM) 等 2 条 |
| 2 | PWA 配置 + Service Worker + 图标生成 | 07-23 | .309409433785034:d732eba08e3ece643f08f2a02d1326a3_6a60feb9103e2f9262702768.6a611f21103e2f9262702f49.6a611f20add19038c350564c:Trae CN.T(7/23/2026, 3:50:57 AM) 等 2 条 |
| 3 | CI/CD 部署问题排查与修复 | 07-23 | .309409433785034:ca178f8f8709b9913f6a99fcd3af0988_6a60feb9103e2f9262702768.6a611b2f103e2f9262702d98.6a611b2fadd19038c3505645:Trae CN.T(7/23/2026, 3:34:07 AM) |
| 4 | 开源字体替换 + download-fonts.sh | 07-23 | .309409433785034:5a2e8d058e554d7d40156364ca4dd553_6a60feb9103e2f9262702768.6a611bf4103e2f9262702e12.6a611bf3add19038c3505648:Trae CN.T(7/23/2026, 3:37:24 AM) |
| 5 | Tailwind CSS + Lucide Icons 集成 | 07-23 | .309409433785034:686e359a6ebda8afdd28bd2bf1b28cf4_6a60feb9103e2f9262702768.6a610ee4103e2f9262702a4f.6a610ee4add19038c350563a:Trae CN.T(7/23/2026, 2:41:40 AM) |
| 6 | 学习闭环三件套(历史+反馈+复习)多 Agent 并行 | 07-23 | .309409433785034:4fea733d3b7183eee00f1ee10b4ba9bf_6a60feb9103e2f9262702768.6a61474f103e2f92627035fa.6a61474eadd19038c3505668:Trae CN.T(7/23/2026, 6:42:23 AM) |
| 7 | 界面辅助(设置中心+引导+演示+难度评估) | 07-23 | .309409433785034:6039b174c9754ff1f45af3d0aa41427b_6a60feb9103e2f9262702768.6a614408103e2f926270357b.6a614407add19038c3505662:Trae CN.T(7/23/2026, 6:28:24 AM) |
| 8 | SVG 矢量字格引擎 + 契约层(v2.4) | 07-25/26 | .309409433785034:534a413834ec6f61284db3dbeeaa6798_6a61fcaebe4273f5764bb50c.6a64c1f675d3caad3f2d947e.6a64c1f3906468fed4eea49c:Trae CN.T(7/25/2026, 10:02:30 PM) 等 2 条 |
| 9 | v2.9.8 真离线笔顺升级(多 Agent) | 08-06 | .309409433785034:4f7b2982bb12da9ffe9517194d1a1e38_6a73dfbe269d50748c245d17.6a73e16e269d50748c245d19.6a73e16eb6da2e3ffe41b19d:Trae CN.T(8/6/2026, 9:20:46 AM) |
| 10 | v2.9.9 AI 组词 + 拼音纠错 | 08-06 | .309409433785034:1e88be66cb76d0dcfe4cc1cb47ccf9ab_6a73dfbe269d50748c245d17.6a7468503b952a3bcc56002b.6a74684ea167bfa655d1db75:Trae CN.T(8/6/2026, 6:56:16 PM) 等 2 条 |
| 11 | v3.0.0 双引擎 AI + 健壮性加固(豆包适配) | 08-07 | 309409433785034:aec2b0f4fdf605d26820b1c7e53c6a9c_6a752c4b7d04eb6a59bb373e.6a7538c13bdf2001d16b4c81.6a7538c13bdf2001d16b4c7f:TraeWork CN.0.1.45.no_sid.no_ppe.T(2026/8/7 09:45:37)(Trae Work,楼层 18 补充) |
注:复赛 Session ID 为 Trae CN 新版格式;v3.0.0 豆包适配为 Trae Work 会话(2026-08-07 09:45,楼层 18 补充);共 17 条(复赛 12 + 初赛 7),满足大赛 ≥3 条要求。
复赛开发过程截图:

复赛 Session ID:
.309409433785034:a11c35564a5fba4de8491b2e5be71a35_6a65420875d3caad3f2d96fd.6a65779c75d3caad3f2d9ba4.6a65779b906468fed4eea4b1:Trae CN.T(7/26/2026, 10:57:32 AM)


复赛 Session ID:
.309409433785034:9712b3aeee26622146a29e85b4e59e78_6a65420875d3caad3f2d96fd.6a654bda75d3caad3f2d9914.6a654bd9906468fed4eea4a5:Trae CN.T(7/26/2026, 7:50:50 AM)


复赛 Session ID:
.309409433785034:534a413834ec6f61284db3dbeeaa6798_6a61fcaebe4273f5764bb50c.6a64c1f675d3caad3f2d947e.6a64c1f3906468fed4eea49c:Trae CN.T(7/25/2026, 10:02:30 PM)

复赛 Session ID:
.309409433785034:534a413834ec6f61284db3dbeeaa6798_6a61fcaebe4273f5764bb50c.6a64c1f675d3caad3f2d947e.6a64c1f3906468fed4eea49c:Trae CN.T(7/25/2026, 10:02:30 PM)



初赛阶段(完整三段式 {thread_id}.{message_id}.{agent_id},已发表于初赛帖子 72722 / 71664,7 条已验证):
- 独立 HTML 打包、JS 内嵌(07-05 19:48):
6a49f7e8f615ceaf1589607b.6a4a44899a9540f3b14ec753.6a4a4488b75d9ac48d921ab0 - 模板字符串修复、UI 增强、字体配置(07-05 20:16):
6a49f7e8f615ceaf1589607b.6a4a4b199a9540f3b14eca1a.6a4a4b19b75d9ac48d921ab1 - PDF 乱码修复、矢量输出、Puppeteer 脚本(07-05 21:04):
6a49f7e8f615ceaf1589607b.6a4a564b9a9540f3b14ecd6a.6a4a564ab75d9ac48d921ab2 - 开发过程截图(1)(07-06 04:36):
6a49f7e8f615ceaf1589607b.6a4ac0459a9540f3b14ed5c4.6a4ac044b75d9ac48d921ab8

- JSON 解析、三层防御、keep-alive 去重、编码兼容(07-06 05:01):
6a49f7e8f615ceaf1589607b.6a4ac6429a9540f3b14ed689.6a4ac640b75d9ac48d921aba

- 开发过程截图(3)(07-06 05:09):
6a49f7e8f615ceaf1589607b.6a4ac81f9a9540f3b14ed6ae.6a4ac81eb75d9ac48d921abb

- “我连文档都是用 AI 写的”(07-06 05:16):
6a49f7e8f615ceaf1589607b.6a4ac9b99a9540f3b14ed718.6a4ac9b8b75d9ac48d921abc

5.6 项目文件结构(v3.0.0)
字帖生成器/
├── src/ # 源代码(27 个 JS 文件,9,973 行)
│ ├── main.js # 入口文件(事件绑定+初始化+模块集成)
│ ├── data/ # 数据文件(3 个,65KB)
│ │ ├── customZuCi.js # 自定义组词数据(1719条,57KB)
│ │ ├── templates.js # 内置模板库(20个模板)
│ │ └── vocabulary.js # 分级字库(3级18分类)
│ ├── components/ # 组件(2 个)
│ │ ├── GridEngine.js # SVG 矢量字格引擎(viewBox 100×100 + CSS mm,703行)
│ │ └── Sidebar.js # 侧栏组件(427行)
│ ├── contracts/
│ │ └── interfaces.js # 接口契约层(GridCellProps/GridType/RenderMode/PdfExportOptions)
│ ├── modules/ # 功能模块(17 个)
│ │ ├── aiZuci.js # 双引擎 AI 组词+拼音纠错(DeepSeek+豆包,三模式分流,509行)⭐v3.0.0
│ │ ├── settingsCenter.js # 设置中心(15 项设置 + 级联开关联动,680行)⭐v3.0.0
│ │ ├── onboarding.js # 新手引导(18步聚光灯 + autoOpen 联动,716行)⭐v3.0.0
│ │ ├── strokeDemoModal.js # 笔顺演示弹窗(双图层 + 4窗管理,711行)⭐v2.9.8
│ │ ├── fileImporter.js # 多格式文件导入(txt/md/csv/xlsx/docx,405行)
│ │ ├── recommender.js # 智能推荐(3维度13主题20模板,351行)
│ │ ├── hanziDataStore.js # 笔顺数据仓库(BASE_URL+new URL,9574字bin,337行)⭐v2.9.8
│ │ ├── reportPanel.js # 学习报告面板(纯原生 Canvas 图表,578行)
│ │ ├── feedback.js # 练习反馈(整体+单字,196行)
│ │ ├── history.js # 历史记录(localStorage+侧边栏,168行)
│ │ ├── fabDrag.js # FAB 拖拽(Pointer Events + 8px 吸附,301行)
│ │ ├── puppeteerClient.js # Puppeteer客户端(本地服务→在线代理→失败回退,189行)
│ │ ├── fontManager.js # 字体管理(FONT_LIST+loadFonts+系统楷体自动匹配★)
│ │ ├── difficulty.js # 难度评估(5级星级,108行)
│ │ ├── settings.js # 基础设置(主题+页眉页脚+localStorage)
│ │ ├── strokes.js # 笔画加载(hanzi-writer)
│ │ ├── zuci.js # 组词查询(三级回退:customZuCi→cnchar→AI缓存)
│ │ └── hanziDataWorker.js # Web Worker 解压(28行)
│ ├── utils/
│ │ └── pdfExport.js # 双轨 PDF 导出(jsPDF+svg2pdf / 原生 print,816行)
│ └── styles/ # 样式文件(19 个,3,486 行)
├── public/ # 静态资源
│ ├── icon-192.svg / icon-512.svg / icon-192-maskable.svg # PWA 图标
│ ├── stroke-demo-guide.html # 笔顺演示介绍页 ⭐v2.9.8
│ ├── fonts/ # 开源字体(CI 下载,114MB)
│ └── hanzi-data/ # 离线汉字笔画数据(hanzi-data.bin 12MB + 嵌入式降级 + fflate)
├── .github/workflows/
│ └── deploy.yml # CI/CD 工作流(retake 分支触发)
├── scripts/
│ └── download-fonts.sh # CI 字体下载脚本(4款开源字体)
├── index.html # HTML 入口
├── vite.config.js # Vite 配置(base:'./' + singlefile + pwa + tailwind)
├── package.json # 项目配置(MIT协议,17 依赖)
├── puppeteer-pdf.cjs # Puppeteer PDF 生成脚本(CommonJS)
├── puppeteer-server.cjs # Puppeteer HTTP 服务
├── README.md / README_EN.md # 项目文档(中英文)
├── README_contest.md # 参赛文档
├── CHANGELOG.md # 更新日志(Keep a Changelog 格式)
├── TASK_BOARD.md # 任务看板
├── 启动Puppeteer.bat # Windows 启动脚本
├── 启动Puppeteer.ps1 # PowerShell 启动脚本
└── 启动Puppeteer.sh # Linux/macOS 启动脚本
5.7 package.json 依赖清单与 npm scripts
运行时依赖(12 个):
| 包名 | 版本 | 用途 |
|---|---|---|
| pinyin-pro | ^3.0.0 | 拼音转换(带声调)+ 多音字判定 |
| cnchar + cnchar-words | ^3.0.0 | 汉字处理 + 组词 + 笔画数 |
| hanzi-writer | ^3.5.0 → 3.7.3 | 笔画 SVG 渲染 + 动态笔顺动画 |
| lucide-static | ^1.25.0 | SVG 图标库 |
| puppeteer | ^23.0.0 | 服务端矢量 PDF 生成 |
| jspdf + svg2pdf.js | ^2.5.2 / ^2.7.0 | 客户端纯矢量 PDF 导出 |
| fflate | ^0.8.3 | 笔顺数据 Gzip 解压 |
| mammoth | ^1.6.0 | DOCX 文件解析(动态 import) |
| xlsx | ^0.18.5 | Excel 文件解析(动态 import) |
开发依赖(5 个):
| 包名 | 版本 | 用途 |
|---|---|---|
| vite | ^5.4.0 | 构建工具 |
| vite-plugin-singlefile | ^2.0.0 | 单 HTML 打包 |
| vite-plugin-pwa | ^0.20.0 | PWA 支持 |
| @tailwindcss/vite | ^4.3.3 | Tailwind v4 Vite 插件 |
| tailwindcss | ^4.3.3 | Tailwind CSS v4 |
npm scripts:
| 命令 | 说明 |
|---|---|
| npm run dev | 启动开发服务器(port 3000) |
| npm run build | 生产构建(输出到 dist/) |
| npm run preview | 预览构建结果(port 4173) |
| npm run pdf | Puppeteer 生成矢量 PDF |
| npm run pdf:help | PDF 命令帮助 |
| npm run pdf:test | 测试 PDF 生成(床前明月光) |
构建验证(v3.0.0): JS 源文件 27 个 / 9,973 行,CSS 19 个 / 3,486 行|模块化结构:17 模块 + 2 组件 + 1 工具 + 1 契约|依赖 17 个(12 运行时 + 5 开发)|构建错误/警告 0/0|PWA precache 3.3MB(v2.9.8 起)|核心 JS/CSS 产物轻量,全量构建产物约 140MB(含开源字体 114MB + 离线笔顺数据 12MB)|Git 版本标签 28+,备份分支 25+。
6. 技术方案分享
6.1 纯前端 PWA + 矢量 PDF 三轨方案
核心理念:零后端依赖,保护用户隐私,离线可用。
用户输入汉字
↓
pinyin-pro 转换拼音 → cnchar 组词 → hanzi-writer 笔画 →(可选)双引擎 AI 组词补齐(DeepSeek / 豆包,三模式分流)
↓
SVG 矢量引擎渲染字格(拼音行 + 汉字行 + 笔画行/动态笔顺演示)
↓
方案A:window.print() → 浏览器打印预览 → 另存为 PDF(全平台)
方案B:jsPDF + svg2pdf 纯前端导出(免安装)
方案C:Puppeteer 无头浏览器 → 矢量 PDF(文字可选可复制,桌面端命令行)
↓
PWA Service Worker 缓存所有资源 → 完全离线可用(含 9574 字笔顺数据)
技术亮点:
- FontFace API 动态注册字体 + document.fonts.check() 验证加载 + 超时重试(5 秒超时 + 3 秒额外等待)
- JSON 解析三层防御(Connection:close + safeJsonParse + 请求去重)→ v3.0.0 升级为 4 级健壮 JSON 解析(直接解析 → 剥离代码块 → 提取首个 {…} → 提取首个 […])
- vite-plugin-singlefile 保留单 HTML 离线分发能力
- 系统楷体自动匹配:启动时从操作系统已安装字体中匹配 1-2 种楷体(★ 标识),解决"字体需求"这一字帖核心痛点(楼层 3/6 的问答落地为功能)
- Web Worker 解压:9574 字笔顺数据(11.75MB Gzip bin)后台解压不阻塞主线程,多级降级(Worker→主线程→Base64→网络备选)
- SVG 矢量引擎细节:viewBox 100×100 抽象坐标 + CSS mm 物理尺寸;行级统一边框消除亚像素误差;填充矩形代替 stroke 保证 PDF 线宽精确;shape-rendering: geometricPrecision;currentColor 智能反色
- ?printdebug=1 真机调试、微信/QQ X5 内核检测、移动端打印适配(含华为 MatePad HarmonyOS 打印多轮修复)
6.2 学习闭环技术方案
生成字帖 → 自动保存到历史记录(localStorage,最多20条)
↓
练习反馈 → 整体反馈(3按钮)+ 单字反馈(DOM事件委托+悬停图标)
↓
复习计划 → 艾宾浩斯规则(mastered→7天 / review→3天 / error→1天)
↓
学习报告 → 纯原生 Canvas 图表(7天趋势/难度分布/掌握率)
↓
首页待复习 → 一键加载复习字 → 生成字帖 → 更新练习时间
跨模块通信:自定义事件 calligraphy:history-updated、calligraphy:char-feedback-updated、calligraphy:settings-updated
6.3 双引擎 AI 技术方案(v3.0.0 核心创新)
输入汉字
↓
本地预处理:多音字判定(pinyin-pro multiple 模式)
↓
三模式分流
├── fast → 仅补齐组词(批次 10 字,max_tokens 2048)
├── single_check → 单音字校验(批次 10 字,max_tokens 4096)
└── poly_check → 多音字深度校验(批次 6 字,自动升级强模型)
↓
引擎自动识别(API Key 前缀)
├── sk- → DeepSeek(deepseek-v4-flash,JSON mode)
└── ark- → 火山引擎豆包(doubao-seed-2-0-lite-260428 / 全量检查升级 doubao-seed-2-1-turbo-260628)
↓
健壮性管道
├── 指数退避重试(MAX_RETRY=3,500ms×attempt)
├── 5 分钟硬超时(HARD_TIMEOUT_MS=300000,partialSuccess 部分成功返回)
└── 4 级健壮 JSON 解析(适配弱模型多余输出)
↓
结果回写:localStorage 缓存(zuci/pinyin/pinyinFixed/pinyinChecked/wordsDetail/ts)
→ AI 拼音优先于默认拼音(getAiPinyin 回退)→ 纠错报告展示
设计要点:
- 双引擎自动识别:用户只需粘贴任意一家 API Key,前缀
sk-/ark-自动路由,无需手动切换;豆包免费入门 + DeepSeek 性价比付费,覆盖不同用户群体 - 三模式分流是工程优化:不是简单"全部丢给 AI",而是本地预分流后针对性调用——多音字才走深度校验(批次缩小 + 强模型),普通字走快速补齐,大幅降低 token 消耗
- 缓存穿透修复:pinyinChecked 字段解决"全量检查与组词补齐互相误跳过"的经典缓存问题(补丁B)
- 紧急逃生门:localStorage.ai_model_override 可免打包切换模型,为未来模型升级留好后门(补丁C)
- 失败友好:超时不卡死(返回部分成功 + 诊断建议),重试不阻塞(失败批次跳过继续后续批次),错误看得懂(HTTP 状态码中文诊断)
6.4 代码规模统计(v3.0.0)
| 指标 | 数值 |
|---|---|
| JS 源文件 | 27 个,9,973 行 |
| CSS 文件 | 19 个,3,486 行 |
| 模块化结构 | 17 模块(src/modules/)+ 2 组件 + 1 工具 + 1 契约 |
| 依赖 | 17 个(12 运行时 + 5 开发) |
| 离线汉字 | 9,574 个(12MB Gzip bin + Web Worker 解压,多级降级) |
| 预设模板 | 20 个(唐诗宋词 8 + 三字经 2 + 千字文 2 + 常用字 3 + 成语 3 + 节日 2) |
| 引导步骤 | 18 步 |
| 网格类型 | 5 种(田字格/米字格/九宫格/回字格/拼音田字格) |
| 颜色预设 | 4 套(传统绿/朱砂红/靛青蓝/墨黑) |
| AI 引擎 | 2 个(DeepSeek + 火山引擎豆包) |
| AI 模式 | 3 种(fast / single_check / poly_check) |
| PDF 导出轨道 | 3 条(浏览器打印 / jsPDF+svg2pdf / Puppeteer) |
| 文件导入格式 | 5 种(txt/md/csv/xlsx/docx) |
| Git 版本标签 | 28+ |
| 代码总计 | 约 13,500 行(JS + CSS) |
7. 社会价值分析
教育公平
- 无网络环境可用:农村学校、无网络家庭、教育资源匮乏地区(乡村老师无网教室打开手机即用;离线优先设计,不背云端模型包袱)
- 零成本:无需付费、无需注册、无需账号;AI 组词提供 免费入门入口(豆包 Lite),不因付费能力剥夺任何人使用 AI 辅助学习的权利,DeepSeek在可预知的大幅涨价之前费用还是比较低的
- 隐私保护:所有数据本地处理,不上传儿童学习数据(AI 组词为可选功能,默认关闭、自配 Key,数据也仅发往用户自选的 DeepSeek/豆包)
文化传承
- 汉字书写教育:拼音 + 组词 + 笔画 + 动态笔顺演示 四位一体,辅助正确书写
- 开源字体推广:霞鹜文楷、思源宋体等开源字体,推动字体生态
- 技术降低门槛:让每个人都能自由定制练字内容(MIT 开源,任何人可定制和深入开发)
学习科学
- 艾宾浩斯遗忘曲线:基于科学记忆规律自动生成复习计划
- 渐进式学习:难度评估帮助用户选择合适内容
- 反馈驱动:练习反馈数据驱动个性化复习与学习报告
环保理念
- 按需打印:只打印需要的练习内容,减少纸张浪费
- 数字预览:屏幕预览确认后再打印,避免错误打印
8. 产品迭代规划
8.1 已完成(复赛最终版 v3.0.0,2026-08-07)
Vite 工程化重构(27 JS 文件 + 19 CSS + 3 数据文件 + 契约层)
PWA 离线支持(v2.9.8 起 SW 3.3MB 轻量安装 + 大文件运行时缓存)
开源字体替换(6 款全合规 + 系统楷体自动匹配 ★)
CI/CD 自动部署(GitHub Actions → Pages)
UI 现代化(Tailwind + Lucide)
SVG 矢量字格引擎(5 网格 × 3 渲染模式 × 18mm 物理精度 + 行级统一边框)
历史记录 / 练习反馈闭环 / 复习计划(艾宾浩斯)/ 学习报告面板
内置模板库(20 个)/ 分级字库(3 级 18 分类)/ 文件导入(txt/md/csv/xlsx/docx)/ 智能推荐
设置中心 / 新手引导(18 步)/ 演示模式 / 难度评估(5 级星级)
米字格/九宫格/回宫格/田字格/拼音田字格 5 种网格
离线动态笔画笔顺演示(9574 字,v2.9.8)
AI 组词补齐 + 拼音纠错(DeepSeek,v2.9.9)
双引擎 AI(DeepSeek + 火山引擎豆包)+ 三模式分流(v3.0.0)
超时重试 + 缓存穿透修复 + 级联开关 + 错误诊断 + 4 级健壮 JSON 解析 + 紧急逃生门(v3.0.0)
演示视频录制上传(12MB,曾因 20MB 上限险些被拒)
8.2 进行中 / 取舍说明
移动端深度优化(已完成初步优化,随版本持续更新;含 MatePad HarmonyOS 打印修复、触屏版 Light 主题修复)
AI 功能稳定性打磨(双引擎已上线,持续根据真实反馈优化提示词与批次策略)- 笔顺演示改写为独立分支功能(不追加主文件版本迭代,作为分支功能之一,MIT 开源欢迎参与者二次开发——楼层 12 说明)
8.3 未来规划(MIT 开源;任何人可自己定制和深入开发)
AI 智能推荐升级(规则版本离线可用已实现;双引擎已接入,可进一步引入更多学习型模型解决知识更新问题)
专用小模型 / 开源社区模型微调(v3.0.0 实战证明:必须从开源社区进一步汲取能量,或微调出专用小模型,否则原创要求很高——这是下一步最想做的方向)
学习报告完善(本地统计,含更多图表维度)
更多格子样式(九宫格已追加,还可以改善)
多语言支持(英文界面——写汉字用,似乎不需要?)
教师批量生成(已添加"导入文件",可批量导入新生字)
9. 版权与字体说明
| 项目 | 协议 |
|---|---|
| 项目代码 | MIT 许可证,可自由使用、修改、分发 |
| 霞鹜文楷 Regular/Light | OFL(SIL Open Font License) |
| 思源宋体 SC Regular | OFL(SIL Open Font License) |
| 文鼎楷体(TW-Kai) | Apache 2.0 License |
| 我逸清晨体楷书 | OFL(SIL Open Font License) |
| TW-Kai | OFL(SIL Open Font License) |
| TeX Gyre Adventor(拼音字体) | GUST Font License |
| pinyin-pro / cnchar / hanzi-writer / jspdf / svg2pdf / fflate / mammoth / xlsx | MIT License |
分发中的所有字体均为开源协议,无版权风险,可安全商用。用户完全可以通过定制、扩展功能引入可以合法免费个人使用但不能打包分发的优秀字体(如方正楷体等)。历次升级时反复确认:未引入任何不合规字体。
10. 致谢
- TRAE IDE — 提供强大的 AI 辅助开发环境,让非专业开发者也能完成工程化项目,多 Agent 并行开发能力极大提升开发效率。写代码、修 Bug,TRAE IDE 在我用过的几款国内 AI 编程工具里综合表现稳居第一(楼层 13 实测体会);用其它工具都可能导致拖延。修改代码优先用 Trae IDE;本次为测试还付费购买了 Trae Work 权限试用(楼层 12 经验:当前 Trae Work 写代码效率还是不如 IDE,但作为多 Agent 并行验证的补充手段是有价值的)。
- DeepSeek — 为 AI 组词功能提供高性价比大模型 API(楼层 16:收到梁兄 API 调价通知后仍果断支持)。
- 火山引擎豆包 — 为双引擎 AI 提供免费入门的大模型入口(doubao-seed-2-0-lite-260428 / doubao-seed-2-1-turbo-260628),让"零成本 AI 辅助"成为可能。
- 开源社区 — pinyin-pro、cnchar、hanzi-writer、Vite、Tailwind CSS、Lucide、fflate、jsPDF、svg2pdf.js、mammoth、SheetJS 等优秀开源项目;v3.0.0 实战更让我深刻体会到:个人开发者做 AI 应用,必须从开源社区汲取能量——健壮 JSON 解析、超时重试、请求合并这些"踩坑方案",社区早有成熟实践。
- 字体作者 — 霞鹜文楷、思源系列、文鼎楷体等开源字体的创作者
- 初赛评委与测试用户 — 你们的反馈让作品更完善
- 所有关注汉字书写教育的人 — 一字一世界,一笔一乾坤
11. 附录:创作心路(楼层 9 全文收录)
以下内容来自楼主在回复楼层 9 的长文《字帖生成器:一个普通人的 AI 探索,却让我看到了未来办公文档的影子》,作为对原贴的重要补充完整收录。
一、始于一个真实得不能再真实的需求
孩子上小学后,每天要练字。市面上的字帖要么内容固定、要么依赖网络、要么收费,更让人头疼的付了费的字帖、打印出来还是位图,放大一点就模糊,根本谈不上"描红"的精度。我自己平时也爱写写毛笔字,同样苦于找不到合适自己进度的字帖(就像背单词不想每次都是 abandon;临字帖,抬眼就是"永和九年")。——我开 1.6L 的经济型车接送孩子,被另一个小朋友感慨"哇,这么豪华",这句感慨让我瞬间震惊:在我们家孩子看来平平常常、甚至还老是嫌弃的,对别人却可能是遥不可及。还有很多类似的小学生,他们应该在不付费的情况下也能够享受类似的机会。这是 MIT 协议的初衷。——这也跟 TRAE 用自己剩余算力、普惠广大未付费用户的初衷类似:我用自己有限的余力,借了 TRAE 的慷慨赞助(至今仍是 free 用户、因为平时实在用不了那么多 token)的东风,取之于免费,还之于 MIT 和普惠。
我就在想:为什么不能自己做一份呢?不就是一份文档吗?有那么难吗?——这个想法早在 ChatGPT 版本还不到 4.0、Claude Sonnet 3.7 在国内有中转可用的时候就萌生了。那个时候 VibeCoding 这个词还没有提出来,我已经实际在这么做(我的 CSDN 博客上留有痕迹和时间戳)。
放在 ChatGPT 时刻以前,这个想法只能停留在脑子里——毕竟我的前端水平只是一个"素人",稀里糊涂懂一点 HTML/CSS/JS 细枝末节,但真要到开发一个完整应用的程度,还是有很大距离。然而,这次不一样,因为我遇到了 TRAE。
从需求到动手,只隔着一个 AI 的距离。
二、AI 赋能:一百次提示词,从零到完整产品
整个开发过程,我使用了 TRAE IDE 的 AI 辅助编程功能,全程实际使用的提示词(Fast Pass,等切换积分制 Credit 的时候我已经完工了)不超过 100 次(含 Fast Pass 时代凌晨无须排队的 Quick Pass)。是的,你没有听错——不到一百次的人机对话,我就从几乎为零开始,完成了一个从单 HTML 文件到工程化 PWA 应用的完整蜕变。
这听起来有点不可思议,但事实就是如此。AI 帮我写代码框架、帮我排查问题、帮我重构模块,而我只需要描述清楚"我想要什么"。我不需要成为前端专家,我只需要成为一个合格的需求提出者和决策者。
初赛时,我的项目只是从一堆散落的文件整理出的一个单 HTML 文件,双击就能运行,核心功能已经能跑通。进入复赛后,我决定不满足于"能用",而是要做成"好用"。于是,在 AI 的帮助下,我用大约几十天时间,把 1.1MB 的单 HTML 拆解为 14 个 JS 模块和 17 个 CSS 文件,引入 Vite 构建工具,配置 PWA 离线支持,完善了 CI/CD 自动部署流程,增加了历史记录、复习计划、分级字库、模板导入等学习闭环功能。——而这些 Vite、PWA、CI/CD 对我来说,都是全新的字眼,需要找 AI 导师搞搞清楚它们是啥,对项目有什么作用,会不会来捣乱、增加调试复杂度。
这是一个从"玩具"到"工具"的质变过程,而 AI 就是这个过程的加速器。
三、这个项目到底优点在哪里?
-
离线优先,随时可用。我坚持"纯前端、零依赖、完全离线可用"的设计理念。你把它安装到桌面或手机主屏(PWA),之后不需要服务器、不需要网络,打开即用(没塞大模型 API Key 调用也是有意的,虽然知道增加 LLM 调用能够显著增色——这部分留给开源和用户在其分支版本自定义和修改——这也是为离线、普惠而须做的取舍;但"AI"的应用贯穿开发全程,我自己没有写一句代码)。这意味着:乡村小学的老师在没有网络的教室里,打开手机就能给孩子生成字帖;家长在地铁上、飞机上也能随时定制练字纸。这不是一个"云端应用",这是一个像纸笔一样随身的工具。
-
真正的矢量 PDF,放大多少倍都清晰。字帖最终是要打印出来练字的。如果打印出来是模糊的位图,那还有什么意义?我实现了双轨矢量 PDF 输出方案:一是直接用浏览器 window.print(),另存为 PDF 即为矢量;二是使用 Puppeteer 无头浏览器生成矢量 PDF,文字可选中、可复制。两种方案覆盖了桌面端和移动端的所有场景。这是专业级的输出质量,绝非普通截图可比。
-
从"生成"到"学习"的闭环。很多字帖工具只负责生成,用完即走。我的项目不止于此——用户可以对每个字标记"掌握/复习/错字",系统会根据反馈自动生成复习计划,按艾宾浩斯遗忘曲线安排下次练习。加上历史记录、难度评估(笔画数分级)、内置模板库(唐诗宋词、三字经、千字文、常用字、成语等)、文件导入功能(支持 txt/md/csv/xlsx/docx 导入生词)……它已经从单纯的"工具"变成了一个"汉字学习平台"。
-
跨平台适配,一个代码全端跑通。从桌面端 Windows/macOS/Linux 到移动端 Android/iOS/HarmonyOS,从浏览器直接打印到 PWA 离线使用,一个代码库全部搞定。尤其是针对华为 MatePad 的 HarmonyOS 打印问题,我专门做了多轮修复,确保移动端打印也能完美输出。
-
持续迭代,认真对待每一个用户反馈。从 v1.0.1 到 v3.0.0,更新日志记录了 90+ 次 commits,这些数字不是用来炫耀的,每一次都对应着真实的使用反馈和功能改进。引导流程从 5 步扩展到 18 步、Dark 模式优化、移动端首次使用引导、桌面端 FAB 拖拽吸附……这些细节,都是因为我真正在使用它、打磨它。——这些次数也意味着,业余时间也足以完成;可能早年混迹于 Stackoverflow、StackExchange 这类论坛,已经习惯了把如何提高提问、追问和回答质量的肌肉记忆融入提示词技巧之中,所以自我感觉 vibe coding 起来其难度并没有想象中那么高:AI 交互出来的交付物,有时候居然能够出人意外地好。
四、我不懂"大模型微调",但我懂"应用落地"——这正是大多数普通用户的特征
有人可能会问:你的技术栈是什么?用了什么大模型?说实话,我的技术栈简单得令人发指——Vite + Tailwind CSS + 几个开源 JS 库(pinyin-pro、cnchar、hanzi-writer、Puppeteer)。
没有微调、没有 RAG、没有复杂的 Agent 框架,这不是偷懒,而是为了"离线普惠"刻意做的取舍——也正因为不背云端模型的包袱,它才能做到乡村无网可用。我想证明的是:AI 时代,不堆技术栈,同样能做出有深度、有温度的应用。
当前 AI 办公市场正处于一个"过渡期":大模型能力增长趋缓,产品形态远未定型,各家厂商还在赛马、还在抢入口。在这个阶段,最重要的不是比拼模型的参数,而是如何把现有能力封装成用户真正需要的产品。
我的字帖生成器,就是这种"应用落地"思维的一个活生生的例子。它不追求酷炫,但追求实用;它不依赖云端,但离线可用;它不强行绑定 AI,但 AI 贯穿了开发的每一个环节。
五、为什么我认为它可能是"下一代办公文档"的雏形?
前段时间我读到一篇文章,提到 HTML 正成为"新 Markdown",因为它可以把 AI 输出从"可读文本"升级为"可审计、可比较、可操作、可回灌的协作界面"。我深有同感。
我的字帖生成器,其核心界面就是一个完整的 HTML 文档——你在浏览器中直接预览、交互、调整、打印,所有操作都在一个页面内完成。而它的"编辑"方式,是通过自然语言输入(你告诉它"我要练这些字":当前是通过 LLM 获取相关文字,支持 md、docx、csv 等格式导入。比如,人民教育出版社 2019 年五年级语文上下册教材生字,这是需要素材、LLM 处理的部分),AI 帮你生成结构化的字帖 HTML。这不就是未来办公文档的样子吗? 你只管说你要什么,AI 负责生成内容、排版、交互、输出,而你只需要看到一个可视化的结果。
虽然 HTML 目前还有"只能看、难编辑"的短板,但 AI 完全有能力弥补这一点——就像我使用 TRAE,通过自然语言指示 AI 修改 HTML 和 CSS 一样。"所见即所得、所见即可改"正在成为现实。
传统文档格式如 DOCX、PPTX、XLSX 不会消失,但它们会退居二线——成为数据源和导出格式。而 HTML 将成为呈现与交互的主角,AI 将成为真正的"编辑器"。我的字帖生成器,可能就是这种趋势中一个微不足道、可以交给时间去验证的不成熟猜想或确凿的先例。
六、为自己加油,也为所有普通创作者加油
参加这次比赛,我最大的收获不是奖项本身,而是让我亲身体验到:AI 正在抹平技术门槛,让每一个有想法的人都有可能把想法变成现实。
我不懂复杂的前端工程,但 AI 帮我完成了重构;我不懂设计模式,但 AI 帮我梳理了模块;我不懂 PWA 配置,但 AI 一步步教我实现。我是一个普通人,但有了 AI,我可以做出不普通的东西。
这种经历让我坚信,在 AI 办公应用这个不确定的过渡期,最理性的策略不是等待"最终答案",而是立刻动手,从真实需求出发,做出能解决实际问题的产品。 数据会积累,反馈会回流,产品会迭代——只要迈出第一步,就已经走在路上了。
我的字帖生成器还远未完美,它是我一个普通人的探索,也是我对未来办公文档形态的一次尝试。我希望评委和观众能看到它的价值,更希望所有看到这个项目的普通人能受到一点启发:别怕技术门槛,AI 会帮你跨过去。
12. 附录:社区互动与答疑(楼层问答收录)
楼层 2(迟迟):“好强的复赛作品” — 感谢鼓励!
楼层 3(u4298416450437755):如果要加载新的字体,可以去哪里寻找?导入字体需要什么格式文件?
答(楼层 4):可以自己搜索、下载、必要的时候购买字体,电脑上自己喜欢的、已经安装的字体都可以加载了备用;后面代码 MIT 协议开源,你还可以用 TRAE 把自己喜欢的字体直接嵌入到代码中作为默认使用。不要想当然认为代码都是别人写或别人用 AI 写的,这种开源的、MIT 协议的,你可以拿去随便改、随便用。
补充(楼层 6):复赛公开的最终版本,启动时自动从当前操作系统(计划支持 Windows/Linux/macOS/Android/HarmonyOS)已安装字体中自动匹配和加载 1-2 种(为避免加载问题作了限制)楷体类型的字体,字体下拉菜单中前面会有五角星符号(★)标识。选择新字体后点击生成或刷新,即对字帖应用新字体,然后就可以打印。
楼层 7(骆谦实):这个垂直领域很实用了,可以直接连接打印机使用吗?
答(楼层 8):可以的;选择打印机就可以。
楼层 10(u907554062350092):“好厉害” ×2 — 感谢鼓励!
楼层 16(关于 AI 组词):AI 组词需要自己准备 API Key 吗?收费吗?
答:是的,AI 组词为可选增强功能,默认关闭,需在设置中心输入自己的 API Key;支持 DeepSeek(sk- 前缀)与火山引擎豆包(ark- 前缀)双引擎自动识别。豆包 Lite 提供免费入门额度,DeepSeek 性价比与口碑兼备(收到梁兄 API 调价通知后仍果断支持)。受大模型概率生成特性影响,冷僻字/多音字场景有时需多次点击才得到理想结果;AI 结果仅供参考,以权威教材/字典为准。
楼层 18(2026-08-07,v3.0.0 豆包适配完成):
进一步的追加——发现如果只用通用大模型,稍微复杂点的任务,自动生成的提示词效果并不理想,可能需要在大模型微调、提示词改进等方面深入打磨,但这已经超过我作为个人开发者的能力范畴了。

好消息是:我终于把豆包也修改得能用了,太不容易了(豆包 lite 弱模型在 JSON 输出稳定性、响应格式上差异明显,经过多轮调试终于适配完成)。

附 Trae Work Session ID:
309409433785034:aec2b0f4fdf605d26820b1c7e53c6a9c_6a752c4b7d04eb6a59bb373e.6a7538c13bdf2001d16b4c81.6a7538c13bdf2001d16b4c7f:TraeWork CN.0.1.45.no_sid.no_ppe.T(2026/8/7 09:45:37)(豆包适配测试、和最终的V3.0.0产品的备份和部署都 Trae Work 完成;界面截图见楼层 18 附图)

愿这份小小的工具,能为汉字教学与书写传承尽一份力。
作品体验入口、源码包等交付物已通过飞书问卷私密提交,仅供评审查看。 按大赛规则,社区帖内不放置体验链接、二维码或可下载的源码/安装包;如需在线体验或有任何疑问,欢迎通过论坛私信联系作者(u309409433785034)。
本文为 TRAE AI 创造力大赛复赛作品说明帖(最终版)|发布日期:2026-07-23(v2.9.5)→ 07-26 更新(v2.9.7)→ 2026-08-06 整合修订(v2.9.9)→ 2026-08-07 最终版(v3.0.0)|版本:复赛 V3.0.0


















