diff --git a/README.md b/README.md index 41fb4a3..8bf9b54 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,8 @@ - **BMI 计算** - 自动计算并显示健康状态(偏瘦/正常/偏胖/肥胖) - **用户切换** - 支持多用户数据隔离 - **数据管理** - 按日期范围或数据类型清除数据 -- **JWT 认证** - 安全的 Token 认证机制 +- **JWT 认证** - HTTPOnly Cookie + Authorization Header 混合认证 +- **记住我** - 可选 1 天或 30 天登录有效期 - **邀请码注册** - 通过邀请码控制用户注册 - **管理员面板** - 用户管理、邀请码管理 @@ -93,8 +94,9 @@ uvicorn vitals.web.app:app --host 0.0.0.0 --port 8080 | 端点 | 方法 | 说明 | |------|------|------| -| `/api/auth/login` | POST | 用户登录,返回 JWT Token | +| `/api/auth/login` | POST | 用户登录,返回 JWT Token + 设置 Cookie | | `/api/auth/register` | POST | 用户注册(需邀请码) | +| `/api/auth/logout` | POST | 用户登出,清除 Cookie | | `/api/auth/me` | GET | 获取当前用户信息 | ### 管理员 @@ -428,6 +430,36 @@ vitals/ - [ ] 部分页面在小屏幕上布局需要调整 - [ ] 书籍封面搜索有时无法找到匹配结果 +## 更新日志 + +### 2026-01-22 + +#### 🔐 混合认证方案优化 +- 修改 login/register API 使用 JSONResponse 正确设置 Cookie +- 添加 `path="/"` 确保 Cookie 在所有路径可用 +- 前端同时使用 localStorage token 进行 API 认证 +- 修复登录后闪屏返回登录页的问题 + +#### ✨ 登录功能全面升级 +- **服务端认证中间件** - 未登录用户自动重定向到登录页 +- **HTTPOnly Cookie** - 使用 HTTPOnly Cookie 存储 token(比 localStorage 更安全) +- **"记住我"功能** - 勾选:30 天有效期,不勾选:1 天有效期 +- **登出 API** - 新增 `/api/auth/logout` 接口 +- **登录后重定向** - 支持登录后返回原访问页面 + +#### 🎨 登录/注册页面 UI 升级 +- 采用 **Neumorphism(新拟态)** 设计风格 +- 健康主题配色(青色 + 绿色渐变) +- Lora + Raleway 字体组合 +- 柔和阴影效果,提升视觉体验 + +### 历史版本 + +- **2026-01-20** - 阅读模块上线(书库、心情追踪、统计图表) +- **2026-01-19** - 设置页面重构(用户档案、数据管理) +- **2026-01-17** - 公网部署支持(JWT 认证、邀请码、管理员面板) +- **2026-01-15** - 第一版发布(核心健康追踪功能) + ## License MIT diff --git a/src/vitals/core/__pycache__/auth.cpython-313.pyc b/src/vitals/core/__pycache__/auth.cpython-313.pyc index ef9ba84..a3624df 100644 Binary files a/src/vitals/core/__pycache__/auth.cpython-313.pyc and b/src/vitals/core/__pycache__/auth.cpython-313.pyc differ diff --git a/src/vitals/web/__pycache__/app.cpython-313.pyc b/src/vitals/web/__pycache__/app.cpython-313.pyc index f483c3d..58135b6 100644 Binary files a/src/vitals/web/__pycache__/app.cpython-313.pyc and b/src/vitals/web/__pycache__/app.cpython-313.pyc differ diff --git a/src/vitals/web/app.py b/src/vitals/web/app.py index d73307a..b5b268f 100644 --- a/src/vitals/web/app.py +++ b/src/vitals/web/app.py @@ -7174,6 +7174,11 @@ def get_settings_page_html() -> str: + + + @@ -7631,12 +7636,37 @@ def get_settings_page_html() -> str: document.getElementById('account-role').textContent = user.is_admin ? '管理员账户' : '普通用户'; if (user.is_admin) { document.getElementById('account-badge').style.display = 'block'; + // 显示管理后台入口 + document.getElementById('admin-entry').style.display = 'block'; } // 保存到 localStorage localStorage.setItem('user', JSON.stringify(user)); + } else { + // 如果获取失败,尝试从 localStorage 获取 + const cachedUser = localStorage.getItem('user'); + if (cachedUser) { + const user = JSON.parse(cachedUser); + document.getElementById('account-name').textContent = user.name; + document.getElementById('account-role').textContent = user.is_admin ? '管理员账户' : '普通用户'; + if (user.is_admin) { + document.getElementById('account-badge').style.display = 'block'; + document.getElementById('admin-entry').style.display = 'block'; + } + } } } catch (error) { console.error('加载账户信息失败:', error); + // 尝试从 localStorage 获取 + const cachedUser = localStorage.getItem('user'); + if (cachedUser) { + const user = JSON.parse(cachedUser); + document.getElementById('account-name').textContent = user.name; + document.getElementById('account-role').textContent = user.is_admin ? '管理员账户' : '普通用户'; + if (user.is_admin) { + document.getElementById('account-badge').style.display = 'block'; + document.getElementById('admin-entry').style.display = 'block'; + } + } } }