fix: 修复签到成功图片不对的问题

This commit is contained in:
2025-12-21 20:44:09 +08:00
parent 70bc35cb64
commit 4f62b3d88b
7 changed files with 109 additions and 33 deletions

View File

@@ -4,10 +4,10 @@ from pathlib import Path
load_dotenv() load_dotenv()
DEBUG = True DEBUG = False
BASE_URL = "https://xiaobei.yinghuaonline.com" BASE_URL = "https://xiaobei.yinghuaonline.com"
HTTPX_TIMEOUT = 10 HTTPX_TIMEOUT = 30
DEFAULT_USER_AGENT = "Mozilla/5.0 (iPhone; CPU iPhone OS 16_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 Html5Plus/1.0 (Immersed/20) uni-app" DEFAULT_USER_AGENT = "Mozilla/5.0 (iPhone; CPU iPhone OS 16_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 Html5Plus/1.0 (Immersed/20) uni-app"
BASE_DIR = Path(__file__).resolve().parent BASE_DIR = Path(__file__).resolve().parent

View File

@@ -0,0 +1,5 @@
# exceptions.py
class UnauthorizedError(Exception):
def __init__(self, message="登录已失效"):
self.message = message
super().__init__(message)

View File

@@ -1,12 +1,14 @@
from datetime import datetime from datetime import datetime
from pathlib import Path
from fastapi import APIRouter, Request, Response from fastapi import APIRouter, Request, Response
from fastapi.responses import JSONResponse, RedirectResponse from fastapi.responses import JSONResponse, RedirectResponse
from models import User from models import User
from services.services import XBXS from services.services import XBXS
from starlette.templating import Jinja2Templates from starlette.templating import Jinja2Templates
from config import BASE_DIR
router = APIRouter() router = APIRouter()
templates = Jinja2Templates(directory="templates") templates = Jinja2Templates(directory=str(BASE_DIR / "templates"))
@router.get("/") @router.get("/")
@@ -23,6 +25,20 @@ async def index(request: Request):
) )
@router.get("/logout")
async def logout(request: Request):
token = request.cookies.get("xbxs_token")
if token:
request.cookies.clear()
return templates.TemplateResponse(
"login.html",
{
"request": request,
"year": datetime.now().year,
},
)
@router.post("/login") @router.post("/login")
async def login(user: User, response: Response): async def login(user: User, response: Response):
xbxs = XBXS() xbxs = XBXS()

View File

