No description
Find a file
WorkEnglish 83176350d5 fix(web): 返回逻辑改为确定性——严格回到声明的逻辑父页
PageHeader.goBack:上一页正好是声明的父页才 router.back()(与系统手势一致、
不留重复条目),否则一律 router.replace(父页) 落到逻辑上一级,杜绝来回跳。
闪卡复习可从首页/学习两处进入,去掉其固定 back-to,改回真正来源页。
2026-09-07 16:41:51 +08:00
public fix(web): 返回逻辑改为确定性——严格回到声明的逻辑父页 2026-09-07 16:41:51 +08:00
scripts feat(books): 词书功能——本地词库预置分类词表,全员一键加入学习目标 2026-09-07 16:02:14 +08:00
src fix(practice): 干扰项取词改内存词池,修复「中译英」拖垮整站 2026-09-07 16:18:45 +08:00
web fix(web): 返回逻辑改为确定性——严格回到声明的逻辑父页 2026-09-07 16:41:51 +08:00
.dockerignore feat(upgrade): 后端自动升级——we-updater 轮询 tag 并 curl 下载归档包,备份/构建/健康校验/失败回滚;新增 /api/health、/api/admin/version 与管理页版本卡片。附带纳入 server.js/AISettingsView 中此前未提交的 CJK 字数统计、服务端 fresh 过滤、模型默认值匹配修复 2026-09-04 22:41:25 +08:00
.gitignore feat(upgrade): 后端自动升级——we-updater 轮询 tag 并 curl 下载归档包,备份/构建/健康校验/失败回滚;新增 /api/health、/api/admin/version 与管理页版本卡片。附带纳入 server.js/AISettingsView 中此前未提交的 CJK 字数统计、服务端 fresh 过滤、模型默认值匹配修复 2026-09-04 22:41:25 +08:00
AGENTS.md feat(books): 词书功能——本地词库预置分类词表,全员一键加入学习目标 2026-09-07 16:02:14 +08:00
docker-compose.yml fix(upgrade): REPO_URL 可由 .env 覆盖;ls-remote 探测失败给出凭据诊断而非误报无 tag 2026-09-04 22:50:40 +08:00
docker-entrypoint.sh WorkEnglish v1.0.0: 从技术文档/会议纪要学习英语的 Web 应用 2026-08-22 23:46:05 +08:00
Dockerfile feat(upgrade): 后端自动升级——we-updater 轮询 tag 并 curl 下载归档包,备份/构建/健康校验/失败回滚;新增 /api/health、/api/admin/version 与管理页版本卡片。附带纳入 server.js/AISettingsView 中此前未提交的 CJK 字数统计、服务端 fresh 过滤、模型默认值匹配修复 2026-09-04 22:41:25 +08:00
Dockerfile.updater perf(updater): Alpine 源切阿里云镜像,避免国内服务器 apk 拉包超时 2026-09-04 23:02:28 +08:00
package-lock.json WorkEnglish v1.0.0: 从技术文档/会议纪要学习英语的 Web 应用 2026-08-22 23:46:05 +08:00
package.json WorkEnglish v1.0.0: 从技术文档/会议纪要学习英语的 Web 应用 2026-08-22 23:46:05 +08:00
README.docker.md docs(readme): 手动 curl 升级示例改用通配符适配归档顶层目录名 2026-09-04 22:56:42 +08:00
README.md feat(ai): 多服务商支持——DeepSeek/通义千问/讯飞星火/Ollama 自由切换 2026-08-23 13:00:13 +08:00
server.js fix(practice): 干扰项取词改内存词池,修复「中译英」拖垮整站 2026-09-07 16:18:45 +08:00
WorkEnglish_前端风格与界面布局设计文档.md feat(books): 词书功能——本地词库预置分类词表,全员一键加入学习目标 2026-09-07 16:02:14 +08:00
WorkEnglish_轻社交功能设计文档.md feat(social): 轻社交一期——打卡动态/点赞/周排行榜/分享图卡 2026-09-07 11:26:14 +08:00

📚 WorkEnglish —— 从工作中学习英语

把你日常的技术文档、英文邮件、中英混合会议纪要变成个人英语生词本 + 间隔重复(SRS)记忆系统。

核心理念:不背单词书。你学的每一个词都来自你真实工作场景的原文语境——技术术语(rollback、pipeline、stakeholder)、会议纪要里的地道表达,学完立刻能在明天的工作里用上。

✨ 功能

