mirror of
https://github.com/jxxghp/MoviePilot-Frontend.git
synced 2026-09-06 08:06:43 +08:00
优化 TorrentCard 和 TorrentItem 组件的样式,调整过滤器相关 UI 组件的显示效果
This commit is contained in:
@@ -103,13 +103,12 @@ onMounted(() => {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<div class="h-full">
|
||||||
<VCard
|
<VCard
|
||||||
:width="props.width || '100%'"
|
:width="props.width || '100%'"
|
||||||
height="300px"
|
|
||||||
:variant="downloaded.includes(torrent?.enclosure || '') ? 'outlined' : 'flat'"
|
:variant="downloaded.includes(torrent?.enclosure || '') ? 'outlined' : 'flat'"
|
||||||
@click="handleAddDownload(props.torrent)"
|
@click="handleAddDownload(props.torrent)"
|
||||||
class="torrent-card"
|
class="torrent-card h-full"
|
||||||
:class="{ 'downloaded-card': downloaded.includes(torrent?.enclosure || '') }"
|
:class="{ 'downloaded-card': downloaded.includes(torrent?.enclosure || '') }"
|
||||||
>
|
>
|
||||||
<!-- 优惠标签 -->
|
<!-- 优惠标签 -->
|
||||||
@@ -164,7 +163,7 @@ onMounted(() => {
|
|||||||
<!-- 种子描述 -->
|
<!-- 种子描述 -->
|
||||||
<div
|
<div
|
||||||
v-if="meta?.subtitle || torrent?.description"
|
v-if="meta?.subtitle || torrent?.description"
|
||||||
class="torrent-desc"
|
class="torrent-desc grow"
|
||||||
:title="meta?.subtitle || torrent?.description"
|
:title="meta?.subtitle || torrent?.description"
|
||||||
>
|
>
|
||||||
{{ meta?.subtitle || torrent?.description }}
|
{{ meta?.subtitle || torrent?.description }}
|
||||||
@@ -457,7 +456,6 @@ onMounted(() => {
|
|||||||
-webkit-box-orient: vertical;
|
-webkit-box-orient: vertical;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
height: 4em;
|
|
||||||
margin-bottom: 8px;
|
margin-bottom: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -10,9 +10,6 @@ const props = defineProps({
|
|||||||
torrent: Object as PropType<Context>,
|
torrent: Object as PropType<Context>,
|
||||||
})
|
})
|
||||||
|
|
||||||
// 更多来源界面
|
|
||||||
const showMoreTorrents = ref(false)
|
|
||||||
|
|
||||||
// 种子信息
|
// 种子信息
|
||||||
const torrent = ref(props.torrent?.torrent_info)
|
const torrent = ref(props.torrent?.torrent_info)
|
||||||
|
|
||||||
@@ -245,7 +242,6 @@ onMounted(() => {
|
|||||||
padding: 12px;
|
padding: 12px;
|
||||||
background-color: rgb(var(--v-theme-surface));
|
background-color: rgb(var(--v-theme-surface));
|
||||||
box-shadow: none;
|
box-shadow: none;
|
||||||
border-bottom: 1px solid rgba(var(--v-theme-on-surface), 0.1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.torrent-item:hover {
|
.torrent-item:hover {
|
||||||
|
|||||||
@@ -62,15 +62,6 @@ const filterOptions: Record<string, string[]> = reactive({
|
|||||||
releaseGroup: [] as string[],
|
releaseGroup: [] as string[],
|
||||||
})
|
})
|
||||||
|
|
||||||
// 非空值的过滤选项
|
|
||||||
const filterOptionsNotEmpty = computed(() => {
|
|
||||||
const options: Record<string, string[]> = {}
|
|
||||||
for (const key in filterOptions) {
|
|
||||||
if (filterOptions[key].length > 0) options[key] = filterOptions[key]
|
|
||||||
}
|
|
||||||
return options
|
|
||||||
})
|
|
||||||
|
|
||||||
// 完整的数据列表
|
// 完整的数据列表
|
||||||
let dataList: SearchTorrent[]
|
let dataList: SearchTorrent[]
|
||||||
// 显示用的数据列表
|
// 显示用的数据列表
|
||||||
@@ -442,7 +433,7 @@ function loadMore({ done }: { done: any }) {
|
|||||||
rounded="pill"
|
rounded="pill"
|
||||||
>
|
>
|
||||||
{{ title }}
|
{{ title }}
|
||||||
<VChip v-if="filterForm[key].length > 0" size="x-small" color="primary" class="ms-1" variant="elevated">{{
|
<VChip v-if="filterForm[key].length > 0" size="small" color="primary" class="ms-1" variant="elevated">{{
|
||||||
filterForm[key].length
|
filterForm[key].length
|
||||||
}}</VChip>
|
}}</VChip>
|
||||||
</VBtn>
|
</VBtn>
|
||||||
@@ -477,7 +468,7 @@ function loadMore({ done }: { done: any }) {
|
|||||||
class="me-1 mt-2 filter-tag"
|
class="me-1 mt-2 filter-tag"
|
||||||
@click:close="removeFilter(key, value)"
|
@click:close="removeFilter(key, value)"
|
||||||
>
|
>
|
||||||
<VIcon size="x-small" :icon="getFilterIcon(key)" class="me-1"></VIcon>
|
<VIcon size="small" :icon="getFilterIcon(key)" class="me-1"></VIcon>
|
||||||
<strong>{{ filterTitles[key] }}:</strong> {{ value }}
|
<strong>{{ filterTitles[key] }}:</strong> {{ value }}
|
||||||
</VChip>
|
</VChip>
|
||||||
</template>
|
</template>
|
||||||
@@ -495,7 +486,7 @@ function loadMore({ done }: { done: any }) {
|
|||||||
<VChip
|
<VChip
|
||||||
color="primary"
|
color="primary"
|
||||||
variant="elevated"
|
variant="elevated"
|
||||||
size="x-small"
|
size="small"
|
||||||
class="search-count me-auto"
|
class="search-count me-auto"
|
||||||
prepend-icon="mdi-magnify"
|
prepend-icon="mdi-magnify"
|
||||||
>
|
>
|
||||||
@@ -526,7 +517,7 @@ function loadMore({ done }: { done: any }) {
|
|||||||
class="filter-btn-mobile"
|
class="filter-btn-mobile"
|
||||||
@click="toggleFilterMenu(key)"
|
@click="toggleFilterMenu(key)"
|
||||||
>
|
>
|
||||||
<VIcon :icon="getFilterIcon(key)" class="filter-icon"></VIcon>
|
<VIcon :icon="getFilterIcon(key)" class="filter-icon me-1"></VIcon>
|
||||||
<span class="filter-label">
|
<span class="filter-label">
|
||||||
{{ title }}
|
{{ title }}
|
||||||
</span>
|
</span>
|
||||||
@@ -765,7 +756,7 @@ function loadMore({ done }: { done: any }) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.filter-label {
|
.filter-label {
|
||||||
font-size: 0.7rem;
|
font-size: 0.8rem;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -60,15 +60,6 @@ const filterOptions: Record<string, string[]> = reactive({
|
|||||||
releaseGroup: [] as string[],
|
releaseGroup: [] as string[],
|
||||||
})
|
})
|
||||||
|
|
||||||
// 非空值的过滤选项
|
|
||||||
const filterOptionsNotEmpty = computed(() => {
|
|
||||||
const options: Record<string, string[]> = {}
|
|
||||||
for (const key in filterOptions) {
|
|
||||||
if (filterOptions[key].length > 0) options[key] = filterOptions[key]
|
|
||||||
}
|
|
||||||
return options
|
|
||||||
})
|
|
||||||
|
|
||||||
// 对季过滤选项进行排序
|
// 对季过滤选项进行排序
|
||||||
const sortSeasonFilterOptions = computed(() => {
|
const sortSeasonFilterOptions = computed(() => {
|
||||||
// 预解析所有选项
|
// 预解析所有选项
|
||||||
@@ -187,13 +178,6 @@ const sortSeasonFilterOptions = computed(() => {
|
|||||||
return parsedOptions.map(option => option.original)
|
return parsedOptions.map(option => option.original)
|
||||||
})
|
})
|
||||||
|
|
||||||
// 列表样式
|
|
||||||
const listStyle = computed(() => {
|
|
||||||
return appMode
|
|
||||||
? 'height: calc(100vh - 7.5rem - env(safe-area-inset-bottom) - 3.5rem)'
|
|
||||||
: 'height: calc(100vh - 6.5rem - env(safe-area-inset-bottom)'
|
|
||||||
})
|
|
||||||
|
|
||||||
// 排序字段
|
// 排序字段
|
||||||
const sortField = ref('default')
|
const sortField = ref('default')
|
||||||
|
|
||||||
@@ -277,7 +261,6 @@ watchEffect(() => {
|
|||||||
if (props.items?.length) {
|
if (props.items?.length) {
|
||||||
// 首先收集所有过滤选项
|
// 首先收集所有过滤选项
|
||||||
props.items.forEach(data => {
|
props.items.forEach(data => {
|
||||||
const { meta_info, torrent_info } = data
|
|
||||||
initOptions(data)
|
initOptions(data)
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -306,19 +289,8 @@ watchEffect(() => {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
// 切换过滤器选项
|
|
||||||
function toggleFilter(key: string, value: string) {
|
|
||||||
const index = filterForm[key].indexOf(value)
|
|
||||||
if (index === -1) {
|
|
||||||
filterForm[key].push(value)
|
|
||||||
} else {
|
|
||||||
filterForm[key].splice(index, 1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 过滤菜单相关
|
// 过滤菜单相关
|
||||||
const filterMenuOpen = ref(false)
|
const filterMenuOpen = ref(false)
|
||||||
const filterMenuAnchor = ref(null)
|
|
||||||
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(() => {
|
||||||
@@ -328,12 +300,6 @@ const currentFilterOptions = computed(() => {
|
|||||||
return filterOptions[currentFilter.value]
|
return filterOptions[currentFilter.value]
|
||||||
})
|
})
|
||||||
|
|
||||||
// 打开过滤菜单
|
|
||||||
function openFilterMenu(key: string) {
|
|
||||||
currentFilter.value = key
|
|
||||||
filterMenuOpen.value = true
|
|
||||||
}
|
|
||||||
|
|
||||||
// 给定过滤类型返回不同图标
|
// 给定过滤类型返回不同图标
|
||||||
function getFilterIcon(key: string) {
|
function getFilterIcon(key: string) {
|
||||||
const icons: Record<string, string> = {
|
const icons: Record<string, string> = {
|
||||||
@@ -417,9 +383,9 @@ function toggleFilterMenu(key: string) {
|
|||||||
rounded="pill"
|
rounded="pill"
|
||||||
>
|
>
|
||||||
{{ title }}
|
{{ title }}
|
||||||
<VChip v-if="filterForm[key].length > 0" size="x-small" color="primary" class="ms-1" variant="elevated">{{
|
<VChip v-if="filterForm[key].length > 0" size="small" color="primary" class="ms-1" variant="elevated">
|
||||||
filterForm[key].length
|
{{ filterForm[key].length }}
|
||||||
}}</VChip>
|
</VChip>
|
||||||
</VBtn>
|
</VBtn>
|
||||||
|
|
||||||
<!-- 清除全部筛选按钮 -->
|
<!-- 清除全部筛选按钮 -->
|
||||||
@@ -452,7 +418,7 @@ function toggleFilterMenu(key: string) {
|
|||||||
class="me-1 mb-1 mt-1 filter-tag"
|
class="me-1 mb-1 mt-1 filter-tag"
|
||||||
@click:close="removeFilter(key, value)"
|
@click:close="removeFilter(key, value)"
|
||||||
>
|
>
|
||||||
<VIcon size="x-small" :icon="getFilterIcon(key)" class="me-1"></VIcon>
|
<VIcon size="small" :icon="getFilterIcon(key)" class="me-1"></VIcon>
|
||||||
<strong>{{ filterTitles[key] }}:</strong> {{ value }}
|
<strong>{{ filterTitles[key] }}:</strong> {{ value }}
|
||||||
</VChip>
|
</VChip>
|
||||||
</template>
|
</template>
|
||||||
@@ -469,7 +435,7 @@ function toggleFilterMenu(key: string) {
|
|||||||
<VChip
|
<VChip
|
||||||
color="primary"
|
color="primary"
|
||||||
variant="elevated"
|
variant="elevated"
|
||||||
size="x-small"
|
size="small"
|
||||||
class="search-count me-auto"
|
class="search-count me-auto"
|
||||||
prepend-icon="mdi-magnify"
|
prepend-icon="mdi-magnify"
|
||||||
>
|
>
|
||||||
@@ -500,7 +466,7 @@ function toggleFilterMenu(key: string) {
|
|||||||
class="filter-btn-mobile"
|
class="filter-btn-mobile"
|
||||||
@click="toggleFilterMenu(key)"
|
@click="toggleFilterMenu(key)"
|
||||||
>
|
>
|
||||||
<VIcon :icon="getFilterIcon(key)" class="filter-icon"></VIcon>
|
<VIcon :icon="getFilterIcon(key)" class="filter-icon me-1"></VIcon>
|
||||||
<span class="filter-label">
|
<span class="filter-label">
|
||||||
{{ title }}
|
{{ title }}
|
||||||
</span>
|
</span>
|
||||||
@@ -571,6 +537,7 @@ function toggleFilterMenu(key: string) {
|
|||||||
<div v-else class="resource-list">
|
<div v-else class="resource-list">
|
||||||
<div v-for="(item, index) in dataList" :key="`${item.torrent_info?.enclosure || ''}-${index}`">
|
<div v-for="(item, index) in dataList" :key="`${item.torrent_info?.enclosure || ''}-${index}`">
|
||||||
<TorrentItem :torrent="item" />
|
<TorrentItem :torrent="item" />
|
||||||
|
<VDivider v-if="index < dataList.length - 1" class="my-2" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -741,15 +708,11 @@ function toggleFilterMenu(key: string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.filter-label {
|
.filter-label {
|
||||||
font-size: 0.7rem;
|
font-size: 0.8rem;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width: 600px) {
|
@media (max-width: 600px) {
|
||||||
.filter-btn {
|
|
||||||
font-size: 0.75rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.sort-select {
|
.sort-select {
|
||||||
min-width: 100px;
|
min-width: 100px;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user