182 lines
4.9 KiB
Python
182 lines
4.9 KiB
Python
from datetime import datetime
|
||
import json
|
||
import os
|
||
from pathlib import Path
|
||
from typing import List
|
||
from uuid import uuid4
|
||
from fastapi import (
|
||
APIRouter,
|
||
Depends,
|
||
File,
|
||
Form,
|
||
HTTPException,
|
||
Request,
|
||
UploadFile,
|
||
status,
|
||
)
|
||
from fastapi.responses import HTMLResponse, RedirectResponse
|
||
from starlette.templating import Jinja2Templates
|
||
from services.services import XBXS
|
||
from config import BASE_DIR
|
||
from exceptions.unauthorized import UnauthorizedError
|
||
|
||
router = APIRouter()
|
||
templates = Jinja2Templates(directory=str(BASE_DIR / "templates"))
|
||
|
||
|
||
def get_xbxs(request: Request) -> XBXS:
|
||
token = request.cookies.get("xbxs_token")
|
||
if not token:
|
||
# 没有 token 跳转到登录页面
|
||
raise HTTPException(
|
||
status_code=status.HTTP_303_SEE_OTHER,
|
||
detail="Redirect to login",
|
||
headers={"Location": "/login"},
|
||
)
|
||
return XBXS(token=token)
|
||
|
||
|
||
@router.get("/home")
|
||
async def home(
|
||
request: Request,
|
||
xbxs: XBXS = Depends(get_xbxs),
|
||
):
|
||
|
||
return templates.TemplateResponse(
|
||
"home.html",
|
||
{
|
||
"request": request,
|
||
"active": "home",
|
||
},
|
||
)
|
||
|
||
|
||
@router.get("/profile")
|
||
async def profile(
|
||
request: Request,
|
||
xbxs: XBXS = Depends(get_xbxs),
|
||
):
|
||
try:
|
||
student = await xbxs.get_student_info_cached()
|
||
return templates.TemplateResponse(
|
||
"profile.html",
|
||
{
|
||
"request": request,
|
||
"student": student,
|
||
"active": "profile",
|
||
},
|
||
)
|
||
except UnauthorizedError as e:
|
||
raise HTTPException(
|
||
status_code=401,
|
||
detail=e.message,
|
||
)
|
||
|
||
|
||
@router.get("/sign")
|
||
async def sign_list(
|
||
request: Request,
|
||
xbxs: XBXS = Depends(get_xbxs),
|
||
):
|
||
try:
|
||
result = await xbxs.get_know_list()
|
||
except UnauthorizedError as e:
|
||
raise HTTPException(
|
||
status_code=401,
|
||
detail=e.message,
|
||
)
|
||
|
||
rows = result.get("rows", [])
|
||
|
||
now = datetime.now()
|
||
|
||
for item in rows:
|
||
# 1️⃣ 计算是否结束(核心)
|
||
end_str = f"{item['endDate']} {item['endTime']}"
|
||
end_time = datetime.strptime(end_str, "%Y-%m-%d %H:%M")
|
||
item["isEnded"] = now > end_time
|
||
|
||
return templates.TemplateResponse(
|
||
"sign_list.html",
|
||
{
|
||
"request": request,
|
||
"list": rows,
|
||
"total": result.get("total", 0),
|
||
},
|
||
)
|
||
|
||
|
||
@router.get("/sign/{knowing_id}", response_class=HTMLResponse)
|
||
async def sign_detail(
|
||
knowing_id: int,
|
||
request: Request,
|
||
xbxs: XBXS = Depends(get_xbxs),
|
||
):
|
||
try:
|
||
know_detail = await xbxs.get_know(str(knowing_id))
|
||
except UnauthorizedError as e:
|
||
raise HTTPException(
|
||
status_code=401,
|
||
detail=e.message,
|
||
)
|
||
|
||
data = know_detail.get("data", {})
|
||
# 获取具体的数据
|
||
knowing_name = data.get("knowingName", "未知签到")
|
||
start_date = data.get("startDate", "未知")
|
||
start_time = data.get("startTime", "未知")
|
||
end_time = data.get("endTime", "未知")
|
||
send_name = data.get("sendName", "未知")
|
||
send_role = data.get("sendRole", "未知")
|
||
is_check = data.get("isCheck", 0)
|
||
is_picture = data.get("isPicture", 0)
|
||
# is_finish_know = data.get("isFinishKnowing", 0)
|
||
locations = json.loads(data.get("location", []))
|
||
|
||
return templates.TemplateResponse(
|
||
"sign_detail.html",
|
||
{
|
||
"request": request,
|
||
"know_id": knowing_id,
|
||
"knowing_name": knowing_name,
|
||
"start_date": start_date,
|
||
"start_time": start_time,
|
||
"end_time": end_time,
|
||
"send_name": send_name,
|
||
"send_role": send_role,
|
||
"is_check": is_check,
|
||
"is_picture": is_picture,
|
||
"locations": locations,
|
||
# "is_finish_know": is_finish_know,
|
||
},
|
||
)
|
||
|
||
|
||
# 完善的 sign 完成接口
|
||
@router.post("/sign/{know_id}/complete")
|
||
async def complete_sign(
|
||
know_id: int,
|
||
request: Request,
|
||
location: str = Form(...), # 获取经纬度,必填
|
||
address: str = Form(...), # 获取经纬度,必填
|
||
remark: str = Form(...), # 获取备注,必填
|
||
images: List[UploadFile] = File(...), # 获取上传的图片,支持多张
|
||
xbxs: XBXS = Depends(get_xbxs),
|
||
):
|
||
# 备注必填,未填写时返回错误
|
||
if not remark:
|
||
raise HTTPException(status_code=400, detail="备注是必填项")
|
||
|
||
try:
|
||
await xbxs.update_student_know(str(know_id), remark, address, location, images)
|
||
except UnauthorizedError as e:
|
||
raise HTTPException(
|
||
status_code=401,
|
||
detail=e.message,
|
||
)
|
||
except Exception as e:
|
||
raise HTTPException(status_code=500, detail="保存签到数据失败")
|
||
|
||
# 成功后跳转到签到列表
|
||
return RedirectResponse(url="/sign", status_code=status.HTTP_303_SEE_OTHER)
|