模块 说明
📥 素材导入 粘贴文本 / 上传文件(txt、md、docx、pdf)/ 扫描服务器目录,三种方式
🔍 智能提取 自动分词、词频统计、过滤基础词(ECDICT 词频 + 停用词),提取技术术语和缩写词(API、SLA)
🀄 中英对照 中文会议纪要里嵌入的英文术语(如"需要做 rollback")自动配对原文中文句做语境
📖 语境卡片 单词 + 音标 + 释义 + 原文例句(英文句或中文对照句),未收录词自动标注
🧠 SRS 间隔重复 SM-2 算法:忘记→明天再见,记得→1/6/14 天渐进拉长,符合遗忘曲线
✏️ 四种练习 英→中、中→英、原文填空(挖空工作原文!)、听音选词(浏览器 TTS)
📈 学习统计 总词数/掌握量/连续打卡/近 30 天学习量/词汇等级分布
🔐 多用户 登录注册、数据隔离、首个用户自动成为管理员;适合团队/跨设备使用
✨ AI 增强(可选) 填入 DeepSeek API Key 即启用「AI 语境讲解」;不填则纯本地离线运行

🚀 快速开始

要求:Node.js ≥ 18(推荐 20+),Python 3(仅安装词库时需要),磁盘剩余 ≥ 2GB。

# 1. 安装依赖
npm install --omit=dev

# 2. 安装离线词库(ECDICT,340 万词条,下载约 207MB)
npm run init-dict

# 3. 启动
npm start                # 默认 http://localhost:3000

浏览器打开 http://localhost:3000,第一个注册的用户自动成为管理员。

端口被占用时:PORT=8787 npm start 数据目录:DATA_DIR=/data/workenglish npm start(默认 ./data)

🛠️ 环境变量

变量 默认值 说明
PORT 3000 监听端口
HOST 0.0.0.0 监听地址
DATA_DIR ./data 数据目录(app.db 用户数据 + stardict.db 词库)
COOKIE_SECURE 未设置 设为 1 表示启用 HTTPS 部署(Cookie 加 Secure 标记)

📦 服务器部署(systemd + nginx)

1. 目录结构

mkdir -p /opt/workenglish/data /var/lib/workdocs
cd /opt/workenglish            # 项目文件放这里

2. systemd 服务

/etc/systemd/system/workenglish.service:

[Unit]
Description=WorkEnglish - learn English from work documents
After=network.target

[Service]
Type=simple
User=www-data
WorkingDirectory=/opt/workenglish
Environment=NODE_ENV=production
Environment=PORT=3000
Environment=DATA_DIR=/opt/workenglish/data
Environment=COOKIE_SECURE=1
ExecStart=/usr/bin/node server.js
Restart=always
RestartSec=3

[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload
sudo systemctl enable --now workenglish

⚠️ 若开启「目录扫描」,www-data 用户需要对扫描目录有读权限,例如: sudo chown -R www-data:www-data /var/lib/workdocs

3. nginx 反向代理(HTTPS 推荐)

/etc/nginx/sites-available/workenglish:

server {
    listen 443 ssl http2;
    server_name english.example.com;

    ssl_certificate     /etc/letsencrypt/live/english.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/english.example.com/privkey.pem;

    client_max_body_size 30m;   # 上传文件上限,与后端一致

    location / {
        proxy_pass http://127.0.0.1:3000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

server {
    listen 80;
    server_name english.example.com;
    return 301 https://$host$request_uri;
}
sudo ln -s /etc/nginx/sites-available/workenglish /etc/nginx/sites-enabled/
sudo nginx -t && sudo systemctl reload nginx

4. 目录扫描配置

  1. 管理员登录 → 「设置」→ 填写服务器上的绝对路径(如 /var/lib/workdocs)→ 保存
  2. 「素材」页点击「扫描目录中的文档」,支持 txt / md / docx / pdf

5. 数据备份

只需备份 data/app.db(用户数据)和 data/stardict.db(词库,可重新下载):

sqlite3 data/app.db ".backup /backup/app-$(date +%F).db"

✨ AI 增强(可选)

  1. 管理员 → 「我的」→「AI 设置」选择服务商并填入 API Key(模型默认见下方各服务商说明)
  2. 「素材导入」候选词可一键「AI 讲解」:AI 基于你的工作原文语境,给出贴合场景的释义和记忆法
  3. 词典兜底:配置后,添加生词时若离线词典未收录,会自动调用 AI 生成中文释义并缓存进生词本(生词本中标记为「AI补」);批量提取同样生效
  4. 不填 Key 则一切功能保持纯本地离线运行,文档数据不出服务器

支持的 AI 服务商(均为 OpenAI 兼容接口,可自由切换)

服务商 申请地址 默认模型 备注
DeepSeek platform.deepseek.com deepseek-chat Key 形如 sk-...
通义千问(阿里云) bailian.console.aliyun.com(DashScope) qwen-plus Key 形如 sk-...,兼容模式地址
讯飞星火 console.xfyun.cn(开通星火大模型) generalv3.5 使用「APIKey 认证」(OpenAI 兼容模式),非旧版签名鉴权
Ollama 本地 本地/内网运行 ollama serve 自定义(如 qwen2.5:7b) 无需 Key;Docker 部署需让容器可访问 Ollama
  • 各服务商的 Key 独立保存,切换服务商无需重填;旧配置 ai_api_key 自动视为 DeepSeek 的 Key
  • 「高级 → 接口地址」可填任意 OpenAI 兼容服务(Moonshot、vLLM 等)覆盖默认地址
  • 每次请求使用当前选中的服务商;某个服务商不可用时切换其它家即可

🧪 测试

# 启动服务后(假设 8787 端口):
node scripts/smoke.js
# 或指定端口:
SMOKE_BASE=http://127.0.0.1:3000 node scripts/smoke.js

v2 冒烟:前端产物检查(SPA 挂载点 / 双主题 token / 入口资源)+ 全部 API 契约全流程(注册登录 → 素材导入候选提取 → 生词增删改查 → 复习评分 → 四种题型 → 统计 → 设置/AI 降级 → 登出)。 新版前端为 Vue 3 SPA(ES Module 构建),jsdom 无法执行,渲染级验证请用浏览器(可用 scripts/browser-smoke.js,需本机装 Playwright 且服务可访问时执行)。

💻 前端开发(web/ 目录)

前端为 Vue 3 + Vite + Vant 4,源码在 web/,构建产物输出到 public/(由 Express 托管,History 路由 fallback 后端已内置)。

# 开发模式(热更新):先起后端(npm start),再
cd web && npm install && npm run dev     # http://localhost:5173,/api 自动代理到 3000

# 生产构建:产物写入 ../public
cd web && npm run build

注意:后端 src/ 与前端 web/src/ 是两个独立目录;public/app.js、public/style.css 为旧版前端(v1),构建不会删除,随时可回退(把 git checkout -- public 还原 index.html 即可)。

❓ 常见问题

  • 词库没装/想重装:删掉 data/stardict.db 后执行 npm run init-dict(支持断点续传)
  • 想叠加多个词库:把任意含 stardict 表的 sqlite 词库放入 data/,命名为 ecdict.db / stardict.db / dict.db 之一即可。多个词库会按 ecdict.db → stardict.db → dict.db 顺序组成 fallback 链,查词时第一个命中的词库返回结果
  • 单词在词典里查不到:添加时会自动标为「未收录」,生词本显示「未收录,点 ✏️ 补释义」。两种补法:① 在「设置」配置 DeepSeek Key,之后新添加的未收录词自动由 AI 补释义;② 在生词本点该词的「✏️ 编辑」按钮手动填写释义
  • 改了释义想恢复:词典词条的释义存在生词本里,编辑后不会自动回写词典;点「✏️ 编辑」随时可改,只需留空即恢复为未收录状态(重新添加时会再次兜底)
  • PDF 解析不出中文:系统内置的 pdf.js 对扫描版 PDF 无法提取文字(那是图片),请配合 OCR 工具先转文本
  • 端口 3000 被占用:项目把端口做成环境变量 PORT=8787 npm start(本机部署建议 8787,避免和常见服务冲突)
  • 忘记管理员密码:sqlite3 data/app.db "UPDATE users SET password_hash='' WHERE is_admin=1" 后重新注册?——不可行,正确做法:直接删除该用户行后用新用户名注册成为新管理员(首个用户自动为管理员)。

📁 项目结构

server.js            # Express 入口 + 全部 API 路由
src/
  db.js              # SQLite 初始化与表结构
  auth.js            # 注册/登录/会话(bcrypt + 签名 Cookie)
  dictionary.js      # 离线词库查询(支持多词库 fallback 链)
  extract.js         # 分词 / 语言识别 / 词频 / 语境例句提取
  files.js           # txt/md/docx/pdf 解析 + 目录扫描
  srs.js             # SM-2 间隔重复算法
  ai.js              # DeepSeek AI 讲解(预留接口,Key 可开关)
public/              # 前端(原生 JS,无构建,适配手机)
scripts/
  fetch-dict.js      # 词库下载安装
  smoke.js           # jsdom 浏览器冒烟测试
data/                # app.db(用户数据)+ stardict.db(词库)

📜 许可与技术说明

  • 离线词库:ECDICT(MIT),包含音标/释义/词频/考试等级标签
  • 间隔重复:SM-2(SuperMemo 2)算法
  • 语音朗读:浏览器原生 SpeechSynthesis(无网络依赖)