补充分割低频组件与响应式渲染优化

根据全站性能审计继续降低低频组件请求、重复 DOM 与重复缓存 URL 成本。

- 二维码组件改为详情弹窗实际渲染时异步加载
- 文件管理仅挂载当前断点对应的移动列表或桌面表格
- Vite 静态与动态资源统一使用 /theme-assets/ 前缀
- 已通过架构检查、类型检查、ESLint 和生产构建
This commit is contained in:
2026-07-21 17:02:09 +08:00
parent aa3743b42d
commit 2fe835d8d2
4 changed files with 20 additions and 6 deletions
+3 -2
View File
@@ -108,10 +108,10 @@
</template>
<script setup lang="ts">
import { inject } from 'vue'
import { defineAsyncComponent, inject } from 'vue'
import { useI18n } from 'vue-i18n'
import { FileIcon, CalendarIcon, HardDriveIcon, DownloadIcon } from 'lucide-vue-next'
import QRCode from 'qrcode.vue'
import type { ReceivedFileRecord } from '@/types'
import { buildDownloadUrl, buildReceivedRecordQrValue } from '@/utils/share-url'
@@ -129,6 +129,7 @@ defineProps<Props>()
defineEmits<Emits>()
const { t } = useI18n()
const isDarkMode = inject('isDarkMode')
const QRCode = defineAsyncComponent(() => import('qrcode.vue'))
const getDownloadUrl = (record: ReceivedFileRecord) => {
return buildDownloadUrl(record.downloadUrl)
@@ -168,7 +168,7 @@
</template>
<script setup lang="ts">
import { computed, inject } from 'vue'
import { computed, defineAsyncComponent, inject } from 'vue'
import {
ClipboardCopyIcon,
ClockIcon,
@@ -177,7 +177,7 @@ import {
TerminalIcon,
XIcon
} from 'lucide-vue-next'
import QRCode from 'qrcode.vue'
import { useI18n } from 'vue-i18n'
import type { SentFileRecord } from '@/types'
@@ -195,6 +195,7 @@ defineEmits<{
const { t } = useI18n()
const isDarkMode = inject('isDarkMode')
const QRCode = defineAsyncComponent(() => import('qrcode.vue'))
const qrValue = computed(() => (props.record ? props.getQRCodeValue(props.record) : ''))
</script>
+13 -2
View File
@@ -262,6 +262,7 @@
</section>
<section
v-if="isMobileViewport"
class="theme-2026-card mb-5 overflow-hidden rounded-[24px] shadow-md md:hidden"
>
<div class="flex items-center justify-between gap-3 border-b px-4 py-3" :class="[isDarkMode ? 'border-gray-700' : 'border-[#d9e4e6]']">
@@ -463,7 +464,7 @@
</aside>
</Transition>
<div class="hidden md:block">
<div v-if="!isMobileViewport" class="hidden md:block">
<DataTable :title="t('fileManage.allFiles')" :headers="fileTableHeaders" table-class="min-w-[1120px]">
<template #actions>
<BaseButton variant="secondary" :loading="isLoading" @click="refreshFileList">
@@ -1663,7 +1664,7 @@
</template>
<script setup lang="ts">
import { computed, onMounted, ref, watch, type Component } from 'vue'
import { computed, onMounted, onUnmounted, ref, watch, type Component } from 'vue'
import { useI18n } from 'vue-i18n'
import { useRoute, useRouter } from 'vue-router'
import type {
@@ -1810,6 +1811,11 @@ const {
const isFilterPanelOpen = ref(false)
const showMobilePolicyActions = ref(false)
const mobileMediaQuery = window.matchMedia('(max-width: 767px)')
const isMobileViewport = ref(mobileMediaQuery.matches)
const syncMobileViewport = (event: MediaQueryListEvent) => {
isMobileViewport.value = event.matches
}
const isLifecycleExpanded = ref(false)
const visibleDetailTimeline = computed(() => {
const rows = selectedFileDetail.value?.detailTimeline || []
@@ -2321,11 +2327,16 @@ watch(
)
onMounted(() => {
mobileMediaQuery.addEventListener('change', syncMobileViewport)
params.value.health = getRouteHealthFilter()
void loadViewPresets()
void loadFiles()
void loadHistoryFiles()
})
onUnmounted(() => {
mobileMediaQuery.removeEventListener('change', syncMobileViewport)
})
</script>
<style scoped>
+1
View File
@@ -6,6 +6,7 @@ import vueJsx from '@vitejs/plugin-vue-jsx'
import tailwindcss from 'tailwindcss'
import autoprefixer from 'autoprefixer'
export default defineConfig({
base: '/theme-assets/',
plugins: [vue(), vueJsx()],
resolve: {
alias: {