Skip to content

SELECTED WORK

作品集

这里收录已经可以使用的课程、持续更新的写作项目,以及从真实需求中生长出来的技术实践。它不是完成清单,而是一份长期建设记录。

英语学习课程 ​

写作与记录 ​

技术与系统 ​

CASE STUDY · CONTENT-DRIVEN LEARNING

gaojian.site · 把学习材料做成可反复使用的工具

这个网站的起点是整理自己的知识,后来逐渐变成一套可以阅读、听读、回忆、练习和复盘的学习系统。技术的任务,是让同一份高质量材料在不同练习中保持一致,让学习者少花精力找功能,多花精力理解和表达。

VitePress + Vue 3构建时整理内容静态音频复用浏览器本地练习

从学习者看,网站要支持什么 ​

我不希望课程只是题目和范文的集合。学习者读懂了一篇文章,并不等于能够在新题里表达同样的意思。课程需要把“看懂”之后的路铺出来:观察表达、遮住参考回忆、组织自己的答案,再用新问题检验。

先让材料容易理解

课程地图帮助选择路线;原文、自然中文、题图与范文对照,降低来回寻找信息的负担。逻辑链、词伙与句型说明,解释答案为什么这样组织。

再让理解变成输出

用词块回忆、英译汉、汉译英和跟读,把“眼熟”变成主动提取。逐句练习降低起步难度,整篇回忆保留段落之间的关系。

最后用新题判断进步

口语练脱稿与换场景;写作保留提纲、初稿、修改、迁移与复盘。自检关注遗漏、逻辑和表达是否改善,完成数量不等同于能力或考试分数。

课程之间也有分工:日常话题练习提供表达情境,雅思100句帮助拆解长句,口语课程训练按问题组织答案,写作课程训练比较、论证与修改,地道写作课程积累语境中的表达。学习者可以按当前问题选择入口,共用的交互方式让切换课程时不用重新学习操作。

从架构师看,先把三件事分开 ​

内容生产、站点分发、个人练习拥有不同的变化节奏。课程文本需要审校,发布资源需要处理版本,个人草稿则要在输入时及时保存。把它们分层,才能分别改进,而不是把所有逻辑塞进一个页面。

两条链路,在学习者的浏览器里汇合点选节点,查看这一层的职责

内容生产与构建

资源分发与学习

结构化与校验

课程生成脚本与 transformPageData 分别把源材料转换成页面和结构化学习数据。句子索引、中英对应和原文版本在这一层核对,浏览器组件按数据展示,避免各个练习模式分别维护一套内容。

学习记录留在当前浏览器:localStorage 保存文字与状态,IndexedDB 保存录音。

Markdown 负责内容,Vue 负责行为 ​

正文保留在 Markdown 中,便于写作、审校和版本对比。题目、路线、参考回答与教学说明进一步整理成 frontmatter 或独立的数据文件;Vue 组件负责交互状态,工具函数负责拆句、词数统计、数据解析等可复用规则。

例如 Task 2 的七种学习方式并不是七篇独立材料。它们基于同一份参考原文和句子索引:标记朗读显示表达重点,双向译练切换提示与答案,逻辑链展示组织关系,词汇与语法回到原句说明。原文一旦修改,相应译文、教学标记和音频就需要一起核对。

重复劳动放到构建阶段 ​

课程生成脚本负责归类、排序、生成目录和页面。部分已有课程通过 VitePress 的 transformPageData 在构建时抽取学习数据;浏览器拿到准备好的结构,不必每次打开页面都重新分析长篇材料。

Task 2 参考回答还保留了原文的 SHA-256 签名。生成时发现原文版本变化,会要求重新核对教学数据;播放器也核对音频清单与当前原文的版本。这个约束解决的是一个很实际的问题:不能让学习者点着新句子,却听到旧版内容。

