From 4a14af706c7d707da134e8c050afde2e0c1fe61c Mon Sep 17 00:00:00 2001 From: jxxghp Date: Mon, 10 Aug 2026 20:33:25 +0800 Subject: [PATCH] =?UTF-8?q?feat(dashboard):=20=E5=AA=92=E4=BD=93=E7=BB=9F?= =?UTF-8?q?=E8=AE=A1=E6=96=B0=E5=A2=9E=E9=9F=B3=E4=B9=90=E6=9C=AC=E6=9C=88?= =?UTF-8?q?=E6=96=B0=E5=A2=9E=E6=95=B0=E9=87=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - monthly_media_statistics 纳入音乐整理记录,按曲目计数并按媒体 ID 去重 - Statistic 新增 music_count_month 字段,仪表板统计接口一并返回 --- app/api/endpoints/dashboard.py | 5 ++++- app/db/models/transferhistory.py | 18 ++++++++++++++---- app/schemas/dashboard.py | 2 ++ tests/test_dashboard_system_info.py | 7 ++++++- 4 files changed, 26 insertions(+), 6 deletions(-) diff --git a/app/api/endpoints/dashboard.py b/app/api/endpoints/dashboard.py index a6828aeb2..98e1d8c65 100644 --- a/app/api/endpoints/dashboard.py +++ b/app/api/endpoints/dashboard.py @@ -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 diff --git a/app/db/models/transferhistory.py b/app/db/models/transferhistory.py index 1856151bf..307b35536 100644 --- a/app/db/models/transferhistory.py +++ b/app/db/models/transferhistory.py @@ -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: diff --git a/app/schemas/dashboard.py b/app/schemas/dashboard.py index 7fec0d496..4156bc854 100644 --- a/app/schemas/dashboard.py +++ b/app/schemas/dashboard.py @@ -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): diff --git a/tests/test_dashboard_system_info.py b/tests/test_dashboard_system_info.py index e60fa2fe2..5e59d9e32 100644 --- a/tests/test_dashboard_system_info.py +++ b/tests/test_dashboard_system_info.py @@ -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: