mirror of
https://github.com/jxxghp/MoviePilot-Frontend.git
synced 2026-09-08 09:16:58 +08:00
重构插件快速访问组件
This commit is contained in:
@@ -7,7 +7,7 @@ import UserNofification from '@/layouts/components/UserNotification.vue'
|
|||||||
import SearchBar from '@/layouts/components/SearchBar.vue'
|
import SearchBar from '@/layouts/components/SearchBar.vue'
|
||||||
import ShortcutBar from '@/layouts/components/ShortcutBar.vue'
|
import ShortcutBar from '@/layouts/components/ShortcutBar.vue'
|
||||||
import UserProfile from '@/layouts/components/UserProfile.vue'
|
import UserProfile from '@/layouts/components/UserProfile.vue'
|
||||||
import PluginQuickAccess from '@/components/misc/PluginQuickAccess.vue'
|
import PluginQuickAccess from '@/layouts/components/PluginQuickAccess.vue'
|
||||||
import { useUserStore } from '@/stores'
|
import { useUserStore } from '@/stores'
|
||||||
import { getNavMenus } from '@/router/i18n-menu'
|
import { getNavMenus } from '@/router/i18n-menu'
|
||||||
import { NavMenu } from '@/@layouts/types'
|
import { NavMenu } from '@/@layouts/types'
|
||||||
|
|||||||
+27
-17
@@ -1,17 +1,14 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { useRouter } from 'vue-router'
|
|
||||||
import api from '@/api'
|
import api from '@/api'
|
||||||
import type { Plugin } from '@/api/types'
|
import type { Plugin } from '@/api/types'
|
||||||
import noImage from '@images/logos/plugin.png'
|
import noImage from '@images/logos/plugin.png'
|
||||||
import { useI18n } from 'vue-i18n'
|
import { useI18n } from 'vue-i18n'
|
||||||
import { useRecentPlugins } from '@/composables/useRecentPlugins'
|
import { useRecentPlugins } from '@/composables/useRecentPlugins'
|
||||||
|
import PluginDataDialog from '@/components/dialog/PluginDataDialog.vue'
|
||||||
|
|
||||||
// 国际化
|
// 国际化
|
||||||
const { t } = useI18n()
|
const { t } = useI18n()
|
||||||
|
|
||||||
// 路由
|
|
||||||
const router = useRouter()
|
|
||||||
|
|
||||||
// 最近访问插件管理
|
// 最近访问插件管理
|
||||||
const { getRecentPlugins, addRecentPlugin } = useRecentPlugins()
|
const { getRecentPlugins, addRecentPlugin } = useRecentPlugins()
|
||||||
|
|
||||||
@@ -42,13 +39,14 @@ const recentPlugins = ref<Plugin[]>([])
|
|||||||
// 是否加载中
|
// 是否加载中
|
||||||
const loading = ref(false)
|
const loading = ref(false)
|
||||||
|
|
||||||
// 图片是否加载失败
|
|
||||||
const imageLoadError = ref(false)
|
|
||||||
|
|
||||||
// 上滑关闭相关状态
|
// 上滑关闭相关状态
|
||||||
const isDraggingToClose = ref(false)
|
const isDraggingToClose = ref(false)
|
||||||
const dragOffset = ref(0)
|
const dragOffset = ref(0)
|
||||||
|
|
||||||
|
// 插件弹窗相关状态
|
||||||
|
const showPluginDataDialog = ref(false)
|
||||||
|
const currentPlugin = ref<Plugin | null>(null)
|
||||||
|
|
||||||
// 计算显示状态
|
// 计算显示状态
|
||||||
const isVisible = computed(() => {
|
const isVisible = computed(() => {
|
||||||
return props.visible // 只基于visible属性显示,不考虑pullDistance
|
return props.visible // 只基于visible属性显示,不考虑pullDistance
|
||||||
@@ -87,7 +85,6 @@ const componentOpacity = computed(() => {
|
|||||||
// 计算插件图标路径
|
// 计算插件图标路径
|
||||||
function getPluginIcon(plugin: Plugin): string {
|
function getPluginIcon(plugin: Plugin): string {
|
||||||
if (!plugin.plugin_icon) return noImage
|
if (!plugin.plugin_icon) return noImage
|
||||||
if (imageLoadError.value) return noImage
|
|
||||||
|
|
||||||
// 如果是网络图片则使用代理后返回
|
// 如果是网络图片则使用代理后返回
|
||||||
if (plugin?.plugin_icon?.startsWith('http'))
|
if (plugin?.plugin_icon?.startsWith('http'))
|
||||||
@@ -136,14 +133,10 @@ function handlePluginClick(plugin: Plugin) {
|
|||||||
loadRecentPlugins()
|
loadRecentPlugins()
|
||||||
|
|
||||||
emit('plugin-click', plugin)
|
emit('plugin-click', plugin)
|
||||||
// 跳转到插件页面并自动打开详情
|
|
||||||
router.push({
|
// 设置当前插件并显示数据弹窗
|
||||||
path: '/plugins',
|
currentPlugin.value = plugin
|
||||||
query: {
|
showPluginDataDialog.value = true
|
||||||
tab: 'installed',
|
|
||||||
id: plugin.id,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 关闭面板
|
// 关闭面板
|
||||||
@@ -151,6 +144,12 @@ function handleClose() {
|
|||||||
emit('close')
|
emit('close')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 关闭插件数据弹窗
|
||||||
|
function handleClosePluginDataDialog() {
|
||||||
|
showPluginDataDialog.value = false
|
||||||
|
currentPlugin.value = null
|
||||||
|
}
|
||||||
|
|
||||||
// 监听可见性变化,加载数据
|
// 监听可见性变化,加载数据
|
||||||
watch(
|
watch(
|
||||||
() => isVisible.value,
|
() => isVisible.value,
|
||||||
@@ -263,7 +262,10 @@ function handleBackdropClick(event: MouseEvent) {
|
|||||||
>
|
>
|
||||||
<div class="plugin-icon">
|
<div class="plugin-icon">
|
||||||
<VAvatar size="48" class="plugin-avatar">
|
<VAvatar size="48" class="plugin-avatar">
|
||||||
<VImg :src="getPluginIcon(plugin)" :alt="plugin.plugin_name" cover @error="imageLoadError = true">
|
<VImg :src="getPluginIcon(plugin)" :alt="plugin.plugin_name" cover>
|
||||||
|
<template #error>
|
||||||
|
<VIcon icon="mdi-puzzle" size="24" />
|
||||||
|
</template>
|
||||||
</VImg>
|
</VImg>
|
||||||
</VAvatar>
|
</VAvatar>
|
||||||
<!-- 运行状态指示 -->
|
<!-- 运行状态指示 -->
|
||||||
@@ -289,6 +291,14 @@ function handleBackdropClick(event: MouseEvent) {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- 插件数据弹窗 -->
|
||||||
|
<PluginDataDialog
|
||||||
|
v-if="showPluginDataDialog && currentPlugin"
|
||||||
|
v-model="showPluginDataDialog"
|
||||||
|
:plugin="currentPlugin"
|
||||||
|
@close="handleClosePluginDataDialog"
|
||||||
|
/>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
+2
-2
@@ -41,7 +41,7 @@ import MediaIdSelector from './components/misc/MediaIdSelector.vue'
|
|||||||
import CronField from './components/field/CronField.vue'
|
import CronField from './components/field/CronField.vue'
|
||||||
import PathField from './components/field/PathField.vue'
|
import PathField from './components/field/PathField.vue'
|
||||||
import HeaderTab from './layouts/components/HeaderTab.vue'
|
import HeaderTab from './layouts/components/HeaderTab.vue'
|
||||||
import PluginQuickAccess from './components/misc/PluginQuickAccess.vue'
|
import QuickAccess from './layouts/components/PluginQuickAccess.vue'
|
||||||
|
|
||||||
// 7. 样式文件 - 合并为单一导入
|
// 7. 样式文件 - 合并为单一导入
|
||||||
import '@/styles/main.scss'
|
import '@/styles/main.scss'
|
||||||
@@ -96,7 +96,7 @@ initializeApp().then(() => {
|
|||||||
.component('VPathField', PathField)
|
.component('VPathField', PathField)
|
||||||
.component('VHeaderTab', HeaderTab)
|
.component('VHeaderTab', HeaderTab)
|
||||||
.component('VPageContentTitle', PageContentTitle)
|
.component('VPageContentTitle', PageContentTitle)
|
||||||
.component('VPluginQuickAccess', PluginQuickAccess)
|
.component('VPluginQuickAccess', QuickAccess)
|
||||||
|
|
||||||
// 5. 注册其他插件
|
// 5. 注册其他插件
|
||||||
app
|
app
|
||||||
|
|||||||
Reference in New Issue
Block a user