diff --git a/src/vitals/web/app.py b/src/vitals/web/app.py
index 4990afc..1b54a04 100644
--- a/src/vitals/web/app.py
+++ b/src/vitals/web/app.py
@@ -1702,9 +1702,13 @@ async def search_books(q: str):
@app.get("/api/users", response_model=list[UserResponse])
-async def get_users():
- """获取所有用户"""
- users = db.get_users()
+async def get_users(current_user: User = Depends(require_user)):
+ """获取用户列表(非管理员仅返回自己)"""
+ if current_user.is_admin:
+ users = db.get_users()
+ else:
+ users = [db.get_user(current_user.id)]
+
return [
UserResponse(
id=u.id,
@@ -1718,7 +1722,7 @@ async def get_users():
bmi=u.bmi,
bmi_status=u.bmi_status,
)
- for u in users
+ for u in users if u
]
@@ -1743,8 +1747,11 @@ async def get_active_user():
@app.get("/api/users/{user_id}", response_model=UserResponse)
-async def get_user(user_id: int):
- """获取指定用户"""
+async def get_user(user_id: int, current_user: User = Depends(require_user)):
+ """获取指定用户(非管理员只能查自己)"""
+ if not current_user.is_admin and user_id != current_user.id:
+ raise HTTPException(status_code=403, detail="无权查看其他用户")
+
user = db.get_user(user_id)
if not user:
raise HTTPException(status_code=404, detail="用户不存在")
@@ -1893,6 +1900,201 @@ async def clear_data(request: DataClearInput):
return {"message": "数据已清除"}
+# ===== 移动端 H5 通用样式和组件 =====
+
+
+def get_common_mobile_styles() -> str:
+ """生成移动端通用 CSS 样式"""
+ return """
+/* 移动端基础 */
+* {
+ -webkit-tap-highlight-color: transparent;
+ touch-action: manipulation;
+}
+
+html {
+ font-size: 16px;
+ -webkit-text-size-adjust: 100%;
+}
+
+/* 响应式断点 */
+@media (max-width: 768px) {
+ html { font-size: 14px; }
+
+ .container {
+ padding: 0 16px;
+ max-width: 100%;
+ }
+
+ /* 隐藏桌面导航 */
+ .desktop-nav, .nav { display: none !important; }
+
+ /* 显示移动端底部导航 */
+ .mobile-nav { display: flex !important; }
+
+ /* 内容区域留出底部导航空间 */
+ .main-content, body {
+ padding-bottom: 80px;
+ }
+}
+
+@media (min-width: 769px) {
+ .mobile-nav { display: none !important; }
+ .desktop-nav, .nav { display: flex; }
+}
+
+/* 触摸目标 */
+.touch-target {
+ min-height: 44px;
+ min-width: 44px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+}
+
+/* 安全区域 */
+.safe-area-bottom {
+ padding-bottom: env(safe-area-inset-bottom, 0);
+}
+"""
+
+
+def get_mobile_nav_html(active_page: str = "", is_admin: bool = False) -> str:
+ """生成移动端底部导航栏"""
+
+ def nav_item(href: str, icon: str, label: str, page: str) -> str:
+ active_class = "active" if active_page == page else ""
+ return f'''
+
+
+
+
+ '''
+
+ # SVG 图标路径
+ icons = {
+ "home": '