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''' + + + {icon} + + {label} + + ''' + + # SVG 图标路径 + icons = { + "home": '', + "exercise": '', + "meal": '', + "sleep": '', + "more": '', + } + + admin_link = f'管理' if is_admin else "" + + return f''' + + + + + + + + ''' + + # ===== 认证页面 HTML =====