mirror of
https://github.com/jxxghp/MoviePilot-Frontend.git
synced 2026-06-17 13:42:07 +08:00
refactor: unify header tab menu definitions
This commit is contained in:
9
src/@layouts/types.d.ts
vendored
9
src/@layouts/types.d.ts
vendored
@@ -121,11 +121,20 @@ export interface NavLink extends NavLinkProps, Partial<AclProperties> {
|
||||
disable?: boolean
|
||||
}
|
||||
|
||||
export interface NavMenuTabItem {
|
||||
title: string
|
||||
icon?: string
|
||||
tab: string
|
||||
description?: string
|
||||
}
|
||||
|
||||
export interface NavMenu extends NavLink {
|
||||
header: string
|
||||
description?: string
|
||||
admin?: boolean
|
||||
footer?: boolean
|
||||
// 水平三级菜单和页面动态标签页共用的静态标签定义。
|
||||
tabs?: NavMenuTabItem[]
|
||||
}
|
||||
|
||||
// 👉 Vertical nav group
|
||||
|
||||
@@ -10,15 +10,7 @@ import UserProfile from '@/layouts/components/UserProfile.vue'
|
||||
import QuickAccess from '@/layouts/components/QuickAccess.vue'
|
||||
import HeaderTab from '@/layouts/components/HeaderTab.vue'
|
||||
import { usePluginSidebarNavStore, useUserStore } from '@/stores'
|
||||
import {
|
||||
getDiscoverTabs,
|
||||
getNavMenus,
|
||||
getPluginTabs,
|
||||
getSettingTabs,
|
||||
getSubscribeMovieTabs,
|
||||
getSubscribeTvTabs,
|
||||
getWorkflowTabs,
|
||||
} from '@/router/i18n-menu'
|
||||
import { getNavMenus } from '@/router/i18n-menu'
|
||||
import { filterPluginSidebarNavEntries } from '@/utils/pluginSidebarNav'
|
||||
import { NavMenu } from '@/@layouts/types'
|
||||
import { useDisplay } from 'vuetify'
|
||||
@@ -210,20 +202,6 @@ const visibleHorizontalHeaderButtons = computed(() => {
|
||||
return (dynamicHeaderTab.value?.appendButtons ?? []).filter(button => resolveMaybeRefValue(button.show, true) !== false)
|
||||
})
|
||||
|
||||
const staticHorizontalNavTabs = computed<Record<string, DynamicHeaderTabItem[]>>(() => ({
|
||||
'/recommend': getRecommendTabs(),
|
||||
'/discover': getDiscoverTabs(t).map(tab => ({
|
||||
title: tab.name,
|
||||
icon: tab.icon,
|
||||
tab: tab.tab,
|
||||
})),
|
||||
'/subscribe/movie': getSubscribeMovieTabs(t),
|
||||
'/subscribe/tv': getSubscribeTvTabs(t),
|
||||
'/workflow': getWorkflowTabs(t),
|
||||
'/plugins': getPluginTabs(t),
|
||||
'/setting': getSettingTabs(t),
|
||||
}))
|
||||
|
||||
// 在组件销毁时清理
|
||||
onUnmounted(() => {
|
||||
dynamicHeaderTab.value = null
|
||||
@@ -370,17 +348,7 @@ function getHorizontalNavTabs(item: NavMenu): DynamicHeaderTabItem[] {
|
||||
return dynamicHeaderTab.value?.items ?? []
|
||||
}
|
||||
|
||||
return staticHorizontalNavTabs.value[targetPath] ?? []
|
||||
}
|
||||
|
||||
function getRecommendTabs(): DynamicHeaderTabItem[] {
|
||||
return [
|
||||
{ title: t('recommend.all'), icon: 'mdi-filmstrip-box-multiple', tab: t('recommend.all') },
|
||||
{ title: t('recommend.categoryMovie'), icon: 'mdi-movie', tab: t('recommend.categoryMovie') },
|
||||
{ title: t('recommend.categoryTV'), icon: 'mdi-television-classic', tab: t('recommend.categoryTV') },
|
||||
{ title: t('recommend.categoryAnime'), icon: 'mdi-animation', tab: t('recommend.categoryAnime') },
|
||||
{ title: t('recommend.categoryRankings'), icon: 'mdi-trophy', tab: t('recommend.categoryRankings') },
|
||||
]
|
||||
return item.tabs ?? []
|
||||
}
|
||||
|
||||
function applyPendingHorizontalTab() {
|
||||
|
||||
@@ -87,7 +87,7 @@ function initDiscoverTabs() {
|
||||
const tabs = getDiscoverTabs(t)
|
||||
for (const tab of tabs) {
|
||||
discoverTabs.value.push({
|
||||
name: tab.name,
|
||||
name: tab.title,
|
||||
mediaid_prefix: tab.tab,
|
||||
api_path: '',
|
||||
filter_params: {},
|
||||
|
||||
@@ -8,6 +8,7 @@ import { useDynamicButton } from '@/composables/useDynamicButton'
|
||||
import { usePWA } from '@/composables/usePWA'
|
||||
import { getItemColor, initializeItemColors } from '@/utils/colorUtils'
|
||||
import { openSharedDialog } from '@/composables/useSharedDialog'
|
||||
import { getRecommendTabs } from '@/router/i18n-menu'
|
||||
|
||||
const ContentToggleSettingsDialog = defineAsyncComponent(() => import('@/components/dialog/ContentToggleSettingsDialog.vue'))
|
||||
|
||||
@@ -222,34 +223,8 @@ async function saveConfig(payload?: { enabled?: Record<string, boolean> }) {
|
||||
settingsDialogController = null
|
||||
}
|
||||
|
||||
// 标签图标映射
|
||||
const categoryItems = computed(() => [
|
||||
{
|
||||
title: t('recommend.all'),
|
||||
icon: 'mdi-filmstrip-box-multiple',
|
||||
tab: t('recommend.all'),
|
||||
},
|
||||
{
|
||||
title: t('recommend.categoryMovie'),
|
||||
icon: 'mdi-movie',
|
||||
tab: t('recommend.categoryMovie'),
|
||||
},
|
||||
{
|
||||
title: t('recommend.categoryTV'),
|
||||
icon: 'mdi-television-classic',
|
||||
tab: t('recommend.categoryTV'),
|
||||
},
|
||||
{
|
||||
title: t('recommend.categoryAnime'),
|
||||
icon: 'mdi-animation',
|
||||
tab: t('recommend.categoryAnime'),
|
||||
},
|
||||
{
|
||||
title: t('recommend.categoryRankings'),
|
||||
icon: 'mdi-trophy',
|
||||
tab: t('recommend.categoryRankings'),
|
||||
},
|
||||
])
|
||||
// 推荐分类标签与导航三级菜单共用同一份定义。
|
||||
const categoryItems = computed(() => getRecommendTabs(t))
|
||||
|
||||
// 注册动态标签页
|
||||
registerHeaderTab({
|
||||
|
||||
@@ -44,7 +44,7 @@ const { registerHeaderTab } = useDynamicHeaderTab()
|
||||
|
||||
// 注册动态标签页
|
||||
registerHeaderTab({
|
||||
items: settingTabs.value,
|
||||
items: settingTabs,
|
||||
modelValue: activeTab,
|
||||
})
|
||||
|
||||
|
||||
@@ -313,7 +313,7 @@ const { registerHeaderTab } = useDynamicHeaderTab()
|
||||
|
||||
// 注册动态标签页
|
||||
registerHeaderTab({
|
||||
items: subscribeTabs.value,
|
||||
items: subscribeTabs,
|
||||
modelValue: activeTab,
|
||||
appendButtons: [
|
||||
{
|
||||
|
||||
@@ -69,7 +69,7 @@ const { registerHeaderTab } = useDynamicHeaderTab()
|
||||
|
||||
// 注册动态标签页
|
||||
registerHeaderTab({
|
||||
items: workflowTabs.value,
|
||||
items: workflowTabs,
|
||||
modelValue: activeTab,
|
||||
appendButtons: [
|
||||
{
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { useGlobalSettingsStore } from '@/stores'
|
||||
import type { NavMenuTabItem } from '@/@layouts/types'
|
||||
import type { Composer } from 'vue-i18n'
|
||||
|
||||
// 构建路由菜单,每次调用时使用当前的语言环境
|
||||
@@ -34,6 +35,7 @@ export function getNavMenus(t: Composer['t']) {
|
||||
admin: false,
|
||||
footer: true,
|
||||
permission: 'discovery',
|
||||
tabs: getRecommendTabs(t),
|
||||
},
|
||||
{
|
||||
title: t('navItems.explore'),
|
||||
@@ -43,6 +45,7 @@ export function getNavMenus(t: Composer['t']) {
|
||||
admin: false,
|
||||
footer: true,
|
||||
permission: 'discovery',
|
||||
tabs: getDiscoverTabs(t),
|
||||
},
|
||||
{
|
||||
title: t('navItems.movie'),
|
||||
@@ -53,6 +56,7 @@ export function getNavMenus(t: Composer['t']) {
|
||||
admin: false,
|
||||
footer: false,
|
||||
permission: 'subscribe',
|
||||
tabs: getSubscribeMovieTabs(t),
|
||||
},
|
||||
{
|
||||
title: t('navItems.tv'),
|
||||
@@ -63,6 +67,7 @@ export function getNavMenus(t: Composer['t']) {
|
||||
admin: false,
|
||||
footer: false,
|
||||
permission: 'subscribe',
|
||||
tabs: getSubscribeTvTabs(t),
|
||||
},
|
||||
{
|
||||
title: t('navItems.workflow'),
|
||||
@@ -73,6 +78,7 @@ export function getNavMenus(t: Composer['t']) {
|
||||
admin: true,
|
||||
footer: false,
|
||||
permission: 'manage',
|
||||
tabs: getWorkflowTabs(t),
|
||||
},
|
||||
{
|
||||
title: t('navItems.calendar'),
|
||||
@@ -114,6 +120,7 @@ export function getNavMenus(t: Composer['t']) {
|
||||
header: t('menu.system'),
|
||||
admin: true,
|
||||
permission: 'manage',
|
||||
tabs: getPluginTabs(t),
|
||||
},
|
||||
{
|
||||
title: t('navItems.siteManager'),
|
||||
@@ -140,14 +147,26 @@ export function getNavMenus(t: Composer['t']) {
|
||||
header: t('menu.system'),
|
||||
admin: true,
|
||||
permission: 'admin',
|
||||
tabs: getSettingTabs(t),
|
||||
},
|
||||
]
|
||||
: []),
|
||||
]
|
||||
}
|
||||
|
||||
// 获取推荐标签页
|
||||
export function getRecommendTabs(t: Composer['t']): NavMenuTabItem[] {
|
||||
return [
|
||||
{ title: t('recommend.all'), icon: 'mdi-filmstrip-box-multiple', tab: t('recommend.all') },
|
||||
{ title: t('recommend.categoryMovie'), icon: 'mdi-movie', tab: t('recommend.categoryMovie') },
|
||||
{ title: t('recommend.categoryTV'), icon: 'mdi-television-classic', tab: t('recommend.categoryTV') },
|
||||
{ title: t('recommend.categoryAnime'), icon: 'mdi-animation', tab: t('recommend.categoryAnime') },
|
||||
{ title: t('recommend.categoryRankings'), icon: 'mdi-trophy', tab: t('recommend.categoryRankings') },
|
||||
]
|
||||
}
|
||||
|
||||
// 获取设置标签页
|
||||
export function getSettingTabs(t: Composer['t']) {
|
||||
export function getSettingTabs(t: Composer['t']): NavMenuTabItem[] {
|
||||
return [
|
||||
{
|
||||
title: t('settingTabs.system.title'),
|
||||
@@ -195,7 +214,7 @@ export function getSettingTabs(t: Composer['t']) {
|
||||
}
|
||||
|
||||
// 获取电影订阅标签页
|
||||
export function getSubscribeMovieTabs(t: Composer['t']) {
|
||||
export function getSubscribeMovieTabs(t: Composer['t']): NavMenuTabItem[] {
|
||||
return [
|
||||
{
|
||||
title: t('subscribeTabs.movie.mysub'),
|
||||
@@ -211,7 +230,7 @@ export function getSubscribeMovieTabs(t: Composer['t']) {
|
||||
}
|
||||
|
||||
// 获取电视剧订阅标签页
|
||||
export function getSubscribeTvTabs(t: Composer['t']) {
|
||||
export function getSubscribeTvTabs(t: Composer['t']): NavMenuTabItem[] {
|
||||
return [
|
||||
{
|
||||
title: t('subscribeTabs.tv.mysub'),
|
||||
@@ -232,7 +251,7 @@ export function getSubscribeTvTabs(t: Composer['t']) {
|
||||
}
|
||||
|
||||
// 获取插件标签页
|
||||
export function getPluginTabs(t: Composer['t']) {
|
||||
export function getPluginTabs(t: Composer['t']): NavMenuTabItem[] {
|
||||
return [
|
||||
{
|
||||
title: t('pluginTabs.installed'),
|
||||
@@ -248,28 +267,28 @@ export function getPluginTabs(t: Composer['t']) {
|
||||
}
|
||||
|
||||
// 获取发现标签页
|
||||
export function getDiscoverTabs(t: Composer['t']) {
|
||||
export function getDiscoverTabs(t: Composer['t']): NavMenuTabItem[] {
|
||||
return [
|
||||
{
|
||||
name: t('discoverTabs.themoviedb'),
|
||||
title: t('discoverTabs.themoviedb'),
|
||||
tab: 'themoviedb',
|
||||
icon: 'themoviedb',
|
||||
icon: 'mdi-movie-search-outline',
|
||||
},
|
||||
{
|
||||
name: t('discoverTabs.douban'),
|
||||
title: t('discoverTabs.douban'),
|
||||
tab: 'douban',
|
||||
icon: 'douban',
|
||||
icon: 'mdi-book-open-page-variant-outline',
|
||||
},
|
||||
{
|
||||
name: t('discoverTabs.bangumi'),
|
||||
title: t('discoverTabs.bangumi'),
|
||||
tab: 'bangumi',
|
||||
icon: 'bangumi',
|
||||
icon: 'mdi-calendar-star-outline',
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
// 获取工作流标签页
|
||||
export function getWorkflowTabs(t: Composer['t']) {
|
||||
export function getWorkflowTabs(t: Composer['t']): NavMenuTabItem[] {
|
||||
return [
|
||||
{
|
||||
title: t('workflowTabs.list'),
|
||||
|
||||
@@ -50,7 +50,7 @@ const { registerHeaderTab } = useDynamicHeaderTab()
|
||||
|
||||
// 注册动态标签页(在setup顶层立即执行)
|
||||
registerHeaderTab({
|
||||
items: pluginTabs.value,
|
||||
items: pluginTabs,
|
||||
modelValue: activeTab,
|
||||
appendButtons: [
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user