diff --git a/西班牙语日记-设计文档.md b/西班牙语日记-设计文档.md index 6295219..5ec894a 100644 --- a/西班牙语日记-设计文档.md +++ b/西班牙语日记-设计文档.md @@ -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//status | 启用/禁用 | +| DELETE | /api/admin/users/ | 删除用户 | + +#### 日记与统计 + +| 方法 | 路径 | 说明 | +|------|------|------| +| GET | /api/entries | 当前用户日记列表 | +| POST | /api/entries | 新建日记 | +| PUT | /api/entries/ | 编辑日记 | +| DELETE | /api/entries/ | 删除日记 | +| GET | /api/entries/stats | 当前用户统计 | + +#### 单词本 + +| 方法 | 路径 | 说明 | +|------|------|------| +| GET | /api/vocabulary | 收藏列表 | +| POST | /api/vocabulary | 收藏单词 | +| DELETE | /api/vocabulary/ | 删除收藏 | + +#### 翻译配置 + +| 方法 | 路径 | 说明 | +|------|------|------| +| 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 部署