# router_posts.py # ========================================== # 💬 讨论区路由模块 # ========================================== # 作用:处理讨论区内容的增删改查和互动功能 # 关联文件: # - 数据库连接.py (JSON数据库读写 posts.json) # - models.py (PostCreate, PostUpdate, PostInteraction) # 前端调用: # - 讨论区列表组件.js (获取帖子列表) # - 讨论区发布组件.js (发布新帖子) # - 讨论区详情组件.js (帖子详情、互动操作) # ========================================== from fastapi import APIRouter, HTTPException import 数据库连接 as db from models import PostCreate, PostUpdate, PostInteraction import time import uuid # 创建子路由实例 router = APIRouter() # ========================================== # 📖 获取讨论区列表 # ========================================== @router.get("/api/posts") async def get_posts(sort: str = "time", page: int = 1, page_size: int = 20): """ 获取讨论区帖子列表 查询参数: - sort: 排序方式 (time=最新, hot=最热) - page: 页码 - page_size: 每页数量 """ posts_db = db.load_data("posts.json", default_data=[]) # 排序 if sort == "hot": # 最热:按点赞+收藏加权排序 posts_db.sort(key=lambda x: x.get("likes", 0) * 2 + x.get("favorites", 0), reverse=True) else: # 最新:按创建时间倒序 posts_db.sort(key=lambda x: x.get("createdAt", 0), reverse=True) # 分页 start = (page - 1) * page_size end = start + page_size paginated = posts_db[start:end] return { "status": "success", "data": paginated, "total": len(posts_db), "page": page, "page_size": page_size } # ========================================== # 📖 获取单个帖子详情 # ========================================== @router.get("/api/posts/{post_id}") async def get_post_detail(post_id: str): """ 获取帖子详情 """ posts_db = db.load_data("posts.json", default_data=[]) post = next((p for p in posts_db if p.get("id") == post_id), None) if not post: raise HTTPException(status_code=404, detail="帖子不存在") # 增加浏览量 post["views"] = post.get("views", 0) + 1 db.save_data("posts.json", posts_db) return {"status": "success", "data": post} # ========================================== # ✏️ 发布新帖子 # ========================================== @router.post("/api/posts") async def create_post(post_data: PostCreate): """ 发布新帖子 """ posts_db = db.load_data("posts.json", default_data=[]) users_db = db.load_data("users.json", default_data={}) # 获取作者信息 author_info = users_db.get(post_data.author, {}) # 构建新帖子对象 new_post = { "id": f"post_{uuid.uuid4().hex[:12]}", "type": "discussion", "title": post_data.title, "content": post_data.content, "coverImage": post_data.coverImage, "images": post_data.images or [], # 作者信息快照 "author": post_data.author, "authorName": author_info.get("name", post_data.author), "authorAvatar": author_info.get("avatarDataUrl", ""), # 互动数据初始化 "likes": 0, "favorites": 0, "comments": 0, "views": 0, # 点赞/收藏用户列表(用于判断当前用户是否已操作) "likedBy": [], "favoritedBy": [], # 打赏数据 "tip_board": [], "totalTips": 0, # 时间戳 "createdAt": int(time.time()), "updatedAt": int(time.time()) } posts_db.insert(0, new_post) # 插入到列表头部 db.save_data("posts.json", posts_db) return {"status": "success", "data": new_post} # ========================================== # ✏️ 更新帖子 # ========================================== @router.put("/api/posts/{post_id}") async def update_post(post_id: str, update_data: PostUpdate, author: str = None): """ 更新帖子内容 """ posts_db = db.load_data("posts.json", default_data=[]) post_idx = next((i for i, p in enumerate(posts_db) if p.get("id") == post_id), None) if post_idx is None: raise HTTPException(status_code=404, detail="帖子不存在") post = posts_db[post_idx] # 权限校验:只有作者可以修改 if author and post.get("author") != author: raise HTTPException(status_code=403, detail="无权修改此帖子") # 更新字段 for k, v in update_data.dict(exclude_unset=True).items(): if v is not None: post[k] = v post["updatedAt"] = int(time.time()) db.save_data("posts.json", posts_db) return {"status": "success", "data": post} # ========================================== # 🗑️ 删除帖子 # ========================================== @router.delete("/api/posts/{post_id}") async def delete_post(post_id: str, author: str = None): """ 删除帖子 """ posts_db = db.load_data("posts.json", default_data=[]) post_idx = next((i for i, p in enumerate(posts_db) if p.get("id") == post_id), None) if post_idx is None: raise HTTPException(status_code=404, detail="帖子不存在") post = posts_db[post_idx] # 权限校验 if author and post.get("author") != author: raise HTTPException(status_code=403, detail="无权删除此帖子") posts_db.pop(post_idx) db.save_data("posts.json", posts_db) return {"status": "success", "message": "帖子已删除"} # ========================================== # ❤️ 点赞/收藏操作 # ========================================== @router.post("/api/posts/interaction") async def toggle_interaction(req: PostInteraction): """ 点赞或收藏帖子 请求参数: - post_id: 帖子ID - user_id: 用户账号 - action_type: like / favorite - is_active: True=添加, False=取消 """ posts_db = db.load_data("posts.json", default_data=[]) users_db = db.load_data("users.json", default_data={}) post_idx = next((i for i, p in enumerate(posts_db) if p.get("id") == req.post_id), None) if post_idx is None: raise HTTPException(status_code=404, detail="帖子不存在") post = posts_db[post_idx] if req.action_type == "like": liked_by = post.get("likedBy", []) if req.is_active and req.user_id not in liked_by: liked_by.append(req.user_id) post["likes"] = post.get("likes", 0) + 1 elif not req.is_active and req.user_id in liked_by: liked_by.remove(req.user_id) post["likes"] = max(0, post.get("likes", 0) - 1) post["likedBy"] = liked_by elif req.action_type == "favorite": favorited_by = post.get("favoritedBy", []) if req.is_active and req.user_id not in favorited_by: favorited_by.append(req.user_id) post["favorites"] = post.get("favorites", 0) + 1 # 同步到用户收藏列表 user = users_db.get(req.user_id, {}) user_favs = user.get("favorited_posts", []) if req.post_id not in user_favs: user_favs.append(req.post_id) user["favorited_posts"] = user_favs users_db[req.user_id] = user db.save_data("users.json", users_db) elif not req.is_active and req.user_id in favorited_by: favorited_by.remove(req.user_id) post["favorites"] = max(0, post.get("favorites", 0) - 1) # 从用户收藏列表移除 user = users_db.get(req.user_id, {}) user_favs = user.get("favorited_posts", []) if req.post_id in user_favs: user_favs.remove(req.post_id) user["favorited_posts"] = user_favs users_db[req.user_id] = user db.save_data("users.json", users_db) post["favoritedBy"] = favorited_by db.save_data("posts.json", posts_db) return { "status": "success", "data": { "likes": post.get("likes", 0), "favorites": post.get("favorites", 0), "isLiked": req.user_id in post.get("likedBy", []), "isFavorited": req.user_id in post.get("favoritedBy", []) } } # ========================================== # 📊 获取用户的帖子列表 # ========================================== @router.get("/api/posts/user/{account}") async def get_user_posts(account: str): """ 获取指定用户发布的帖子 """ posts_db = db.load_data("posts.json", default_data=[]) user_posts = [p for p in posts_db if p.get("author") == account] user_posts.sort(key=lambda x: x.get("createdAt", 0), reverse=True) return {"status": "success", "data": user_posts}