diff --git a/docs/plans/2026-01-23-h5-mysql-permissions-design.md b/docs/plans/2026-01-23-h5-mysql-permissions-design.md new file mode 100644 index 0000000..0a92b06 --- /dev/null +++ b/docs/plans/2026-01-23-h5-mysql-permissions-design.md @@ -0,0 +1,209 @@ +# Vitals 改造设计方案 + +> 日期: 2026-01-23 +> 状态: 已确认 + +## 概述 + +本次改造包含三个主要目标: +1. **H5 移动端适配** - 所有页面优化为移动端友好 +2. **MySQL 数据库迁移** - 从 SQLite 迁移到 MySQL +3. **用户权限增强** - 非管理员仅能看到自己 + +## 一、技术决策 + +| 决策项 | 选择 | 理由 | +|--------|------|------| +| 前端框架 | 保持 Python 渲染 HTML | 改动最小,无需重写前端 | +| 数据库驱动 | mysql-connector-python 裸 SQL | 保持现有查询结构 | +| CSS 方案 | 响应式 CSS + 媒体查询 | 无需引入新框架 | + +## 二、H5 移动端设计系统 + +### 2.1 配色方案 + +| 元素 | 色值 | 用途 | +|------|------|------| +| Primary | `#3B82F6` | 主色调、链接、选中状态 | +| Secondary | `#60A5FA` | 辅助色、次要元素 | +| CTA | `#F97316` | 主要操作按钮、强调 | +| Background | `#F8FAFC` | 页面背景 | +| Text | `#1E293B` | 正文文字 | + +### 2.2 字体 + +```css +@import url('https://fonts.googleapis.com/css2?family=Fira+Code:wght@400;500;600;700&family=Fira+Sans:wght@300;400;500;600;700&display=swap'); + +--font-heading: 'Fira Sans', sans-serif; +--font-body: 'Fira Sans', sans-serif; +--font-mono: 'Fira Code', monospace; +``` + +### 2.3 响应式断点 + +```css +/* 移动优先策略 */ +默认样式 → 手机 (< 768px) +@media (min-width: 768px) → 平板 +@media (min-width: 1024px) → 桌面 +``` + +### 2.4 移动端 UX 规范 + +| 规范 | 要求 | +|------|------| +| 触摸目标 | 最小 44x44px | +| 触摸间距 | 元素间至少 8px | +| 输入框 | 使用正确的 `inputmode` 属性 | +| 点击优化 | `touch-action: manipulation` | +| 固定元素 | 使用 `z-index: 50` | +| 安全区域 | 底部导航考虑 `safe-area-inset-bottom` | + +### 2.5 导航栏改造 + +**桌面端 (≥768px):** 保持顶部水平导航 + +**移动端 (<768px):** 底部 Tab 栏 +``` +┌─────────────────────────────────────┐ +│ 页面内容区域 │ +│ │ +├─────────────────────────────────────┤ +│ 🏠 🏃 🍽️ 😴 ⚙️ │ +│ 首页 运动 饮食 睡眠 更多 │ +└─────────────────────────────────────┘ + +"更多" 展开菜单:体重、阅读、报告、设置、管理(仅管理员) +``` + +### 2.6 页面适配清单 + +| 页面 | 适配要点 | +|------|----------| +| 登录/注册 | 全屏表单,大按钮 | +| 首页 Dashboard | 卡片单列堆叠,数据卡片全宽 | +| 数据录入页 | 表单全宽,输入框加大 | +| 数据列表 | 表格改卡片列表 | +| 图表 | 响应式宽度 100% | +| 设置/管理 | 单列列表布局 | + +## 三、MySQL 数据库迁移 + +### 3.1 SQLite vs MySQL 差异 + +| 功能 | SQLite | MySQL | +|------|--------|-------| +| 占位符 | `?` | `%s` | +| 自增 | `AUTOINCREMENT` | `AUTO_INCREMENT` | +| 时间函数 | `datetime('now')` | `NOW()` | +| 字符串拼接 | `\|\|` | `CONCAT()` | + +### 3.2 配置方式 + +```bash +# 环境变量 +MYSQL_HOST=localhost +MYSQL_PORT=3306 +MYSQL_USER=vitals +MYSQL_PASSWORD=xxx +MYSQL_DATABASE=vitals +``` + +### 3.3 database.py 改动清单 + +1. 添加 MySQL 连接池管理 +2. 所有 `?` 占位符改为 `%s` +3. `AUTOINCREMENT` 改为 `AUTO_INCREMENT` +4. 时间函数调整 +5. 字段类型映射 (TEXT → VARCHAR/TEXT) + +### 3.4 表结构映射 + +```sql +-- users 表 +CREATE TABLE users ( + id INT PRIMARY KEY AUTO_INCREMENT, + name VARCHAR(255) NOT NULL UNIQUE, + created_at DATETIME NOT NULL, + is_active TINYINT DEFAULT 0, + gender VARCHAR(10), + height_cm FLOAT, + weight_kg FLOAT, + age INT, + password_hash VARCHAR(255), + email VARCHAR(255), + is_admin TINYINT DEFAULT 0, + is_disabled TINYINT DEFAULT 0 +); + +-- 其他表类似处理 +``` + +## 四、用户权限增强 + +### 4.1 权限模型 + +``` +管理员 (is_admin=1) +├── 查看所有用户列表 +├── 启用/禁用用户 +├── 删除用户 +├── 管理邀请码 +└── 访问 /admin 页面 + +普通用户 (is_admin=0) +├── 仅能看到自己的用户信息 +├── 无法访问 /admin 页面 +└── 无法看到其他用户存在 +``` + +### 4.2 API 接口改动 + +| 接口 | 当前行为 | 改动后 | +|------|----------|--------| +| `GET /api/users` | 返回所有用户 | 非管理员仅返回自己 | +| `GET /api/users/{id}` | 返回指定用户 | 非管理员只能查自己,否则 403 | + +### 4.3 页面访问控制 + +| 页面 | 管理员 | 普通用户 | +|------|--------|----------| +| `/admin` | 完整功能 | 重定向到首页 | +| `/settings` | 完整功能 | 仅自己信息 | +| 导航栏「管理」 | 显示 | 隐藏 | + +## 五、实施阶段 + +### 阶段 1: MySQL 迁移 +- [ ] 改造 database.py 支持 MySQL +- [ ] 编写数据迁移脚本 +- [ ] 测试所有数据库操作 + +### 阶段 2: 用户权限 +- [ ] 修改 /api/users 接口 +- [ ] 修改 /api/users/{id} 接口 +- [ ] 隐藏非管理员的管理入口 + +### 阶段 3: H5 移动端适配 +- [ ] 全局样式基础设施(viewport, 字体, 变量) +- [ ] 底部导航栏组件 +- [ ] 逐页适配(11个页面) + +### 阶段 4: 测试验证 +- [ ] 移动端真机测试 +- [ ] MySQL 生产环境测试 +- [ ] 权限功能测试 + +## 六、不变的部分 + +以下模块保持不变,不在本次改造范围: +- `models.py` - 数据模型定义 +- `auth.py` - 认证逻辑 +- `vision/` - AI 食物识别 +- `importers/` - 数据导入 +- `backup.py` - 备份功能 +- `export.py` - 导出功能 +- `report.py` - 报告生成 +- `calories.py` - 热量计算 +- API 业务逻辑(仅改数据库层和权限检查)