mirror of
https://github.com/jxxghp/MoviePilot-Frontend.git
synced 2026-09-05 23:56:42 +08:00
feat:订阅历史
This commit is contained in:
@@ -88,6 +88,9 @@ export interface Subscribe {
|
|||||||
|
|
||||||
// 保存目录
|
// 保存目录
|
||||||
save_path: string
|
save_path: string
|
||||||
|
|
||||||
|
// 时间
|
||||||
|
date: string
|
||||||
}
|
}
|
||||||
|
|
||||||
// 历史记录
|
// 历史记录
|
||||||
|
|||||||
@@ -1,9 +1,8 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import type { Axios } from 'axios'
|
import type { Axios } from 'axios'
|
||||||
import axios from 'axios'
|
import axios from 'axios'
|
||||||
import List from './filebrowser/List.vue'
|
import FileList from './filebrowser/FileList.vue'
|
||||||
|
import FileToolbar from './filebrowser/FileToolbar.vue'
|
||||||
import Toolbar from './filebrowser/Toolbar.vue'
|
|
||||||
import type { EndPoints } from '@/api/types'
|
import type { EndPoints } from '@/api/types'
|
||||||
|
|
||||||
// 输入参数
|
// 输入参数
|
||||||
@@ -100,7 +99,7 @@ onMounted(() => {
|
|||||||
<template>
|
<template>
|
||||||
<VCard class="mx-auto" :loading="loading > 0 || !path">
|
<VCard class="mx-auto" :loading="loading > 0 || !path">
|
||||||
<div v-if="path">
|
<div v-if="path">
|
||||||
<Toolbar
|
<FileToolbar
|
||||||
:path="path"
|
:path="path"
|
||||||
:storages="storagesArray"
|
:storages="storagesArray"
|
||||||
:storage="activeStorage"
|
:storage="activeStorage"
|
||||||
@@ -111,7 +110,7 @@ onMounted(() => {
|
|||||||
@foldercreated="refreshPending = true"
|
@foldercreated="refreshPending = true"
|
||||||
@sortchanged="sortChanged"
|
@sortchanged="sortChanged"
|
||||||
/>
|
/>
|
||||||
<List
|
<FileList
|
||||||
:path="path"
|
:path="path"
|
||||||
:storage="activeStorage"
|
:storage="activeStorage"
|
||||||
:icons="fileIcons"
|
:icons="fileIcons"
|
||||||
|
|||||||
@@ -1,50 +0,0 @@
|
|||||||
<script setup lang="ts">
|
|
||||||
import { kFormatter } from '@core/utils/formatters'
|
|
||||||
|
|
||||||
interface Props {
|
|
||||||
title: string
|
|
||||||
color?: string
|
|
||||||
icon: string
|
|
||||||
stats: number
|
|
||||||
change: number
|
|
||||||
}
|
|
||||||
|
|
||||||
const props = withDefaults(defineProps<Props>(), {
|
|
||||||
color: 'primary',
|
|
||||||
})
|
|
||||||
|
|
||||||
const isPositive = controlledComputed(() => props.change, () => Math.sign(props.change) === 1)
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<VCard>
|
|
||||||
<VCardText class="d-flex align-center">
|
|
||||||
<VAvatar
|
|
||||||
size="44"
|
|
||||||
rounded
|
|
||||||
:color="props.color"
|
|
||||||
variant="tonal"
|
|
||||||
class="me-4"
|
|
||||||
>
|
|
||||||
<VIcon
|
|
||||||
:icon="props.icon"
|
|
||||||
size="30"
|
|
||||||
/>
|
|
||||||
</VAvatar>
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<span class="text-caption">{{ props.title }}</span>
|
|
||||||
<div class="d-flex align-center flex-wrap">
|
|
||||||
<span class="text-h6 font-weight-semibold">{{ kFormatter(props.stats) }}</span>
|
|
||||||
<div
|
|
||||||
v-if="props.change"
|
|
||||||
:class="`${isPositive ? 'text-success' : 'text-error'} mt-1`"
|
|
||||||
>
|
|
||||||
<VIcon :icon="isPositive ? 'mdi-chevron-up' : 'mdi-chevron-down'" />
|
|
||||||
<span class="text-caption font-weight-semibold">{{ Math.abs(props.change) }}%</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</VCardText>
|
|
||||||
</VCard>
|
|
||||||
</template>
|
|
||||||
@@ -1,56 +0,0 @@
|
|||||||
<script setup lang="ts">
|
|
||||||
interface Props {
|
|
||||||
title: string
|
|
||||||
color?: string
|
|
||||||
icon: string
|
|
||||||
stats: string
|
|
||||||
change: number
|
|
||||||
subtitle: string
|
|
||||||
}
|
|
||||||
|
|
||||||
const props = withDefaults(defineProps<Props>(), {
|
|
||||||
color: 'primary',
|
|
||||||
})
|
|
||||||
|
|
||||||
const isPositive = controlledComputed(() => props.change, () => Math.sign(props.change) === 1)
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<VCard>
|
|
||||||
<VCardText class="d-flex align-center">
|
|
||||||
<VAvatar
|
|
||||||
v-if="props.icon"
|
|
||||||
size="38"
|
|
||||||
:color="props.color"
|
|
||||||
>
|
|
||||||
<VIcon
|
|
||||||
:icon="props.icon"
|
|
||||||
size="24"
|
|
||||||
/>
|
|
||||||
</VAvatar>
|
|
||||||
|
|
||||||
<VSpacer />
|
|
||||||
|
|
||||||
<MoreBtn class="me-n3 mt-n1" />
|
|
||||||
</VCardText>
|
|
||||||
|
|
||||||
<VCardText>
|
|
||||||
<h6 class="text-sm font-weight-semibold mb-2">
|
|
||||||
{{ props.title }}
|
|
||||||
</h6>
|
|
||||||
<div
|
|
||||||
v-if="props.change"
|
|
||||||
class="d-flex align-center mb-2"
|
|
||||||
>
|
|
||||||
<span class="font-weight-semibold text-h5 me-2">{{ props.stats }}</span>
|
|
||||||
<span
|
|
||||||
:class="isPositive ? 'text-success' : 'text-error'"
|
|
||||||
class="text-caption"
|
|
||||||
>
|
|
||||||
{{ isPositive ? `+${props.change}` : props.change }}%
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<span class="text-caption">{{ props.subtitle }}</span>
|
|
||||||
</VCardText>
|
|
||||||
</VCard>
|
|
||||||
</template>
|
|
||||||
@@ -1,65 +0,0 @@
|
|||||||
<script setup lang="ts">
|
|
||||||
interface Props {
|
|
||||||
title: string
|
|
||||||
subtitle: string
|
|
||||||
stats: string
|
|
||||||
change: number
|
|
||||||
image: string
|
|
||||||
color?: string
|
|
||||||
}
|
|
||||||
|
|
||||||
const props = withDefaults(defineProps<Props>(), {
|
|
||||||
color: 'primary',
|
|
||||||
})
|
|
||||||
|
|
||||||
const isPositive = controlledComputed(() => props.change, () => Math.sign(props.change) === 1)
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<VCard class="overflow-visible">
|
|
||||||
<div class="d-flex position-relative">
|
|
||||||
<VCardText>
|
|
||||||
<h6 class="text-base font-weight-semibold mb-4">
|
|
||||||
{{ props.title }}
|
|
||||||
</h6>
|
|
||||||
<div class="d-flex align-center flex-wrap mb-4">
|
|
||||||
<h5 class="text-h5 font-weight-semibold me-2">
|
|
||||||
{{ props.stats }}
|
|
||||||
</h5>
|
|
||||||
<span
|
|
||||||
class="text-caption"
|
|
||||||
:class="isPositive ? 'text-success' : 'text-error'"
|
|
||||||
>
|
|
||||||
{{ isPositive ? `+${props.change}` : props.change }}%
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<VChip
|
|
||||||
v-if="props.subtitle"
|
|
||||||
size="small"
|
|
||||||
:color="props.color"
|
|
||||||
>
|
|
||||||
{{ props.subtitle }}
|
|
||||||
</VChip>
|
|
||||||
</VCardText>
|
|
||||||
|
|
||||||
<VSpacer />
|
|
||||||
|
|
||||||
<div class="illustrator-img">
|
|
||||||
<VImg
|
|
||||||
v-if="props.image"
|
|
||||||
:src="props.image"
|
|
||||||
:width="110"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</VCard>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<style lang="scss">
|
|
||||||
.illustrator-img {
|
|
||||||
position: absolute;
|
|
||||||
inset-block-end: 0;
|
|
||||||
inset-inline-end: 5%;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { useToast } from 'vue-toast-notification'
|
import { useToast } from 'vue-toast-notification'
|
||||||
import TmdbSelectorCard from '../cards/TmdbSelectorCard.vue'
|
import TmdbSelector from '../misc/TmdbSelector.vue'
|
||||||
import store from '@/store'
|
import store from '@/store'
|
||||||
import api from '@/api'
|
import api from '@/api'
|
||||||
import { numberValidator } from '@/@validators'
|
import { numberValidator } from '@/@validators'
|
||||||
@@ -306,7 +306,7 @@ async function transfer() {
|
|||||||
scrollable
|
scrollable
|
||||||
max-height="85vh"
|
max-height="85vh"
|
||||||
>
|
>
|
||||||
<TmdbSelectorCard
|
<TmdbSelector
|
||||||
v-model="transferForm.tmdbid"
|
v-model="transferForm.tmdbid"
|
||||||
@close="tmdbSelectorDialog = false"
|
@close="tmdbSelectorDialog = false"
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ const subscribeForm = ref<Subscribe>({
|
|||||||
username: '',
|
username: '',
|
||||||
current_priority: 0,
|
current_priority: 0,
|
||||||
save_path: '',
|
save_path: '',
|
||||||
|
date: ''
|
||||||
})
|
})
|
||||||
|
|
||||||
// 提示框
|
// 提示框
|
||||||
@@ -265,169 +266,164 @@ onMounted(() => {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<VDialog
|
<VCard
|
||||||
scrollable
|
:title="`${props.default ? `${props.type}默认订阅规则` : `编辑订阅 - ${subscribeForm.name} ${subscribeForm.season ? `第 ${subscribeForm.season} 季` : ''}`}`"
|
||||||
max-width="60rem"
|
class="rounded-t"
|
||||||
>
|
>
|
||||||
<VCard
|
<VCardText class="pt-2">
|
||||||
:title="`${props.default ? `设置${props.type}默认订阅规则` : `编辑订阅 - ${subscribeForm.name} ${subscribeForm.season ? `第 ${subscribeForm.season} 季` : ''}`}`"
|
<DialogCloseBtn @click="emit('close')" />
|
||||||
class="rounded-t"
|
<VForm @submit.prevent="() => {}">
|
||||||
>
|
<VRow>
|
||||||
<VCardText class="pt-2">
|
<VCol
|
||||||
<DialogCloseBtn @click="emit('close')" />
|
cols="12"
|
||||||
<VForm @submit.prevent="() => {}">
|
md="8"
|
||||||
<VRow>
|
>
|
||||||
<VCol
|
<VTextField
|
||||||
cols="12"
|
v-if="!props.default"
|
||||||
md="8"
|
v-model="subscribeForm.keyword"
|
||||||
>
|
label="搜索关键词"
|
||||||
<VTextField
|
hint="设定搜索关键词后,将使用此关键词搜索站点资源,否则自动使用themoviedb中的名称搜索"
|
||||||
v-if="!props.default"
|
/>
|
||||||
v-model="subscribeForm.keyword"
|
</VCol>
|
||||||
label="搜索关键词"
|
<VCol
|
||||||
hint="设定搜索关键词后,将使用此关键词搜索站点资源,否则自动使用themoviedb中的名称搜索"
|
v-if="subscribeForm.type === '电视剧'"
|
||||||
/>
|
cols="12"
|
||||||
</VCol>
|
md="2"
|
||||||
<VCol
|
>
|
||||||
v-if="subscribeForm.type === '电视剧'"
|
<VTextField
|
||||||
cols="12"
|
v-model="subscribeForm.total_episode"
|
||||||
md="2"
|
label="总集数"
|
||||||
>
|
:rules="[numberValidator]"
|
||||||
<VTextField
|
hint="设定剧集的总集数,以应对themoviedb中剧集信息未维护完整,导致提前结束订阅的情况"
|
||||||
v-model="subscribeForm.total_episode"
|
/>
|
||||||
label="总集数"
|
</VCol>
|
||||||
:rules="[numberValidator]"
|
<VCol
|
||||||
hint="设定剧集的总集数,以应对themoviedb中剧集信息未维护完整,导致提前结束订阅的情况"
|
v-if="subscribeForm.type === '电视剧'"
|
||||||
/>
|
cols="12"
|
||||||
</VCol>
|
md="2"
|
||||||
<VCol
|
>
|
||||||
v-if="subscribeForm.type === '电视剧'"
|
<VTextField
|
||||||
cols="12"
|
v-model="subscribeForm.start_episode"
|
||||||
md="2"
|
label="开始集数"
|
||||||
>
|
:rules="[numberValidator]"
|
||||||
<VTextField
|
hint="只订阅下载此集数及之后的剧集"
|
||||||
v-model="subscribeForm.start_episode"
|
/>
|
||||||
label="开始集数"
|
</VCol>
|
||||||
:rules="[numberValidator]"
|
</VRow>
|
||||||
hint="只订阅下载此集数及之后的剧集"
|
<VRow>
|
||||||
/>
|
<VCol
|
||||||
</VCol>
|
cols="12"
|
||||||
</VRow>
|
md="4"
|
||||||
<VRow>
|
>
|
||||||
<VCol
|
<VSelect
|
||||||
cols="12"
|
v-model="subscribeForm.quality"
|
||||||
md="4"
|
label="质量"
|
||||||
>
|
:items="qualityOptions"
|
||||||
<VSelect
|
/>
|
||||||
v-model="subscribeForm.quality"
|
</VCol>
|
||||||
label="质量"
|
<VCol
|
||||||
:items="qualityOptions"
|
cols="12"
|
||||||
/>
|
md="4"
|
||||||
</VCol>
|
>
|
||||||
<VCol
|
<VSelect
|
||||||
cols="12"
|
v-model="subscribeForm.resolution"
|
||||||
md="4"
|
label="分辨率"
|
||||||
>
|
:items="resolutionOptions"
|
||||||
<VSelect
|
/>
|
||||||
v-model="subscribeForm.resolution"
|
</VCol>
|
||||||
label="分辨率"
|
<VCol
|
||||||
:items="resolutionOptions"
|
cols="12"
|
||||||
/>
|
md="4"
|
||||||
</VCol>
|
>
|
||||||
<VCol
|
<VSelect
|
||||||
cols="12"
|
v-model="subscribeForm.effect"
|
||||||
md="4"
|
label="特效"
|
||||||
>
|
:items="effectOptions"
|
||||||
<VSelect
|
/>
|
||||||
v-model="subscribeForm.effect"
|
</VCol>
|
||||||
label="特效"
|
</VRow>
|
||||||
:items="effectOptions"
|
<VRow>
|
||||||
/>
|
<VCol
|
||||||
</VCol>
|
cols="12"
|
||||||
</VRow>
|
md="4"
|
||||||
<VRow>
|
>
|
||||||
<VCol
|
<VTextField
|
||||||
cols="12"
|
v-model="subscribeForm.include"
|
||||||
md="4"
|
label="包含(关键字、正则式)"
|
||||||
>
|
hint="支持正则表达式,多个关键字用 | 分隔表示或"
|
||||||
<VTextField
|
/>
|
||||||
v-model="subscribeForm.include"
|
</VCol>
|
||||||
label="包含(关键字、正则式)"
|
<VCol
|
||||||
hint="支持正则表达式,多个关键字用 | 分隔表示或"
|
cols="12"
|
||||||
/>
|
md="4"
|
||||||
</VCol>
|
>
|
||||||
<VCol
|
<VTextField
|
||||||
cols="12"
|
v-model="subscribeForm.exclude"
|
||||||
md="4"
|
label="排除(关键字、正则式)"
|
||||||
>
|
hint="支持正则表达式,多个关键字用 | 分隔表示或"
|
||||||
<VTextField
|
/>
|
||||||
v-model="subscribeForm.exclude"
|
</VCol>
|
||||||
label="排除(关键字、正则式)"
|
<VCol
|
||||||
hint="支持正则表达式,多个关键字用 | 分隔表示或"
|
cols="12"
|
||||||
/>
|
md="4"
|
||||||
</VCol>
|
>
|
||||||
<VCol
|
<VSelect
|
||||||
cols="12"
|
v-model="subscribeForm.sites"
|
||||||
md="4"
|
:items="selectSitesOptions"
|
||||||
>
|
chips
|
||||||
<VSelect
|
label="订阅站点"
|
||||||
v-model="subscribeForm.sites"
|
multiple
|
||||||
:items="selectSitesOptions"
|
hint="只订阅选中的订阅站点,不选则订阅所有可订阅站点"
|
||||||
chips
|
/>
|
||||||
label="订阅站点"
|
</VCol>
|
||||||
multiple
|
</VRow>
|
||||||
hint="只订阅选中的订阅站点,不选则订阅所有可订阅站点"
|
<VRow>
|
||||||
/>
|
<VCol
|
||||||
</VCol>
|
cols="12"
|
||||||
</VRow>
|
>
|
||||||
<VRow>
|
<VTextField
|
||||||
<VCol
|
v-model="subscribeForm.save_path"
|
||||||
cols="12"
|
label="保存路径"
|
||||||
>
|
hint="指定该订阅的下载保存路径,留空自动使用设定的下载目录"
|
||||||
<VTextField
|
/>
|
||||||
v-model="subscribeForm.save_path"
|
</VCol>
|
||||||
label="保存路径"
|
</VRow>
|
||||||
hint="指定该订阅的下载保存路径,留空自动使用设定的下载目录"
|
<VRow>
|
||||||
/>
|
<VCol
|
||||||
</VCol>
|
cols="12"
|
||||||
</VRow>
|
md="4"
|
||||||
<VRow>
|
>
|
||||||
<VCol
|
<VSwitch
|
||||||
cols="12"
|
v-model="subscribeForm.best_version"
|
||||||
md="4"
|
label="洗版"
|
||||||
>
|
hint="开启后不管媒体库是否存在,均会根据洗版优先级进行过滤下载,直到下载到了最高优先级的资源为止"
|
||||||
<VSwitch
|
/>
|
||||||
v-model="subscribeForm.best_version"
|
</VCol>
|
||||||
label="洗版"
|
<VCol
|
||||||
hint="开启后不管媒体库是否存在,均会根据洗版优先级进行过滤下载,直到下载到了最高优先级的资源为止"
|
cols="12"
|
||||||
/>
|
md="4"
|
||||||
</VCol>
|
>
|
||||||
<VCol
|
<VSwitch
|
||||||
cols="12"
|
v-model="subscribeForm.search_imdbid"
|
||||||
md="4"
|
label="使用 ImdbID 搜索"
|
||||||
>
|
hint="开启后将使用 ImdbID 搜索资源,搜索结果更精确,但不是所有站点都支持"
|
||||||
<VSwitch
|
/>
|
||||||
v-model="subscribeForm.search_imdbid"
|
</VCol>
|
||||||
label="使用 ImdbID 搜索"
|
</VRow>
|
||||||
hint="开启后将使用 ImdbID 搜索资源,搜索结果更精确,但不是所有站点都支持"
|
</VForm>
|
||||||
/>
|
</VCardText>
|
||||||
</VCol>
|
|
||||||
</VRow>
|
|
||||||
</VForm>
|
|
||||||
</VCardText>
|
|
||||||
|
|
||||||
<VCardActions>
|
<VCardActions>
|
||||||
<VBtn v-if="!props.default" color="error" @click="removeSubscribe">
|
<VBtn v-if="!props.default" color="error" @click="removeSubscribe">
|
||||||
取消订阅
|
取消订阅
|
||||||
</VBtn>
|
</VBtn>
|
||||||
<VSpacer />
|
<VSpacer />
|
||||||
<VBtn
|
<VBtn
|
||||||
variant="tonal"
|
variant="tonal"
|
||||||
@click="`${props.default ? saveDefaultSubscribeConfig() : updateSubscribeInfo()}`"
|
@click="`${props.default ? saveDefaultSubscribeConfig() : updateSubscribeInfo()}`"
|
||||||
>
|
>
|
||||||
保存
|
保存
|
||||||
</VBtn>
|
</VBtn>
|
||||||
</VCardActions>
|
</VCardActions>
|
||||||
</VCard>
|
</VCard>
|
||||||
</VDialog>
|
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -0,0 +1,197 @@
|
|||||||
|
<script lang="ts" setup>
|
||||||
|
import api from '@/api';
|
||||||
|
import { Subscribe } from '@/api/types';
|
||||||
|
import { formatDateDifference } from '@core/utils/formatters'
|
||||||
|
|
||||||
|
// 输入参数
|
||||||
|
const props = defineProps({
|
||||||
|
type: String,
|
||||||
|
})
|
||||||
|
|
||||||
|
// 定义触发的自定义事件
|
||||||
|
const emit = defineEmits(['close'])
|
||||||
|
|
||||||
|
// 订阅历史列表
|
||||||
|
const historyList = ref<Subscribe[]>([])
|
||||||
|
|
||||||
|
// 当前加载数据
|
||||||
|
const currData = ref<Subscribe[]>([])
|
||||||
|
|
||||||
|
// 当前页
|
||||||
|
const currentPage = ref(1)
|
||||||
|
|
||||||
|
// 每页数量
|
||||||
|
const pageSize = ref(30)
|
||||||
|
|
||||||
|
// 是否加载中
|
||||||
|
const loading = ref(false)
|
||||||
|
|
||||||
|
// 是否加载完成
|
||||||
|
const isRefreshed = ref(false)
|
||||||
|
|
||||||
|
// 调用API查询列表
|
||||||
|
async function loadHistory({ done }: { done: any }) {
|
||||||
|
// 如果正在加载中,直接返回
|
||||||
|
if (loading.value) {
|
||||||
|
done('ok')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 设置加载中
|
||||||
|
loading.value = true
|
||||||
|
|
||||||
|
// 调用API查询列表
|
||||||
|
try {
|
||||||
|
currData.value = await api.get(`subscribe/history/${props.type}`, {
|
||||||
|
params: {
|
||||||
|
page: currentPage.value,
|
||||||
|
count: pageSize.value,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
// 标计为已请求完成
|
||||||
|
isRefreshed.value = true
|
||||||
|
if (currData.value.length === 0) {
|
||||||
|
// 如果没有数据,跳出
|
||||||
|
done('ok')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// 合并数据
|
||||||
|
historyList.value = [...historyList.value, ...currData.value]
|
||||||
|
// 页码+1
|
||||||
|
currentPage.value++
|
||||||
|
// 取消加载中
|
||||||
|
loading.value = false
|
||||||
|
// 返回加载成功
|
||||||
|
done('ok')
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e)
|
||||||
|
// 返回加载失败
|
||||||
|
done('error')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 重新订阅
|
||||||
|
function reSubscribe(item: Subscribe) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// 删除记录
|
||||||
|
function deleteHistory(item: Subscribe) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// 弹出菜单
|
||||||
|
const dropdownItems = ref([
|
||||||
|
{
|
||||||
|
title: '重新订阅',
|
||||||
|
value: 1,
|
||||||
|
color: '',
|
||||||
|
props: {
|
||||||
|
prependIcon: 'mdi-redo',
|
||||||
|
click: reSubscribe,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '删除',
|
||||||
|
value: 2,
|
||||||
|
color: 'error',
|
||||||
|
props: {
|
||||||
|
prependIcon: 'mdi-delete',
|
||||||
|
click: deleteHistory,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
])
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<VCard
|
||||||
|
class="mx-auto"
|
||||||
|
width="100%"
|
||||||
|
:title = "props.type + '订阅历史'"
|
||||||
|
>
|
||||||
|
<DialogCloseBtn @click="() => { emit('close') }" />
|
||||||
|
<div
|
||||||
|
v-if="!isRefreshed"
|
||||||
|
class="mt-12 w-full text-center text-gray-500 text-sm flex flex-col items-center"
|
||||||
|
>
|
||||||
|
<VProgressCircular
|
||||||
|
size="48"
|
||||||
|
indeterminate
|
||||||
|
color="primary"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<VList
|
||||||
|
lines="two"
|
||||||
|
>
|
||||||
|
<VInfiniteScroll
|
||||||
|
mode="intersect"
|
||||||
|
side="end"
|
||||||
|
:items="historyList"
|
||||||
|
class="overflow-hidden"
|
||||||
|
@load="loadHistory"
|
||||||
|
>
|
||||||
|
<template #loading />
|
||||||
|
<template v-for="(item, i) in historyList" :key="i">
|
||||||
|
<VListItem>
|
||||||
|
<template #prepend>
|
||||||
|
<VImg
|
||||||
|
height="75"
|
||||||
|
width="50"
|
||||||
|
:src="item.poster"
|
||||||
|
aspect-ratio="2/3"
|
||||||
|
class="object-cover rounded shadow ring-gray-500 me-3"
|
||||||
|
cover
|
||||||
|
>
|
||||||
|
<template #placeholder>
|
||||||
|
<div class="w-full h-full">
|
||||||
|
<VSkeletonLoader class="object-cover aspect-w-2 aspect-h-3" />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</VImg>
|
||||||
|
</template>
|
||||||
|
<VListItemTitle v-if="item.type == '电视剧'">
|
||||||
|
{{ item.name }} <span class="text-sm">第 {{ item.season }} 季</span>
|
||||||
|
</VListItemTitle>
|
||||||
|
<VListItemTitle v-else>
|
||||||
|
{{ item.name }}
|
||||||
|
</VListItemTitle>
|
||||||
|
<VListItemSubtitle class="mt-2">{{ formatDateDifference(item.date) }}</VListItemSubtitle>
|
||||||
|
<VListItemSubtitle class="mt-2">{{ item.description }}</VListItemSubtitle>
|
||||||
|
<template #append>
|
||||||
|
<div class="me-n3">
|
||||||
|
<IconBtn>
|
||||||
|
<VIcon
|
||||||
|
icon="mdi-dots-vertical"
|
||||||
|
/>
|
||||||
|
<VMenu
|
||||||
|
activator="parent"
|
||||||
|
close-on-content-click
|
||||||
|
>
|
||||||
|
<VList>
|
||||||
|
<VListItem
|
||||||
|
v-for="(item, i) in dropdownItems"
|
||||||
|
:key="i"
|
||||||
|
variant="plain"
|
||||||
|
:base-color="item.color"
|
||||||
|
@click="item.props.click"
|
||||||
|
>
|
||||||
|
<template #prepend>
|
||||||
|
<VIcon :icon="item.props.prependIcon" />
|
||||||
|
</template>
|
||||||
|
<VListItemTitle v-text="item.title" />
|
||||||
|
</VListItem>
|
||||||
|
</VList>
|
||||||
|
</VMenu>
|
||||||
|
</IconBtn>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</VListItem>
|
||||||
|
</template>
|
||||||
|
</VInfiniteScroll>
|
||||||
|
</VList>
|
||||||
|
<VCardText v-if="historyList.length == 0 && isRefreshed" class="text-center">
|
||||||
|
没有数据
|
||||||
|
</VCardText>
|
||||||
|
</VCard>
|
||||||
|
</template>
|
||||||
@@ -5,6 +5,7 @@ import type { Subscribe } from '@/api/types'
|
|||||||
import NoDataFound from '@/components/NoDataFound.vue'
|
import NoDataFound from '@/components/NoDataFound.vue'
|
||||||
import SubscribeCard from '@/components/cards/SubscribeCard.vue'
|
import SubscribeCard from '@/components/cards/SubscribeCard.vue'
|
||||||
import SubscribeEditForm from '@/components/form/SubscribeEditForm.vue'
|
import SubscribeEditForm from '@/components/form/SubscribeEditForm.vue'
|
||||||
|
import SubscribeHistory from '@/components/misc/SubscribeHistory.vue'
|
||||||
import store from '@/store'
|
import store from '@/store'
|
||||||
|
|
||||||
// 输入参数
|
// 输入参数
|
||||||
@@ -21,6 +22,9 @@ const dataList = ref<Subscribe[]>([])
|
|||||||
// 弹窗
|
// 弹窗
|
||||||
const subscribeEditDialog = ref(false)
|
const subscribeEditDialog = ref(false)
|
||||||
|
|
||||||
|
// 历史记录弹窗
|
||||||
|
const historyDialog = ref(false)
|
||||||
|
|
||||||
// 获取订阅列表数据
|
// 获取订阅列表数据
|
||||||
async function fetchData() {
|
async function fetchData() {
|
||||||
try {
|
try {
|
||||||
@@ -102,15 +106,43 @@ const filteredDataList = computed(() => {
|
|||||||
appear
|
appear
|
||||||
@click="subscribeEditDialog = true"
|
@click="subscribeEditDialog = true"
|
||||||
/>
|
/>
|
||||||
|
<VFab
|
||||||
|
icon="mdi-history"
|
||||||
|
color="info"
|
||||||
|
location="bottom end"
|
||||||
|
class="mb-2"
|
||||||
|
size="x-large"
|
||||||
|
fixed
|
||||||
|
app
|
||||||
|
appear
|
||||||
|
@click="historyDialog = true"
|
||||||
|
/>
|
||||||
<!-- 订阅编辑弹窗 -->
|
<!-- 订阅编辑弹窗 -->
|
||||||
<SubscribeEditForm
|
<VDialog
|
||||||
v-if="subscribeEditDialog"
|
v-if="subscribeEditDialog"
|
||||||
v-model="subscribeEditDialog"
|
v-model="subscribeEditDialog"
|
||||||
:default="true"
|
scrollable
|
||||||
:type="props.type"
|
max-width="60rem"
|
||||||
@save="subscribeEditDialog = false"
|
>
|
||||||
@close="subscribeEditDialog = false"
|
<SubscribeEditForm
|
||||||
/>
|
:default="true"
|
||||||
|
:type="props.type"
|
||||||
|
@save="subscribeEditDialog = false"
|
||||||
|
@close="subscribeEditDialog = false"
|
||||||
|
/>
|
||||||
|
</VDialog>
|
||||||
|
<!-- 历史记录弹窗 -->
|
||||||
|
<VDialog
|
||||||
|
v-if="historyDialog"
|
||||||
|
v-model="historyDialog"
|
||||||
|
scrollable
|
||||||
|
max-width="50rem"
|
||||||
|
>
|
||||||
|
<SubscribeHistory
|
||||||
|
:type="props.type"
|
||||||
|
@close="historyDialog = false"
|
||||||
|
/>
|
||||||
|
</VDialog>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
|
|||||||
Reference in New Issue
Block a user