mirror of
https://github.com/jxxghp/MoviePilot-Frontend.git
synced 2026-09-05 07:28:37 +08:00
fix 订阅历史记录
This commit is contained in:
Vendored
+1
@@ -10,6 +10,7 @@ declare module 'vue' {
|
|||||||
DialogCloseBtn: typeof import('./src/@core/components/DialogCloseBtn.vue')['default']
|
DialogCloseBtn: typeof import('./src/@core/components/DialogCloseBtn.vue')['default']
|
||||||
ErrorHeader: typeof import('./src/@core/components/ErrorHeader.vue')['default']
|
ErrorHeader: typeof import('./src/@core/components/ErrorHeader.vue')['default']
|
||||||
ExistIcon: typeof import('./src/@core/components/ExistIcon.vue')['default']
|
ExistIcon: typeof import('./src/@core/components/ExistIcon.vue')['default']
|
||||||
|
LoadingBanner: typeof import('./src/@core/components/LoadingBanner.vue')['default']
|
||||||
MoreBtn: typeof import('./src/@core/components/MoreBtn.vue')['default']
|
MoreBtn: typeof import('./src/@core/components/MoreBtn.vue')['default']
|
||||||
RouterLink: typeof import('vue-router')['RouterLink']
|
RouterLink: typeof import('vue-router')['RouterLink']
|
||||||
RouterView: typeof import('vue-router')['RouterView']
|
RouterView: typeof import('vue-router')['RouterView']
|
||||||
|
|||||||
@@ -0,0 +1,28 @@
|
|||||||
|
<script lang="ts" setup>
|
||||||
|
// 定义输入参数
|
||||||
|
const props = defineProps({
|
||||||
|
progress: Number,
|
||||||
|
text: String
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div
|
||||||
|
class="w-full text-center text-gray-500 text-sm flex flex-col items-center"
|
||||||
|
>
|
||||||
|
<VProgressCircular
|
||||||
|
v-if="!props.text"
|
||||||
|
size="48"
|
||||||
|
indeterminate
|
||||||
|
color="primary"
|
||||||
|
/>
|
||||||
|
<VProgressCircular
|
||||||
|
v-if="props.progress"
|
||||||
|
class="mb-3"
|
||||||
|
color="primary"
|
||||||
|
:model-value="props.progress"
|
||||||
|
size="64"
|
||||||
|
/>
|
||||||
|
<span>{{ props.text }}</span>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
@@ -1,13 +1,8 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { useToast } from 'vue-toast-notification'
|
import { useToast } from 'vue-toast-notification'
|
||||||
import { useTheme } from 'vuetify'
|
import { useTheme } from 'vuetify'
|
||||||
|
|
||||||
import store from './store'
|
import store from './store'
|
||||||
|
|
||||||
import { fixArrayAt } from '@/@core/utils/compatibility'
|
|
||||||
|
|
||||||
// 修复低版本Safari等浏览器数组不支持at函数的问题
|
|
||||||
fixArrayAt()
|
|
||||||
|
|
||||||
// 提示框
|
// 提示框
|
||||||
const $toast = useToast()
|
const $toast = useToast()
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ const props = defineProps({
|
|||||||
})
|
})
|
||||||
|
|
||||||
// 定义触发的自定义事件
|
// 定义触发的自定义事件
|
||||||
const emit = defineEmits(['close'])
|
const emit = defineEmits(['close', 'save'])
|
||||||
|
|
||||||
// 订阅历史列表
|
// 订阅历史列表
|
||||||
const historyList = ref<Subscribe[]>([])
|
const historyList = ref<Subscribe[]>([])
|
||||||
@@ -29,6 +29,12 @@ const loading = ref(false)
|
|||||||
// 是否加载完成
|
// 是否加载完成
|
||||||
const isRefreshed = ref(false)
|
const isRefreshed = ref(false)
|
||||||
|
|
||||||
|
// 进度框
|
||||||
|
const progressDialog = ref(false)
|
||||||
|
|
||||||
|
// 进度文字
|
||||||
|
const progressText = ref('正在重新订阅...')
|
||||||
|
|
||||||
// 调用API查询列表
|
// 调用API查询列表
|
||||||
async function loadHistory({ done }: { done: any }) {
|
async function loadHistory({ done }: { done: any }) {
|
||||||
// 如果正在加载中,直接返回
|
// 如果正在加载中,直接返回
|
||||||
@@ -71,13 +77,33 @@ async function loadHistory({ done }: { done: any }) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 重新订阅
|
// 重新订阅
|
||||||
function reSubscribe(item: Subscribe) {
|
async function reSubscribe(item: Subscribe) {
|
||||||
|
if (item.type === '电影')
|
||||||
|
progressText.value = `正在重新订阅 ${item.name} ...`
|
||||||
|
else
|
||||||
|
progressText.value = `正在重新订阅 ${item.name} 第 ${item.season} 季 ...`
|
||||||
|
progressDialog.value = true
|
||||||
|
try {
|
||||||
|
const result: {[key: string]: any} = await api.post('subscribe', item)
|
||||||
|
if (result.success){
|
||||||
|
emit('save')
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e)
|
||||||
|
}
|
||||||
|
progressDialog.value = false
|
||||||
}
|
}
|
||||||
|
|
||||||
// 删除记录
|
// 删除记录
|
||||||
function deleteHistory(item: Subscribe) {
|
async function deleteHistory(item: Subscribe) {
|
||||||
|
try {
|
||||||
|
const result: {[key: string]: any} = await api.delete(`subscribe/history/${item.id}`)
|
||||||
|
if (result.success){
|
||||||
|
historyList.value = historyList.value.filter((i) => i.id !== item.id)
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 弹出菜单
|
// 弹出菜单
|
||||||
@@ -108,12 +134,15 @@ const dropdownItems = ref([
|
|||||||
<VDialog
|
<VDialog
|
||||||
scrollable
|
scrollable
|
||||||
max-width="50rem"
|
max-width="50rem"
|
||||||
|
max-height="90vh"
|
||||||
>
|
>
|
||||||
<VCard
|
<VCard
|
||||||
class="mx-auto"
|
class="mx-auto"
|
||||||
width="100%"
|
width="100%"
|
||||||
:title = "props.type + '订阅历史'"
|
|
||||||
>
|
>
|
||||||
|
<VCardItem class="pb-0">
|
||||||
|
<VCardTitle>{{ props.type + '订阅历史' }}</VCardTitle>
|
||||||
|
</VCardItem>
|
||||||
<DialogCloseBtn @click="() => { emit('close') }" />
|
<DialogCloseBtn @click="() => { emit('close') }" />
|
||||||
<VList
|
<VList
|
||||||
lines="two"
|
lines="two"
|
||||||
@@ -126,16 +155,7 @@ const dropdownItems = ref([
|
|||||||
@load="loadHistory"
|
@load="loadHistory"
|
||||||
>
|
>
|
||||||
<template #loading>
|
<template #loading>
|
||||||
<div
|
<LoadingBanner />
|
||||||
v-if="!isRefreshed"
|
|
||||||
class="w-full text-center text-gray-500 text-sm flex flex-col items-center"
|
|
||||||
>
|
|
||||||
<VProgressCircular
|
|
||||||
size="48"
|
|
||||||
indeterminate
|
|
||||||
color="primary"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
<template v-for="(item, i) in historyList" :key="i">
|
<template v-for="(item, i) in historyList" :key="i">
|
||||||
<VListItem>
|
<VListItem>
|
||||||
@@ -175,16 +195,16 @@ const dropdownItems = ref([
|
|||||||
>
|
>
|
||||||
<VList>
|
<VList>
|
||||||
<VListItem
|
<VListItem
|
||||||
v-for="(item, i) in dropdownItems"
|
v-for="(menu, i) in dropdownItems"
|
||||||
:key="i"
|
:key="i"
|
||||||
variant="plain"
|
variant="plain"
|
||||||
:base-color="item.color"
|
:base-color="menu.color"
|
||||||
@click="item.props.click"
|
@click="menu.props.click(item)"
|
||||||
>
|
>
|
||||||
<template #prepend>
|
<template #prepend>
|
||||||
<VIcon :icon="item.props.prependIcon" />
|
<VIcon :icon="menu.props.prependIcon" />
|
||||||
</template>
|
</template>
|
||||||
<VListItemTitle v-text="item.title" />
|
<VListItemTitle v-text="menu.title" />
|
||||||
</VListItem>
|
</VListItem>
|
||||||
</VList>
|
</VList>
|
||||||
</VMenu>
|
</VMenu>
|
||||||
@@ -199,5 +219,24 @@ const dropdownItems = ref([
|
|||||||
</VInfiniteScroll>
|
</VInfiniteScroll>
|
||||||
</VList>
|
</VList>
|
||||||
</VCard>
|
</VCard>
|
||||||
|
<!-- 进度框 -->
|
||||||
|
<VDialog
|
||||||
|
v-model="progressDialog"
|
||||||
|
:scrim="false"
|
||||||
|
width="25rem"
|
||||||
|
>
|
||||||
|
<VCard
|
||||||
|
color="primary"
|
||||||
|
>
|
||||||
|
<VCardText class="text-center">
|
||||||
|
{{ progressText }}
|
||||||
|
<VProgressLinear
|
||||||
|
indeterminate
|
||||||
|
color="white"
|
||||||
|
class="mb-0 mt-1"
|
||||||
|
/>
|
||||||
|
</VCardText>
|
||||||
|
</VCard>
|
||||||
|
</VDialog>
|
||||||
</VDialog>
|
</VDialog>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -18,7 +18,12 @@ import 'vue-toast-notification/dist/theme-bootstrap.css'
|
|||||||
import { PerfectScrollbarPlugin } from 'vue3-perfect-scrollbar';
|
import { PerfectScrollbarPlugin } from 'vue3-perfect-scrollbar';
|
||||||
import 'vue3-perfect-scrollbar/style.css';
|
import 'vue3-perfect-scrollbar/style.css';
|
||||||
import DialogCloseBtn from '@/@core/components/DialogCloseBtn.vue'
|
import DialogCloseBtn from '@/@core/components/DialogCloseBtn.vue'
|
||||||
|
import { fixArrayAt } from '@/@core/utils/compatibility'
|
||||||
|
|
||||||
|
// 修复低版本Safari等浏览器数组不支持at函数的问题
|
||||||
|
fixArrayAt()
|
||||||
|
|
||||||
|
// 加载字体
|
||||||
loadFonts()
|
loadFonts()
|
||||||
|
|
||||||
// 创建Vue实例
|
// 创建Vue实例
|
||||||
|
|||||||
@@ -120,11 +120,12 @@ onMounted(() => {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div v-if="!isRefreshed" class="mt-12 w-full text-center text-gray-500 text-sm flex flex-col items-center">
|
<LoadingBanner
|
||||||
<VProgressCircular v-if="!keyword" size="48" indeterminate color="primary" />
|
v-if="!isRefreshed"
|
||||||
<VProgressCircular v-if="keyword" class="mb-3" color="primary" :model-value="progressValue" size="64" />
|
class="mt-12"
|
||||||
<span>{{ progressText }}</span>
|
:text="progressText"
|
||||||
</div>
|
:progress="progressValue"
|
||||||
|
/>
|
||||||
<NoDataFound
|
<NoDataFound
|
||||||
v-if="dataList.length === 0 && isRefreshed"
|
v-if="dataList.length === 0 && isRefreshed"
|
||||||
:error-title="errorTitle"
|
:error-title="errorTitle"
|
||||||
|
|||||||
@@ -123,16 +123,10 @@ async function fetchData({ done }: { done: any }) {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div
|
<LoadingBanner
|
||||||
v-if="!isRefreshed"
|
v-if="!isRefreshed"
|
||||||
class="mt-12 w-full text-center text-gray-500 text-sm flex flex-col items-center"
|
class="mt-12"
|
||||||
>
|
/>
|
||||||
<VProgressCircular
|
|
||||||
size="48"
|
|
||||||
indeterminate
|
|
||||||
color="primary"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<VInfiniteScroll
|
<VInfiniteScroll
|
||||||
mode="intersect"
|
mode="intersect"
|
||||||
side="end"
|
side="end"
|
||||||
|
|||||||
@@ -457,16 +457,10 @@ onBeforeMount(() => {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div
|
<LoadingBanner
|
||||||
v-if="!isRefreshed"
|
v-if="!isRefreshed"
|
||||||
class="mt-12 w-full text-center text-gray-500 text-sm flex flex-col items-center"
|
class="mt-12"
|
||||||
>
|
/>
|
||||||
<VProgressCircular
|
|
||||||
size="48"
|
|
||||||
indeterminate
|
|
||||||
color="primary"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div v-if="mediaDetail.tmdb_id || mediaDetail.douban_id || mediaDetail.bangumi_id" class="max-w-8xl mx-auto px-4">
|
<div v-if="mediaDetail.tmdb_id || mediaDetail.douban_id || mediaDetail.bangumi_id" class="max-w-8xl mx-auto px-4">
|
||||||
<template v-if="mediaDetail.backdrop_path || mediaDetail.poster_path">
|
<template v-if="mediaDetail.backdrop_path || mediaDetail.poster_path">
|
||||||
<div class="vue-media-back absolute left-0 top-0 w-full h-96">
|
<div class="vue-media-back absolute left-0 top-0 w-full h-96">
|
||||||
@@ -638,16 +632,10 @@ onBeforeMount(() => {
|
|||||||
</VExpansionPanelTitle>
|
</VExpansionPanelTitle>
|
||||||
<VExpansionPanelText>
|
<VExpansionPanelText>
|
||||||
<template #default>
|
<template #default>
|
||||||
<div
|
<LoadingBanner
|
||||||
v-if="!seasonEpisodesInfo[season.season_number || 0]"
|
v-if="!seasonEpisodesInfo[season.season_number || 0]"
|
||||||
class="mt-3 w-full text-center text-gray-500 text-sm flex flex-col items-center"
|
class="mt-3"
|
||||||
>
|
/>
|
||||||
<VProgressCircular
|
|
||||||
size="48"
|
|
||||||
indeterminate
|
|
||||||
color="primary"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div class="flex flex-col justify-center divide-y divide-gray-700">
|
<div class="flex flex-col justify-center divide-y divide-gray-700">
|
||||||
<div v-for="episode in seasonEpisodesInfo[season.season_number || 0]" :key="episode.episode_number" class="flex flex-col space-y-4 py-4 xl:flex-row xl:space-y-4 xl:space-x-4">
|
<div v-for="episode in seasonEpisodesInfo[season.season_number || 0]" :key="episode.episode_number" class="flex flex-col space-y-4 py-4 xl:flex-row xl:space-y-4 xl:space-x-4">
|
||||||
<div class="flex-1">
|
<div class="flex-1">
|
||||||
|
|||||||
@@ -117,16 +117,10 @@ async function fetchData({ done }: { done: any }) {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div
|
<LoadingBanner
|
||||||
v-if="!isRefreshed"
|
v-if="!isRefreshed"
|
||||||
class="mt-12 w-full text-center text-gray-500 text-sm flex flex-col items-center"
|
class="mt-12"
|
||||||
>
|
/>
|
||||||
<VProgressCircular
|
|
||||||
size="48"
|
|
||||||
indeterminate
|
|
||||||
color="primary"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<VInfiniteScroll
|
<VInfiniteScroll
|
||||||
mode="intersect"
|
mode="intersect"
|
||||||
side="end"
|
side="end"
|
||||||
|
|||||||
@@ -48,16 +48,10 @@ onBeforeMount(() => {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div
|
<LoadingBanner
|
||||||
v-if="!isRefreshed"
|
v-if="!isRefreshed"
|
||||||
class="mt-12 w-full text-center text-gray-500 text-sm flex flex-col items-center"
|
class="mt-12"
|
||||||
>
|
/>
|
||||||
<VProgressCircular
|
|
||||||
size="48"
|
|
||||||
indeterminate
|
|
||||||
color="primary"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div v-if="personDetail.id" class="max-w-8xl mx-auto px-4">
|
<div v-if="personDetail.id" class="max-w-8xl mx-auto px-4">
|
||||||
<div class="relative z-10 mt-4 mb-8 flex flex-col items-center lg:flex-row ">
|
<div class="relative z-10 mt-4 mb-8 flex flex-col items-center lg:flex-row ">
|
||||||
<VAvatar
|
<VAvatar
|
||||||
|
|||||||
@@ -211,17 +211,10 @@ onBeforeMount(() => {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div
|
<LoadingBanner
|
||||||
v-if="!isRefreshed"
|
v-if="!isRefreshed"
|
||||||
class="mt-12 w-full text-center text-gray-500 text-sm flex flex-col items-center"
|
class="mt-12"
|
||||||
>
|
/>
|
||||||
<VProgressCircular
|
|
||||||
v-if="!isRefreshed"
|
|
||||||
size="48"
|
|
||||||
indeterminate
|
|
||||||
color="primary"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div
|
<div
|
||||||
v-if="dataList.length > 0"
|
v-if="dataList.length > 0"
|
||||||
class="grid gap-4 grid-plugin-card"
|
class="grid gap-4 grid-plugin-card"
|
||||||
@@ -285,17 +278,10 @@ onBeforeMount(() => {
|
|||||||
</VToolbar>
|
</VToolbar>
|
||||||
</div>
|
</div>
|
||||||
<VCardText>
|
<VCardText>
|
||||||
<div
|
<LoadingBanner
|
||||||
v-if="!isAppMarketLoaded"
|
v-if="!isAppMarketLoaded"
|
||||||
class="mt-12 w-full text-center text-gray-500 text-sm flex flex-col items-center"
|
class="mt-12"
|
||||||
>
|
/>
|
||||||
<VProgressCircular
|
|
||||||
v-if="!isAppMarketLoaded"
|
|
||||||
size="48"
|
|
||||||
indeterminate
|
|
||||||
color="primary"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div v-if="isAppMarketLoaded" class="grid gap-4 grid-plugin-card">
|
<div v-if="isAppMarketLoaded" class="grid gap-4 grid-plugin-card">
|
||||||
<PluginAppCard
|
<PluginAppCard
|
||||||
v-for="data in sortedUninstalledList"
|
v-for="data in sortedUninstalledList"
|
||||||
|
|||||||
@@ -67,17 +67,10 @@ onUnmounted(() => {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div
|
<LoadingBanner
|
||||||
v-if="!isRefreshed"
|
v-if="!isRefreshed"
|
||||||
class="mt-12 w-full text-center text-gray-500 text-sm flex flex-col items-center"
|
class="mt-12"
|
||||||
>
|
/>
|
||||||
<VProgressCircular
|
|
||||||
v-if="!isRefreshed"
|
|
||||||
size="48"
|
|
||||||
indeterminate
|
|
||||||
color="primary"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<PullRefresh
|
<PullRefresh
|
||||||
v-model="loading"
|
v-model="loading"
|
||||||
@refresh="onRefresh"
|
@refresh="onRefresh"
|
||||||
|
|||||||
@@ -35,17 +35,10 @@ onBeforeMount(fetchData)
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div
|
<LoadingBanner
|
||||||
v-if="!isRefreshed"
|
v-if="!isRefreshed"
|
||||||
class="mt-12 w-full text-center text-gray-500 text-sm flex flex-col items-center"
|
class="mt-12"
|
||||||
>
|
/>
|
||||||
<VProgressCircular
|
|
||||||
v-if="!isRefreshed"
|
|
||||||
size="48"
|
|
||||||
indeterminate
|
|
||||||
color="primary"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div
|
<div
|
||||||
v-if="dataList.length > 0"
|
v-if="dataList.length > 0"
|
||||||
class="grid gap-3 grid-site-card"
|
class="grid gap-3 grid-site-card"
|
||||||
|
|||||||
@@ -62,17 +62,10 @@ const filteredDataList = computed(() => {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div
|
<LoadingBanner
|
||||||
v-if="!isRefreshed"
|
v-if="!isRefreshed"
|
||||||
class="mt-12 w-full text-center text-gray-500 text-sm flex flex-col items-center"
|
class="mt-12"
|
||||||
>
|
/>
|
||||||
<VProgressCircular
|
|
||||||
v-if="!isRefreshed"
|
|
||||||
size="48"
|
|
||||||
indeterminate
|
|
||||||
color="primary"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<PullRefresh
|
<PullRefresh
|
||||||
v-model="loading"
|
v-model="loading"
|
||||||
@refresh="onRefresh"
|
@refresh="onRefresh"
|
||||||
@@ -132,6 +125,7 @@ const filteredDataList = computed(() => {
|
|||||||
v-model="historyDialog"
|
v-model="historyDialog"
|
||||||
:type="props.type"
|
:type="props.type"
|
||||||
@close="historyDialog = false"
|
@close="historyDialog = false"
|
||||||
|
@save="() => {historyDialog = false; fetchData()}"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user