mirror of
https://github.com/truewhile/MeBox.git
synced 2026-10-09 06:46:37 +08:00
优化排序
This commit is contained in:
@@ -3,7 +3,7 @@ import { Check, Film, ListVideo, Play, Search, X } from 'lucide-react'
|
|||||||
|
|
||||||
import { imageURL } from '../api/client'
|
import { imageURL } from '../api/client'
|
||||||
import type { Media } from '../types'
|
import type { Media } from '../types'
|
||||||
import { seriesTitleFromPath } from '../utils/groupSeries'
|
import { seasonLabel, seasonSortOrder, seriesTitleFromPath } from '../utils/groupSeries'
|
||||||
|
|
||||||
export type SeasonGroup = {
|
export type SeasonGroup = {
|
||||||
season: number
|
season: number
|
||||||
@@ -42,7 +42,7 @@ export function PlayerPlaylistPanel({
|
|||||||
list.sort((a, b) => (a.episode_num || 0) - (b.episode_num || 0))
|
list.sort((a, b) => (a.episode_num || 0) - (b.episode_num || 0))
|
||||||
}
|
}
|
||||||
return Array.from(seasonsMap.entries())
|
return Array.from(seasonsMap.entries())
|
||||||
.sort(([a], [b]) => a - b)
|
.sort(([a], [b]) => seasonSortOrder(a) - seasonSortOrder(b))
|
||||||
.map(([season, list]) => ({ season, episodes: list }))
|
.map(([season, list]) => ({ season, episodes: list }))
|
||||||
}, [episodes])
|
}, [episodes])
|
||||||
|
|
||||||
@@ -128,7 +128,7 @@ export function PlayerPlaylistPanel({
|
|||||||
: 'bg-white/5 text-white/70 hover:bg-white/10 hover:text-white'
|
: 'bg-white/5 text-white/70 hover:bg-white/10 hover:text-white'
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
<span>{season === 0 ? '特别篇' : `第 ${season} 季`}</span>
|
<span>{seasonLabel(season)}</span>
|
||||||
<span className="text-[10px] opacity-75">({sesEps.length})</span>
|
<span className="text-[10px] opacity-75">({sesEps.length})</span>
|
||||||
{isPlayingThisSeason && !isSelected && (
|
{isPlayingThisSeason && !isSelected && (
|
||||||
<span className="h-1.5 w-1.5 rounded-full bg-rose-400" />
|
<span className="h-1.5 w-1.5 rounded-full bg-rose-400" />
|
||||||
|
|||||||
@@ -5,17 +5,8 @@ import { imageURL } from '../api/client'
|
|||||||
import { ExternalPlayerButton } from '../components/ExternalPlayerButton'
|
import { ExternalPlayerButton } from '../components/ExternalPlayerButton'
|
||||||
import type { Media } from '../types'
|
import type { Media } from '../types'
|
||||||
import {
|
import {
|
||||||
BONUS_SEASON,
|
|
||||||
EXTRA_SEASON,
|
|
||||||
isTheatricalFeature,
|
isTheatricalFeature,
|
||||||
NCED_SEASON,
|
seasonLabel,
|
||||||
NCOP_SEASON,
|
|
||||||
OAD_SEASON,
|
|
||||||
OMAKE_SEASON,
|
|
||||||
ONA_SEASON,
|
|
||||||
OVA_SEASON,
|
|
||||||
OVD_SEASON,
|
|
||||||
PICTURE_DRAMA_SEASON,
|
|
||||||
seriesTitleFromPath,
|
seriesTitleFromPath,
|
||||||
THEATRICAL_SEASON,
|
THEATRICAL_SEASON,
|
||||||
} from '../utils/groupSeries'
|
} from '../utils/groupSeries'
|
||||||
@@ -148,24 +139,6 @@ export function LibrarySeriesEpisodes({
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
function seasonLabel(season: number): string {
|
|
||||||
switch (season) {
|
|
||||||
case 0: return '特别篇'
|
|
||||||
case THEATRICAL_SEASON: return '剧场版'
|
|
||||||
case OVA_SEASON: return 'OVA'
|
|
||||||
case OAD_SEASON: return 'OAD'
|
|
||||||
case OVD_SEASON: return 'OVD'
|
|
||||||
case ONA_SEASON: return 'ONA'
|
|
||||||
case EXTRA_SEASON: return 'Extra'
|
|
||||||
case BONUS_SEASON: return 'Bonus'
|
|
||||||
case OMAKE_SEASON: return 'Omake'
|
|
||||||
case PICTURE_DRAMA_SEASON: return 'Picture Drama'
|
|
||||||
case NCOP_SEASON: return 'NCOP'
|
|
||||||
case NCED_SEASON: return 'NCED'
|
|
||||||
default: return `第 ${season} 季`
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function episodeDisplayTitle(ep: Media, siblings: Media[]): string {
|
function episodeDisplayTitle(ep: Media, siblings: Media[]): string {
|
||||||
let mainTitle = ''
|
let mainTitle = ''
|
||||||
const epTitle = ep.episode_title?.trim()
|
const epTitle = ep.episode_title?.trim()
|
||||||
|
|||||||
@@ -2,20 +2,10 @@ import { useEffect, useMemo } from 'react'
|
|||||||
|
|
||||||
import type { Media } from '../types'
|
import type { Media } from '../types'
|
||||||
import {
|
import {
|
||||||
BONUS_SEASON,
|
|
||||||
EXTRA_SEASON,
|
|
||||||
getSeriesKey,
|
getSeriesKey,
|
||||||
isTheatricalFeature,
|
isTheatricalFeature,
|
||||||
NCED_SEASON,
|
seasonSortOrder,
|
||||||
NCOP_SEASON,
|
|
||||||
OAD_SEASON,
|
|
||||||
OMAKE_SEASON,
|
|
||||||
ONA_SEASON,
|
|
||||||
OVA_SEASON,
|
|
||||||
OVD_SEASON,
|
|
||||||
PICTURE_DRAMA_SEASON,
|
|
||||||
specialSectionForMedia,
|
specialSectionForMedia,
|
||||||
THEATRICAL_SEASON,
|
|
||||||
type SeriesCard,
|
type SeriesCard,
|
||||||
} from '../utils/groupSeries'
|
} from '../utils/groupSeries'
|
||||||
|
|
||||||
@@ -146,21 +136,3 @@ export function useLibrarySeriesSelection({
|
|||||||
clearSelectedSeries,
|
clearSelectedSeries,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function seasonSortOrder(season: number): number {
|
|
||||||
switch (season) {
|
|
||||||
case 0: return 0
|
|
||||||
case OVA_SEASON: return 1
|
|
||||||
case OAD_SEASON: return 2
|
|
||||||
case OVD_SEASON: return 3
|
|
||||||
case ONA_SEASON: return 4
|
|
||||||
case EXTRA_SEASON: return 5
|
|
||||||
case BONUS_SEASON: return 6
|
|
||||||
case OMAKE_SEASON: return 7
|
|
||||||
case PICTURE_DRAMA_SEASON: return 8
|
|
||||||
case NCOP_SEASON: return 9
|
|
||||||
case NCED_SEASON: return 10
|
|
||||||
case THEATRICAL_SEASON: return 11
|
|
||||||
default: return 100 + season
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import { playbackAPI } from '../api/playback'
|
|||||||
import { confirmActionResult } from '../components/confirmAction'
|
import { confirmActionResult } from '../components/confirmAction'
|
||||||
import { useEpisodeArtworkPreference } from '../hooks/useEpisodeArtworkPreference'
|
import { useEpisodeArtworkPreference } from '../hooks/useEpisodeArtworkPreference'
|
||||||
import type { Media } from '../types'
|
import type { Media } from '../types'
|
||||||
|
import { seasonSortOrder } from '../utils/groupSeries'
|
||||||
import { mediaLibraryBackTarget } from './MediaDetailPageModel'
|
import { mediaLibraryBackTarget } from './MediaDetailPageModel'
|
||||||
|
|
||||||
interface MediaDetailPageStateParams {
|
interface MediaDetailPageStateParams {
|
||||||
@@ -77,7 +78,7 @@ export function useMediaDetailPageState({ id, navigate }: MediaDetailPageStatePa
|
|||||||
list.sort((a, b) => (a.episode_num || 0) - (b.episode_num || 0))
|
list.sort((a, b) => (a.episode_num || 0) - (b.episode_num || 0))
|
||||||
}
|
}
|
||||||
return Array.from(seasons.entries())
|
return Array.from(seasons.entries())
|
||||||
.sort(([a], [b]) => a - b)
|
.sort(([a], [b]) => seasonSortOrder(a) - seasonSortOrder(b))
|
||||||
.map(([season, list]) => ({ season, episodes: list }))
|
.map(([season, list]) => ({ season, episodes: list }))
|
||||||
}, [episodes])
|
}, [episodes])
|
||||||
|
|
||||||
|
|||||||
@@ -151,6 +151,49 @@ export function specialSectionForMedia(media: Media): number | null {
|
|||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 季按钮显示顺序:第一季、第二季 … 第 XX 季 → 特别篇 → 剧场版 → OVA → OAD → 其余特典。
|
||||||
|
*
|
||||||
|
* 正片季(季号 > 0)按季号升序排最前;特殊分区(0 / 负数季)按固定优先级排在后面。
|
||||||
|
* 各季分组页(剧集库 / 详情页 / 播放器选集)共用这一顺序,避免三处各排各的。
|
||||||
|
*/
|
||||||
|
export function seasonSortOrder(season: number): number {
|
||||||
|
if (season > 0) return season
|
||||||
|
switch (season) {
|
||||||
|
case 0: return 1000 // 特别篇紧随正片
|
||||||
|
case THEATRICAL_SEASON: return 1001 // 剧场版
|
||||||
|
case OVA_SEASON: return 1002
|
||||||
|
case OAD_SEASON: return 1003
|
||||||
|
case OVD_SEASON: return 1004
|
||||||
|
case ONA_SEASON: return 1005
|
||||||
|
case EXTRA_SEASON: return 1006
|
||||||
|
case BONUS_SEASON: return 1007
|
||||||
|
case OMAKE_SEASON: return 1008
|
||||||
|
case PICTURE_DRAMA_SEASON: return 1009
|
||||||
|
case NCOP_SEASON: return 1010
|
||||||
|
case NCED_SEASON: return 1011
|
||||||
|
default: return 2000 // 未知季兜底,排最后
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function seasonLabel(season: number): string {
|
||||||
|
switch (season) {
|
||||||
|
case 0: return '特别篇'
|
||||||
|
case THEATRICAL_SEASON: return '剧场版'
|
||||||
|
case OVA_SEASON: return 'OVA'
|
||||||
|
case OAD_SEASON: return 'OAD'
|
||||||
|
case OVD_SEASON: return 'OVD'
|
||||||
|
case ONA_SEASON: return 'ONA'
|
||||||
|
case EXTRA_SEASON: return 'Extra'
|
||||||
|
case BONUS_SEASON: return 'Bonus'
|
||||||
|
case OMAKE_SEASON: return 'Omake'
|
||||||
|
case PICTURE_DRAMA_SEASON: return 'Picture Drama'
|
||||||
|
case NCOP_SEASON: return 'NCOP'
|
||||||
|
case NCED_SEASON: return 'NCED'
|
||||||
|
default: return `第 ${season} 季`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export function isSeriesCard(card: SeriesCard): boolean {
|
export function isSeriesCard(card: SeriesCard): boolean {
|
||||||
return (
|
return (
|
||||||
card.count > 1 ||
|
card.count > 1 ||
|
||||||
|
|||||||
Reference in New Issue
Block a user