116 lines
4.9 KiB
Python
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}
|