@@ -1,6 +1,7 @@
from datetime import datetime from datetime import datetime
import json import json
import os import os
from pathlib import Path
from typing import List from typing import List
from uuid import uuid4 from uuid import uuid4
from fastapi import ( from fastapi import (
@@ -16,9 +17,11 @@ from fastapi import (
from fastapi.responses import HTMLResponse, RedirectResponse from fastapi.responses import HTMLResponse, RedirectResponse
from starlette.templating import Jinja2Templates from starlette.templating import Jinja2Templates
from services.services import XBXS from services.services import XBXS
from config import BASE_DIR
from exceptions.unauthorized import UnauthorizedError
router = APIRouter() router = APIRouter()
templates = Jinja2Templates(directory="templates") templates = Jinja2Templates(directory=str(BASE_DIR / "templates"))
def get_xbxs(request: Request) -> XBXS: def get_xbxs(request: Request) -> XBXS:
@@ -53,8 +56,8 @@ async def profile(
request: Request, request: Request,
xbxs: XBXS = Depends(get_xbxs), xbxs: XBXS = Depends(get_xbxs),
): ):
try:
student = await xbxs.get_student_info_cached() student = await xbxs.get_student_info_cached()
return templates.TemplateResponse( return templates.TemplateResponse(
"profile.html", "profile.html",
{ {
@@ -63,6 +66,11 @@ async def profile(
"active": "profile", "active": "profile",
}, },
) )
except UnauthorizedError as e:
raise HTTPException(
status_code=401,
detail=e.message,
)
@router.get("/sign") @router.get("/sign")
@@ -70,7 +78,13 @@ async def sign_list(
request: Request, request: Request,
xbxs: XBXS = Depends(get_xbxs), xbxs: XBXS = Depends(get_xbxs),
): ):
try:
result = await xbxs.get_know_list() result = await xbxs.get_know_list()
except UnauthorizedError as e:
raise HTTPException(
status_code=401,
detail=e.message,
)
rows = result.get("rows", []) rows = result.get("rows", [])
@@ -98,7 +112,13 @@ async def sign_detail(
request: Request, request: Request,
xbxs: XBXS = Depends(get_xbxs), xbxs: XBXS = Depends(get_xbxs),
): ):
try:
know_detail = await xbxs.get_know(str(knowing_id)) 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", {}) data = know_detail.get("data", {})
# 获取具体的数据 # 获取具体的数据
@@ -147,10 +167,13 @@ async def complete_sign(
if not remark: if not remark:
raise HTTPException(status_code=400, detail="备注是必填项") raise HTTPException(status_code=400, detail="备注是必填项")
print(location, remark, know_id, images, address)
try: try:
await xbxs.update_student_know(str(know_id), remark, address, location, images) 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: except Exception as e:
raise HTTPException(status_code=500, detail="保存签到数据失败") raise HTTPException(status_code=500, detail="保存签到数据失败")

View File

@@ -5,6 +5,7 @@ from fastapi import UploadFile
import httpx import httpx
import config import config
from services.student_cache import get_student_by_token, save_student from services.student_cache import get_student_by_token, save_student
from exceptions.unauthorized import UnauthorizedError
SEX_MAP = { SEX_MAP = {
@@ -22,8 +23,18 @@ class XBXS:
self.token = token self.token = token
self.client = httpx.AsyncClient( self.client = httpx.AsyncClient(
trust_env=False,
base_url=config.BASE_URL, base_url=config.BASE_URL,
timeout=config.HTTPX_TIMEOUT, timeout=httpx.Timeout(
connect=10.0,
read=30.0,
write=30.0,
pool=10.0,
),
limits=httpx.Limits(
max_connections=1, # 每个请求使用单独连接,不使用连接池
max_keepalive_connections=1,
),
headers={ headers={
"user-agent": UA, "user-agent": UA,
"accept": "*/*", "accept": "*/*",
@@ -74,6 +85,8 @@ class XBXS:
resp = await self.client.get("/xiaobei-api/getInfo") resp = await self.client.get("/xiaobei-api/getInfo")
resp.raise_for_status() resp.raise_for_status()
result = resp.json() result = resp.json()
if result.get("code") == "401":
raise UnauthorizedError("token 已失效,请重新登录")
return { return {
"userName": result.get("user", {}).get("userName", ""), "userName": result.get("user", {}).get("userName", ""),
"nickName": result.get("user", {}).get("nickName", ""), "nickName": result.get("user", {}).get("nickName", ""),
@@ -92,6 +105,9 @@ class XBXS:
sex = result.get("data", {}).get("studentSex", "") sex = result.get("data", {}).get("studentSex", "")
sex_text = SEX_MAP.get(sex, "未知") sex_text = SEX_MAP.get(sex, "未知")
if result.get("code") == "401":
raise UnauthorizedError("token 已失效,请重新登录")
return { return {
"id": result.get("data", {}).get("id", ""), "id": result.get("data", {}).get("id", ""),
"studentNumber": result.get("data", {}).get("studentNumber", ""), "studentNumber": result.get("data", {}).get("studentNumber", ""),
@@ -114,18 +130,30 @@ class XBXS:
resp = await self.client.get("/xiaobei-api/student/deptId") resp = await self.client.get("/xiaobei-api/student/deptId")
resp.raise_for_status() resp.raise_for_status()
result = resp.json() result = resp.json()
if result.get("code") == "401":
raise UnauthorizedError("token 已失效,请重新登录")
return result return result
async def get_user_sig2(self): async def get_user_sig2(self):
resp = await self.client.get("/xiaobei-api/trtc/genUserSig2") resp = await self.client.get("/xiaobei-api/trtc/genUserSig2")
resp.raise_for_status() resp.raise_for_status()
result = resp.json() result = resp.json()
if result.get("code") == "401":
raise UnauthorizedError("token 已失效,请重新登录")
return result return result
async def get_know_list(self): async def get_know_list(self):
resp = await self.client.get("/xiaobei-api/student/know/list") resp = await self.client.get("/xiaobei-api/student/know/list")
resp.raise_for_status() resp.raise_for_status()
result = resp.json() result = resp.json()
if result.get("code") == "401":
raise UnauthorizedError("token 已失效,请重新登录")
if result.get("total", 0) > 0: if result.get("total", 0) > 0:
pass pass
return result return result
@@ -134,6 +162,10 @@ class XBXS:
resp = await self.client.get(f"/xiaobei-api/student/know/{know}") resp = await self.client.get(f"/xiaobei-api/student/know/{know}")
resp.raise_for_status() resp.raise_for_status()
result = resp.json() result = resp.json()
if result.get("code") == "401":
raise UnauthorizedError("token 已失效,请重新登录")
if result.get("total", 0) > 0: if result.get("total", 0) > 0:
pass pass
return result return result
@@ -146,14 +178,20 @@ class XBXS:
location: str, location: str,
images: List[UploadFile], images: List[UploadFile],
): ):
files = {} files = []
for i, image in enumerate(images): for i, image in enumerate(images):
# 为每个图片生成一个唯一的 UUID 文件名 files.append(
files[f"file{i}"] = ( (
str(uuid4()), # 这里使用 UUID 作为文件名 f"file{i}",
await image.read(), (
"image/jpeg", # 假设是 jpeg 格式,按需修改 f"{uuid4()}.jpg",
image.file,
image.content_type or "image/jpeg",
),
) )
)
resp = await self.client.post( resp = await self.client.post(
"/xiaobei-api/student/know/updateStudentKnow", "/xiaobei-api/student/know/updateStudentKnow",
data={ data={
@@ -161,7 +199,6 @@ class XBXS:
"remark": remark, "remark": remark,
"knowingId": knowingID, "knowingId": knowingID,
"location": location, "location": location,
# "location": "106.5346788194445:29.343291015625",
"size": len(images), "size": len(images),
}, },
files=files, files=files,

View File

@@ -1,9 +1,7 @@
import time import time
import json import json
import sqlite3 import sqlite3
from config import DB_PATH
DB_PATH = "data.db"
def get_student_by_token(token: str): def get_student_by_token(token: str):
conn = sqlite3.connect(DB_PATH) conn = sqlite3.connect(DB_PATH)

View File

@@ -53,8 +53,6 @@
</div> </div>
</div> </div>
<!-- 签到表单 -->
{% if is_finish_know == 0 and is_check == 0 %}
<form method="POST" action="/sign/{{ know_id }}/complete" enctype="multipart/form-data" <form method="POST" action="/sign/{{ know_id }}/complete" enctype="multipart/form-data"
class="space-y-4 border rounded-lg p-4 bg-zinc-50"> class="space-y-4 border rounded-lg p-4 bg-zinc-50">
@@ -109,7 +107,7 @@
</div> </div>
<!-- 图片上传 --> <!-- 图片上传 -->
{% if is_picture == 1 %} {% if is_picture == 0 %}
<div> <div>
<label class="block text-sm font-medium text-zinc-700 mb-1"> <label class="block text-sm font-medium text-zinc-700 mb-1">
上传图片(可多张) 上传图片(可多张)
@@ -123,7 +121,6 @@
完成签到 完成签到
</button> </button>
</form> </form>
{% endif %}
</div> </div>