text
内容与页面        docs/ 下的 Markdown
交互组件          docs/.vitepress/components/
规则与学习数据    docs/.vitepress/utils/、data/、composables/
课程整理与生成    scripts/ 及对应的源材料
公共媒体          docs/public/ 下的题图、音频、视频
发布产物          docs/.vitepress/dist/

目录的价值不在于分了多少文件,而在于边界清楚:调整练习样式不应迫使作者重写教材,修订译文也不应改变学习者保存草稿所用的课程标识。

音频:用完整音轨承载逐句练习 ​

雅思写作的 Task 2 与话题工作坊采用了一个重要取舍:每份材料、每种口音生成一条完整音轨,同时保存每句话的起止时间。前端按时间范围播放单句,或者连续播放全文。句子是练习单位,完整音轨是媒体文件单位。

44份参考材料
88条英美音轨
420个句子练习单元

这批文件合计约76.7 MB。若逐句生成两种口音,会形成840个句子文件,全文还可能需要另外处理;当前方案用88条音轨,同时支撑点读和全文跟读。它减少媒体碎片,也保留同一篇回答的声音连贯性。代价是播放一句时仍然要加载或定位到完整音轨中的对应位置,逐句体验依赖时间标记、网络和浏览器的媒体定位能力。

音频清单保存路径、口音、音色、时长、原文版本和句子区间。播放控制统一处理当前音轨、速度、跟读次数和活动句子;原文朗读、英译汉、汉译英与语法原句复用同一份音频。页面切换或学习模式改变时停止原来的播放,避免声音和界面脱节;新写的拓展句没有对应录音时,不套用原句音频。

语音生成发生在材料制作阶段。学习者点击播放时访问已经生成的静态媒体,不实时调用语音生成接口,因此重复收听主要消耗资源分发带宽。制作费用和日常访问成本可以分开考虑,也更容易在发布前检查音频与文本是否一致。

个人数据:及时保存,也说清边界 ​

数据当前保存方式为什么这样选择
学习状态、实践笔记、写作稿localStorage轻量、输入后就能保存,适合当前没有账号系统的练习流程
支持录音课程中的跟读录音MediaRecorder 采集,IndexedDB 保存 Blob二进制媒体与文字状态分开保存,录音组件无需上传到业务服务器
课程文本、示例音频与题图静态构建产物与公共媒体内容制作一次,发布后可以供多人重复访问

这种设计让用户不必先注册就能练习,也降低了账号和个人录音服务的维护成本。相应的限制同样真实:记录留在当前浏览器与站点域名下,换设备、切换浏览器或清理站点数据后,不会自动找回。写作台因此提供文本导出;浏览器保存失败时,也会提示用户备份。

当前的复盘与检查属于学习者自评,没有接入自动判分,也不把一次勾选当作官方能力评估。站点配置中的 Google Analytics 是独立的访问分析服务,不承担草稿和录音的保存;“学习记录保存在本地”也不意味着页面没有其他网络请求。

发布与分发:静态不等于没有系统设计 ​

VitePress 先生成可直接阅读的 HTML,Vue 再在浏览器中接管交互。课程正文不依赖实时业务 API,发布对象主要是页面、代码、搜索索引与媒体资源。导航、分组侧栏、本地搜索、站点地图和 canonical 地址共同解决“怎么找到内容”与“如何保持页面身份清楚”的问题。

线上站点是 www.gaojian.site。源站是一台运行 OpenCloudOS 的腾讯云服务器,由 Nginx 提供静态文件,再通过 腾讯云 EdgeOne 对外分发。当前采用手动发布:本地完成构建后,用 WebStorm Deployment 把 dist 中的构建产物上传到服务器的站点目录。

text
本地编辑与构建
  → WebStorm Deployment 上传 dist
  → 腾讯云服务器 / Nginx / 页面与媒体
  → EdgeOne 边缘分发
  → www.gaojian.site / 学习者浏览器

为什么暂时不把音频放进对象存储 ​

