From c586a38b3ae76eab67041e061b9d6ccd7d9ae41f Mon Sep 17 00:00:00 2001 From: shangfangjian Date: Sun, 20 Sep 2026 20:05:40 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E7=A7=AF=E5=88=86=E6=A6=9C"b?= =?UTF-8?q?ody=20stream=20already=20read"=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 两个根因: 1. src/api/routes/standings 端点使用 func.max() 但未导入 func → NameError(500) → 在 matches.py 的 sqlalchemy 导入中加入 func 2. 前端 api.ts 错误处理中先调 res.json() 失败后回退 res text(), 但 Response body 流只能读一次 → "body stream already read" → 改为先 res.text() 再 JSON.parse(),避免重复读取 Co-Authored-By: new-provider/LongCat-2.0 <> --- frontend/src/admin/api.ts | 11 +++++++---- src/api/routes/matches.py | 2 +- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/frontend/src/admin/api.ts b/frontend/src/admin/api.ts index 1bfd8e6..9ab4274 100644 --- a/frontend/src/admin/api.ts +++ b/frontend/src/admin/api.ts @@ -49,14 +49,17 @@ async function request( }) if (!res.ok) { - let detail: unknown + // 先读 text 再尝试 JSON 解析:Response body 流只能读一次, + // 若先调 res.json() 失败(如返回 HTML 错误页),再调 res.text() 会抛 "body stream already read"。 + const rawText = await res.text() + let detail: unknown = rawText try { - detail = await res.json() + detail = JSON.parse(rawText) } catch { - detail = await res.text() + // 非 JSON(如 HTML 错误页),保留原始文本 } let message = - detail && typeof detail === 'object' && 'detail' in detail + detail && typeof detail === 'object' && detail !== null && 'detail' in detail ? String((detail as { detail: unknown }).detail) : `HTTP ${res.status}: ${res.statusText}` // 401 仅在没有显式跳过时广播未登录事件(改密接口的 401 表示当前密码错误,非会话过期) diff --git a/src/api/routes/matches.py b/src/api/routes/matches.py index f2ead70..89e647d 100644 --- a/src/api/routes/matches.py +++ b/src/api/routes/matches.py @@ -4,7 +4,7 @@ from __future__ import annotations from datetime import datetime, timedelta from fastapi import APIRouter, Depends, HTTPException, Query -from sqlalchemy import or_, select +from sqlalchemy import func, or_, select from sqlalchemy.orm import selectinload from src.api.deps import require_admin