feat(dashboard): 媒体统计新增音乐本月新增数量

- monthly_media_statistics 纳入音乐整理记录,按曲目计数并按媒体 ID 去重
- Statistic 新增 music_count_month 字段,仪表板统计接口一并返回
This commit is contained in:
jxxghp
2026-08-10 20:33:25 +08:00
parent 24a5102aa8
commit 4a14af706c
4 changed files with 26 additions and 6 deletions

View File

@@ -44,10 +44,13 @@ def _build_statistic(db: Session, name: Optional[str] = None) -> schemas.Statist
else:
ret_statistic = schemas.Statistic()
movie_count_month, tv_count_month, episode_count_month = TransferHistory.monthly_media_statistics(db)
movie_count_month, tv_count_month, episode_count_month, music_count_month = (
TransferHistory.monthly_media_statistics(db)
)
ret_statistic.movie_count_month = movie_count_month
ret_statistic.tv_count_month = tv_count_month
ret_statistic.episode_count_month = episode_count_month
ret_statistic.music_count_month = music_count_month
return ret_statistic

View File

@@ -338,22 +338,32 @@ class TransferHistory(Base):
@db_query
def monthly_media_statistics(cls, db: Session):
"""
统计当月成功整理的电影、电视剧剧集数量。
统计当月成功整理的电影、电视剧剧集和音乐数量。
电影和电视剧按媒体身份去重;剧集优先按历史记录中的集数字段计算,
缺少集数时按单条成功整理记录计数。
缺少集数时按单条成功整理记录计数;音乐按曲目计数,识别到媒体 ID 的曲目按 ID 去重
"""
month_prefix = time.strftime("%Y-%m-", time.localtime())
histories = db.query(cls).filter(
cls.status.is_(True),
cls.date.like(f"{month_prefix}%"),
cls.type.in_([MediaType.MOVIE.value, MediaType.TV.value]),
cls.type.in_([MediaType.MOVIE.value, MediaType.TV.value, MediaType.MUSIC.value]),
).all()
movie_identities = set()
tv_identities = set()
episode_count = 0
music_count = 0
music_identities = set()
for history in histories:
if history.type == MediaType.MUSIC.value:
# 有媒体 ID 的曲目按 ID 去重,避免同一首歌多次整理重复计数
if history.media_id:
music_identities.add(history.media_id)
else:
music_count += 1
continue
identity = (history.tmdbid or 0, history.title or "", history.year or "")
if history.type == MediaType.MOVIE.value:
movie_identities.add(identity)
@@ -362,7 +372,7 @@ class TransferHistory(Base):
tv_identities.add(identity)
episode_count += cls._history_episode_count(history)
return len(movie_identities), len(tv_identities), episode_count
return len(movie_identities), len(tv_identities), episode_count, music_count + len(music_identities)
@staticmethod
def _history_episode_count(history: "TransferHistory") -> int:

View File

@@ -24,6 +24,8 @@ class Statistic(BaseModel):
tv_count_month: Optional[int] = 0
# 本月新增剧集数量
episode_count_month: Optional[int] = 0
# 本月新增音乐数量
music_count_month: Optional[int] = 0
class Storage(BaseModel):

View File

@@ -74,13 +74,18 @@ def test_monthly_media_statistics_counts_successful_unique_media():
TransferHistory(status=True, date=f"{month}02 10:00:00", type=MediaType.MOVIE.value, tmdbid=1, title="电影"),
TransferHistory(status=True, date=f"{month}03 10:00:00", type=MediaType.TV.value, tmdbid=2, title="剧集", episodes="E01-E03"),
TransferHistory(status=False, date=f"{month}04 10:00:00", type=MediaType.TV.value, tmdbid=3, title="失败剧集"),
# 同一首歌多次整理只计一首,无媒体 ID 的曲目按记录计数
TransferHistory(status=True, date=f"{month}05 10:00:00", type=MediaType.MUSIC.value, title="晴天", media_id="musicbrainz:r1"),
TransferHistory(status=True, date=f"{month}06 10:00:00", type=MediaType.MUSIC.value, title="晴天", media_id="musicbrainz:r1"),
TransferHistory(status=True, date=f"{month}07 10:00:00", type=MediaType.MUSIC.value, title="未知曲目"),
TransferHistory(status=False, date=f"{month}08 10:00:00", type=MediaType.MUSIC.value, title="失败曲目"),
]
db = SessionFactory()
try:
db.add_all(histories)
db.commit()
assert TransferHistory.monthly_media_statistics(db) == (1, 1, 3)
assert TransferHistory.monthly_media_statistics(db) == (1, 1, 3, 2)
finally:
history_ids = [history.id for history in histories if history.id is not None]
if history_ids: