Files
2026-05-12 08:59:02 +08:00

116 lines
4.9 KiB
Python

from fastapi import APIRouter, HTTPException, Depends
from pydantic import BaseModel
from typing import Optional
import auth
import issue_db
router = APIRouter()
class IssueCreate(BaseModel):
title: str
type: str = "bug"
description: str
markdown_sample: str = ""
class ReplyCreate(BaseModel):
content: str
class StatusUpdate(BaseModel):
status: str
# ==================== 用户接口 ====================
@router.post("/api/issues")
def create_issue(data: IssueCreate, current_user: dict = Depends(auth.get_current_user)):
"""用户提交新 Issue"""
if not data.title or not data.title.strip():
raise HTTPException(status_code=400, detail="标题不能为空")
if not data.description or not data.description.strip():
raise HTTPException(status_code=400, detail="描述不能为空")
if data.type not in ("bug", "feature", "other"):
raise HTTPException(status_code=400, detail="类型无效,请选择 bug / feature / other")
new_issue = issue_db.create_issue(
user_id=current_user["id"],
username=current_user["username"],
title=data.title.strip(),
issue_type=data.type,
description=data.description.strip(),
markdown_sample=data.markdown_sample
)
return {"message": "Issue 已提交", "issue": new_issue}
@router.get("/api/issues/my")
def get_my_issues(current_user: dict = Depends(auth.get_current_user)):
"""获取当前用户提交的 Issue 列表"""
issues = issue_db.get_user_issues(current_user["id"])
return {"issues": issues}
@router.get("/api/issues/{issue_id}")
def get_issue_detail(issue_id: int, current_user: dict = Depends(auth.get_current_user)):
"""获取单条 Issue 详情(用户只能查看自己的,admin 可以查看所有)"""
issue = issue_db.get_issue_by_id(issue_id)
if not issue:
raise HTTPException(status_code=404, detail="Issue 不存在")
# 权限校验:只有 Issue 提交者或 admin 可以查看
if issue["user_id"] != current_user["id"] and current_user["username"] != "admin":
raise HTTPException(status_code=403, detail="无权查看此 Issue")
return {"issue": issue}
@router.post("/api/issues/{issue_id}/reply")
def user_reply_issue(issue_id: int, data: ReplyCreate, current_user: dict = Depends(auth.get_current_user)):
"""用户对自己的 Issue 追加回复"""
if not data.content or not data.content.strip():
raise HTTPException(status_code=400, detail="回复内容不能为空")
issue = issue_db.get_issue_by_id(issue_id)
if not issue:
raise HTTPException(status_code=404, detail="Issue 不存在")
if issue["user_id"] != current_user["id"] and current_user["username"] != "admin":
raise HTTPException(status_code=403, detail="无权回复此 Issue")
reply = issue_db.add_reply(issue_id, current_user["username"], data.content.strip())
if not reply:
raise HTTPException(status_code=500, detail="回复失败")
return {"message": "回复成功", "reply": reply}
# ==================== 管理员接口 ====================
@router.get("/api/admin/issues")
def admin_get_all_issues(current_user: dict = Depends(auth.get_current_user)):
"""管理员获取所有 Issue"""
if current_user["username"] != "admin":
raise HTTPException(status_code=403, detail="无权访问,需要管理员权限")
issues = issue_db.get_all_issues()
return {"issues": issues, "total": len(issues)}
@router.post("/api/admin/issues/{issue_id}/reply")
def admin_reply_issue(issue_id: int, data: ReplyCreate, current_user: dict = Depends(auth.get_current_user)):
"""管理员回复 Issue"""
if current_user["username"] != "admin":
raise HTTPException(status_code=403, detail="无权访问")
if not data.content or not data.content.strip():
raise HTTPException(status_code=400, detail="回复内容不能为空")
issue = issue_db.get_issue_by_id(issue_id)
if not issue:
raise HTTPException(status_code=404, detail="Issue 不存在")
reply = issue_db.add_reply(issue_id, "admin", data.content.strip())
if not reply:
raise HTTPException(status_code=500, detail="回复失败")
return {"message": "回复成功", "reply": reply}
@router.put("/api/admin/issues/{issue_id}/status")
def admin_update_status(issue_id: int, data: StatusUpdate, current_user: dict = Depends(auth.get_current_user)):
"""管理员更新 Issue 状态"""
if current_user["username"] != "admin":
raise HTTPException(status_code=403, detail="无权访问")
if data.status not in ("open", "in_progress", "closed"):
raise HTTPException(status_code=400, detail="状态无效,请选择 open / in_progress / closed")
issue = issue_db.update_issue_status(issue_id, data.status)
if not issue:
raise HTTPException(status_code=404, detail="Issue 不存在")
return {"message": "状态更新成功", "issue": issue}