feat: 阶段2 Python后端、用户管理、统计、单词收藏与响应式适配
This commit is contained in:
@@ -0,0 +1,347 @@
|
||||
# 西班牙语日记本 — 设计文档
|
||||
|
||||
## 概述
|
||||
|
||||
一个日常使用的西班牙语学习工具。用户每天用西语写日记,系统自动显示英语和中文翻译,支持发音朗读。数据持久化存储,分两阶段交付。
|
||||
|
||||
## 项目阶段
|
||||
|
||||
| 阶段 | 存储 | 翻译 | 部署 |
|
||||
|------|------|------|------|
|
||||
| 阶段1 (纯前端) | IndexedDB | Mock 数据 | 浏览器直接打开 |
|
||||
| 阶段2 (Python 后端) | SQLite | 翻译 API | Flask/FastAPI + 静态文件 |
|
||||
|
||||
## 布局方案
|
||||
|
||||
选择 **方案B — 左右对照布局**
|
||||
|
||||
### 三栏结构
|
||||
|
||||
```
|
||||
+-------------------+---------------------+----------------------+
|
||||
| 左侧面板 | 主编辑区 | 右侧面板 |
|
||||
| 日记列表 | 西语输入 | 翻译区 |
|
||||
| | | |
|
||||
| 📅 2026-07-31 | 📝 Mi Diario | English |
|
||||
| Hoy fui al... | (text area) | Today I went to... |
|
||||
| 📅 2026-07-30 | | |
|
||||
| Ayer aprendí... | [🔊 保存] | 中文 |
|
||||
| 📅 2026-07-29 | | 今天我去了... |
|
||||
| Estoy cansado... | | |
|
||||
| | | [🔊 发音] |
|
||||
| [+ 新建] | | |
|
||||
+-------------------+---------------------+----------------------+
|
||||
```
|
||||
|
||||
### 左侧面板 — 日记列表
|
||||
|
||||
- 按日期倒序显示所有记录
|
||||
- 每条显示:日期 + 西语内容前 20 字预览
|
||||
- 当前选中的记录高亮
|
||||
- 顶部 "+" 按钮新建当日记录
|
||||
- 每条记录悬停时显示编辑/删除图标
|
||||
- 删除需要二次确认
|
||||
|
||||
### 主编辑区 — 西语输入
|
||||
|
||||
- 标题自动设为当天日期(格式:2026-07-31),可手动修改
|
||||
- 可编辑文本区用于输入西语日记
|
||||
- 底部保存按钮
|
||||
- 保存后自动更新左侧列表和右侧翻译
|
||||
|
||||
### 右侧面板 — 翻译区
|
||||
|
||||
- 只读展示,不可编辑
|
||||
- 上半部分:英文翻译
|
||||
- 下半部分:中文翻译
|
||||
- 每条翻译下方有 🔊 发音按钮(点击朗读对应语言的翻译文本)
|
||||
|
||||
## 功能需求
|
||||
|
||||
### 阶段1 (纯前端)
|
||||
|
||||
1. **CRUD 操作**
|
||||
- 新建日记:自动填入当天日期,西语内容为空
|
||||
- 编辑:点击已有记录,在主编辑区修改后保存
|
||||
- 删除:悬停时出现删除按钮,点击后弹窗确认
|
||||
|
||||
2. **翻译功能**
|
||||
- 阶段1 使用内置 mock 翻译数据(有限的预设短语库)
|
||||
- 保存后立即在右侧显示英/中文对照翻译
|
||||
- 纯前端无法调用翻译 API,预设覆盖日常日记常用句式
|
||||
如 "Hoy fui a..."、"Estoy..."、"Ayer..."、"Me gusta..." 等
|
||||
- 不在预设库中的内容显示原文 + 占位提示
|
||||
|
||||
3. **发音功能**
|
||||
- 使用浏览器 Web Speech API (SpeechSynthesis)
|
||||
- 支持西班牙语、英语、中文三种语言的文本朗读
|
||||
|
||||
4. **数据存储**
|
||||
- 使用 IndexedDB
|
||||
- 数据模型:
|
||||
```json
|
||||
{
|
||||
"id": "uuid",
|
||||
"date": "2026-07-31",
|
||||
"spanish": "Hoy fui al parque con mi amigo.",
|
||||
"english": "Today I went to the park with my friend.",
|
||||
"chinese": "今天我和朋友去了公园。",
|
||||
"createdAt": "2026-07-31T10:00:00Z",
|
||||
"updatedAt": "2026-07-31T10:00:00Z"
|
||||
}
|
||||
```
|
||||
|
||||
### 阶段2 (Python 后端)
|
||||
|
||||
#### 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 使用原生 API
|
||||
- Web Speech API 用于发音
|
||||
- 无构建工具,无依赖
|
||||
|
||||
### 阶段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 — 应用逻辑
|
||||
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 手机端可用
|
||||
|
||||
## 交互细节
|
||||
|
||||
- 点击左侧列表中的记录 → 主编辑区加载该记录内容,右侧显示翻译
|
||||
- 阶段1:修改主编辑区内容后点击保存 → 更新 IndexedDB,刷新左侧列表和右侧翻译
|
||||
- 阶段2:通过后端 API 保存,同一账号在不同设备可同步
|
||||
- 点击 🔊 → 使用 Web Speech API 朗读文本(自动选择对应语言语音)
|
||||
- 选择日期与已有记录相同 → 打开该记录而非新建
|
||||
|
||||
## 成功标准
|
||||
|
||||
### 阶段1
|
||||
|
||||
- 打开 HTML 文件即可使用,无需任何安装
|
||||
- 新建、编辑、删除操作流畅无刷新
|
||||
- 翻译在保存后即时显示
|
||||
- 发音功能在主流浏览器(Chrome/Edge)正常工作
|
||||
- 页面关闭后重新打开,数据完整保留
|
||||
|
||||
### 阶段2
|
||||
|
||||
- 用户可注册、登录、登出
|
||||
- 管理员可添加、禁用、删除用户
|
||||
- 不同用户日记数据完全隔离
|
||||
- 知识库对所有用户共享
|
||||
- 每个用户可配置翻译方式和在线翻译
|
||||
- 每个用户可查看日记统计
|
||||
- 每个用户可收藏和管理自己的单词
|
||||
- 前端在手机、平板、桌面均可用
|
||||
- 后端 API 启动后前端通过 API 读写数据
|
||||
- 未登录时不能访问个人数据接口
|
||||
- 被禁用用户无法登录且已有会话失效
|
||||
- 密码不以明文保存
|
||||
|
||||
## 后续阶段
|
||||
|
||||
- 阶段3 可增加:
|
||||
- 忘记密码与邮箱验证
|
||||
- 用户头像与个人资料
|
||||
- 分享日记
|
||||
- 导出/导入数据
|
||||
- Docker 部署
|
||||
- HTTPS 部署
|
||||
|
||||
Reference in New Issue
Block a user