mirror of
https://github.com/jxxghp/MoviePilot-Frontend.git
synced 2026-07-12 16:01:35 +08:00
feat: 添加剧集组功能,支持自动查询和手动输入剧集组编号
This commit is contained in:
@@ -150,6 +150,15 @@ let previewFileBodyResizeObserver: ResizeObserver | undefined
|
||||
// 所有存储
|
||||
const storages = ref<StorageConf[]>([])
|
||||
|
||||
// 所有剧集组
|
||||
const episodeGroups = ref<{ [key: string]: any }[]>([])
|
||||
|
||||
// 剧集组加载状态
|
||||
const episodeGroupLoading = ref(false)
|
||||
|
||||
// 剧集组查询防抖句柄
|
||||
let episodeGroupQueryTimer: ReturnType<typeof setTimeout> | undefined
|
||||
|
||||
// 查询存储
|
||||
async function loadStorages() {
|
||||
try {
|
||||
@@ -169,6 +178,57 @@ const storageOptions = computed(() => {
|
||||
}))
|
||||
})
|
||||
|
||||
// 剧集组选项属性
|
||||
function episodeGroupItemProps(item: { title: string; subtitle?: string }) {
|
||||
return {
|
||||
title: item.title,
|
||||
subtitle: item.subtitle,
|
||||
}
|
||||
}
|
||||
|
||||
// 剧集组选项,保留空值作为不指定剧集组。
|
||||
const episodeGroupOptions = computed(() => {
|
||||
const options = (
|
||||
episodeGroups.value as { id: string; name: string; group_count: number; episode_count: number }[]
|
||||
).map(item => {
|
||||
return {
|
||||
title: item.name,
|
||||
subtitle: `${t('dialog.reorganize.seasonCount', { count: item.group_count })} • ${t(
|
||||
'dialog.reorganize.episodeCount',
|
||||
{ count: item.episode_count },
|
||||
)}`,
|
||||
value: item.id,
|
||||
}
|
||||
})
|
||||
|
||||
options.unshift({
|
||||
title: t('dialog.reorganize.defaultEpisodeGroup'),
|
||||
subtitle: t('dialog.reorganize.defaultEpisodeGroupHint'),
|
||||
value: '',
|
||||
})
|
||||
|
||||
return options
|
||||
})
|
||||
|
||||
// 查询指定 TMDB 剧集的所有剧集组。
|
||||
async function getEpisodeGroups(tmdbid?: number | string) {
|
||||
const normalizedTmdbId = Number(tmdbid)
|
||||
if (!Number.isInteger(normalizedTmdbId) || normalizedTmdbId <= 0) {
|
||||
episodeGroups.value = []
|
||||
return
|
||||
}
|
||||
|
||||
episodeGroupLoading.value = true
|
||||
try {
|
||||
episodeGroups.value = await api.get(`media/groups/${normalizedTmdbId}`)
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
episodeGroups.value = []
|
||||
} finally {
|
||||
episodeGroupLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
// 标题
|
||||
const dialogTitle = computed(() => {
|
||||
return t('dialog.reorganize.manualTitle')
|
||||
@@ -252,6 +312,31 @@ watch(
|
||||
},
|
||||
)
|
||||
|
||||
// 监听 TMDB 编号变化,自动加载可用剧集组并清空旧选择。
|
||||
watch(
|
||||
() => transferForm.tmdbid,
|
||||
tmdbid => {
|
||||
transferForm.episode_group = ''
|
||||
episodeGroups.value = []
|
||||
if (episodeGroupQueryTimer) clearTimeout(episodeGroupQueryTimer)
|
||||
if (transferForm.type_name !== '电视剧' || mediaSource.value !== 'themoviedb') return
|
||||
episodeGroupQueryTimer = setTimeout(() => getEpisodeGroups(tmdbid), 400)
|
||||
},
|
||||
)
|
||||
|
||||
// 切换媒体类型或识别源时,非 TMDB 电视剧不保留剧集组选择。
|
||||
watch(
|
||||
[() => transferForm.type_name, () => mediaSource.value],
|
||||
([typeName, source]) => {
|
||||
if (typeName === '电视剧' && source === 'themoviedb' && transferForm.tmdbid) {
|
||||
getEpisodeGroups(transferForm.tmdbid)
|
||||
return
|
||||
}
|
||||
transferForm.episode_group = ''
|
||||
episodeGroups.value = []
|
||||
},
|
||||
)
|
||||
|
||||
// 过滤后的预览数据
|
||||
const filteredPreviewItems = computed(() => {
|
||||
return previewData.value?.items ?? []
|
||||
@@ -528,6 +613,7 @@ function createTransferPayload(options: { item?: FileItem; items?: FileItem[]; l
|
||||
...transferForm,
|
||||
fileitem: sourceItem,
|
||||
logid: options.logid ?? 0,
|
||||
episode_group: transferForm.episode_group?.trim() || undefined,
|
||||
}
|
||||
|
||||
if (options.items?.length) {
|
||||
@@ -1014,6 +1100,7 @@ onMounted(() => {
|
||||
|
||||
onUnmounted(() => {
|
||||
stopLoadingProgress()
|
||||
if (episodeGroupQueryTimer) clearTimeout(episodeGroupQueryTimer)
|
||||
previewFileBodyResizeObserver?.disconnect()
|
||||
})
|
||||
</script>
|
||||
@@ -1123,9 +1210,14 @@ onUnmounted(() => {
|
||||
</VCol>
|
||||
</VRow>
|
||||
<VRow v-show="transferForm.type_name === '电视剧'">
|
||||
<VCol cols="12" md="6">
|
||||
<VTextField
|
||||
<VCol v-if="mediaSource === 'themoviedb'" cols="12" md="6">
|
||||
<VCombobox
|
||||
v-model="transferForm.episode_group"
|
||||
:items="episodeGroupOptions"
|
||||
:item-props="episodeGroupItemProps"
|
||||
:loading="episodeGroupLoading"
|
||||
:disabled="!transferForm.tmdbid"
|
||||
clearable
|
||||
:label="t('dialog.reorganize.episodeGroup')"
|
||||
:placeholder="t('dialog.reorganize.episodeGroupPlaceholder')"
|
||||
:hint="t('dialog.reorganize.episodeGroupHint')"
|
||||
|
||||
Reference in New Issue
Block a user