fix:批量修复了一些问题

This commit is contained in:
shangfangjian
2026-09-19 22:51:35 +08:00
parent 835d7217d0
commit 8e6ad5394e
44 changed files with 4921 additions and 395 deletions
+108 -4
View File
@@ -4,13 +4,13 @@ from __future__ import annotations
from datetime import datetime, timedelta
from fastapi import APIRouter, Depends, HTTPException, Query
from sqlalchemy import select
from sqlalchemy import or_, select
from sqlalchemy.orm import selectinload
from src.api.deps import require_admin
from src.api.schemas import MatchListOut, MatchOut
from src.api.schemas import MatchListOut, MatchOut, PredictionOut
from src.db.base import AsyncSession, get_db_read
from src.db.models import League, Match
from src.db.models import League, Match, Prediction
router = APIRouter(prefix="/api/v1", tags=["data"])
@@ -114,12 +114,26 @@ async def list_matches(
async def get_match(match_id: int, db: AsyncSession = Depends(get_db_read)):
stmt = (
select(Match)
.options(selectinload(Match.league), selectinload(Match.home_team), selectinload(Match.away_team))
.options(
selectinload(Match.league),
selectinload(Match.home_team),
selectinload(Match.away_team),
selectinload(Match.stats),
)
.where(Match.id == match_id)
)
m = (await db.execute(stmt)).scalar_one_or_none()
if m is None:
raise HTTPException(404, "match not found")
# 最近预测(倒序,最多 5 条)——复用 PredictionOut 结构,只读,不触发 LLM
preds = (
await db.execute(
select(Prediction)
.where(Prediction.match_id == match_id)
.order_by(Prediction.created_at.desc())
.limit(5)
)
).scalars().all()
return MatchOut(
id=m.id,
league_code=m.league.code if m.league else None,
@@ -135,4 +149,94 @@ async def get_match(match_id: int, db: AsyncSession = Depends(get_db_read)):
match_stage=m.match_stage,
home_xg=m.stats.home_xg if m.stats else None,
away_xg=m.stats.away_xg if m.stats else None,
recent_predictions=[
PredictionOut(
id=p.id, match_id=p.match_id, provider=p.provider, model=p.model,
prompt_version=p.prompt_version, mode=p.mode or "single",
pred_home_goals=p.pred_home_goals, pred_away_goals=p.pred_away_goals,
alt_pred_home_goals=p.alt_pred_home_goals, alt_pred_away_goals=p.alt_pred_away_goals,
pred_1x2=p.pred_1x2, subjective_confidence=p.subjective_confidence,
reasoning=p.reasoning, status=p.status or "success",
agent_outputs=p.agent_outputs, agent_weights=p.agent_weights,
created_at=p.created_at, actual_home_goals=p.actual_home_goals,
actual_away_goals=p.actual_away_goals, settled=p.settled,
)
for p in preds
],
)
@router.get("/matches/{match_id}/context", dependencies=[Depends(require_admin)])
async def match_context(match_id: int, db: AsyncSession = Depends(get_db_read)):
"""比赛上下文(只读,不触发 LLM):双方近况 + 历史交锋。
全部基于现有数据聚合:
- recent_home / recent客队:该队最近 5 场已完赛(进球/结果)
- h2h:双方最近 5 次交手
若数据不足,对应列表为空(前端展示空态)。
"""
m = (
await db.execute(
select(Match)
.options(selectinload(Match.home_team), selectinload(Match.away_team))
.where(Match.id == match_id)
)
).scalar_one_or_none()
if m is None:
raise HTTPException(404, "match not found")
home_id = m.home_team_id
away_id = m.away_team_id
def _row_to_dict(row):
return {
"match_date": row.match_date.isoformat() if row.match_date else None,
"home_team": row.home_team.name_zh or row.home_team.name if row.home_team else None,
"away_team": row.away_team.name_zh or row.away_team.name if row.away_team else None,
"home_goals": row.home_goals,
"away_goals": row.away_goals,
}
# 主队近况(已完赛,含主/客场)
home_recent = (
await db.execute(
select(Match)
.where(Match.match_status == "finished", Match.home_team_id == home_id)
.order_by(Match.match_date.desc())
.limit(5)
.options(selectinload(Match.home_team), selectinload(Match.away_team))
)
).scalars().all()
# 客队近况
away_recent = (
await db.execute(
select(Match)
.where(Match.match_status == "finished", Match.away_team_id == away_id)
.order_by(Match.match_date.desc())
.limit(5)
.options(selectinload(Match.home_team), selectinload(Match.away_team))
)
).scalars().all()
# 历史交锋(双方已完赛)
h2h = (
await db.execute(
select(Match)
.where(
Match.match_status == "finished",
or_(
(Match.home_team_id == home_id) & (Match.away_team_id == away_id),
(Match.home_team_id == away_id) & (Match.away_team_id == home_id),
),
)
.order_by(Match.match_date.desc())
.limit(5)
.options(selectinload(Match.home_team), selectinload(Match.away_team))
)
).scalars().all()
return {
"home_recent": [_row_to_dict(r) for r in home_recent],
"away_recent": [_row_to_dict(r) for r in away_recent],
"h2h": [_row_to_dict(r) for r in h2h],
}