mirror of
https://github.com/jxxghp/MoviePilot-Frontend.git
synced 2026-08-02 11:57:24 +08:00
perf: optimize initial load by implementing lazy loading for modules and fine-tuning authentication/resource initialization logic.
This commit is contained in:
@@ -1,15 +1,12 @@
|
||||
<script lang="ts" setup>
|
||||
import draggable from 'vuedraggable'
|
||||
import { useToast } from 'vue-toastification'
|
||||
import api from '@/api'
|
||||
import type { Plugin } from '@/api/types'
|
||||
import NoDataFound from '@/components/NoDataFound.vue'
|
||||
import PluginAppCard from '@/components/cards/PluginAppCard.vue'
|
||||
import { getLogoUrl } from '@/utils/imageUtils'
|
||||
import { useDisplay } from 'vuetify'
|
||||
import { isNullOrEmptyObject } from '@/@core/utils'
|
||||
import { getPluginTabs } from '@/router/i18n-menu'
|
||||
import PluginMarketSettingDialog from '@/components/dialog/PluginMarketSettingDialog.vue'
|
||||
import { useDynamicButton } from '@/composables/useDynamicButton'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import PluginMixedSortCard from '@/components/cards/PluginMixedSortCard.vue'
|
||||
@@ -22,6 +19,11 @@ const { t } = useI18n()
|
||||
|
||||
const route = useRoute()
|
||||
|
||||
// 市场卡片、拖拽排序和市场设置只在对应标签/操作中需要,延迟到真正使用时加载。
|
||||
const Draggable = defineAsyncComponent(() => import('vuedraggable').then(module => module.default))
|
||||
const PluginAppCard = defineAsyncComponent(() => import('@/components/cards/PluginAppCard.vue'))
|
||||
const PluginMarketSettingDialog = defineAsyncComponent(() => import('@/components/dialog/PluginMarketSettingDialog.vue'))
|
||||
|
||||
// 显示器宽度
|
||||
const display = useDisplay()
|
||||
|
||||
@@ -1536,7 +1538,7 @@ function onDragStartPlugin(evt: any) {
|
||||
<!-- 混合排序列表(文件夹和插件) -->
|
||||
<template v-if="!currentFolder">
|
||||
<!-- 主列表:使用draggable进行混合排序 -->
|
||||
<draggable
|
||||
<Draggable
|
||||
v-if="canDragSort"
|
||||
v-model="mixedSortList"
|
||||
@end="saveMixedSortOrder"
|
||||
@@ -1565,7 +1567,7 @@ function onDragStartPlugin(evt: any) {
|
||||
@drop-to-folder="(event, folderName) => handleDropToFolder(event, folderName)"
|
||||
/>
|
||||
</template>
|
||||
</draggable>
|
||||
</Draggable>
|
||||
<ProgressiveCardGrid
|
||||
v-else-if="shouldVirtualizeInstalledMainList"
|
||||
:items="mixedSortList"
|
||||
@@ -1598,7 +1600,7 @@ function onDragStartPlugin(evt: any) {
|
||||
|
||||
<template v-else>
|
||||
<!-- 文件夹内:使用draggable排序 + 移出按钮 -->
|
||||
<draggable
|
||||
<Draggable
|
||||
v-if="canDragSort"
|
||||
v-model="draggableFolderPlugins"
|
||||
@end="saveFolderPluginOrder"
|
||||
@@ -1624,7 +1626,7 @@ function onDragStartPlugin(evt: any) {
|
||||
@remove-from-folder="removeFromFolder"
|
||||
/>
|
||||
</template>
|
||||
</draggable>
|
||||
</Draggable>
|
||||
<ProgressiveCardGrid
|
||||
v-else-if="shouldVirtualizeInstalledFolderList"
|
||||
:items="draggableFolderPlugins"
|
||||
|
||||
@@ -1,14 +1,10 @@
|
||||
<!-- eslint-disable sonarjs/no-duplicate-string -->
|
||||
<script lang="ts" setup>
|
||||
import { useToast } from 'vue-toastification'
|
||||
import draggable from 'vuedraggable'
|
||||
import { VRow } from 'vuetify/lib/components/index.mjs'
|
||||
import api from '@/api'
|
||||
import { TransferDirectoryConf, StorageConf } from '@/api/types'
|
||||
import DirectoryCard from '@/components/cards/DirectoryCard.vue'
|
||||
import StorageCard from '@/components/cards/StorageCard.vue'
|
||||
import ProgressDialog from '@/components/dialog/ProgressDialog.vue'
|
||||
import CategoryEditDialog from '@/components/dialog/CategoryEditDialog.vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { useTheme } from 'vuetify'
|
||||
import { storageAttributes } from '@/api/constants'
|
||||
@@ -16,6 +12,11 @@ import { storageAttributes } from '@/api/constants'
|
||||
const { t } = useI18n()
|
||||
const { global: globalTheme } = useTheme()
|
||||
|
||||
// 拖拽排序和分类编辑弹窗按需加载,避免设置框架预加载目录页时带上这些交互依赖。
|
||||
const Draggable = defineAsyncComponent(() => import('vuedraggable').then(module => module.default))
|
||||
const ProgressDialog = defineAsyncComponent(() => import('@/components/dialog/ProgressDialog.vue'))
|
||||
const CategoryEditDialog = defineAsyncComponent(() => import('@/components/dialog/CategoryEditDialog.vue'))
|
||||
|
||||
// 所有下载目录
|
||||
const directories = ref<TransferDirectoryConf[]>([])
|
||||
|
||||
@@ -264,7 +265,7 @@ onMounted(() => {
|
||||
<VCardSubtitle>{{ t('setting.directory.storageDesc') }}</VCardSubtitle>
|
||||
</VCardItem>
|
||||
<VCardText>
|
||||
<draggable
|
||||
<Draggable
|
||||
v-model="storages"
|
||||
handle=".cursor-move"
|
||||
item-key="name"
|
||||
@@ -274,7 +275,7 @@ onMounted(() => {
|
||||
<template #item="{ element }">
|
||||
<StorageCard :storage="element" @close="removeStorage(element)" @done="loadStorages" />
|
||||
</template>
|
||||
</draggable>
|
||||
</Draggable>
|
||||
</VCardText>
|
||||
<VCardText>
|
||||
<VForm @submit.prevent="() => {}">
|
||||
@@ -309,7 +310,7 @@ onMounted(() => {
|
||||
<VCardSubtitle>{{ t('setting.directory.directoryDesc') }}</VCardSubtitle>
|
||||
</VCardItem>
|
||||
<VCardText>
|
||||
<draggable
|
||||
<Draggable
|
||||
v-model="directories"
|
||||
handle=".cursor-move"
|
||||
item-key="pri"
|
||||
@@ -331,7 +332,7 @@ onMounted(() => {
|
||||
@close="removeDirectory(element)"
|
||||
/>
|
||||
</template>
|
||||
</draggable>
|
||||
</Draggable>
|
||||
</VCardText>
|
||||
<VCardText>
|
||||
<VForm @submit.prevent="() => {}">
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
<script lang="ts" setup>
|
||||
import { useToast } from 'vue-toastification'
|
||||
import api from '@/api'
|
||||
import draggable from 'vuedraggable'
|
||||
import type { NotificationConf, NotificationSwitchConf } from '@/api/types'
|
||||
import NotificationChannelCard from '@/components/cards/NotificationChannelCard.vue'
|
||||
import ProgressDialog from '@/components/dialog/ProgressDialog.vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { notificationSwitchDict } from '@/api/constants'
|
||||
import { useTheme, useDisplay } from 'vuetify'
|
||||
@@ -15,6 +13,10 @@ const display = useDisplay()
|
||||
// 国际化
|
||||
const { t } = useI18n()
|
||||
|
||||
// 通知渠道排序和进度弹窗按需加载,避免通知设置 chunk 直接包含拖拽库。
|
||||
const Draggable = defineAsyncComponent(() => import('vuedraggable').then(module => module.default))
|
||||
const ProgressDialog = defineAsyncComponent(() => import('@/components/dialog/ProgressDialog.vue'))
|
||||
|
||||
// 初始化模板配置字典
|
||||
const templateConfigs = ref<Record<string, string>>({
|
||||
organizeSuccess: '{}',
|
||||
@@ -324,7 +326,7 @@ onMounted(() => {
|
||||
<VCardSubtitle>{{ t('setting.notification.channelsDesc') }}</VCardSubtitle>
|
||||
</VCardItem>
|
||||
<VCardText>
|
||||
<draggable
|
||||
<Draggable
|
||||
v-model="notifications"
|
||||
handle=".cursor-move"
|
||||
item-key="name"
|
||||
@@ -339,7 +341,7 @@ onMounted(() => {
|
||||
@close="removeNotification(element)"
|
||||
/>
|
||||
</template>
|
||||
</draggable>
|
||||
</Draggable>
|
||||
</VCardText>
|
||||
<VCardText>
|
||||
<VForm @submit.prevent="() => {}">
|
||||
|
||||
@@ -2,17 +2,19 @@
|
||||
<script lang="ts" setup>
|
||||
import { useToast } from 'vue-toastification'
|
||||
import { copyToClipboard } from '@/@core/utils/navigator'
|
||||
import draggable from 'vuedraggable'
|
||||
import api from '@/api'
|
||||
import { CustomRule, FilterRuleGroup } from '@/api/types'
|
||||
import CustomerRuleCard from '@/components/cards/CustomRuleCard.vue'
|
||||
import FilterRuleGroupCard from '@/components/cards/FilterRuleGroupCard.vue'
|
||||
import ImportCodeDialog from '@/components/dialog/ImportCodeDialog.vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
|
||||
// 国际化
|
||||
const { t } = useI18n()
|
||||
|
||||
// 拖拽库和导入弹窗只在规则编辑交互中需要,拆出设置页入口 chunk。
|
||||
const Draggable = defineAsyncComponent(() => import('vuedraggable').then(module => module.default))
|
||||
const ImportCodeDialog = defineAsyncComponent(() => import('@/components/dialog/ImportCodeDialog.vue'))
|
||||
|
||||
// 自定义规则列表
|
||||
const customRules = ref<CustomRule[]>([])
|
||||
|
||||
@@ -381,7 +383,7 @@ onMounted(() => {
|
||||
<VCardSubtitle>{{ t('setting.rule.customRulesDesc') }}</VCardSubtitle>
|
||||
</VCardItem>
|
||||
<VCardText>
|
||||
<draggable
|
||||
<Draggable
|
||||
v-model="customRules"
|
||||
handle=".cursor-move"
|
||||
item-key="name"
|
||||
@@ -396,7 +398,7 @@ onMounted(() => {
|
||||
@change="onRuleChange"
|
||||
/>
|
||||
</template>
|
||||
</draggable>
|
||||
</Draggable>
|
||||
</VCardText>
|
||||
<VCardText>
|
||||
<VForm @submit.prevent="() => {}">
|
||||
@@ -432,7 +434,7 @@ onMounted(() => {
|
||||
<VCardSubtitle>{{ t('setting.rule.priorityRuleGroupsDesc') }}</VCardSubtitle>
|
||||
</VCardItem>
|
||||
<VCardText>
|
||||
<draggable
|
||||
<Draggable
|
||||
v-model="filterRuleGroups"
|
||||
handle=".cursor-move"
|
||||
item-key="name"
|
||||
@@ -449,7 +451,7 @@ onMounted(() => {
|
||||
@change="changeRuleGroup"
|
||||
/>
|
||||
</template>
|
||||
</draggable>
|
||||
</Draggable>
|
||||
</VCardText>
|
||||
<VCardText>
|
||||
<VForm @submit.prevent="() => {}">
|
||||
|
||||
@@ -1,14 +1,11 @@
|
||||
<!-- eslint-disable sonarjs/no-duplicate-string -->
|
||||
<script lang="ts" setup>
|
||||
import { useToast } from 'vue-toastification'
|
||||
import { VRow } from 'vuetify/lib/components/index.mjs'
|
||||
import draggable from 'vuedraggable'
|
||||
import api from '@/api'
|
||||
import { DownloaderConf, MediaServerConf } from '@/api/types'
|
||||
import DownloaderCard from '@/components/cards/DownloaderCard.vue'
|
||||
import MediaServerCard from '@/components/cards/MediaServerCard.vue'
|
||||
import { copyToClipboard } from '@/@core/utils/navigator'
|
||||
import ProgressDialog from '@/components/dialog/ProgressDialog.vue'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { downloaderOptions, mediaServerOptions } from '@/api/constants'
|
||||
import { useDisplay, useTheme } from 'vuetify'
|
||||
@@ -22,6 +19,10 @@ const isTransparentTheme = computed(() => theme.name.value === 'transparent')
|
||||
// 国际化
|
||||
const { t } = useI18n()
|
||||
|
||||
// 下载器/媒体服务器排序和进度弹窗按需加载,降低系统设置页入口解析量。
|
||||
const Draggable = defineAsyncComponent(() => import('vuedraggable').then(module => module.default))
|
||||
const ProgressDialog = defineAsyncComponent(() => import('@/components/dialog/ProgressDialog.vue'))
|
||||
|
||||
// 系统设置项
|
||||
const SystemSettings = ref<any>({
|
||||
// 基础设置
|
||||
@@ -1405,7 +1406,7 @@ watch(currentLlmSnapshotKey, (snapshotKey, previousSnapshotKey) => {
|
||||
<VCardSubtitle>{{ t('setting.system.downloadersDesc') }}</VCardSubtitle>
|
||||
</VCardItem>
|
||||
<VCardText>
|
||||
<draggable
|
||||
<Draggable
|
||||
v-model="downloaders"
|
||||
handle=".cursor-move"
|
||||
item-key="name"
|
||||
@@ -1421,7 +1422,7 @@ watch(currentLlmSnapshotKey, (snapshotKey, previousSnapshotKey) => {
|
||||
:allow-refresh="isRequest"
|
||||
/>
|
||||
</template>
|
||||
</draggable>
|
||||
</Draggable>
|
||||
</VCardText>
|
||||
<VCardText>
|
||||
<VForm @submit.prevent="() => {}">
|
||||
@@ -1456,7 +1457,7 @@ watch(currentLlmSnapshotKey, (snapshotKey, previousSnapshotKey) => {
|
||||
<VCardSubtitle>{{ t('setting.system.mediaServersDesc') }}</VCardSubtitle>
|
||||
</VCardItem>
|
||||
<VCardText>
|
||||
<draggable
|
||||
<Draggable
|
||||
v-model="mediaServers"
|
||||
handle=".cursor-move"
|
||||
item-key="name"
|
||||
@@ -1471,7 +1472,7 @@ watch(currentLlmSnapshotKey, (snapshotKey, previousSnapshotKey) => {
|
||||
@change="onMediaServerChange"
|
||||
/>
|
||||
</template>
|
||||
</draggable>
|
||||
</Draggable>
|
||||
</VCardText>
|
||||
<VCardText>
|
||||
<VForm @submit.prevent="() => {}">
|
||||
|
||||
@@ -1,12 +1,8 @@
|
||||
<script lang="ts" setup>
|
||||
import draggable from 'vuedraggable'
|
||||
import api from '@/api'
|
||||
import type { Site, SiteUserData } from '@/api/types'
|
||||
import SiteCard from '@/components/cards/SiteCard.vue'
|
||||
import NoDataFound from '@/components/NoDataFound.vue'
|
||||
import SiteAddEditDialog from '@/components/dialog/SiteAddEditDialog.vue'
|
||||
import SiteStatisticsDialog from '@/components/dialog/SiteStatisticsDialog.vue'
|
||||
import SiteImportDialog from '@/components/dialog/SiteImportDialog.vue'
|
||||
import ProgressiveCardGrid from '@/components/misc/ProgressiveCardGrid.vue'
|
||||
import { useDynamicButton } from '@/composables/useDynamicButton'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
@@ -25,6 +21,12 @@ const route = useRoute()
|
||||
// APP 模式检测
|
||||
const { appMode } = usePWA()
|
||||
|
||||
// 拖拽排序和站点弹窗都不是站点列表首屏必需,打开对应功能时再加载。
|
||||
const Draggable = defineAsyncComponent(() => import('vuedraggable').then(module => module.default))
|
||||
const SiteAddEditDialog = defineAsyncComponent(() => import('@/components/dialog/SiteAddEditDialog.vue'))
|
||||
const SiteStatisticsDialog = defineAsyncComponent(() => import('@/components/dialog/SiteStatisticsDialog.vue'))
|
||||
const SiteImportDialog = defineAsyncComponent(() => import('@/components/dialog/SiteImportDialog.vue'))
|
||||
|
||||
// 站点列表
|
||||
const siteList = ref<Site[]>([])
|
||||
|
||||
@@ -402,7 +404,7 @@ useDynamicButton({
|
||||
</VAlert>
|
||||
|
||||
<LoadingBanner v-if="!isRefreshed" class="mt-12" />
|
||||
<draggable
|
||||
<Draggable
|
||||
v-if="draggableSiteList.length > 0 && canDragSort"
|
||||
v-model="draggableSiteList"
|
||||
@end="savaSitesPriority"
|
||||
@@ -421,7 +423,7 @@ useDynamicButton({
|
||||
@refresh-stats="handleRefreshStats"
|
||||
/>
|
||||
</template>
|
||||
</draggable>
|
||||
</Draggable>
|
||||
<ProgressiveCardGrid
|
||||
v-else-if="draggableSiteList.length > 0 && shouldVirtualizeList"
|
||||
:items="draggableSiteList"
|
||||
|
||||
Reference in New Issue
Block a user