mirror of
https://github.com/jxxghp/MoviePilot-Frontend.git
synced 2026-05-18 05:57:35 +08:00
feat:订阅和插件支持手动排序
This commit is contained in:
@@ -149,80 +149,82 @@ const dropdownItems = ref([
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<VCard :width="props.width" :height="props.height" @click="installPlugin" class="flex flex-col">
|
||||
<div class="me-n3 absolute bottom-0 right-3">
|
||||
<IconBtn>
|
||||
<VIcon icon="mdi-dots-vertical" />
|
||||
<VMenu activator="parent" close-on-content-click>
|
||||
<VList>
|
||||
<VListItem
|
||||
v-for="(item, i) in dropdownItems"
|
||||
v-show="item.show"
|
||||
:key="i"
|
||||
variant="plain"
|
||||
@click="item.props.click"
|
||||
>
|
||||
<template #prepend>
|
||||
<VIcon :icon="item.props.prependIcon" />
|
||||
</template>
|
||||
<VListItemTitle v-text="item.title" />
|
||||
</VListItem>
|
||||
</VList>
|
||||
</VMenu>
|
||||
</IconBtn>
|
||||
</div>
|
||||
<div
|
||||
class="relative flex flex-row items-start pa-3 justify-between grow"
|
||||
:style="{ background: `${backgroundColor}` }"
|
||||
>
|
||||
<div>
|
||||
<VCard :width="props.width" :height="props.height" @click="installPlugin" class="flex flex-col h-full">
|
||||
<div
|
||||
class="absolute inset-0 bg-cover bg-center"
|
||||
:style="{ background: `${backgroundColor}`, filter: 'brightness(0.5)' }"
|
||||
></div>
|
||||
<div class="relative flex-1 min-w-0">
|
||||
<VCardTitle class="text-white px-2 text-shadow whitespace-nowrap overflow-hidden text-ellipsis">
|
||||
{{ props.plugin?.plugin_name }}
|
||||
<span class="text-sm text-gray-200">v{{ props.plugin?.plugin_version }}</span>
|
||||
</VCardTitle>
|
||||
<VCardText class="text-white px-2 py-1 text-shadow line-clamp-3">
|
||||
{{ props.plugin?.plugin_desc }}
|
||||
</VCardText>
|
||||
class="relative flex flex-row items-start pa-3 justify-between grow"
|
||||
:style="{ background: `${backgroundColor}` }"
|
||||
>
|
||||
<div
|
||||
class="absolute inset-0 bg-cover bg-center"
|
||||
:style="{ background: `${backgroundColor}`, filter: 'brightness(0.5)' }"
|
||||
></div>
|
||||
<div class="relative flex-1 min-w-0">
|
||||
<VCardTitle class="text-white px-2 text-shadow whitespace-nowrap overflow-hidden text-ellipsis">
|
||||
{{ props.plugin?.plugin_name }}
|
||||
<span class="text-sm text-gray-200">v{{ props.plugin?.plugin_version }}</span>
|
||||
</VCardTitle>
|
||||
<VCardText class="text-white px-2 py-1 text-shadow line-clamp-3">
|
||||
{{ props.plugin?.plugin_desc }}
|
||||
</VCardText>
|
||||
</div>
|
||||
<div class="relative flex-shrink-0 self-center">
|
||||
<VAvatar size="64">
|
||||
<VImg
|
||||
ref="imageRef"
|
||||
:src="iconPath"
|
||||
aspect-ratio="4/3"
|
||||
cover
|
||||
:class="{ shadow: isImageLoaded }"
|
||||
@load="imageLoaded"
|
||||
@error="imageLoadError = true"
|
||||
/>
|
||||
</VAvatar>
|
||||
</div>
|
||||
</div>
|
||||
<div class="relative flex-shrink-0 self-center">
|
||||
<VAvatar size="64">
|
||||
<VImg
|
||||
ref="imageRef"
|
||||
:src="iconPath"
|
||||
aspect-ratio="4/3"
|
||||
cover
|
||||
:class="{ shadow: isImageLoaded }"
|
||||
@load="imageLoaded"
|
||||
@error="imageLoadError = true"
|
||||
/>
|
||||
</VAvatar>
|
||||
</div>
|
||||
</div>
|
||||
<VCardText class="flex flex-none align-self-baseline py-3 w-full align-end">
|
||||
<span>
|
||||
<VIcon icon="mdi-github" class="me-1" />
|
||||
<a :href="props.plugin?.author_url" target="_blank" @click.stop>
|
||||
{{ props.plugin?.plugin_author }}
|
||||
</a>
|
||||
</span>
|
||||
<span v-if="props.count" class="ms-3">
|
||||
<VIcon icon="mdi-download" />
|
||||
<span class="text-sm ms-1 mt-1">{{ props.count?.toLocaleString() }}</span>
|
||||
</span>
|
||||
</VCardText>
|
||||
</VCard>
|
||||
<!-- 安装插件进度框 -->
|
||||
<ProgressDialog v-if="progressDialog" v-model="progressDialog" :text="progressText" />
|
||||
<!-- 更新日志 -->
|
||||
<VDialog v-if="releaseDialog" v-model="releaseDialog" width="600" scrollable>
|
||||
<VCard :title="`${props.plugin?.plugin_name} 更新说明`">
|
||||
<DialogCloseBtn @click="releaseDialog = false" />
|
||||
<VDivider />
|
||||
<VersionHistory :history="props.plugin?.history" />
|
||||
<VCardText class="flex flex-none align-self-baseline py-3 w-full align-end">
|
||||
<span>
|
||||
<VIcon icon="mdi-github" class="me-1" />
|
||||
<a :href="props.plugin?.author_url" target="_blank" @click.stop>
|
||||
{{ props.plugin?.plugin_author }}
|
||||
</a>
|
||||
</span>
|
||||
<span v-if="props.count" class="ms-3">
|
||||
<VIcon icon="mdi-download" />
|
||||
<span class="text-sm ms-1 mt-1">{{ props.count?.toLocaleString() }}</span>
|
||||
</span>
|
||||
<div class="me-n3 absolute bottom-1 right-3">
|
||||
<IconBtn>
|
||||
<VIcon icon="mdi-dots-vertical" />
|
||||
<VMenu activator="parent" close-on-content-click>
|
||||
<VList>
|
||||
<VListItem
|
||||
v-for="(item, i) in dropdownItems"
|
||||
v-show="item.show"
|
||||
:key="i"
|
||||
variant="plain"
|
||||
@click="item.props.click"
|
||||
>
|
||||
<template #prepend>
|
||||
<VIcon :icon="item.props.prependIcon" />
|
||||
</template>
|
||||
<VListItemTitle v-text="item.title" />
|
||||
</VListItem>
|
||||
</VList>
|
||||
</VMenu>
|
||||
</IconBtn>
|
||||
</div>
|
||||
</VCardText>
|
||||
</VCard>
|
||||
</VDialog>
|
||||
<!-- 安装插件进度框 -->
|
||||
<ProgressDialog v-if="progressDialog" v-model="progressDialog" :text="progressText" />
|
||||
<!-- 更新日志 -->
|
||||
<VDialog v-if="releaseDialog" v-model="releaseDialog" width="600" scrollable>
|
||||
<VCard :title="`${props.plugin?.plugin_name} 更新说明`">
|
||||
<DialogCloseBtn @click="releaseDialog = false" />
|
||||
<VDivider />
|
||||
<VersionHistory :history="props.plugin?.history" />
|
||||
</VCard>
|
||||
</VDialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -390,130 +390,146 @@ watch(
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<!-- 插件卡片 -->
|
||||
<VCard v-if="isVisible" :width="props.width" :height="props.height" @click="openPluginDetail" class="flex flex-col">
|
||||
<div class="me-n3 absolute bottom-0 right-3">
|
||||
<IconBtn>
|
||||
<VIcon icon="mdi-dots-vertical" />
|
||||
<VMenu activator="parent" close-on-content-click>
|
||||
<VList>
|
||||
<VListItem
|
||||
v-for="(item, i) in dropdownItems"
|
||||
v-show="item.show"
|
||||
:key="i"
|
||||
variant="plain"
|
||||
:base-color="item.props.color"
|
||||
@click="item.props.click"
|
||||
>
|
||||
<template #prepend>
|
||||
<VIcon :icon="item.props.prependIcon" />
|
||||
</template>
|
||||
<VListItemTitle v-text="item.title" />
|
||||
</VListItem>
|
||||
</VList>
|
||||
</VMenu>
|
||||
</IconBtn>
|
||||
</div>
|
||||
<div
|
||||
class="relative flex flex-row items-start pa-3 justify-between grow"
|
||||
:style="{ background: `${backgroundColor}` }"
|
||||
>
|
||||
<div
|
||||
class="absolute inset-0 bg-cover bg-center"
|
||||
:style="{ background: `${backgroundColor}`, filter: 'brightness(0.5)' }"
|
||||
/>
|
||||
<div class="relative flex-1 min-w-0">
|
||||
<VCardTitle class="text-white px-2 text-shadow whitespace-nowrap overflow-hidden text-ellipsis">
|
||||
<VBadge v-if="props.plugin?.state" dot inline color="success" />
|
||||
{{ props.plugin?.plugin_name }}
|
||||
<span class="text-sm mt-1 text-gray-200">v{{ props.plugin?.plugin_version }}</span>
|
||||
</VCardTitle>
|
||||
<VCardText class="px-2 py-1 text-white text-shadow line-clamp-3">
|
||||
{{ props.plugin?.plugin_desc }}
|
||||
<div>
|
||||
<!-- 插件卡片 -->
|
||||
<VHover>
|
||||
<template #default="hover">
|
||||
<VCard
|
||||
v-if="isVisible"
|
||||
v-bind="hover.props"
|
||||
:width="props.width"
|
||||
:height="props.height"
|
||||
@click="openPluginDetail"
|
||||
class="flex flex-col h-full"
|
||||
>
|
||||
<div
|
||||
class="relative flex flex-row items-start pa-3 justify-between grow"
|
||||
:style="{ background: `${backgroundColor}` }"
|
||||
>
|
||||
<div
|
||||
class="absolute inset-0 bg-cover bg-center"
|
||||
:style="{ background: `${backgroundColor}`, filter: 'brightness(0.5)' }"
|
||||
/>
|
||||
<div class="relative flex-1 min-w-0">
|
||||
<VCardTitle class="text-white px-2 text-shadow whitespace-nowrap overflow-hidden text-ellipsis">
|
||||
<VBadge v-if="props.plugin?.state" dot inline color="success" />
|
||||
{{ props.plugin?.plugin_name }}
|
||||
<span class="text-sm mt-1 text-gray-200">v{{ props.plugin?.plugin_version }}</span>
|
||||
</VCardTitle>
|
||||
<VCardText class="px-2 py-1 text-white text-shadow line-clamp-3">
|
||||
{{ props.plugin?.plugin_desc }}
|
||||
</VCardText>
|
||||
</div>
|
||||
<div class="relative flex-shrink-0 self-center">
|
||||
<VAvatar size="64">
|
||||
<VImg
|
||||
ref="imageRef"
|
||||
:src="iconPath"
|
||||
aspect-ratio="4/3"
|
||||
cover
|
||||
:class="{ shadow: isImageLoaded }"
|
||||
@load="imageLoaded"
|
||||
@error="imageLoadError = true"
|
||||
/>
|
||||
</VAvatar>
|
||||
</div>
|
||||
</div>
|
||||
<VCardText class="flex flex-none align-self-baseline py-3 w-full align-end">
|
||||
<span class="author-info">
|
||||
<VImg :src="authorPath" class="author-avatar" @load="isAvatarLoaded = true">
|
||||
<VIcon v-if="!isAvatarLoaded" icon="mdi-github" class="me-1" />
|
||||
</VImg>
|
||||
<a :href="props.plugin?.author_url" target="_blank" @click.stop>
|
||||
{{ props.plugin?.plugin_author }}
|
||||
</a>
|
||||
</span>
|
||||
<span v-if="props.count" class="ms-3">
|
||||
<VIcon icon="mdi-download" />
|
||||
<span class="text-sm ms-1 mt-1">{{ props.count?.toLocaleString() }}</span>
|
||||
</span>
|
||||
<div class="me-n3 absolute bottom-1 right-3">
|
||||
<IconBtn>
|
||||
<VIcon icon="mdi-dots-vertical" />
|
||||
<VMenu activator="parent" close-on-content-click>
|
||||
<VList>
|
||||
<VListItem
|
||||
v-for="(item, i) in dropdownItems"
|
||||
v-show="item.show"
|
||||
:key="i"
|
||||
variant="plain"
|
||||
:base-color="item.props.color"
|
||||
@click="item.props.click"
|
||||
>
|
||||
<template #prepend>
|
||||
<VIcon :icon="item.props.prependIcon" />
|
||||
</template>
|
||||
<VListItemTitle v-text="item.title" />
|
||||
</VListItem>
|
||||
</VList>
|
||||
</VMenu>
|
||||
</IconBtn>
|
||||
</div>
|
||||
</VCardText>
|
||||
<div v-if="hover.isHovering" class="me-n3 absolute top-0 right-5">
|
||||
<VIcon class="cursor-move text-white">mdi-drag</VIcon>
|
||||
</div>
|
||||
<div v-else-if="props.plugin?.has_update" class="me-n3 absolute top-0 right-5">
|
||||
<VIcon icon="mdi-new-box" class="text-white" />
|
||||
</div>
|
||||
</VCard>
|
||||
</template>
|
||||
</VHover>
|
||||
|
||||
<!-- 插件配置页面 -->
|
||||
<VDialog v-model="pluginConfigDialog" scrollable max-width="60rem" :fullscreen="!display.mdAndUp.value">
|
||||
<VCard :title="`${props.plugin?.plugin_name} - 配置`" class="rounded-t">
|
||||
<DialogCloseBtn v-model="pluginConfigDialog" />
|
||||
<VDivider />
|
||||
<VCardText>
|
||||
<FormRender v-for="(item, index) in pluginFormItems" :key="index" :config="item" :form="pluginConfigForm" />
|
||||
</VCardText>
|
||||
</div>
|
||||
<div class="relative flex-shrink-0 self-center">
|
||||
<VAvatar size="64">
|
||||
<VImg
|
||||
ref="imageRef"
|
||||
:src="iconPath"
|
||||
aspect-ratio="4/3"
|
||||
cover
|
||||
:class="{ shadow: isImageLoaded }"
|
||||
@load="imageLoaded"
|
||||
@error="imageLoadError = true"
|
||||
/>
|
||||
</VAvatar>
|
||||
</div>
|
||||
</div>
|
||||
<VCardText class="flex flex-none align-self-baseline py-3 w-full align-end">
|
||||
<span class="author-info">
|
||||
<VImg :src="authorPath" class="author-avatar" @load="isAvatarLoaded = true">
|
||||
<VIcon v-if="!isAvatarLoaded" icon="mdi-github" class="me-1" />
|
||||
</VImg>
|
||||
<a :href="props.plugin?.author_url" target="_blank" @click.stop>
|
||||
{{ props.plugin?.plugin_author }}
|
||||
</a>
|
||||
</span>
|
||||
<span v-if="props.count" class="ms-3">
|
||||
<VIcon icon="mdi-download" />
|
||||
<span class="text-sm ms-1 mt-1">{{ props.count?.toLocaleString() }}</span>
|
||||
</span>
|
||||
</VCardText>
|
||||
<div v-if="props.plugin?.has_update" class="me-n3 absolute top-0 right-5">
|
||||
<VIcon icon="mdi-new-box" class="text-white" />
|
||||
</div>
|
||||
</VCard>
|
||||
<VCardActions class="pt-3">
|
||||
<VBtn v-if="pluginPageItems.length > 0" @click="showPluginInfo" variant="outlined" color="info">
|
||||
查看数据
|
||||
</VBtn>
|
||||
<VSpacer />
|
||||
<VBtn @click="savePluginConf" variant="elevated" prepend-icon="mdi-content-save" class="px-5"> 保存 </VBtn>
|
||||
</VCardActions>
|
||||
</VCard>
|
||||
</VDialog>
|
||||
|
||||
<!-- 插件配置页面 -->
|
||||
<VDialog v-model="pluginConfigDialog" scrollable max-width="60rem" :fullscreen="!display.mdAndUp.value">
|
||||
<VCard :title="`${props.plugin?.plugin_name} - 配置`" class="rounded-t">
|
||||
<DialogCloseBtn v-model="pluginConfigDialog" />
|
||||
<VDivider />
|
||||
<VCardText>
|
||||
<FormRender v-for="(item, index) in pluginFormItems" :key="index" :config="item" :form="pluginConfigForm" />
|
||||
</VCardText>
|
||||
<VCardActions class="pt-3">
|
||||
<VBtn v-if="pluginPageItems.length > 0" @click="showPluginInfo" variant="outlined" color="info">
|
||||
查看数据
|
||||
</VBtn>
|
||||
<VSpacer />
|
||||
<VBtn @click="savePluginConf" variant="elevated" prepend-icon="mdi-content-save" class="px-5"> 保存 </VBtn>
|
||||
</VCardActions>
|
||||
</VCard>
|
||||
</VDialog>
|
||||
<!-- 插件数据页面 -->
|
||||
<VDialog v-model="pluginInfoDialog" scrollable max-width="80rem" :fullscreen="!display.mdAndUp.value">
|
||||
<VCard :title="`${props.plugin?.plugin_name}`" class="rounded-t">
|
||||
<DialogCloseBtn v-model="pluginInfoDialog" />
|
||||
<VCardText class="min-h-40">
|
||||
<PageRender @action="loadPluginPage" v-for="(item, index) in pluginPageItems" :key="index" :config="item" />
|
||||
</VCardText>
|
||||
<VFab icon="mdi-cog" location="bottom" size="x-large" fixed app appear @click="showPluginConfig" />
|
||||
</VCard>
|
||||
</VDialog>
|
||||
|
||||
<!-- 插件数据页面 -->
|
||||
<VDialog v-model="pluginInfoDialog" scrollable max-width="80rem" :fullscreen="!display.mdAndUp.value">
|
||||
<VCard :title="`${props.plugin?.plugin_name}`" class="rounded-t">
|
||||
<DialogCloseBtn v-model="pluginInfoDialog" />
|
||||
<VCardText class="min-h-40">
|
||||
<PageRender @action="loadPluginPage" v-for="(item, index) in pluginPageItems" :key="index" :config="item" />
|
||||
</VCardText>
|
||||
<VFab icon="mdi-cog" location="bottom" size="x-large" fixed app appear @click="showPluginConfig" />
|
||||
</VCard>
|
||||
</VDialog>
|
||||
<!-- 进度框 -->
|
||||
<ProgressDialog v-if="progressDialog" v-model="progressDialog" :text="progressText" />
|
||||
|
||||
<!-- 进度框 -->
|
||||
<ProgressDialog v-if="progressDialog" v-model="progressDialog" :text="progressText" />
|
||||
|
||||
<!-- 更新日志 -->
|
||||
<VDialog v-if="releaseDialog" v-model="releaseDialog" width="600" scrollable>
|
||||
<VCard :title="`${props.plugin?.plugin_name} 更新说明`">
|
||||
<DialogCloseBtn @click="releaseDialog = false" />
|
||||
<VDivider />
|
||||
<VersionHistory :history="props.plugin?.history" />
|
||||
<VDivider />
|
||||
<VCardText>
|
||||
<VBtn @click="updatePlugin" block>
|
||||
<template #prepend>
|
||||
<VIcon icon="mdi-arrow-up-circle-outline" />
|
||||
</template>
|
||||
更新到最新版本
|
||||
</VBtn>
|
||||
</VCardText>
|
||||
</VCard>
|
||||
</VDialog>
|
||||
<!-- 更新日志 -->
|
||||
<VDialog v-if="releaseDialog" v-model="releaseDialog" width="600" scrollable>
|
||||
<VCard :title="`${props.plugin?.plugin_name} 更新说明`">
|
||||
<DialogCloseBtn @click="releaseDialog = false" />
|
||||
<VDivider />
|
||||
<VersionHistory :history="props.plugin?.history" />
|
||||
<VDivider />
|
||||
<VCardText>
|
||||
<VBtn @click="updatePlugin" block>
|
||||
<template #prepend>
|
||||
<VIcon icon="mdi-arrow-up-circle-outline" />
|
||||
</template>
|
||||
更新到最新版本
|
||||
</VBtn>
|
||||
</VCardText>
|
||||
</VCard>
|
||||
</VDialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
@@ -271,134 +271,136 @@ function onSubscribeEditRemove() {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<VHover>
|
||||
<template #default="hover">
|
||||
<VCard
|
||||
v-bind="hover.props"
|
||||
:key="props.media?.id"
|
||||
class="flex flex-col rounded-lg"
|
||||
:class="{
|
||||
'outline-dashed outline-1': props.media?.best_version && imageLoaded,
|
||||
'transition transform-cpu duration-300 scale-105 shadow-lg': hover.isHovering,
|
||||
'opacity-70': subscribeState === 'S',
|
||||
}"
|
||||
min-height="170"
|
||||
@click="editSubscribeDialog"
|
||||
>
|
||||
<div class="me-n3 absolute top-1 right-2">
|
||||
<IconBtn>
|
||||
<VIcon icon="mdi-dots-vertical" color="white" />
|
||||
<VMenu activator="parent" close-on-content-click>
|
||||
<VList>
|
||||
<template v-for="(item, i) in dropdownItems" :key="i">
|
||||
<VListItem
|
||||
v-if="item.show !== false"
|
||||
variant="plain"
|
||||
:base-color="item.props.color"
|
||||
@click="item.props.click"
|
||||
>
|
||||
<template #prepend>
|
||||
<VIcon :icon="item.props.prependIcon" />
|
||||
</template>
|
||||
<VListItemTitle v-text="item.title" />
|
||||
</VListItem>
|
||||
</template>
|
||||
</VList>
|
||||
</VMenu>
|
||||
</IconBtn>
|
||||
</div>
|
||||
<template #image>
|
||||
<VImg :src="backdropUrl || posterUrl" aspect-ratio="3/2" cover @load="imageLoadHandler" position="top">
|
||||
<template #placeholder>
|
||||
<div class="w-full h-full">
|
||||
<VSkeletonLoader class="object-cover aspect-w-3 aspect-h-2" />
|
||||
</div>
|
||||
</template>
|
||||
<div class="absolute inset-0 subscribe-card-background"></div>
|
||||
</VImg>
|
||||
<div
|
||||
v-if="subscribeState === 'P'"
|
||||
class="absolute inset-0 bg-yellow-900 opacity-40 pointer-events-none"
|
||||
></div>
|
||||
</template>
|
||||
<div>
|
||||
<VCardText class="flex items-center">
|
||||
<div class="h-auto w-12 flex-shrink-0 overflow-hidden rounded-md shadow-lg" v-if="imageLoaded">
|
||||
<VImg :src="posterUrl" aspect-ratio="2/3" cover @click.stop="viewMediaDetail">
|
||||
<template #placeholder>
|
||||
<div class="w-full h-full">
|
||||
<VSkeletonLoader class="object-cover aspect-w-2 aspect-h-3" />
|
||||
</div>
|
||||
</template>
|
||||
</VImg>
|
||||
</div>
|
||||
<div class="flex flex-col justify-center overflow-hidden pl-2 xl:pl-4">
|
||||
<div class="text-sm font-medium text-white sm:pt-1">{{ props.media?.year }}</div>
|
||||
<div class="mr-2 min-w-0 text-lg font-bold text-white">
|
||||
{{ props.media?.name }}
|
||||
{{ formatSeason(props.media?.season ? props.media?.season.toString() : '') }}
|
||||
</div>
|
||||
</div>
|
||||
</VCardText>
|
||||
<VCardText class="flex justify-space-between align-center flex-wrap">
|
||||
<div class="flex align-center">
|
||||
<IconBtn
|
||||
v-if="props.media?.total_episode"
|
||||
v-bind="props"
|
||||
icon="mdi-progress-download"
|
||||
color="white"
|
||||
class="me-1"
|
||||
/>
|
||||
<div v-if="props.media?.season" class="text-subtitle-2 me-4 text-white">
|
||||
{{ (props.media?.total_episode || 0) - (props.media?.lack_episode || 0) }} /
|
||||
{{ props.media?.total_episode }}
|
||||
</div>
|
||||
<IconBtn v-if="props.media?.username" icon="mdi-account" color="white" class="me-1" />
|
||||
<span v-if="props.media?.username" class="text-subtitle-2 me-4 text-white">
|
||||
{{ props.media?.username }}
|
||||
</span>
|
||||
</div>
|
||||
</VCardText>
|
||||
<VCardText v-if="lastUpdateText" class="absolute right-0 bottom-0 d-flex align-center p-2 text-gray-300">
|
||||
<VIcon icon="mdi-download" class="me-1" />
|
||||
{{ lastUpdateText }}
|
||||
</VCardText>
|
||||
<div class="w-full absolute bottom-0">
|
||||
<VProgressLinear
|
||||
v-if="getPercentage() > 0"
|
||||
:model-value="getPercentage()"
|
||||
bg-color="success"
|
||||
color="success"
|
||||
/>
|
||||
<div>
|
||||
<VHover>
|
||||
<template #default="hover">
|
||||
<VCard
|
||||
v-bind="hover.props"
|
||||
:key="props.media?.id"
|
||||
class="flex flex-col rounded-lg h-full"
|
||||
:class="{
|
||||
'outline-dashed outline-1': props.media?.best_version && imageLoaded,
|
||||
'transition transform-cpu duration-300 scale-105 shadow-lg': hover.isHovering,
|
||||
'opacity-70': subscribeState === 'S',
|
||||
}"
|
||||
min-height="170"
|
||||
@click="editSubscribeDialog"
|
||||
>
|
||||
<div class="me-n3 absolute top-1 right-2">
|
||||
<IconBtn>
|
||||
<VIcon icon="mdi-dots-vertical" color="white" />
|
||||
<VMenu activator="parent" close-on-content-click>
|
||||
<VList>
|
||||
<template v-for="(item, i) in dropdownItems" :key="i">
|
||||
<VListItem
|
||||
v-if="item.show !== false"
|
||||
variant="plain"
|
||||
:base-color="item.props.color"
|
||||
@click="item.props.click"
|
||||
>
|
||||
<template #prepend>
|
||||
<VIcon :icon="item.props.prependIcon" />
|
||||
</template>
|
||||
<VListItemTitle v-text="item.title" />
|
||||
</VListItem>
|
||||
</template>
|
||||
</VList>
|
||||
</VMenu>
|
||||
</IconBtn>
|
||||
</div>
|
||||
</div>
|
||||
</VCard>
|
||||
</template>
|
||||
</VHover>
|
||||
<!-- 订阅编辑弹窗 -->
|
||||
<SubscribeEditDialog
|
||||
v-if="subscribeEditDialog"
|
||||
v-model="subscribeEditDialog"
|
||||
:subid="props.media?.id"
|
||||
@remove="onSubscribeEditRemove"
|
||||
@save="onSubscribeEditSave"
|
||||
@close="subscribeEditDialog = false"
|
||||
/>
|
||||
<template #image>
|
||||
<VImg :src="backdropUrl || posterUrl" aspect-ratio="3/2" cover @load="imageLoadHandler" position="top">
|
||||
<template #placeholder>
|
||||
<div class="w-full h-full">
|
||||
<VSkeletonLoader class="object-cover aspect-w-3 aspect-h-2" />
|
||||
</div>
|
||||
</template>
|
||||
<div class="absolute inset-0 subscribe-card-background"></div>
|
||||
</VImg>
|
||||
<div v-if="subscribeState === 'P'" class="absolute inset-0 bg-yellow-900 opacity-80 pointer-events-none" />
|
||||
</template>
|
||||
<div>
|
||||
<VCardText class="flex items-center">
|
||||
<div class="h-auto w-12 flex-shrink-0 overflow-hidden rounded-md shadow-lg" v-if="imageLoaded">
|
||||
<VImg :src="posterUrl" aspect-ratio="2/3" cover @click.stop="viewMediaDetail">
|
||||
<template #placeholder>
|
||||
<div class="w-full h-full">
|
||||
<VSkeletonLoader class="object-cover aspect-w-2 aspect-h-3" />
|
||||
</div>
|
||||
</template>
|
||||
</VImg>
|
||||
</div>
|
||||
<div class="flex flex-col justify-center overflow-hidden pl-2 xl:pl-4">
|
||||
<div class="text-sm font-medium text-white sm:pt-1">{{ props.media?.year }}</div>
|
||||
<div class="mr-2 min-w-0 text-lg font-bold text-white">
|
||||
{{ props.media?.name }}
|
||||
{{ formatSeason(props.media?.season ? props.media?.season.toString() : '') }}
|
||||
</div>
|
||||
</div>
|
||||
</VCardText>
|
||||
<VCardText class="flex justify-space-between align-center flex-wrap">
|
||||
<div class="flex align-center">
|
||||
<IconBtn
|
||||
v-if="props.media?.total_episode"
|
||||
v-bind="props"
|
||||
icon="mdi-progress-download"
|
||||
color="white"
|
||||
class="me-1"
|
||||
/>
|
||||
<div v-if="props.media?.season" class="text-subtitle-2 me-4 text-white">
|
||||
{{ (props.media?.total_episode || 0) - (props.media?.lack_episode || 0) }} /
|
||||
{{ props.media?.total_episode }}
|
||||
</div>
|
||||
<IconBtn v-if="props.media?.username" icon="mdi-account" color="white" class="me-1" />
|
||||
<span v-if="props.media?.username" class="text-subtitle-2 me-4 text-white">
|
||||
{{ props.media?.username }}
|
||||
</span>
|
||||
</div>
|
||||
</VCardText>
|
||||
<VCardText v-if="lastUpdateText" class="absolute right-0 bottom-0 d-flex align-center p-2 text-gray-300">
|
||||
<VIcon icon="mdi-download" class="me-1" />
|
||||
{{ lastUpdateText }}
|
||||
</VCardText>
|
||||
<div class="w-full absolute bottom-0">
|
||||
<VProgressLinear
|
||||
v-if="getPercentage() > 0"
|
||||
:model-value="getPercentage()"
|
||||
bg-color="success"
|
||||
color="success"
|
||||
/>
|
||||
</div>
|
||||
<div v-if="hover.isHovering" class="me-n3 absolute top-1 right-10">
|
||||
<IconBtn><VIcon class="cursor-move text-white">mdi-drag</VIcon></IconBtn>
|
||||
</div>
|
||||
</div>
|
||||
</VCard>
|
||||
</template>
|
||||
</VHover>
|
||||
<!-- 订阅编辑弹窗 -->
|
||||
<SubscribeEditDialog
|
||||
v-if="subscribeEditDialog"
|
||||
v-model="subscribeEditDialog"
|
||||
:subid="props.media?.id"
|
||||
@remove="onSubscribeEditRemove"
|
||||
@save="onSubscribeEditSave"
|
||||
@close="subscribeEditDialog = false"
|
||||
/>
|
||||
|
||||
<!-- 订阅文件信息弹窗 -->
|
||||
<SubscribeFilesDialog
|
||||
v-if="subscribeFilesDialog"
|
||||
v-model="subscribeFilesDialog"
|
||||
:subid="props.media?.id"
|
||||
@close="subscribeFilesDialog = false"
|
||||
/>
|
||||
<!-- 分享订阅弹窗 -->
|
||||
<SubscribeShareDialog
|
||||
v-if="subscribeShareDialog"
|
||||
v-model="subscribeShareDialog"
|
||||
:sub="props.media"
|
||||
@close="subscribeShareDialog = false"
|
||||
/>
|
||||
<!-- 订阅文件信息弹窗 -->
|
||||
<SubscribeFilesDialog
|
||||
v-if="subscribeFilesDialog"
|
||||
v-model="subscribeFilesDialog"
|
||||
:subid="props.media?.id"
|
||||
@close="subscribeFilesDialog = false"
|
||||
/>
|
||||
<!-- 分享订阅弹窗 -->
|
||||
<SubscribeShareDialog
|
||||
v-if="subscribeShareDialog"
|
||||
v-model="subscribeShareDialog"
|
||||
:sub="props.media"
|
||||
@close="subscribeShareDialog = false"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
<style lang="scss">
|
||||
.subscribe-card-background {
|
||||
|
||||
Reference in New Issue
Block a user