Files
hci_work/backend/app/api/routes_student.py
T
2026-06-06 23:54:11 +08:00

162 lines
6.3 KiB
Python

from __future__ import annotations
from typing import Annotated
from fastapi import APIRouter, Depends, File, HTTPException, UploadFile, status
from app.api.deps import require_student
from app.core.database import get_connection
from app.core.ratelimit import check_diagnosis_rate_limit
from app.core.schemas import (
DiagnosisAnswerRequest,
DiagnosisResponse,
DiagnosisStartRequest,
FeedbackRequest,
OrderCreateRequest,
OrderDetailOut,
OrderSummaryOut,
ReworkRequest,
SavedAddressOut,
UserProfile,
)
from app.services import repository
from app.services.diagnosis import get_diagnosis_provider
router = APIRouter(prefix="/api/student", tags=["student"])
@router.post("/diagnosis/start", response_model=DiagnosisResponse)
async def start_diagnosis(
payload: DiagnosisStartRequest,
_: Annotated[UserProfile, Depends(require_student)],
_rl: None = Depends(check_diagnosis_rate_limit),
) -> DiagnosisResponse:
provider = get_diagnosis_provider()
return await provider.start(payload.message)
@router.post("/diagnosis/answer", response_model=DiagnosisResponse)
async def answer_diagnosis(
payload: DiagnosisAnswerRequest,
_: Annotated[UserProfile, Depends(require_student)],
_rl: None = Depends(check_diagnosis_rate_limit),
) -> DiagnosisResponse:
try:
provider = get_diagnosis_provider()
return await provider.answer(payload.session_id, payload.answers)
except KeyError as error:
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=error.args[0]) from error
@router.get("/addresses", response_model=list[SavedAddressOut])
def list_addresses(user: Annotated[UserProfile, Depends(require_student)]) -> list[dict[str, object]]:
with get_connection() as connection:
return repository.list_addresses(connection, user.id)
@router.delete("/addresses/{address_id}")
def delete_address(address_id: int, user: Annotated[UserProfile, Depends(require_student)]) -> dict[str, str]:
with get_connection() as connection:
if not repository.delete_address(connection, address_id, user.id):
raise HTTPException(status_code=404, detail="地址不存在")
return {"message": "已删除"}
@router.post("/orders")
def create_order(payload: OrderCreateRequest, user: Annotated[UserProfile, Depends(require_student)]) -> dict[str, int]:
with get_connection() as connection:
order_id = repository.create_order(connection, user, payload)
return {"order_id": order_id}
@router.post("/orders/{order_id}/attachments")
def upload_attachments(
order_id: int,
user: Annotated[UserProfile, Depends(require_student)],
files: Annotated[list[UploadFile], File(...)],
) -> dict[str, str]:
with get_connection() as connection:
order = repository.get_order_detail(connection, order_id, student_id=user.id)
if order is None:
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="order_not_found")
for file in files:
try:
repository.save_attachment(connection, order_id, file)
except ValueError as error:
raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=str(error)) from error
return {"status": "ok"}
@router.post("/orders/{order_id}/cancel")
def cancel_order(
order_id: int,
user: Annotated[UserProfile, Depends(require_student)],
) -> dict[str, str]:
with get_connection() as connection:
try:
repository.cancel_order(connection, order_id, user)
except KeyError as error:
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=error.args[0]) from error
except ValueError as error:
raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=error.args[0]) from error
return {"status": "ok"}
@router.get("/orders", response_model=list[OrderSummaryOut])
def list_orders(user: Annotated[UserProfile, Depends(require_student)]) -> list[dict[str, str]]:
with get_connection() as connection:
return repository.list_orders(connection, student_id=user.id)
@router.get("/orders/{order_id}", response_model=OrderDetailOut)
def get_order(order_id: int, user: Annotated[UserProfile, Depends(require_student)]) -> dict[str, str]:
with get_connection() as connection:
detail = repository.get_order_detail(connection, order_id, student_id=user.id)
if detail is None:
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="order_not_found")
return detail
@router.post("/orders/{order_id}/confirm")
def confirm_order(order_id: int, user: Annotated[UserProfile, Depends(require_student)]) -> dict[str, str]:
with get_connection() as connection:
try:
repository.confirm_order(connection, order_id, user)
except KeyError as error:
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=error.args[0]) from error
except ValueError as error:
raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=error.args[0]) from error
return {"status": "ok"}
@router.post("/orders/{order_id}/feedback")
def submit_feedback(
order_id: int,
payload: FeedbackRequest,
user: Annotated[UserProfile, Depends(require_student)],
) -> dict[str, str]:
with get_connection() as connection:
try:
repository.add_feedback(connection, order_id, user, payload)
except KeyError as error:
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=error.args[0]) from error
except ValueError as error:
raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=error.args[0]) from error
return {"status": "ok"}
@router.post("/orders/{order_id}/rework")
def submit_rework(
order_id: int,
payload: ReworkRequest,
user: Annotated[UserProfile, Depends(require_student)],
) -> dict[str, str]:
with get_connection() as connection:
try:
repository.request_rework(connection, order_id, user, payload)
except KeyError as error:
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=error.args[0]) from error
except ValueError as error:
raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=error.args[0]) from error
return {"status": "ok"}