考研英语一的英译汉,大概是整张试卷里最让人心里没底的题型——翻完不知道对不对,没人帮你批,答案看懂了也不知道自己差在哪。于是就有了 译文岛,一个微信小程序,用 DeepSeek 做 AI 翻译评分,从准确性、语法、词汇、流畅四个维度给你打分,还带逐句批改。
这篇文章聊聊这个项目的技术选型、架构设计,以及我在 uni-app 和微信云开发里踩过的那些坑。
一、产品长什么样:动森风 + 完整学习闭环
界面用的是类似动物森友会的手绘风格,岛民画风 + 暖色圆角,试图让“练习翻译”这件事不那么痛苦。
功能上,它试图覆盖从输入到复盘的全流程:
-
范文库:历年真题原文,分句展示,标出考点和参考译文
-
AI 评分:提交你的翻译,AI 从四个维度打分,并返回每句话的问题
-
水波训练:针对某个难句反复精讲,像教辅书一样拆解
-
反转训练:看着中文回译英文,双向巩固
-
图片导入:拍照或相册导入题目,AI 自动提取英文原文
-
错题本:自动收录错误表达,按 3/7 天间隔提醒复习,支持导出文本、图片和 PDF
-
学习报告:每周生成一张 Canvas 海报,数据可视化 + 可保存分享
-
生词短语池 + 默写:AI 自动收录生词,卡片式默写自测
-
打卡:连续打卡日历 + 订阅消息提醒
这些功能全部通过 AI 调用串联,而且用户可以选择用自己的 DeepSeek API Key,把算力成本从平台身上转移出去。
二、技术选型:为什么是 uni-app + 微信云开发?
虽然现在跨端框架很多,但这个小程序只服务微信生态,不需要跨端。选 uni-app 主要是为了:
-
Vue3 + Composition API:状态管理灵活,能支撑复杂的评分流程状态机
-
HBuilderX 配套工具链:虽然不如原生好用,但编译发布流程成熟
-
组件化:错题本、短语默写、学习报告这些模块可以被多个页面复用
至于后端,直接用微信云开发,省掉了服务器运维。云函数负责 DeepSeek 调用和定时任务,云数据库存用户 Key 和订阅状态,云存储放生成的 PDF 和图片。整个后端只有三个云函数,代码量很少。
三、架构设计:AI 调用的“双密钥”机制
这是整个项目最核心的设计——怎么在保护平台密钥的同时,又允许用户用自己的 Key?
text
客户端 → 云函数 callAI
↓
读取 ai_keys(按 openid)
↓
用户配置了 Key? → 是 → 用用户 Key 请求 DeepSeek
↓ 否
用环境变量 DEEPSEEK_API_KEY(平台兜底)
↓
记录 token 用量到 ai_usage 集合
↓
返回结果给客户端
-
用户 Key 存在云端数据库
ai_keys里,权限设为“仅云函数可读写”,永不回传客户端 -
调用时优先用用户 Key,没有才用平台 Key
-
Token 用量实时统计到
ai_usage集合,可用于成本监控
这个设计让平台的运营成本可控(活跃用户通常愿意用自己的 Key,毕竟 DeepSeek 现在很便宜),同时保留了开箱即用的体验——不配置 Key 也能用。
四、演示模式:让比赛评审和体验用户都能跑通
为了让评审在没有真实 API Key 的情况下也能完整体验功能,项目内置了一套演示模式:
js
// src/common/constants.js
export const DEMO_MODE = true // 开发/演示时打开
当 DEMO_MODE 为 true 时,所有 AI 调用都不会真正发出请求,而是返回 demo.js 里预设的模拟数据。评分、水波解析、词根分析、图片提取——每个功能都有配套的假数据,保证交互流程完整。
更巧妙的是,uni-app 编译器会按常量裁剪代码。也就是说,DEMO_MODE = false 时,那些 if (DEMO_MODE) 分支里的代码根本不会打包进最终产物。所以演示和生产的切换不需要手动删代码,改一个布尔值重新构建就行。
界面顶部还有一个“演示模式”的角标,避免用户把模拟评分当成真实结果。
五、那些踩过的坑
1. 图标字体的 hack
因为小程序 wxss 不支持本地 @font-face,所有动森风格的图标字体只能用 base64 编码后,通过 uni.loadFontFace 在 App.vue 里全局注册。构建后还需要一个后处理脚本 fix-fonts.cjs,把某些组件库(wot)引入的失效字体引用清理掉,否则会报一堆 ENOENT 错误。
2. 构建时锁文件
uni-app 的 npm run build:mp-weixin 会在 dist/build 里生成产物。如果微信开发者工具还开着项目,它的热重载监视器会锁住目录,导致构建报 EPERM。所以现在构建前必须先退出开发者工具——这是一个很容易浪费半小时的坑。
3. Canvas 2d 画布的顺序陷阱
学习报告海报和错题导出 PDF 用的是小程序 type="2d" 的 Canvas。注意:必须先 getContext('2d') 再设置宽高,否则画布坐标系会错乱。这个顺序在小程序文档里并不醒目,但在实际绘制时是致命的。
4. 云函数内置中文字体
exportMistakesPdf 云函数用 pdfkit 生成 PDF,需要中文字体。直接引入完整的 Noto Sans SC 有十几 MB,超出云函数包大小限制。最后手动裁剪了一个约 1.2MB 的子集,只包含常用汉字,刚好能满足错题本导出的需求。
5. 订阅消息模板的字段顺序
微信的订阅消息模板对关键词顺序很敏感。sendCheckin 云函数里构造的 data 对象的字段顺序,必须和后台申请的模板关键词顺序完全一致,否则消息发不出去且不报错。这个就只能靠“对着模板 ID 一个字段一个字段核对”来排查。
六、项目代码结构一览
text
miniapp/
├── cloudfunctions/ callAI / sendCheckin / exportMistakesPdf
├── src/
│ ├── api/ai.js 云函数调用封装
│ ├── common/ constants · demo数据 · 真题 · icon-font
│ ├── components/ 错题本 / 学习报告 / 短语默写 / 词根分析等
│ ├── pages/ essays(范文库)· practice(练习)· mine(我的)
│ ├── store/index.js 全局状态管理
│ └── utils/ 本地存储 / 翻译对齐 / 格式化等
└── project.config.json 指向 dist/build/mp-weixin
整体很轻量,没有引入 Vuex/Pinia,直接用 Composition API + reactive 对象做状态管理。因为页面不多,过度工程化反而增加理解成本。
七、部署上线 checklist
如果想把这个项目转成自己可用的版本,按以下步骤操作:
-
创建云数据库集合:
ai_keys、ai_usage、checkin_subscribers -
部署三个云函数,并配置环境变量(DeepSeek Key、订阅模板 ID)
-
修改前端常量:关闭演示模式,填入真实的云环境 ID 和订阅模板 ID
-
申请订阅消息模板(教育类目,字段匹配)
-
重新构建,在微信开发者工具里上传审核
整个过程如果环境变量和权限设置正确,大约半小时就能跑通。
八、一点感想
这个小程序从写第一行代码到功能完备,用了一个多月。最大的感受是:AI API 的接入成本现在真的极低了。DeepSeek 的响应质量和价格,让“每人一个 AI 翻译教练”这件事变得可行。微信云开发也让个人开发者不需要碰服务器——三个云函数就撑起了一整套后端。
当然,考研党是否愿意在一个新小程序里坚持练习,还需要时间验证。但至少从技术上来说,这件事的门槛已经降到足够低了。
如果你也在用 uni-app 或微信云开发做类似项目,欢迎交流。源码已开源在 GitHub,感兴趣的同学可以去看看。