From a24017eb69555904d3ab619584f7e6812e746b0d Mon Sep 17 00:00:00 2001 From: WorkBuddy Date: Mon, 21 Sep 2026 20:55:26 +0800 Subject: [PATCH 1/3] =?UTF-8?q?feat(api):=20=E6=AF=94=E8=B5=9B=E4=B8=8A?= =?UTF-8?q?=E4=B8=8B=E6=96=87=E4=B8=8E=E8=81=94=E8=B5=9B=E5=88=97=E8=A1=A8?= =?UTF-8?q?=E6=94=B9=E5=85=AC=E5=BC=80=E5=8F=AA=E8=AF=BB(P1-2/P1-3)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - GET /matches/{id}/context 移除 require_admin:公开站详情页「近况/交锋」 数据来源,匿名 401 会导致前端静默空态;响应结构不变,不触发 LLM - GET /leagues 改公开只读:公开站联赛筛选动态加载;仅返回 id/code/name/country 四个展示字段,不含配置或密钥信息 - 前端新增 useLeagues hook:优先请求 /api/v1/leagues,失败/空回退 本地五大联赛常量(已知代码保留中文标签,新联赛按 API 名称追加) - 新增 tests/test_public_readonly_api.py(6 项):匿名 200/404、响应形状、 路由依赖声明检查(matches 路由无 require_admin)+ 判别力守卫 (ingest 路由必须检出 require_admin,防检测器恒真) --- frontend/src/pages/Matches.tsx | 9 +- .../src/pages/matches/hooks/useLeagues.ts | 38 ++++ src/api/routes/matches.py | 8 +- tests/test_public_readonly_api.py | 163 ++++++++++++++++++ 4 files changed, 211 insertions(+), 7 deletions(-) create mode 100644 frontend/src/pages/matches/hooks/useLeagues.ts create mode 100644 tests/test_public_readonly_api.py diff --git a/frontend/src/pages/Matches.tsx b/frontend/src/pages/Matches.tsx index a34372e..15f2f9f 100644 --- a/frontend/src/pages/Matches.tsx +++ b/frontend/src/pages/Matches.tsx @@ -15,13 +15,16 @@ import { fetchMatchDetail, fetchMatchContext } from '../admin/dal' import type { MatchDetailOut, MatchContextOut } from '../admin/types' import { useMatchesList } from './matches/hooks/useMatchesList' import { useMatchPredict } from './matches/hooks/useMatchPredict' +import { useLeagues } from './matches/hooks/useLeagues' import { PredictModal } from './matches/components/MatchPredictPanel' import { MatchRow } from './matches/components/MatchDetailSection' import { Spinner, SkeletonRows, Switch, formatDateHeader, groupByDate, withinNext3Days } from './matches/ui' -import { LEAGUES, type Match } from './matches/types' +import { type Match } from './matches/types' export default function Matches() { const [error, setError] = useState(null) // 列表与预测共用(拆分前即如此) + // P1-3: 联赛列表优先请求 /api/v1/leagues,失败/空回退本地五大联赛常量 + const leagues = useLeagues() const { league, setLeague, status, setStatus, @@ -58,7 +61,7 @@ export default function Matches() { }, []) const scrollToTop = () => window.scrollTo({ top: 0, behavior: 'smooth' }) - const leagueName = LEAGUES.find(l => l.code === league)?.name ?? league + const leagueName = leagues.find(l => l.code === league)?.name ?? league /** 未开赛默认仅展示未来 3 天;其余状态展示全部。showAllUpcoming=true 时展开全部。 */ const isScheduledView = status === 'scheduled' @@ -91,7 +94,7 @@ export default function Matches() {
{/* ── 联赛版面切换 ── */}