fix: 修复签到成功图片不对的问题
This commit is contained in:
@@ -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
|
||||||
|
|||||||
5
exceptions/unauthorized.py
Normal file
5
exceptions/unauthorized.py
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
# exceptions.py
|
||||||
|
class UnauthorizedError(Exception):
|
||||||
|
def __init__(self, message="登录已失效"):
|
||||||
|
self.message = message
|
||||||
|
super().__init__(message)
|
||||||
@@ -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()
|
||||||
|
|||||||
@@ -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="保存签到数据失败")
|
||||||
|
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user