mirror of
https://github.com/jxxghp/MoviePilot-Frontend.git
synced 2026-09-04 23:18:44 +08:00
feat:订阅统计共享
This commit is contained in:
@@ -1,9 +1,44 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import SubscribeListView from '@/views/subscribe/SubscribeListView.vue'
|
import SubscribeListView from '@/views/subscribe/SubscribeListView.vue'
|
||||||
|
import SubscribePopularView from '@/views/subscribe/SubscribePopularView.vue'
|
||||||
|
|
||||||
|
const route = useRoute()
|
||||||
|
|
||||||
|
// 标签页
|
||||||
|
const tabs = [
|
||||||
|
{
|
||||||
|
title: '我的订阅',
|
||||||
|
tab: 'mysub',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '热门订阅',
|
||||||
|
tab: 'popular',
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
// 当前标签
|
||||||
|
const activeTab = ref(route.params.tab)
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<SubscribeListView type="电影" />
|
<VTabs v-model="activeTab">
|
||||||
|
<VTab v-for="item in tabs" :value="item.tab">
|
||||||
|
<span class="mx-5">{{ item.title }}</span>
|
||||||
|
</VTab>
|
||||||
|
</VTabs>
|
||||||
|
|
||||||
|
<VWindow v-model="activeTab" class="mt-5 disable-tab-transition" :touch="false">
|
||||||
|
<VWindowItem value="mysub">
|
||||||
|
<transition name="fade-slide" appear>
|
||||||
|
<SubscribeListView type="电影" />
|
||||||
|
</transition>
|
||||||
|
</VWindowItem>
|
||||||
|
<VWindowItem value="popular">
|
||||||
|
<transition name="fade-slide" appear>
|
||||||
|
<SubscribePopularView type="电影" />
|
||||||
|
</transition>
|
||||||
|
</VWindowItem>
|
||||||
|
</VWindow>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -1,9 +1,44 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import SubscribeListView from '@/views/subscribe/SubscribeListView.vue'
|
import SubscribeListView from '@/views/subscribe/SubscribeListView.vue'
|
||||||
|
import SubscribePopularView from '@/views/subscribe/SubscribePopularView.vue'
|
||||||
|
|
||||||
|
const route = useRoute()
|
||||||
|
|
||||||
|
// 标签页
|
||||||
|
const tabs = [
|
||||||
|
{
|
||||||
|
title: '我的订阅',
|
||||||
|
tab: 'mysub',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '热门订阅',
|
||||||
|
tab: 'popular',
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
// 当前标签
|
||||||
|
const activeTab = ref(route.params.tab)
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<SubscribeListView type="电视剧" />
|
<VTabs v-model="activeTab">
|
||||||
|
<VTab v-for="item in tabs" :value="item.tab">
|
||||||
|
<span class="mx-5">{{ item.title }}</span>
|
||||||
|
</VTab>
|
||||||
|
</VTabs>
|
||||||
|
|
||||||
|
<VWindow v-model="activeTab" class="mt-5 disable-tab-transition" :touch="false">
|
||||||
|
<VWindowItem value="mysub">
|
||||||
|
<transition name="fade-slide" appear>
|
||||||
|
<SubscribeListView type="电视剧" />
|
||||||
|
</transition>
|
||||||
|
</VWindowItem>
|
||||||
|
<VWindowItem value="popular">
|
||||||
|
<transition name="fade-slide" appear>
|
||||||
|
<SubscribePopularView type="电视剧" />
|
||||||
|
</transition>
|
||||||
|
</VWindowItem>
|
||||||
|
</VWindow>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -0,0 +1,135 @@
|
|||||||
|
<script lang="ts" setup>
|
||||||
|
import api from '@/api'
|
||||||
|
import type { MediaInfo } from '@/api/types'
|
||||||
|
import MediaCard from '@/components/cards/MediaCard.vue'
|
||||||
|
import NoDataFound from '@/components/NoDataFound.vue'
|
||||||
|
|
||||||
|
// 输入参数
|
||||||
|
const props = defineProps({
|
||||||
|
type: String,
|
||||||
|
})
|
||||||
|
|
||||||
|
// 判断是否有滚动条
|
||||||
|
function hasScroll() {
|
||||||
|
return document.body.scrollHeight - (window.innerHeight || document.documentElement.clientHeight) > 2
|
||||||
|
}
|
||||||
|
|
||||||
|
// API
|
||||||
|
const apipath = 'subscribe/popular'
|
||||||
|
|
||||||
|
// 当前页码
|
||||||
|
const page = ref(1)
|
||||||
|
|
||||||
|
// 是否加载中
|
||||||
|
const loading = ref(false)
|
||||||
|
|
||||||
|
// 是否加载完成
|
||||||
|
const isRefreshed = ref(false)
|
||||||
|
|
||||||
|
// 数据列表
|
||||||
|
const dataList = ref<MediaInfo[]>([])
|
||||||
|
const currData = ref<MediaInfo[]>([])
|
||||||
|
|
||||||
|
// 拼装参数
|
||||||
|
function getParams() {
|
||||||
|
let params = {
|
||||||
|
stype: props.type,
|
||||||
|
page: page.value,
|
||||||
|
count: 30,
|
||||||
|
}
|
||||||
|
return params
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取列表数据
|
||||||
|
async function fetchData({ done }: { done: any }) {
|
||||||
|
try {
|
||||||
|
// 如果正在加载中,直接返回
|
||||||
|
if (loading.value) {
|
||||||
|
done('ok')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 加载到满屏或者加载出错
|
||||||
|
if (!hasScroll()) {
|
||||||
|
// 加载多次
|
||||||
|
while (!hasScroll()) {
|
||||||
|
// 设置加载中
|
||||||
|
loading.value = true
|
||||||
|
// 请求API
|
||||||
|
currData.value = await api.get(apipath, {
|
||||||
|
params: getParams(),
|
||||||
|
})
|
||||||
|
// 取消加载中
|
||||||
|
loading.value = false
|
||||||
|
// 标计为已请求完成
|
||||||
|
isRefreshed.value = true
|
||||||
|
if (currData.value.length === 0) {
|
||||||
|
// 如果没有数据,跳出
|
||||||
|
done('empty')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// 合并数据
|
||||||
|
dataList.value = [...dataList.value, ...currData.value]
|
||||||
|
// 页码+1
|
||||||
|
page.value++
|
||||||
|
// 返回加载成功
|
||||||
|
done('ok')
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 加载一次
|
||||||
|
// 设置加载中
|
||||||
|
loading.value = true
|
||||||
|
// 请求API
|
||||||
|
currData.value = await api.get(apipath, {
|
||||||
|
params: getParams(),
|
||||||
|
})
|
||||||
|
// 标计为已请求完成
|
||||||
|
isRefreshed.value = true
|
||||||
|
if (currData.value.length === 0) {
|
||||||
|
// 如果没有数据,跳出
|
||||||
|
done('empty')
|
||||||
|
} else {
|
||||||
|
// 合并数据
|
||||||
|
dataList.value = [...dataList.value, ...currData.value]
|
||||||
|
// 页码+1
|
||||||
|
page.value++
|
||||||
|
// 返回加载成功
|
||||||
|
done('ok')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 取消加载中
|
||||||
|
loading.value = false
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error)
|
||||||
|
// 返回加载失败
|
||||||
|
done('error')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<LoadingBanner v-if="!isRefreshed" class="mt-12" />
|
||||||
|
<VInfiniteScroll mode="intersect" side="end" :items="dataList" class="overflow-hidden" @load="fetchData">
|
||||||
|
<template #loading />
|
||||||
|
<template #empty />
|
||||||
|
<div v-if="dataList.length > 0" class="grid gap-4 grid-media-card mx-3" tabindex="0">
|
||||||
|
<MediaCard v-for="data in dataList" :key="data.tmdb_id || data.douban_id" :media="data" />
|
||||||
|
</div>
|
||||||
|
<NoDataFound
|
||||||
|
v-if="dataList.length === 0 && isRefreshed"
|
||||||
|
error-code="404"
|
||||||
|
error-title="没有数据"
|
||||||
|
error-description="未获取到热门订阅数据,服务器无法连接。"
|
||||||
|
/>
|
||||||
|
</VInfiniteScroll>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.grid-media-card {
|
||||||
|
grid-template-columns: repeat(auto-fill, minmax(9.375rem, 1fr));
|
||||||
|
}
|
||||||
|
|
||||||
|
.v-tabs:not(.v-tabs-pill).v-tabs--horizontal {
|
||||||
|
border-block-end: 1px solid rgba(var(--v-border-color), var(--v-border-opacity));
|
||||||
|
}
|
||||||
|
</style>
|
||||||
Reference in New Issue
Block a user