Spaces:
Running
Running
File size: 5,185 Bytes
f68778c 515f3e9 2bd6575 515f3e9 f68778c 515f3e9 2bd6575 515f3e9 f68778c | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 | # router_users_profile.py
# ==========================================
# 👤 用户资料路由模块
# ==========================================
# 作用:处理用户资料的获取和更新
# 关联文件:
# - 数据库连接.py (JSON数据库读写 users.json, items.json)
# - models.py (UserUpdate 数据模型)
# - router_users.py (主路由聚合此模块)
# 前端调用:
# - 个人中心视图.js (获取/展示用户资料)
# - 个人设置表单组件.js (更新用户资料)
# ==========================================
from fastapi import APIRouter, HTTPException
import 数据库连接 as db
from models import UserUpdate
# 创建子路由实例
router = APIRouter()
# ==========================================
# 📖 获取用户资料接口
# ==========================================
# 作用:根据账号获取用户的完整资料信息
# 关联:
# - users.json (存储用户基本信息)
# - items.json (统计用户发布的内容获得的互动数据)
# 前端调用:
# - 个人中心视图.js 的 fetchUserProfile()
# - 列表卡片组件.js 显示作者信息时也会调用
@router.get("/api/users/{account}")
async def get_user_profile(account: str):
"""
获取用户资料接口
路径参数:
- account: 用户账号
返回数据:
- 用户基本信息(排除密码)
- receivedLikes: 收到的总点赞数
- receivedFavorites: 收到的总收藏数
- receivedUses: 发布内容被使用的总次数
"""
# 加载用户数据库
users_db = db.load_data("users.json", default_data={})
# 检查用户是否存在
if account not in users_db:
raise HTTPException(status_code=404, detail="用户不存在")
user_data = users_db[account]
# ========== 统计用户作品获得的互动数据 ==========
# 作用:遍历所有内容,统计该用户发布的内容收到的互动
# 关联:items.json 存储所有发布的工具/应用/推荐内容
items_db = db.load_data("items.json", default_data=[])
user_items = [item for item in items_db if item.get("author") == account]
# 累加所有作品的互动数据
user_data["receivedLikes"] = sum(item.get("likes", 0) for item in user_items)
user_data["receivedFavorites"] = sum(item.get("favorites", 0) for item in user_items)
user_data["receivedUses"] = sum(item.get("uses", 0) for item in user_items)
# 🔒 运行时自愈:如果 avatarDataUrl 是 base64,清除它并持久化修复
if (user_data.get("avatarDataUrl") or "").startswith("data:"):
user_data["avatarDataUrl"] = ""
users_db[account] = user_data
db.save_data("users.json", users_db)
# 返回用户数据(排除敏感的密码字段)
return {"status": "success", "data": {k: v for k, v in user_data.items() if k != "password"}}
# ==========================================
# ✏️ 更新用户资料接口
# ==========================================
# 作用:更新用户的个人资料(昵称、头像、简介等)
# 关联:
# - users.json (保存更新后的用户信息)
# - models.py 的 UserUpdate 模型定义可更新的字段
# 前端调用:
# - 个人设置表单组件.js 的 handleSaveProfile()
@router.put("/api/users/{account}")
async def update_user_profile(account: str, update_data: UserUpdate):
"""
更新用户资料接口
路径参数:
- account: 用户账号
请求参数:(UserUpdate 模型,所有字段可选)
- name: 昵称
- intro: 个人介绍(最多100字)
- avatarDataUrl: 头像(Base64格式)
- gender: 性别 (male/female/secret)
- age: 年龄
- country: 国家
- region: 地区
"""
# 加载用户数据库
users_db = db.load_data("users.json", default_data={})
# 检查用户是否存在
if account not in users_db:
raise HTTPException(status_code=404, detail="用户不存在")
# ========== 字段校验 ==========
# 个人介绍长度限制
if update_data.intro and len(update_data.intro) > 100:
raise HTTPException(status_code=400, detail="个人介绍不能超过100个字符")
# ========== 更新用户数据 ==========
user = users_db[account]
# 遍历请求中的字段,只更新非空值
# exclude_unset=True 表示只包含请求中明确传递的字段
update_dict = update_data.dict(exclude_unset=True)
# 🔒 安全防护:拒绝 base64 头像数据,防止 JSON 膨胀
if (update_dict.get("avatarDataUrl") or "").startswith("data:"):
del update_dict["avatarDataUrl"]
for k, v in update_dict.items():
if v is not None:
user[k] = v
# 保存更新后的数据
db.save_data("users.json", users_db)
# 返回更新后的用户数据(排除密码)
return {"status": "success", "data": {k: v for k, v in user.items() if k != "password"}}
|