mirror of
https://github.com/jxxghp/MoviePilot-Frontend.git
synced 2026-09-04 23:18:44 +08:00
feat(PluginAppCard, PluginCard): 添加插件详情弹窗并优化样式
This commit is contained in:
@@ -43,11 +43,8 @@ const imageLoadError = ref(false)
|
|||||||
// 更新日志弹窗
|
// 更新日志弹窗
|
||||||
const releaseDialog = ref(false)
|
const releaseDialog = ref(false)
|
||||||
|
|
||||||
// 计算插件标签
|
// 插件详情弹窗
|
||||||
const pluginLabels = computed(() => {
|
const detailDialog = ref(false)
|
||||||
if (!props.plugin?.plugin_label) return []
|
|
||||||
return props.plugin.plugin_label.split(',')
|
|
||||||
})
|
|
||||||
|
|
||||||
// 图片加载完成
|
// 图片加载完成
|
||||||
async function imageLoaded() {
|
async function imageLoaded() {
|
||||||
@@ -76,7 +73,7 @@ async function installPlugin() {
|
|||||||
|
|
||||||
if (result.success) {
|
if (result.success) {
|
||||||
$toast.success(`插件 ${props.plugin?.plugin_name} 安装成功!`)
|
$toast.success(`插件 ${props.plugin?.plugin_name} 安装成功!`)
|
||||||
|
detailDialog.value = false
|
||||||
// 通知父组件刷新
|
// 通知父组件刷新
|
||||||
emit('install')
|
emit('install')
|
||||||
} else {
|
} else {
|
||||||
@@ -150,7 +147,7 @@ const dropdownItems = ref([
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<VCard :width="props.width" :height="props.height" @click="installPlugin" class="flex flex-col h-full">
|
<VCard :width="props.width" :height="props.height" @click="detailDialog = true" class="flex flex-col h-full">
|
||||||
<div
|
<div
|
||||||
class="relative flex flex-row items-start pa-3 justify-between grow"
|
class="relative flex flex-row items-start pa-3 justify-between grow"
|
||||||
:style="{ background: `${backgroundColor}` }"
|
:style="{ background: `${backgroundColor}` }"
|
||||||
@@ -160,11 +157,11 @@ const dropdownItems = ref([
|
|||||||
:style="{ background: `${backgroundColor}`, filter: 'brightness(0.5)' }"
|
:style="{ background: `${backgroundColor}`, filter: 'brightness(0.5)' }"
|
||||||
></div>
|
></div>
|
||||||
<div class="relative flex-1 min-w-0">
|
<div class="relative flex-1 min-w-0">
|
||||||
<VCardTitle class="text-white px-2 text-shadow whitespace-nowrap overflow-hidden text-ellipsis">
|
<VCardTitle class="text-white text-lg px-2 text-shadow whitespace-nowrap overflow-hidden text-ellipsis">
|
||||||
{{ props.plugin?.plugin_name }}
|
{{ props.plugin?.plugin_name }}
|
||||||
<span class="text-sm text-gray-200">v{{ props.plugin?.plugin_version }}</span>
|
<span class="text-sm text-gray-200">v{{ props.plugin?.plugin_version }}</span>
|
||||||
</VCardTitle>
|
</VCardTitle>
|
||||||
<VCardText class="text-white px-2 py-1 text-shadow line-clamp-3">
|
<VCardText class="text-white text-sm px-2 py-1 text-shadow line-clamp-3">
|
||||||
{{ props.plugin?.plugin_desc }}
|
{{ props.plugin?.plugin_desc }}
|
||||||
</VCardText>
|
</VCardText>
|
||||||
</div>
|
</div>
|
||||||
@@ -226,5 +223,64 @@ const dropdownItems = ref([
|
|||||||
<VersionHistory :history="props.plugin?.history" />
|
<VersionHistory :history="props.plugin?.history" />
|
||||||
</VCard>
|
</VCard>
|
||||||
</VDialog>
|
</VDialog>
|
||||||
|
<!-- 插件详情-->
|
||||||
|
<VDialog v-if="detailDialog" v-model="detailDialog" max-width="30rem">
|
||||||
|
<VCard>
|
||||||
|
<DialogCloseBtn @click="detailDialog = false" />
|
||||||
|
<VCardText>
|
||||||
|
<VCol>
|
||||||
|
<div class="d-flex justify-space-between flex-wrap flex-md-nowrap flex-column flex-md-row">
|
||||||
|
<div class="mx-auto mt-5">
|
||||||
|
<VAvatar size="64">
|
||||||
|
<VImg
|
||||||
|
ref="imageRef"
|
||||||
|
:src="iconPath"
|
||||||
|
aspect-ratio="4/3"
|
||||||
|
cover
|
||||||
|
:class="{ shadow: isImageLoaded }"
|
||||||
|
@load="imageLoaded"
|
||||||
|
@error="imageLoadError = true"
|
||||||
|
/>
|
||||||
|
</VAvatar>
|
||||||
|
</div>
|
||||||
|
<div class="flex-grow">
|
||||||
|
<VCardItem>
|
||||||
|
<VCardTitle class="text-center text-md-left">
|
||||||
|
{{ props.plugin?.plugin_name }}
|
||||||
|
</VCardTitle>
|
||||||
|
<VCardSubtitle
|
||||||
|
class="text-center text-md-left break-words whitespace-break-spaces line-clamp-4 overflow-hidden text-ellipsis ..."
|
||||||
|
>
|
||||||
|
{{ props.plugin?.plugin_desc }}
|
||||||
|
</VCardSubtitle>
|
||||||
|
<VList lines="one">
|
||||||
|
<VListItem class="ps-0">
|
||||||
|
<VListItemTitle class="text-center text-md-left">
|
||||||
|
<span class="font-weight-medium">版本:</span>
|
||||||
|
<span class="text-body-1"> v{{ props.plugin?.plugin_version }}</span>
|
||||||
|
</VListItemTitle>
|
||||||
|
</VListItem>
|
||||||
|
<VListItem class="ps-0">
|
||||||
|
<VListItemTitle class="text-center text-md-left">
|
||||||
|
<span class="font-weight-medium">作者:</span>
|
||||||
|
<span class="text-body-1 cursor-pointer" @click="visitPluginPage">
|
||||||
|
{{ props.plugin?.plugin_author }}
|
||||||
|
</span>
|
||||||
|
</VListItemTitle>
|
||||||
|
</VListItem>
|
||||||
|
</VList>
|
||||||
|
<div class="text-center text-md-left">
|
||||||
|
<VBtn color="primary" @click="installPlugin" prepend-icon="mdi-download"> 安装到本地 </VBtn>
|
||||||
|
<div class="text-xs mt-2" v-if="props.count">
|
||||||
|
<VIcon icon="mdi-fire" />共 {{ props.count?.toLocaleString() }} 次下载
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</VCardItem>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</VCol>
|
||||||
|
</VCardText>
|
||||||
|
</VCard>
|
||||||
|
</VDialog>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { useToast } from 'vue-toast-notification'
|
import { useToast } from 'vue-toast-notification'
|
||||||
import { useConfirm } from 'vuetify-use-dialog'
|
import { useConfirm } from 'vuetify-use-dialog'
|
||||||
import { VIcon } from 'vuetify/lib/components/index.mjs'
|
|
||||||
import api from '@/api'
|
import api from '@/api'
|
||||||
import type { Plugin } from '@/api/types'
|
import type { Plugin } from '@/api/types'
|
||||||
import FormRender from '@/components/render/FormRender.vue'
|
import FormRender from '@/components/render/FormRender.vue'
|
||||||
@@ -49,6 +48,9 @@ const pluginConfigDialog = ref(false)
|
|||||||
// 插件配置表单数据
|
// 插件配置表单数据
|
||||||
const pluginConfigForm = ref({})
|
const pluginConfigForm = ref({})
|
||||||
|
|
||||||
|
// 菜单显示状态
|
||||||
|
const menuVisible = ref(false)
|
||||||
|
|
||||||
// 进度框
|
// 进度框
|
||||||
const progressDialog = ref(false)
|
const progressDialog = ref(false)
|
||||||
|
|
||||||
@@ -400,7 +402,7 @@ watch(
|
|||||||
:width="props.width"
|
:width="props.width"
|
||||||
:height="props.height"
|
:height="props.height"
|
||||||
@click="openPluginDetail"
|
@click="openPluginDetail"
|
||||||
class="flex flex-col h-full"
|
class="flex flex-col"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
class="relative flex flex-row items-start pa-3 justify-between grow"
|
class="relative flex flex-row items-start pa-3 justify-between grow"
|
||||||
@@ -411,12 +413,15 @@ watch(
|
|||||||
:style="{ background: `${backgroundColor}`, filter: 'brightness(0.5)' }"
|
:style="{ background: `${backgroundColor}`, filter: 'brightness(0.5)' }"
|
||||||
/>
|
/>
|
||||||
<div class="relative flex-1 min-w-0">
|
<div class="relative flex-1 min-w-0">
|
||||||
<VCardTitle class="text-white px-2 text-shadow whitespace-nowrap overflow-hidden text-ellipsis">
|
<VCardTitle class="text-white text-lg px-2 text-shadow whitespace-nowrap overflow-hidden text-ellipsis">
|
||||||
<VBadge v-if="props.plugin?.state" dot inline color="success" />
|
<VBadge v-if="props.plugin?.state" dot inline color="success" />
|
||||||
{{ props.plugin?.plugin_name }}
|
{{ props.plugin?.plugin_name }}
|
||||||
<span class="text-sm mt-1 text-gray-200">v{{ props.plugin?.plugin_version }}</span>
|
<span class="text-sm mt-1 text-gray-200">v{{ props.plugin?.plugin_version }}</span>
|
||||||
</VCardTitle>
|
</VCardTitle>
|
||||||
<VCardText class="px-2 py-1 text-white text-shadow line-clamp-3">
|
<VCardText
|
||||||
|
v-show="hover.isHovering || menuVisible"
|
||||||
|
class="px-2 py-1 text-white text-sm text-shadow line-clamp-3"
|
||||||
|
>
|
||||||
{{ props.plugin?.plugin_desc }}
|
{{ props.plugin?.plugin_desc }}
|
||||||
</VCardText>
|
</VCardText>
|
||||||
</div>
|
</div>
|
||||||
@@ -443,14 +448,14 @@ watch(
|
|||||||
{{ props.plugin?.plugin_author }}
|
{{ props.plugin?.plugin_author }}
|
||||||
</a>
|
</a>
|
||||||
</span>
|
</span>
|
||||||
<span v-if="props.count" class="ms-3">
|
<span v-if="props.count" v-show="hover.isHovering" class="ms-3">
|
||||||
<VIcon icon="mdi-download" />
|
<VIcon icon="mdi-download" />
|
||||||
<span class="text-sm ms-1 mt-1">{{ props.count?.toLocaleString() }}</span>
|
<span class="text-sm ms-1 mt-1">{{ props.count?.toLocaleString() }}</span>
|
||||||
</span>
|
</span>
|
||||||
<div class="me-n3 absolute bottom-1 right-3">
|
<div class="me-n3 absolute bottom-1 right-3">
|
||||||
<IconBtn>
|
<IconBtn>
|
||||||
<VIcon icon="mdi-dots-vertical" />
|
<VIcon icon="mdi-dots-vertical" />
|
||||||
<VMenu activator="parent" close-on-content-click>
|
<VMenu v-model="menuVisible" activator="parent" close-on-content-click>
|
||||||
<VList>
|
<VList>
|
||||||
<VListItem
|
<VListItem
|
||||||
v-for="(item, i) in dropdownItems"
|
v-for="(item, i) in dropdownItems"
|
||||||
|
|||||||
@@ -156,7 +156,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.grid-plugin-card {
|
.grid-plugin-card {
|
||||||
grid-template-columns: repeat(auto-fill, minmax(20rem, 1fr));
|
grid-template-columns: repeat(auto-fill, minmax(18rem, 1fr));
|
||||||
padding-block-end: 1rem;
|
padding-block-end: 1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user