优化媒体卡片和海报卡片的点击事件处理,改进路由滚动行为,注册中止控制器以管理异步请求

This commit is contained in:
jxxghp
2025-01-16 19:25:51 +08:00
parent e4af05cd56
commit f021ba8a98
4 changed files with 31 additions and 30 deletions

View File

@@ -59,11 +59,7 @@ const seasonInfos = ref<TmdbSeason[]>([])
// 选中的订阅季
const seasonsSelected = ref<TmdbSeason[]>([])
let abortController: AbortController | null = null
abortController = new AbortController()
registerAbortController(abortController)
const { signal } = abortController
// 来源角标字典
const sourceIconDict: { [key: string]: any } = {
themoviedb: tmdbImage,
@@ -100,7 +96,6 @@ function getChipColor(type: string) {
}
// 添加订阅处理
async function handleAddSubscribe() {
if (props.media?.type === '电视剧' && props.media?.tmdb_id) {
// TMDB电视剧
@@ -229,6 +224,9 @@ async function handleCheckSubscribe() {
// 查询当前媒体是否已入库
async function handleCheckExists() {
try {
const abortController = new AbortController()
registerAbortController(abortController)
const { signal } = abortController
const result: { [key: string]: any } = await api.get('mediaserver/exists', {
params: {
tmdbid: props.media?.tmdb_id,
@@ -249,8 +247,10 @@ async function handleCheckExists() {
// 调用API检查是否已订阅电视剧需要指定季
async function checkSubscribe(season = 0) {
try {
const abortController = new AbortController()
registerAbortController(abortController)
const { signal } = abortController
const mediaid = getMediaId()
const result: Subscribe = await api.get(`subscribe/media/${mediaid}`, {
params: {
season,
@@ -279,7 +279,6 @@ async function checkSeasonsNotExists() {
let state = 0
if (item.episodes.length === 0) state = 2
else if (item.episodes.length < item.total_episode) state = 1
seasonsNotExisted.value[item.season] = state
})
}
@@ -502,7 +501,7 @@ function onRemoveSubscribe() {
<p class="leading-4 line-clamp-4 overflow-hidden text-ellipsis ...">
{{ props.media?.overview }}
</p>
<div v-if="props.media?.collection_id" class="mb-3"></div>
<div v-if="props.media?.collection_id" class="mb-3" @click.stop=""></div>
<div v-else class="flex align-center justify-between">
<IconBtn icon="mdi-magnify" color="white" @click.stop="handleSearch" />
<IconBtn icon="mdi-heart" :color="isSubscribed ? 'error' : 'white'" @click.stop="handleSubscribe" />

View File

@@ -79,6 +79,7 @@ function goPlay(isHovering = false) {
<VCardText
v-show="hover.isHovering || imageLoadError"
class="w-full flex flex-col flex-wrap justify-end align-left text-white absolute bottom-0 cursor-pointer pa-2"
@click.stop=""
>
<span class="font-bold">{{ props.media?.subtitle }}</span>
<h1 class="mb-1 text-white font-extrabold text-xl line-clamp-2 overflow-hidden text-ellipsis ...">

View File

@@ -8,7 +8,7 @@ configureNProgress()
// Router
const router = createRouter({
history: createWebHashHistory(import.meta.env.BASE_URL),
scrollBehavior(to, from, savedPosition) {
scrollBehavior(to: any, from: any, savedPosition: any) {
// 如果页面有缓存那么恢复其位置, 否则始终滚动到顶部
if (to.meta.keepAlive && savedPosition) return savedPosition
return { top: 0 }
@@ -189,31 +189,36 @@ const router = createRouter({
},
],
})
const abortControllers = new Set<AbortController>()
// 注册中止控制器
function registerAbortController(controller: AbortController) {
abortControllers.add(controller)
}
// 中止所有组件的任务
function abortAllControllers() {
for (const controller of abortControllers) {
controller.abort()
}
abortControllers.clear()
}
// 路由导航守卫
router.beforeEach((to, from, next) => {
router.beforeEach((to: any, from: any, next: any) => {
// 总是记录非login路由
if (to.fullPath != '/login') store.state.auth.originalPath = to.fullPath
const isAuthenticated = store.state.auth.token !== null
if (to.meta.requiresAuth && !isAuthenticated) {
next('/login')
} else {
abortAllControllers() // 中止所有组件的任务
abortAllControllers()
next()
}
})
export default router // 导出默认对象
export { registerAbortController } // 另行导出其他功能
// 导出默认对象
export default router
// 另行导出其他功能
export { registerAbortController }

View File

@@ -3,7 +3,7 @@ import api from '@/api'
import type { MediaInfo } from '@/api/types'
import MediaCard from '@/components/cards/MediaCard.vue'
import SlideView from '@/components/slide/SlideView.vue'
import { registerAbortController } from "@/router";
import { registerAbortController } from '@/router'
// 输入参数
const props = defineProps({
@@ -11,8 +11,8 @@ const props = defineProps({
linkurl: String,
title: String,
})
let abortController: AbortController | null = null;
// 提供给子组件的属性
provide('rankingPropsKey', reactive({ ...props }))
// 组件加载完成
@@ -24,30 +24,26 @@ const dataList = ref<MediaInfo[]>([])
// 获取订阅列表数据
async function fetchData() {
try {
if (!props.apipath)
return
abortController = new AbortController();
registerAbortController(abortController);
const { signal } = abortController;
if (!props.apipath) return
const abortController = new AbortController()
registerAbortController(abortController)
const { signal } = abortController
dataList.value = await api.get(props.apipath, { signal })
if (dataList.value.length > 0)
componentLoaded.value = true
}
catch (error) {
if (dataList.value.length > 0) componentLoaded.value = true
} catch (error) {
console.error(error)
}
}
// 加载时获取数据
onMounted(() => {
fetchData();
});
fetchData()
})
onActivated(() => {
if (dataList.value.length == 0) {
fetchData();
fetchData()
}
});
})
</script>
<template>