demand_grade_videos.py 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263
  1. """Resolve demand_grade.video_list → multi_demand_video_detail."""
  2. from __future__ import annotations
  3. import json
  4. from typing import Any
  5. from supply_infra.db.repositories.demand_grade_repo import DemandGradeRepository
  6. from supply_infra.db.repositories.multi_demand_video_detail_repo import (
  7. MultiDemandVideoDetailRepository,
  8. )
  9. from supply_infra.db.session import get_session
  10. def _parse_json_list(raw: str | None) -> list[Any]:
  11. if not raw:
  12. return []
  13. try:
  14. parsed = json.loads(raw)
  15. except json.JSONDecodeError:
  16. return []
  17. return parsed if isinstance(parsed, list) else []
  18. def _parse_video_ids(raw: str | None) -> list[str]:
  19. return [str(v).strip() for v in _parse_json_list(raw) if v is not None and str(v).strip()]
  20. def list_videos_for_demand_grade(demand_grade_id: int) -> dict[str, Any] | None:
  21. """
  22. 按 demand_grade.id 返回关联视频详情。
  23. 顺序与 video_list 一致;详情表缺失的 vid 仍返回,title/三点 JSON 为空。
  24. category_ids 返回该分级需求归属的全部全局树节点 id(可能不止一个)。
  25. """
  26. with get_session() as session:
  27. grade = DemandGradeRepository(session).get_by_id(demand_grade_id)
  28. if grade is None:
  29. return None
  30. vids = _parse_video_ids(grade.video_list)
  31. details = MultiDemandVideoDetailRepository(session).list_by_vids(vids)
  32. videos: list[dict[str, Any]] = []
  33. for vid in vids:
  34. row = details.get(vid)
  35. videos.append(
  36. {
  37. "vid": vid,
  38. "title": row.title if row else None,
  39. "inspiration_points_json": row.inspiration_points_json if row else None,
  40. "purpose_points_json": row.purpose_points_json if row else None,
  41. "key_points_json": row.key_points_json if row else None,
  42. }
  43. )
  44. return {
  45. "demand_grade_id": grade.id,
  46. "demand_name": grade.demand_name,
  47. "category_ids": [int(c) for c in _parse_json_list(grade.category_ids)],
  48. "grade": grade.grade,
  49. "strategies": _parse_json_list(grade.strategies),
  50. "videos": videos,
  51. }