目前图片和音频与页面一起由源站提供。前期材料主要供站长自己使用,已有服务器套餐包含无限流量、峰值带宽200 Mbps;复用这台服务器,可以减少新引入的存储服务及其计费、权限和资源迁移管理。这个选择基于当前使用规模和已有资源,而不是因为静态学习网站必须这样部署。

它的代价是媒体容量、并发传输与页面资源共用服务器的磁盘和带宽。峰值带宽不是每位访客都能独占的下载速度;随着课程媒体和访问量增长,需要再依据实际访问、容量和边缘分发成本决定是否拆出媒体存储。内容、媒体路径与播放清单已经分开组织,后续迁移可以从资源层着手。

发布时更需要关注资源之间的版本一致性:

  • Nginx 配置对 /assets/ 中的哈希资源设置长期缓存与 immutable;新内容对应新文件名。
  • HTML 使用不缓存策略,同名的音频、图片要求重新验证。搜索索引随构建更新;边缘规则也要与源站策略一致,不能把所有资源一律长缓存。
  • Nginx 的音频配置保留字节范围请求能力,为媒体定位提供支持。页面也不应提前下载所有音轨;Task 2 播放器使用 preload="none",按用户操作加载。
  • 源码、原始工作材料和部署配置,与公开内容及构建产物分开。尤其是本项目的 MP3、MP4 不进入 Git,媒体需要独立备份;克隆源码并不等于恢复了完整站点。

构建通过只证明生成成功。一个完整的发布过程还应核对页面引用的资源版本、目录与深层链接、图片与音频是否可访问,以及边缘缓存是否已经更新。当前 WebStorm 上传流程和自动部署脚本是两件事:日常发布仍由站长手动完成。发布清单要覆盖媒体文件与缓存更新,不能把脚本的存在当作这些检查已经自动执行。

关键决策与代价 ​

选择解决的问题同时承担的代价
静态正文 + 浏览器交互让内容易维护,练习可独立演进,减少运行时业务依赖内容变更需要重新构建和发布;交互组件增多后仍要控制前端体积
原文、句子索引与版本校验共用降低译文、标记、练习与音频错位的风险修订原文时需要联动审校,不能只替换一段文字
完整音轨 + 句子时间范围点读和全文复用,减少文件碎片定位精度、媒体加载和长音轨体积需要持续检查
浏览器本地保存无需账号即可开始,草稿输入及时保存缺少跨设备同步,用户需要理解保存范围并备份
共享组件与移动端适配不同课程沿用熟悉的操作方式改动播放速度、弹层等共用组件时,要检查其他课程是否受影响

作为架构师,我更关心这些选择是否服务于当前的学习问题。技术上的简洁,是减少用户需要操心的事情:看图时能同时读范文,展开速度菜单不挤动邻近按钮,播放完毕有明确反馈,小屏幕仍能完整操作。它们是系统质量的一部分,而不是功能做完后的装饰。

继续建设 ​

后续的重点,是让已经能用的系统更稳定、更容易判断学习效果:

  1. 把内容校验继续前移。 保持题目、原文、中文与音频的对应,补充课程修订记录;自动校验负责找出错位,人工审校负责表达与教学质量。
  2. 按课程拆分前端负担。 随着共用组件、目录和数据增多,持续检查首屏资源与构建体积,按实际使用路径考虑延迟加载,而不是让每个读者一次承担整个站点的交互代码。
  3. 让复盘形成可观察的作品。 用初稿、修改稿与新题作答看进步,改善备份和学习记录的可见性;跨设备同步若成为真实需求,再评估账号和数据服务。
  4. 把发布检查与媒体备份固化。 不只检查首页,还检查课程深链、音频定位、移动端操作和资源版本,减少“代码上传了,学习材料却没完整到达”的问题。

这个项目让我学到:课程质量、交互质量和交付质量需要一起设计。更多技术层次并不自然带来更好的学习体验;真正有用的架构,应当让内容更准确、练习更顺畅,并让后续维护有据可循。