@@ -0,0 +1,115 @@
|
||||
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}
|
||||
Reference in New Issue
Block a user