mirror of
https://github.com/jxxghp/MoviePilot-Frontend.git
synced 2026-09-06 08:06:43 +08:00
feat: Add subscribe filtering and localization
Co-authored-by: jxxghp <jxxghp@qq.com>
This commit is contained in:
@@ -872,6 +872,7 @@ export default {
|
|||||||
batchEnableError: 'Batch enable operation failed',
|
batchEnableError: 'Batch enable operation failed',
|
||||||
batchPauseError: 'Batch pause operation failed',
|
batchPauseError: 'Batch pause operation failed',
|
||||||
batchDeleteError: 'Batch delete operation failed',
|
batchDeleteError: 'Batch delete operation failed',
|
||||||
|
minSubscribers: 'Min Subscribers',
|
||||||
},
|
},
|
||||||
recommend: {
|
recommend: {
|
||||||
all: 'All',
|
all: 'All',
|
||||||
|
|||||||
@@ -869,6 +869,7 @@ export default {
|
|||||||
batchEnableError: '批量启用操作失败',
|
batchEnableError: '批量启用操作失败',
|
||||||
batchPauseError: '批量暂停操作失败',
|
batchPauseError: '批量暂停操作失败',
|
||||||
batchDeleteError: '批量删除操作失败',
|
batchDeleteError: '批量删除操作失败',
|
||||||
|
minSubscribers: '最小订阅人数',
|
||||||
},
|
},
|
||||||
recommend: {
|
recommend: {
|
||||||
all: '全部',
|
all: '全部',
|
||||||
|
|||||||
@@ -34,13 +34,96 @@ const isRefreshed = ref(false)
|
|||||||
const dataList = ref<MediaInfo[]>([])
|
const dataList = ref<MediaInfo[]>([])
|
||||||
const currData = ref<MediaInfo[]>([])
|
const currData = ref<MediaInfo[]>([])
|
||||||
|
|
||||||
|
// 筛选参数
|
||||||
|
const filterParams = reactive({
|
||||||
|
genre_id: '',
|
||||||
|
min_rating: 0,
|
||||||
|
max_rating: 10,
|
||||||
|
min_sub: 1,
|
||||||
|
})
|
||||||
|
|
||||||
|
// 当前Key(用于重新加载数据)
|
||||||
|
const currentKey = ref(0)
|
||||||
|
|
||||||
|
// TMDB电影风格字典
|
||||||
|
const tmdbMovieGenreDict: Record<string, string> = {
|
||||||
|
'28': t('tmdb.genreType.action'),
|
||||||
|
'12': t('tmdb.genreType.adventure'),
|
||||||
|
'16': t('tmdb.genreType.animation'),
|
||||||
|
'35': t('tmdb.genreType.comedy'),
|
||||||
|
'80': t('tmdb.genreType.crime'),
|
||||||
|
'99': t('tmdb.genreType.documentary'),
|
||||||
|
'18': t('tmdb.genreType.drama'),
|
||||||
|
'10751': t('tmdb.genreType.family'),
|
||||||
|
'14': t('tmdb.genreType.fantasy'),
|
||||||
|
'36': t('tmdb.genreType.history'),
|
||||||
|
'27': t('tmdb.genreType.horror'),
|
||||||
|
'10402': t('tmdb.genreType.music'),
|
||||||
|
'9648': t('tmdb.genreType.mystery'),
|
||||||
|
'10749': t('tmdb.genreType.romance'),
|
||||||
|
'878': t('tmdb.genreType.scienceFiction'),
|
||||||
|
'10770': t('tmdb.genreType.tvMovie'),
|
||||||
|
'53': t('tmdb.genreType.thriller'),
|
||||||
|
'10752': t('tmdb.genreType.war'),
|
||||||
|
'37': t('tmdb.genreType.western'),
|
||||||
|
}
|
||||||
|
|
||||||
|
// TMDB电视剧风格字典
|
||||||
|
const tmdbTvGenreDict: Record<string, string> = {
|
||||||
|
'10759': t('tmdb.genreType.actionAdventure'),
|
||||||
|
'16': t('tmdb.genreType.animation'),
|
||||||
|
'35': t('tmdb.genreType.comedy'),
|
||||||
|
'80': t('tmdb.genreType.crime'),
|
||||||
|
'99': t('tmdb.genreType.documentary'),
|
||||||
|
'18': t('tmdb.genreType.drama'),
|
||||||
|
'10751': t('tmdb.genreType.family'),
|
||||||
|
'10762': t('tmdb.genreType.kids'),
|
||||||
|
'9648': t('tmdb.genreType.mystery'),
|
||||||
|
'10763': t('tmdb.genreType.news'),
|
||||||
|
'10764': t('tmdb.genreType.reality'),
|
||||||
|
'10765': t('tmdb.genreType.sciFiFantasy'),
|
||||||
|
'10766': t('tmdb.genreType.soap'),
|
||||||
|
'10767': t('tmdb.genreType.talk'),
|
||||||
|
'10768': t('tmdb.genreType.warPolitics'),
|
||||||
|
'37': t('tmdb.genreType.western'),
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取当前类型对应的风格字典
|
||||||
|
const currentGenreDict = computed(() => {
|
||||||
|
return props.type === '电影' ? tmdbMovieGenreDict : tmdbTvGenreDict
|
||||||
|
})
|
||||||
|
|
||||||
|
// 监听筛选参数变化
|
||||||
|
watch(filterParams, () => {
|
||||||
|
// 重置数据
|
||||||
|
dataList.value = []
|
||||||
|
page.value = 1
|
||||||
|
isRefreshed.value = false
|
||||||
|
currentKey.value++
|
||||||
|
}, { deep: true })
|
||||||
|
|
||||||
// 拼装参数
|
// 拼装参数
|
||||||
function getParams() {
|
function getParams() {
|
||||||
let params = {
|
let params: { [key: string]: any } = {
|
||||||
stype: props.type,
|
stype: props.type,
|
||||||
page: page.value,
|
page: page.value,
|
||||||
count: 30,
|
count: 30,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 添加筛选参数
|
||||||
|
if (filterParams.genre_id) {
|
||||||
|
params.genre_id = parseInt(filterParams.genre_id)
|
||||||
|
}
|
||||||
|
if (filterParams.min_rating > 0) {
|
||||||
|
params.min_rating = filterParams.min_rating
|
||||||
|
}
|
||||||
|
if (filterParams.max_rating < 10) {
|
||||||
|
params.max_rating = filterParams.max_rating
|
||||||
|
}
|
||||||
|
if (filterParams.min_sub > 1) {
|
||||||
|
params.min_sub = filterParams.min_sub
|
||||||
|
}
|
||||||
|
|
||||||
return params
|
return params
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -110,8 +193,78 @@ async function fetchData({ done }: { done: any }) {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
<!-- 筛选器 -->
|
||||||
|
<div class="px-3 mb-4">
|
||||||
|
<div class="flex justify-start align-center mb-3">
|
||||||
|
<div class="mr-5">
|
||||||
|
<VLabel>{{ t('tmdb.genre') }}</VLabel>
|
||||||
|
</div>
|
||||||
|
<VChipGroup v-model="filterParams.genre_id">
|
||||||
|
<VChip
|
||||||
|
:color="filterParams.genre_id == key ? 'primary' : ''"
|
||||||
|
filter
|
||||||
|
tile
|
||||||
|
:value="key"
|
||||||
|
v-for="(value, key) in currentGenreDict"
|
||||||
|
:key="key"
|
||||||
|
>
|
||||||
|
{{ value }}
|
||||||
|
</VChip>
|
||||||
|
</VChipGroup>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="flex justify-start align-center mb-3">
|
||||||
|
<div class="mr-5">
|
||||||
|
<VLabel>{{ t('tmdb.rating') }}</VLabel>
|
||||||
|
</div>
|
||||||
|
<div class="flex align-center" style="width: 300px;">
|
||||||
|
<VTextField
|
||||||
|
v-model="filterParams.min_rating"
|
||||||
|
variant="outlined"
|
||||||
|
density="compact"
|
||||||
|
type="number"
|
||||||
|
hide-details
|
||||||
|
single-line
|
||||||
|
min="0"
|
||||||
|
max="10"
|
||||||
|
step="0.1"
|
||||||
|
style="width: 80px;"
|
||||||
|
/>
|
||||||
|
<span class="mx-2">-</span>
|
||||||
|
<VTextField
|
||||||
|
v-model="filterParams.max_rating"
|
||||||
|
variant="outlined"
|
||||||
|
density="compact"
|
||||||
|
type="number"
|
||||||
|
hide-details
|
||||||
|
single-line
|
||||||
|
min="0"
|
||||||
|
max="10"
|
||||||
|
step="0.1"
|
||||||
|
style="width: 80px;"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="flex justify-start align-center">
|
||||||
|
<div class="mr-5">
|
||||||
|
<VLabel>{{ t('subscribe.minSubscribers') }}</VLabel>
|
||||||
|
</div>
|
||||||
|
<VTextField
|
||||||
|
v-model="filterParams.min_sub"
|
||||||
|
variant="outlined"
|
||||||
|
density="compact"
|
||||||
|
type="number"
|
||||||
|
hide-details
|
||||||
|
single-line
|
||||||
|
min="1"
|
||||||
|
style="width: 120px;"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<LoadingBanner v-if="!isRefreshed" class="mt-12" />
|
<LoadingBanner v-if="!isRefreshed" class="mt-12" />
|
||||||
<VInfiniteScroll mode="intersect" side="end" :items="dataList" class="overflow-visible px-2" @load="fetchData">
|
<VInfiniteScroll mode="intersect" side="end" :items="dataList" class="overflow-visible px-2" @load="fetchData" :key="currentKey">
|
||||||
<template #loading />
|
<template #loading />
|
||||||
<template #empty />
|
<template #empty />
|
||||||
<div v-if="dataList.length > 0" class="grid gap-4 grid-media-card" tabindex="0">
|
<div v-if="dataList.length > 0" class="grid gap-4 grid-media-card" tabindex="0">
|
||||||
|
|||||||
Reference in New Issue
Block a user