添加“综合筛选”和“清除全部”功能

This commit is contained in:
jxxghp
2025-05-07 12:22:54 +08:00
parent df8857fb52
commit ae9a13e0fa
5 changed files with 226 additions and 38 deletions
+3 -1
View File
@@ -727,6 +727,8 @@ export default {
filterResolution: 'Resolution', filterResolution: 'Resolution',
filterReleaseGroup: 'Release Group', filterReleaseGroup: 'Release Group',
noMatchingResults: 'No matching data', noMatchingResults: 'No matching data',
allFilters: 'All Filters',
clearAll: 'Clear All',
}, },
calendar: { calendar: {
episode: 'Episode {number}', episode: 'Episode {number}',
@@ -1120,7 +1122,7 @@ export default {
channelsDesc: 'Set message sending channel parameters.', channelsDesc: 'Set message sending channel parameters.',
organizeSuccess: 'Media Import', organizeSuccess: 'Media Import',
downloadAdded: 'Download Added', downloadAdded: 'Download Added',
subscribeAdded: 'Subscribe Added', subscribeAdded: 'Subscribe Added',
subscribeComplete: 'Subscribe Complete', subscribeComplete: 'Subscribe Complete',
templateConfigTitle: 'Message Template', templateConfigTitle: 'Message Template',
templateConfigDesc: 'Set message template, support Jinja2 syntax.', templateConfigDesc: 'Set message template, support Jinja2 syntax.',
+2
View File
@@ -724,6 +724,8 @@ export default {
filterResolution: '分辨率', filterResolution: '分辨率',
filterReleaseGroup: '制作组', filterReleaseGroup: '制作组',
noMatchingResults: '没有数据', noMatchingResults: '没有数据',
allFilters: '综合筛选',
clearAll: '清除全部',
}, },
calendar: { calendar: {
episode: '第{number}集', episode: '第{number}集',
+2
View File
@@ -725,6 +725,8 @@ export default {
filterResolution: '分辨率', filterResolution: '分辨率',
filterReleaseGroup: '製作組', filterReleaseGroup: '製作組',
noMatchingResults: '沒有數據', noMatchingResults: '沒有數據',
allFilters: '綜合篩選',
clearAll: '清除全部',
}, },
calendar: { calendar: {
episode: '第{number}集', episode: '第{number}集',
+89 -31
View File
@@ -78,10 +78,9 @@ const groupedDataList = ref<Map<string, Context[]>>()
// 过滤菜单相关 // 过滤菜单相关
const filterMenuOpen = ref(false) const filterMenuOpen = ref(false)
const currentFilter = ref('site') const currentFilter = ref('site')
const currentFilterTitle = computed(() => filterTitles[currentFilter.value])
const currentFilterOptions = computed(() => { // 添加全部筛选菜单相关
return filterOptions[currentFilter.value] const allFilterMenuOpen = ref(false)
})
// 初始化过滤选项 // 初始化过滤选项
function initOptions(data: Context) { function initOptions(data: Context) {
@@ -303,6 +302,11 @@ function toggleFilterMenu(key: string) {
} }
} }
// 开关全部筛选菜单
function toggleAllFilterMenu() {
allFilterMenuOpen.value = !allFilterMenuOpen.value
}
// 清除所有过滤条件 // 清除所有过滤条件
function clearAllFilters() { function clearAllFilters() {
for (const key in filterForm) { for (const key in filterForm) {
@@ -432,6 +436,22 @@ function loadMore({ done }: { done: any }) {
</VMenu> </VMenu>
</VBtn> </VBtn>
<!-- 全部筛选按钮 -->
<VBtn
variant="tonal"
size="small"
color="primary"
class="filter-btn ms-2"
prepend-icon="mdi-filter-variant"
rounded="pill"
@click="toggleAllFilterMenu"
>
{{ t('torrent.allFilters') }}
<VChip v-if="getFilterCount > 0" size="small" color="primary" class="ms-1" variant="elevated">
{{ getFilterCount }}
</VChip>
</VBtn>
<!-- 清除全部筛选按钮 --> <!-- 清除全部筛选按钮 -->
<VBtn <VBtn
v-if="getFilterCount > 0" v-if="getFilterCount > 0"
@@ -529,46 +549,73 @@ function loadMore({ done }: { done: any }) {
</div> </div>
</VCard> </VCard>
<!-- 筛选弹窗 --> <!-- 全部筛选弹窗 -->
<VDialog v-model="filterMenuOpen" max-width="25rem" max-height="80%" location="center"> <VDialog v-model="allFilterMenuOpen" max-width="50rem" location="center" scrollable>
<VCard> <VCard>
<VDialogCloseBtn @click="allFilterMenuOpen = false" />
<VCardTitle class="py-3 d-flex align-center"> <VCardTitle class="py-3 d-flex align-center">
<VIcon :icon="getFilterIcon(currentFilter)" class="me-2"></VIcon> <VIcon icon="mdi-filter-variant" class="me-2"></VIcon>
<span>{{ currentFilterTitle }}</span> <span>{{ t('torrent.allFilters') }}</span>
<VSpacer /> <VSpacer />
<VBtn <VBtn
v-if="filterForm[currentFilter].length > 0" v-if="getFilterCount > 0"
class="me-10"
variant="text" variant="text"
size="small" size="small"
color="error" color="error"
@click="clearFilter(currentFilter)" @click="clearAllFilters"
> >
{{ t('torrent.clear') }} {{ t('torrent.clearAll') }}
</VBtn>
<VBtn variant="text" size="small" color="primary" @click="selectAll(currentFilter)">
{{ t('torrent.selectAll') }}
</VBtn> </VBtn>
</VCardTitle> </VCardTitle>
<VDivider /> <VDivider />
<VCardText class="filter-menu-content pt-4"> <VCardText>
<VChipGroup v-model="filterForm[currentFilter]" column multiple class="filter-options"> <div class="all-filters-grid">
<VChip <VCard
v-for="option in currentFilterOptions" v-for="(title, key) in filterTitles"
:key="option" variant="tonal"
:value="option" :key="key"
filter class="filter-section"
variant="elevated" v-show="filterOptions[key].length > 0"
class="ma-1 filter-chip"
size="small"
> >
{{ option }} <VCardItem class="py-2">
</VChip> <template #prepend>
</VChipGroup> <VIcon :icon="getFilterIcon(key)" class="me-2"></VIcon>
</template>
<VCardTitle>{{ title }}</VCardTitle>
<template #append>
<VBtn variant="text" size="small" color="primary" @click="selectAll(key)">
{{ t('torrent.selectAll') }}
</VBtn>
<VBtn
v-if="filterForm[key].length > 0"
variant="text"
size="small"
color="error"
@click="clearFilter(key)"
>
{{ t('torrent.clear') }}
</VBtn>
</template>
</VCardItem>
<VCardText>
<VChipGroup v-model="filterForm[key]" column multiple class="filter-options">
<VChip
v-for="option in filterOptions[key]"
:key="option"
:value="option"
filter
variant="elevated"
class="ma-1 filter-chip"
size="small"
>
{{ option }}
</VChip>
</VChipGroup>
</VCardText>
</VCard>
</div>
</VCardText> </VCardText>
<VCardActions>
<VSpacer />
<VBtn variant="elevated" color="primary" @click="filterMenuOpen = false"> {{ t('torrent.confirm') }} </VBtn>
</VCardActions>
</VCard> </VCard>
</VDialog> </VDialog>
@@ -633,6 +680,7 @@ function loadMore({ done }: { done: any }) {
} }
.filter-menu-content { .filter-menu-content {
max-block-size: 50vh;
overflow-y: auto; overflow-y: auto;
} }
@@ -739,4 +787,14 @@ function loadMore({ done }: { done: any }) {
background-color: rgba(var(--v-theme-background), 0.95); background-color: rgba(var(--v-theme-background), 0.95);
inset-block-start: 0; inset-block-start: 0;
} }
.all-filters-grid {
display: grid;
gap: 24px;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
}
.filter-section {
background-color: rgba(var(--v-theme-surface-variant), 0.08);
}
</style> </style>
+130 -6
View File
@@ -277,10 +277,17 @@ const filterMenuOpen = ref(false)
const currentFilter = ref('site') const currentFilter = ref('site')
const currentFilterTitle = computed(() => filterTitles[currentFilter.value]) const currentFilterTitle = computed(() => filterTitles[currentFilter.value])
const currentFilterOptions = computed(() => { const currentFilterOptions = computed(() => {
// 季集选项不再需要特殊处理,直接从 filterOptions 获取
return filterOptions[currentFilter.value] return filterOptions[currentFilter.value]
}) })
// 添加全部筛选菜单相关
const allFilterMenuOpen = ref(false)
// 开关全部筛选菜单
function toggleAllFilterMenu() {
allFilterMenuOpen.value = !allFilterMenuOpen.value
}
// 给定过滤类型返回不同图标 // 给定过滤类型返回不同图标
function getFilterIcon(key: string) { function getFilterIcon(key: string) {
const icons: Record<string, string> = { const icons: Record<string, string> = {
@@ -361,6 +368,7 @@ onMounted(() => {
> >
</VSelect> </VSelect>
<div class="filter-divider"></div> <div class="filter-divider"></div>
<!-- 筛选按钮 --> <!-- 筛选按钮 -->
<VBtn <VBtn
v-for="(title, key) in filterTitles" v-for="(title, key) in filterTitles"
@@ -412,6 +420,22 @@ onMounted(() => {
</VMenu> </VMenu>
</VBtn> </VBtn>
<!-- 全部筛选按钮 -->
<VBtn
variant="tonal"
size="small"
color="primary"
class="filter-btn me-2"
prepend-icon="mdi-filter-variant"
rounded="pill"
@click="toggleAllFilterMenu"
>
{{ t('torrent.allFilters') }}
<VChip v-if="getFilterCount > 0" size="small" color="primary" class="ms-1" variant="elevated">
{{ getFilterCount }}
</VChip>
</VBtn>
<!-- 清除全部筛选按钮 --> <!-- 清除全部筛选按钮 -->
<VBtn <VBtn
v-if="getFilterCount > 0" v-if="getFilterCount > 0"
@@ -463,7 +487,7 @@ onMounted(() => {
class="search-count me-auto" class="search-count me-auto"
prepend-icon="mdi-magnify" prepend-icon="mdi-magnify"
> >
{{ props.items?.length || 0 }} 个资源 {{ props.items?.length || 0 }} {{ t('torrent.resources') }}
</VChip> </VChip>
<!-- 排序选择 --> <!-- 排序选择 -->
@@ -482,6 +506,22 @@ onMounted(() => {
<!-- 筛选图标按钮区域 --> <!-- 筛选图标按钮区域 -->
<div class="filter-buttons-grid w-100 mt-2"> <div class="filter-buttons-grid w-100 mt-2">
<!-- 全部筛选按钮 -->
<VBtn variant="text" color="primary" class="filter-btn-mobile" @click="toggleAllFilterMenu">
<VIcon icon="mdi-filter-variant" class="filter-icon me-1"></VIcon>
<span class="filter-label">
{{ t('torrent.allFilters') }}
</span>
<VBadge
v-if="getFilterCount > 0"
:content="getFilterCount"
color="primary"
location="top end"
offset-x="-10"
offset-y="-10"
></VBadge>
</VBtn>
<VBtn <VBtn
v-for="(title, key) in filterTitles" v-for="(title, key) in filterTitles"
v-show="filterOptions[key].length > 0" v-show="filterOptions[key].length > 0"
@@ -508,6 +548,76 @@ onMounted(() => {
</div> </div>
</VCard> </VCard>
<!-- 全部筛选弹窗 -->
<VDialog v-model="allFilterMenuOpen" max-width="50rem" location="center" scrollable>
<VCard>
<VDialogCloseBtn @click="allFilterMenuOpen = false" />
<VCardTitle class="py-3 d-flex align-center">
<VIcon icon="mdi-filter-variant" class="me-2"></VIcon>
<span>{{ t('torrent.allFilters') }}</span>
<VSpacer />
<VBtn
v-if="getFilterCount > 0"
class="me-10"
variant="text"
size="small"
color="error"
@click="clearAllFilters"
>
{{ t('torrent.clearAll') }}
</VBtn>
</VCardTitle>
<VDivider />
<VCardText>
<div class="all-filters-grid">
<VCard
v-for="(title, key) in filterTitles"
variant="tonal"
:key="key"
class="filter-section"
v-show="filterOptions[key].length > 0"
>
<VCardItem class="py-2">
<template #prepend>
<VIcon :icon="getFilterIcon(key)" class="me-2"></VIcon>
</template>
<VCardTitle>{{ title }}</VCardTitle>
<template #append>
<VBtn variant="text" size="small" color="primary" @click="selectAll(key)">
{{ t('torrent.selectAll') }}
</VBtn>
<VBtn
v-if="filterForm[key].length > 0"
variant="text"
size="small"
color="error"
@click="clearFilter(key)"
>
{{ t('torrent.clear') }}
</VBtn>
</template>
</VCardItem>
<VCardText>
<VChipGroup v-model="filterForm[key]" column multiple class="filter-options">
<VChip
v-for="option in filterOptions[key]"
:key="option"
:value="option"
filter
variant="elevated"
class="ma-1 filter-chip"
size="small"
>
{{ option }}
</VChip>
</VChipGroup>
</VCardText>
</VCard>
</div>
</VCardText>
</VCard>
</VDialog>
<!-- 筛选弹窗 --> <!-- 筛选弹窗 -->
<VDialog v-model="filterMenuOpen" max-width="25rem" max-height="80%" location="center"> <VDialog v-model="filterMenuOpen" max-width="25rem" max-height="80%" location="center">
<VCard> <VCard>
@@ -522,12 +632,14 @@ onMounted(() => {
color="error" color="error"
@click="clearFilter(currentFilter)" @click="clearFilter(currentFilter)"
> >
清除 {{ t('torrent.clear') }}
</VBtn>
<VBtn variant="text" size="small" color="primary" @click="selectAll(currentFilter)">
{{ t('torrent.selectAll') }}
</VBtn> </VBtn>
<VBtn variant="text" size="small" color="primary" @click="selectAll(currentFilter)"> 全选 </VBtn>
</VCardTitle> </VCardTitle>
<VDivider /> <VDivider />
<VCardText class="filter-menu-content pt-4"> <VCardText>
<VChipGroup v-model="filterForm[currentFilter]" column multiple class="filter-options"> <VChipGroup v-model="filterForm[currentFilter]" column multiple class="filter-options">
<VChip <VChip
v-for="option in currentFilterOptions" v-for="option in currentFilterOptions"
@@ -544,7 +656,9 @@ onMounted(() => {
</VCardText> </VCardText>
<VCardActions> <VCardActions>
<VSpacer /> <VSpacer />
<VBtn variant="elevated" color="primary" @click="filterMenuOpen = false"> {{ t('torrent.confirm') }} </VBtn> <VBtn variant="elevated" color="primary" @click="filterMenuOpen = false">
{{ t('torrent.confirm') }}
</VBtn>
</VCardActions> </VCardActions>
</VCard> </VCard>
</VDialog> </VDialog>
@@ -729,4 +843,14 @@ onMounted(() => {
max-inline-size: 130px; max-inline-size: 130px;
min-inline-size: 110px; min-inline-size: 110px;
} }
.all-filters-grid {
display: grid;
gap: 24px;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
}
.filter-section {
background-color: rgba(var(--v-theme-surface-variant), 0.08);
}
</style> </style>