From 59abda63e38805567086d07909db9e04ed7151aa Mon Sep 17 00:00:00 2001 From: jxxghp Date: Sun, 28 Jun 2026 09:58:11 +0800 Subject: [PATCH] Format season episodes in calendar tags --- src/@core/utils/formatters.ts | 37 ++++++++++++++++++++++++ src/views/subscribe/FullCalendarView.vue | 13 ++++----- 2 files changed, 42 insertions(+), 8 deletions(-) diff --git a/src/@core/utils/formatters.ts b/src/@core/utils/formatters.ts index 05419a61..e64e0499 100644 --- a/src/@core/utils/formatters.ts +++ b/src/@core/utils/formatters.ts @@ -66,6 +66,43 @@ export const prefixWithPlus = (value: number) => (value > 0 ? `+${value}` : valu // 格式化为Sxx export const formatSeason = (value: string) => (value ? `S${value.padStart(2, '0')}` : '') +/** + * 格式化为 SxxExx 季集标识,多个连续集会合并为范围。 + */ +export function formatSeasonEpisode( + season: number | string | null | undefined, + episodeNumbers: number[], +): string { + const seasonText = season === null || season === undefined || season === '' ? '' : formatSeason(String(season)) + const normalizedNumbers = [...new Set(episodeNumbers)] + .map(number => Number(number)) + .filter(number => Number.isFinite(number) && number > 0) + .sort((first, second) => first - second) + + if (!normalizedNumbers.length) return seasonText + + const formatEpisode = (number: number) => `E${String(number).padStart(2, '0')}` + const ranges: string[] = [] + let start = normalizedNumbers[0] + let end = normalizedNumbers[0] + + for (let index = 1; index < normalizedNumbers.length; index++) { + const currentNumber = normalizedNumbers[index] + + if (currentNumber === end + 1) { + end = currentNumber + } else { + ranges.push(start === end ? `${seasonText}${formatEpisode(start)}` : `${seasonText}${formatEpisode(start)}-${formatEpisode(end)}`) + start = currentNumber + end = currentNumber + } + } + + ranges.push(start === end ? `${seasonText}${formatEpisode(start)}` : `${seasonText}${formatEpisode(start)}-${formatEpisode(end)}`) + + return ranges.join('、') +} + // 格式化为xx[TGMK]B export function formatFileSize(bytes: number, decimals = 2, prefix = false) { // 负数标记 diff --git a/src/views/subscribe/FullCalendarView.vue b/src/views/subscribe/FullCalendarView.vue index c346ea55..d5850d36 100644 --- a/src/views/subscribe/FullCalendarView.vue +++ b/src/views/subscribe/FullCalendarView.vue @@ -7,7 +7,7 @@ import FullCalendar from '@fullcalendar/vue3' import type { Ref } from 'vue' import type { MediaInfo, Subscribe, TmdbEpisode } from '@/api/types' import api from '@/api' -import { formatDateDifference, formatEp, parseDate } from '@/@core/utils/formatters' +import { formatDateDifference, formatEp, formatSeasonEpisode, parseDate } from '@/@core/utils/formatters' import { useI18n } from 'vue-i18n' import { useDisplay } from 'vuetify' import { getCurrentLocale } from '@/plugins/i18n' @@ -526,12 +526,9 @@ function getMobileEventSubtitle(event: CalendarEventInfo) { // 获取移动端集季标识。 function getMobileEventEpisodeTag(event: CalendarEventInfo) { if (event.mediaType === '电影') return t('calendar.movie') - if (!event.subtitle && !event.season) return '' + if (!event.episodeNumbers.length && !event.season) return '' - const seasonText = event.season ? `S${event.season}` : '' - const episodeText = event.subtitle ? `E${event.subtitle}` : '' - - return `${seasonText}${episodeText}` + return formatSeasonEpisode(event.season, event.episodeNumbers) } // 获取移动端时长标识。 @@ -829,8 +826,8 @@ onActivated(() => { - - EP {{ calendarEvent.subtitle }} + + {{ getMobileEventEpisodeTag(calendarEvent) }}