docs: 更新阶段2设计文档

2026-08-01 17:46:24 +08:00
parent f7ff61fec2
commit a47b6c8297
+216 -12
@@ -93,51 +93,255 @@
### 阶段2 (Python 后端)
1. **存储迁移**:IndexedDB → SQLite
2. **REST API**:Flask/FastAPI 提供 CRUD 接口
3. **真实翻译**:接入 Google Translate API 或 DeepL API
4. **部署**:前端静态文件由后端服务
#### 2.1 后端与存储
- 使用 Python + Flask 提供 REST API,并直接托管前端静态文件
- 使用 SQLite 数据库,表结构见下方“数据库设计”
- 密码使用 Werkzeug 哈希存储,禁止明文
- 使用服务端 Session 管理登录状态,Cookie 存储 session id
#### 2.2 用户管理
- 注册:用户名、密码、显示名
- 登录 / 登出
- 管理员用户可:
- 查看全部用户
- 添加用户
- 禁用 / 启用用户
- 删除用户(同时删除该用户日记、收藏单词等数据)
- 普通用户不能访问管理员接口
- 被禁用用户无法登录,已登录会话立即失效
#### 2.3 数据隔离
- 日记、统计、收藏单词、翻译配置全部按 `user_id` 隔离
- 所有查询必须带当前登录用户的 `user_id`
- 服务端校验资源归属,禁止通过修改 URL/ID 访问他人数据
#### 2.4 知识库共享
- 知识库为公共静态页面,所有用户共享
- 不要求登录即可浏览知识库
#### 2.5 翻译配置
- 每个用户可以配置自己的翻译方式:
- 本地词典
- MyMemory 免费接口
- 自定义 HTTP 翻译接口(可配置 URL、请求头、字段映射)
- 配置项保存在用户自己的 `settings` 表中
- 后端执行在线翻译,避免浏览器跨域限制,也便于统一记录配置
#### 2.6 日记统计
- 每个用户可查看自己的统计:
- 总日记数
- 本月日记数
- 本周日记数
- 连续写作天数(streak)
- 最近 7 天每日条数
- 总西语字符数 / 平均每天字数
#### 2.7 单词本
- 每个用户可收藏单词
- 单词来自 B1 词库或日记中出现的词
- 收藏内容包括:西语单词、英语释义、中文释义、主题分类
- 支持添加、删除、列表查询
#### 2.8 前端适配
- 桌面:三栏布局
- 平板(768px - 1024px):两栏或紧凑三栏
- 手机(< 768px):单栏,列表、编辑、翻译通过页面区域切换
- 按钮触控区域不小于 40px,滚动区域适配触摸
- 保留 Web Speech API 发音
#### 2.9 安全
- 密码哈希存储
- Session Cookie 使用 `HttpOnly`、`SameSite=Lax`
- API 输入校验,防止 SQL 注入和 XSS
- 删除用户为级联删除
- 生产部署建议使用反向代理 + HTTPS
## 技术方案
### 阶段1 技术栈
- 纯 HTML + CSS + JavaScript
- IndexedDB 使用 idb 库或原生 API
- IndexedDB 使用原生 API
- Web Speech API 用于发音
- 无构建工具,无依赖
### 项目文件结构 (阶段1)
### 阶段2 技术栈
- Python 3 + Flask
- SQLite(Python 内置 sqlite3)
- Werkzeug(Flask 自带密码哈希)
- Vanilla JS 前端,保持无构建工具
### 项目文件结构 (阶段2)
```
spanish-diary/
server/
app.py — Flask 应用入口与路由
db.py — SQLite 初始化与连接
auth.py — 登录/会话/管理员权限
entries_api.py — 日记 CRUD 与统计
vocab_api.py — 单词本接口
settings_api.py — 翻译配置接口
translate_service.py — 本地/MyMemory/自定义翻译
index.html — 主页面
style.css — 样式
app.js — 应用逻辑
db.js — IndexedDB 操作封装
api.js — 后端 API 客户端
db.js — IndexedDB 操作封装(阶段1兼容)
translate.js — 翻译模块
speech.js — 发音模块
knowledge.html — 知识库首页
knowledge/ — 知识库分类页
b1-vocab.js — B1 词库
```
### 数据库设计
```sql
CREATE TABLE users (
id INTEGER PRIMARY KEY AUTOINCREMENT,
username TEXT UNIQUE NOT NULL,
password_hash TEXT NOT NULL,
display_name TEXT NOT NULL,
is_admin INTEGER NOT NULL DEFAULT 0,
is_active INTEGER NOT NULL DEFAULT 1,
created_at TEXT NOT NULL
);
CREATE TABLE entries (
id INTEGER PRIMARY KEY AUTOINCREMENT,
user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
date TEXT NOT NULL,
spanish TEXT NOT NULL,
english TEXT NOT NULL DEFAULT '',
chinese TEXT NOT NULL DEFAULT '',
created_at TEXT NOT NULL,
updated_at TEXT NOT NULL
);
CREATE INDEX idx_entries_user_date ON entries(user_id, date);
CREATE TABLE vocabulary (
id INTEGER PRIMARY KEY AUTOINCREMENT,
user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
word TEXT NOT NULL,
english TEXT NOT NULL DEFAULT '',
chinese TEXT NOT NULL DEFAULT '',
category TEXT NOT NULL DEFAULT '',
created_at TEXT NOT NULL,
UNIQUE(user_id, word)
);
CREATE TABLE settings (
user_id INTEGER PRIMARY KEY REFERENCES users(id) ON DELETE CASCADE,
translator TEXT NOT NULL DEFAULT 'local',
api_url TEXT NOT NULL DEFAULT '',
api_key TEXT NOT NULL DEFAULT '',
extra_config TEXT NOT NULL DEFAULT '{}',
updated_at TEXT NOT NULL
);
```
### API 设计
#### 用户与认证
| 方法 | 路径 | 说明 |
|------|------|------|
| POST | /api/register | 注册 |
| POST | /api/login | 登录 |
| POST | /api/logout | 登出 |
| GET | /api/me | 当前用户信息 |
| GET | /api/admin/users | 管理员查看用户 |
| POST | /api/admin/users | 管理员添加用户 |
| PUT | /api/admin/users/<id>/status | 启用/禁用 |
| DELETE | /api/admin/users/<id> | 删除用户 |
#### 日记与统计
| 方法 | 路径 | 说明 |
|------|------|------|
| GET | /api/entries | 当前用户日记列表 |
| POST | /api/entries | 新建日记 |
| PUT | /api/entries/<id> | 编辑日记 |
| DELETE | /api/entries/<id> | 删除日记 |
| GET | /api/entries/stats | 当前用户统计 |
#### 单词本
| 方法 | 路径 | 说明 |
|------|------|------|
| GET | /api/vocabulary | 收藏列表 |
| POST | /api/vocabulary | 收藏单词 |
| DELETE | /api/vocabulary/<id> | 删除收藏 |
#### 翻译配置
| 方法 | 路径 | 说明 |
|------|------|------|
| GET | /api/settings/translation | 获取翻译配置 |
| PUT | /api/settings/translation | 更新翻译配置 |
| POST | /api/translate | 翻译接口 |
### 前端兼容性
- 桌面:三栏
- 平板 768-1024px:两栏,编辑区优先
- 手机 <768px:单栏,通过标签或底部导航切换“日记 / 编辑 / 翻译 / 我的”
- 使用 CSS Grid + Media Query
- 输入框和按钮适配触摸操作
- 所有页面在 Chrome、Edge、Safari 手机端可用
## 交互细节
- 点击左侧列表中的记录 → 主编辑区加载该记录内容,右侧显示翻译
- 修改主编辑区内容后点击保存 → 更新 IndexedDB,刷新左侧列表和右侧翻译
- 阶段1:修改主编辑区内容后点击保存 → 更新 IndexedDB,刷新左侧列表和右侧翻译
- 阶段2:通过后端 API 保存,同一账号在不同设备可同步
- 点击 🔊 → 使用 Web Speech API 朗读文本(自动选择对应语言语音)
- 选择日期与已有记录相同 → 打开该记录而非新建
## 成功标准
### 阶段1
- 打开 HTML 文件即可使用,无需任何安装
- 新建、编辑、删除操作流畅无刷新
- 翻译在保存后即时显示
- 发音功能在主流浏览器(Chrome/Edge)正常工作
- 页面关闭后重新打开,数据完整保留
### 阶段2
- 用户可注册、登录、登出
- 管理员可添加、禁用、删除用户
- 不同用户日记数据完全隔离
- 知识库对所有用户共享
- 每个用户可配置翻译方式和在线翻译
- 每个用户可查看日记统计
- 每个用户可收藏和管理自己的单词
- 前端在手机、平板、桌面均可用
- 后端 API 启动后前端通过 API 读写数据
- 未登录时不能访问个人数据接口
- 被禁用用户无法登录且已有会话失效
- 密码不以明文保存
## 后续阶段
- 阶段2 将 IndexedDB 数据迁移到 SQLite,通过 REST API 操作
- 接入真实翻译 API
- 用户认证(可选)
- 多设备同步(可选)
- 阶段3 可增加:
- 忘记密码与邮箱验证
- 用户头像与个人资料
- 分享日记
- 导出/导入数据
- Docker 部署
- HTTPS 部署