mirror of
https://github.com/jxxghp/MoviePilot-Frontend.git
synced 2026-06-08 09:09:57 +08:00
优化动态标签页注册逻辑
This commit is contained in:
@@ -14,6 +14,7 @@ import { useDynamicButton } from '@/composables/useDynamicButton'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import PluginMixedSortCard from '@/components/cards/PluginMixedSortCard.vue'
|
||||
import { usePWA } from '@/composables/usePWA'
|
||||
import { useDynamicHeaderTab } from '@/composables/useDynamicHeaderTab'
|
||||
|
||||
// 国际化
|
||||
const { t } = useI18n()
|
||||
@@ -33,6 +34,81 @@ const activeTab = ref('installed')
|
||||
// 获取插件标签页
|
||||
const pluginTabs = computed(() => getPluginTabs())
|
||||
|
||||
// 使用动态标签页
|
||||
const { registerHeaderTab } = useDynamicHeaderTab()
|
||||
|
||||
// 注册动态标签页(在setup顶层立即执行)
|
||||
registerHeaderTab({
|
||||
items: pluginTabs.value,
|
||||
modelValue: activeTab,
|
||||
appendButtons: [
|
||||
{
|
||||
icon: 'mdi-filter-multiple-outline',
|
||||
variant: 'text',
|
||||
color: computed(() =>
|
||||
installedFilter.value || hasUpdateFilter.value || enabledFilter.value ? 'primary' : 'gray',
|
||||
),
|
||||
class: 'settings-icon-button',
|
||||
dataAttr: 'installed-filter-btn',
|
||||
action: () => {
|
||||
filterInstalledPluginDialog.value = true
|
||||
},
|
||||
show: computed(() => activeTab.value === 'installed'),
|
||||
},
|
||||
{
|
||||
icon: 'mdi-filter-multiple-outline',
|
||||
variant: 'text',
|
||||
color: computed(() => (isFilterFormEmpty.value ? 'gray' : 'primary')),
|
||||
class: 'settings-icon-button',
|
||||
dataAttr: 'market-filter-btn',
|
||||
action: () => {
|
||||
filterMarketPluginDialog.value = true
|
||||
},
|
||||
show: computed(() => activeTab.value === 'market'),
|
||||
},
|
||||
{
|
||||
icon: 'mdi-refresh',
|
||||
variant: 'text',
|
||||
color: 'gray',
|
||||
class: 'settings-icon-button',
|
||||
action: () => {
|
||||
refreshMarket()
|
||||
},
|
||||
show: computed(() => activeTab.value === 'market'),
|
||||
},
|
||||
{
|
||||
icon: 'mdi-store-cog',
|
||||
variant: 'text',
|
||||
color: 'gray',
|
||||
class: 'settings-icon-button',
|
||||
action: () => {
|
||||
MarketSettingDialog.value = true
|
||||
},
|
||||
show: computed(() => activeTab.value === 'market'),
|
||||
},
|
||||
{
|
||||
icon: 'mdi-folder-plus',
|
||||
variant: 'text',
|
||||
color: 'gray',
|
||||
class: 'settings-icon-button',
|
||||
action: () => {
|
||||
showNewFolderDialog()
|
||||
},
|
||||
show: computed(() => activeTab.value === 'installed' && !currentFolder.value),
|
||||
},
|
||||
{
|
||||
icon: 'mdi-arrow-left',
|
||||
variant: 'text',
|
||||
color: 'gray',
|
||||
class: 'settings-icon-button',
|
||||
action: () => {
|
||||
backToMain()
|
||||
},
|
||||
show: computed(() => activeTab.value === 'installed' && !!currentFolder.value),
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
// 插件ID参数
|
||||
const pluginId = ref(route.query.id)
|
||||
|
||||
@@ -798,6 +874,7 @@ function loadMarketMore({ done }: { done: any }) {
|
||||
}
|
||||
|
||||
// 组件挂载后
|
||||
|
||||
onMounted(async () => {
|
||||
await loadPluginOrderConfig()
|
||||
await loadPluginFolders() // 加载文件夹配置
|
||||
@@ -1215,173 +1292,118 @@ function onDragStartPlugin(evt: any) {
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<VHeaderTab :items="pluginTabs" v-model="activeTab">
|
||||
<template #append>
|
||||
<VMenu
|
||||
v-if="activeTab === 'installed'"
|
||||
v-model="filterInstalledPluginDialog"
|
||||
width="20rem"
|
||||
:close-on-content-click="false"
|
||||
scrim
|
||||
>
|
||||
<template #activator="{ props }">
|
||||
<VBtn
|
||||
icon="mdi-filter-multiple-outline"
|
||||
variant="text"
|
||||
:color="installedFilter || hasUpdateFilter || enabledFilter ? 'primary' : 'gray'"
|
||||
size="default"
|
||||
class="settings-icon-button"
|
||||
v-bind="props"
|
||||
/>
|
||||
</template>
|
||||
<VCard>
|
||||
<VCardItem>
|
||||
<VCardTitle>
|
||||
<VIcon icon="mdi-filter-multiple-outline" class="mr-2" />
|
||||
{{ t('plugin.filterPlugins') }}
|
||||
</VCardTitle>
|
||||
<VDialogCloseBtn @click="filterInstalledPluginDialog = false" />
|
||||
</VCardItem>
|
||||
<VCardText>
|
||||
<!-- 过滤弹窗 -->
|
||||
<Teleport to="body" v-if="filterInstalledPluginDialog">
|
||||
<VMenu
|
||||
v-model="filterInstalledPluginDialog"
|
||||
width="20rem"
|
||||
:close-on-content-click="false"
|
||||
:activator="'[data-menu-activator=installed-filter-btn]'"
|
||||
location="bottom end"
|
||||
>
|
||||
<VCard>
|
||||
<VCardItem>
|
||||
<VCardTitle>
|
||||
<VIcon icon="mdi-filter-multiple-outline" class="mr-2" />
|
||||
{{ t('plugin.filterPlugins') }}
|
||||
</VCardTitle>
|
||||
<VDialogCloseBtn @click="filterInstalledPluginDialog = false" />
|
||||
</VCardItem>
|
||||
<VCardText>
|
||||
<VRow>
|
||||
<VCol cols="12">
|
||||
<VCombobox
|
||||
v-model="installedFilter"
|
||||
:items="installedPluginNames"
|
||||
:label="t('plugin.name')"
|
||||
density="comfortable"
|
||||
clearable
|
||||
/>
|
||||
</VCol>
|
||||
<VCol cols="6">
|
||||
<VSwitch v-model="enabledFilter" :label="t('plugin.running')" />
|
||||
</VCol>
|
||||
<VCol cols="6">
|
||||
<VSwitch v-model="hasUpdateFilter" :label="t('plugin.hasNewVersion')" />
|
||||
</VCol>
|
||||
</VRow>
|
||||
</VCardText>
|
||||
</VCard>
|
||||
</VMenu>
|
||||
</Teleport>
|
||||
|
||||
<Teleport to="body" v-if="filterMarketPluginDialog">
|
||||
<VMenu
|
||||
v-model="filterMarketPluginDialog"
|
||||
width="25rem"
|
||||
:close-on-content-click="false"
|
||||
:activator="'[data-menu-activator=market-filter-btn]'"
|
||||
location="bottom end"
|
||||
>
|
||||
<VCard>
|
||||
<VCardItem>
|
||||
<VCardTitle>
|
||||
<VIcon icon="mdi-filter-multiple-outline" class="mr-2" />
|
||||
{{ t('plugin.filterPlugins') }}
|
||||
</VCardTitle>
|
||||
<VDialogCloseBtn @click="filterMarketPluginDialog = false" />
|
||||
</VCardItem>
|
||||
<VCardText>
|
||||
<!-- 过滤表单 -->
|
||||
<div v-if="isAppMarketLoaded">
|
||||
<VRow>
|
||||
<VCol cols="12">
|
||||
<VCombobox
|
||||
v-model="installedFilter"
|
||||
:items="installedPluginNames"
|
||||
:label="t('plugin.name')"
|
||||
<VCol cols="6">
|
||||
<VTextField v-model="filterForm.name" density="comfortable" :label="t('plugin.name')" clearable />
|
||||
</VCol>
|
||||
<VCol v-if="authorFilterOptions.length > 0" cols="6">
|
||||
<VSelect
|
||||
v-model="filterForm.author"
|
||||
:items="authorFilterOptions"
|
||||
density="comfortable"
|
||||
chips
|
||||
:label="t('plugin.author')"
|
||||
multiple
|
||||
clearable
|
||||
/>
|
||||
</VCol>
|
||||
<VCol cols="6">
|
||||
<VSwitch v-model="enabledFilter" :label="t('plugin.running')" />
|
||||
<VCol v-if="labelFilterOptions.length > 0" cols="6">
|
||||
<VSelect
|
||||
v-model="filterForm.label"
|
||||
:items="labelFilterOptions"
|
||||
density="comfortable"
|
||||
chips
|
||||
:label="t('plugin.label')"
|
||||
multiple
|
||||
clearable
|
||||
/>
|
||||
</VCol>
|
||||
<VCol cols="6">
|
||||
<VSwitch v-model="hasUpdateFilter" :label="t('plugin.hasNewVersion')" />
|
||||
<VCol v-if="repoFilterOptions.length > 0" cols="6">
|
||||
<VSelect
|
||||
v-model="filterForm.repo"
|
||||
:items="repoFilterOptions"
|
||||
density="comfortable"
|
||||
chips
|
||||
:label="t('plugin.repository')"
|
||||
multiple
|
||||
clearable
|
||||
/>
|
||||
</VCol>
|
||||
<VCol v-if="sortOptions.length > 0" cols="6">
|
||||
<VSelect
|
||||
v-model="activeSort"
|
||||
:items="sortOptions"
|
||||
density="comfortable"
|
||||
:label="t('plugin.sortTitle')"
|
||||
/>
|
||||
</VCol>
|
||||
</VRow>
|
||||
</VCardText>
|
||||
</VCard>
|
||||
</VMenu>
|
||||
<VMenu
|
||||
v-if="activeTab === 'market'"
|
||||
v-model="filterMarketPluginDialog"
|
||||
width="25rem"
|
||||
:close-on-content-click="false"
|
||||
scrim
|
||||
>
|
||||
<template #activator="{ props }">
|
||||
<VBtn
|
||||
icon="mdi-filter-multiple-outline"
|
||||
variant="text"
|
||||
:color="isFilterFormEmpty ? 'gray' : 'primary'"
|
||||
size="default"
|
||||
class="settings-icon-button"
|
||||
v-bind="props"
|
||||
/>
|
||||
</template>
|
||||
<VCard>
|
||||
<VCardItem>
|
||||
<VCardTitle>
|
||||
<VIcon icon="mdi-filter-multiple-outline" class="mr-2" />
|
||||
{{ t('plugin.filterPlugins') }}
|
||||
</VCardTitle>
|
||||
<VDialogCloseBtn @click="filterMarketPluginDialog = false" />
|
||||
</VCardItem>
|
||||
<VCardText>
|
||||
<!-- 过滤表单 -->
|
||||
<div v-if="isAppMarketLoaded">
|
||||
<VRow>
|
||||
<VCol cols="6">
|
||||
<VTextField v-model="filterForm.name" density="comfortable" :label="t('plugin.name')" clearable />
|
||||
</VCol>
|
||||
<VCol v-if="authorFilterOptions.length > 0" cols="6">
|
||||
<VSelect
|
||||
v-model="filterForm.author"
|
||||
:items="authorFilterOptions"
|
||||
density="comfortable"
|
||||
chips
|
||||
:label="t('plugin.author')"
|
||||
multiple
|
||||
clearable
|
||||
/>
|
||||
</VCol>
|
||||
<VCol v-if="labelFilterOptions.length > 0" cols="6">
|
||||
<VSelect
|
||||
v-model="filterForm.label"
|
||||
:items="labelFilterOptions"
|
||||
density="comfortable"
|
||||
chips
|
||||
:label="t('plugin.label')"
|
||||
multiple
|
||||
clearable
|
||||
/>
|
||||
</VCol>
|
||||
<VCol v-if="repoFilterOptions.length > 0" cols="6">
|
||||
<VSelect
|
||||
v-model="filterForm.repo"
|
||||
:items="repoFilterOptions"
|
||||
density="comfortable"
|
||||
chips
|
||||
:label="t('plugin.repository')"
|
||||
multiple
|
||||
clearable
|
||||
/>
|
||||
</VCol>
|
||||
<VCol v-if="sortOptions.length > 0" cols="6">
|
||||
<VSelect
|
||||
v-model="activeSort"
|
||||
:items="sortOptions"
|
||||
density="comfortable"
|
||||
:label="t('plugin.sortTitle')"
|
||||
/>
|
||||
</VCol>
|
||||
</VRow>
|
||||
</div>
|
||||
</VCardText>
|
||||
</VCard>
|
||||
</VMenu>
|
||||
<VBtn
|
||||
v-if="activeTab === 'market'"
|
||||
icon="mdi-refresh"
|
||||
variant="text"
|
||||
color="gray"
|
||||
size="default"
|
||||
class="settings-icon-button"
|
||||
:loading="isMarketRefreshing"
|
||||
@click="refreshMarket"
|
||||
/>
|
||||
<VBtn
|
||||
v-if="activeTab === 'market'"
|
||||
icon="mdi-store-cog"
|
||||
variant="text"
|
||||
color="gray"
|
||||
size="default"
|
||||
class="settings-icon-button"
|
||||
@click="MarketSettingDialog = true"
|
||||
/>
|
||||
<VBtn
|
||||
v-if="activeTab === 'installed' && !currentFolder"
|
||||
icon="mdi-folder-plus"
|
||||
variant="text"
|
||||
color="gray"
|
||||
size="default"
|
||||
class="settings-icon-button"
|
||||
@click="showNewFolderDialog"
|
||||
/>
|
||||
<VBtn
|
||||
v-if="activeTab === 'installed' && currentFolder"
|
||||
icon="mdi-arrow-left"
|
||||
variant="text"
|
||||
color="gray"
|
||||
size="default"
|
||||
class="settings-icon-button"
|
||||
@click="backToMain"
|
||||
/>
|
||||
</template>
|
||||
</VHeaderTab>
|
||||
</div>
|
||||
</VCardText>
|
||||
</VCard>
|
||||
</VMenu>
|
||||
</Teleport>
|
||||
|
||||
<VWindow v-model="activeTab" class="mt-5 disable-tab-transition px-2" :touch="false">
|
||||
<VWindow v-model="activeTab" class="disable-tab-transition px-2" :touch="false">
|
||||
<!-- 我的插件 -->
|
||||
<VWindowItem value="installed">
|
||||
<transition name="fade-slide" appear>
|
||||
@@ -1626,7 +1648,3 @@ function onDragStartPlugin(evt: any) {
|
||||
</VCard>
|
||||
</VDialog>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
// 样式已移至 PluginMixedSortCard 组件
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user