perf(admin): 优化管理端页面切换性能与包体积
- 阶段 A: 增加 KeepAlive 缓存高频列表页,改用 onActivated 进行后台静默刷新,优化 tab 切换与 HomeEntry 闪屏 - 阶段 B: beforeEach 守卫在 TTL 内走同步快速路径,api 请求拦截器缓存 token 避免重复解析 JWT - 阶段 C: 引入 unplugin 插件启用 Element Plus 组件按需加载,清理 App.vue 中 960+ 行冗余暗色主题 CSS - i18n 拆包: 将三语文案包提取为独立懒加载 chunks,主包体积从 209KB 减少至 99KB (降低 53%)
This commit is contained in:
@@ -1,5 +1,7 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted, computed, watch, reactive, h } from 'vue';
|
||||
import { ref, onMounted, onActivated, computed, watch, reactive, h } from 'vue';
|
||||
|
||||
defineOptions({ name: 'AdminAgentManager' });
|
||||
import { useRouter } from 'vue-router';
|
||||
import { ElMessage, ElMessageBox } from 'element-plus';
|
||||
import { useAdminLocale } from '../composables/useAdminLocale';
|
||||
@@ -423,6 +425,11 @@ onMounted(() => {
|
||||
loadTier1Agents();
|
||||
}
|
||||
});
|
||||
// KeepAlive 激活时静默刷新列表(不重复page-init)
|
||||
onActivated(() => {
|
||||
if (canViewUsers.value && allPlayers.value.length > 0) void loadAllPlayers();
|
||||
if (canViewAgents.value && tier1Agents.value.length > 0) void loadTier1Agents();
|
||||
});
|
||||
|
||||
async function loadUsersPageInit() {
|
||||
try {
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted } from 'vue';
|
||||
import { ref, onMounted, onActivated } from 'vue';
|
||||
|
||||
defineOptions({ name: 'AdminBets' });
|
||||
import api from '../api';
|
||||
import { formatAmount, formatAmountFull } from '../utils/format-amount';
|
||||
import {
|
||||
@@ -33,6 +35,8 @@ const detail = ref<BetDetail | null>(null);
|
||||
const detailLoading = ref(false);
|
||||
|
||||
onMounted(load);
|
||||
// KeepAlive 激活时:有缓存数据则后台静默刷新,避免白屏等待
|
||||
onActivated(() => { if (bets.value.length > 0) void load(); });
|
||||
|
||||
function betContentCounts(row: BetListRow) {
|
||||
const singles = row.betType === 'SINGLE' ? 1 : 0;
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
<script setup lang="ts">
|
||||
import { computed, onMounted, ref } from 'vue';
|
||||
import { computed, onMounted, onActivated, ref } from 'vue';
|
||||
|
||||
defineOptions({ name: 'AdminCashback' });
|
||||
import type { TableColumnCtx } from 'element-plus';
|
||||
import { ElMessage, ElMessageBox } from 'element-plus';
|
||||
import { useAdminLocale } from '../composables/useAdminLocale';
|
||||
@@ -249,6 +251,8 @@ function onHistoryStatusChange() {
|
||||
}
|
||||
|
||||
onMounted(loadHistory);
|
||||
// KeepAlive 激活时静默刷新
|
||||
onActivated(() => { if (history.value.length > 0) void loadHistory(); });
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
||||
@@ -44,8 +44,8 @@ function switchTab(key: string) {
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<DepositOrders v-if="activeTab === 'orders'" />
|
||||
<PaymentMethods v-if="activeTab === 'methods'" />
|
||||
<DepositOrders v-show="activeTab === 'orders'" />
|
||||
<PaymentMethods v-show="activeTab === 'methods'" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted } from 'vue';
|
||||
import { ref, onMounted, onActivated } from 'vue';
|
||||
|
||||
defineOptions({ name: 'AdminDepositOrders' });
|
||||
import { ElMessage, ElMessageBox } from 'element-plus';
|
||||
import { useAdminLocale } from '../composables/useAdminLocale';
|
||||
import { resolveApiError } from '../i18n/form-validation';
|
||||
@@ -248,6 +250,8 @@ function prevPage() { if (page.value > 1) { page.value--; fetchList(); } }
|
||||
function nextPage() { if (page.value * pageSize.value < total.value) { page.value++; fetchList(); } }
|
||||
|
||||
onMounted(fetchList);
|
||||
// KeepAlive 激活时静默刷新
|
||||
onActivated(() => { if (items.value.length > 0) void fetchList(); });
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, computed, onMounted, watch } from 'vue';
|
||||
import { ref, computed, onMounted, onActivated, watch } from 'vue';
|
||||
|
||||
defineOptions({ name: 'AdminFinanceLogs' });
|
||||
import { useRoute, useRouter } from 'vue-router';
|
||||
import { useAuthStore } from '../stores/auth';
|
||||
import { useAdminLocale } from '../composables/useAdminLocale';
|
||||
@@ -204,6 +206,11 @@ onMounted(() => {
|
||||
if (activeTab.value === 'credit') void loadCredit();
|
||||
else void loadTransfer();
|
||||
});
|
||||
// KeepAlive 激活时静默刷新
|
||||
onActivated(() => {
|
||||
if (activeTab.value === 'credit' && creditItems.value.length > 0) void loadCredit();
|
||||
else if (activeTab.value === 'transfer' && transferItems.value.length > 0) void loadTransfer();
|
||||
});
|
||||
|
||||
watch(
|
||||
() => route.query.agentId,
|
||||
|
||||
@@ -3,7 +3,6 @@ import { shallowRef, onBeforeMount, type Component } from 'vue';
|
||||
import { RouterView, RouterLink, useRoute, useRouter } from 'vue-router';
|
||||
import { useAdminLocale } from '../composables/useAdminLocale';
|
||||
import { useAuthStore } from '../stores/auth';
|
||||
import { ensureStaffSession } from '../utils/session-hydrate';
|
||||
import DashboardSubNav from '../components/DashboardSubNav.vue';
|
||||
import { usePermissions } from '../composables/usePermissions';
|
||||
import { AdminPerm } from '../constants/permissions';
|
||||
@@ -14,12 +13,11 @@ const router = useRouter();
|
||||
const { t } = useAdminLocale();
|
||||
const { hasPermission, role } = usePermissions();
|
||||
const agentDashboard = shallowRef<Component | null>(null);
|
||||
const booting = shallowRef(true);
|
||||
|
||||
const showSupportShortcuts = shallowRef(false);
|
||||
|
||||
onBeforeMount(async () => {
|
||||
await ensureStaffSession();
|
||||
// router beforeEach 已执行过 ensureStaffSession,此处仅做菜单路由重定向逻辑,不再重复远程请求
|
||||
if (auth.isAdmin.value) {
|
||||
const code = role.value;
|
||||
if (code === 'FINANCE_ADMIN' && route.path === '/') {
|
||||
@@ -37,13 +35,11 @@ onBeforeMount(async () => {
|
||||
} else {
|
||||
agentDashboard.value = (await import('./agent/Dashboard.vue')).default;
|
||||
}
|
||||
booting.value = false;
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div v-if="booting" v-loading="true" class="home-boot" />
|
||||
<template v-else-if="auth.isAdmin.value">
|
||||
<template v-if="auth.isAdmin.value">
|
||||
<div v-if="showSupportShortcuts" class="support-shortcuts">
|
||||
<RouterLink v-if="hasPermission(AdminPerm.usersView, AdminPerm.agentsView)" to="/users" class="support-link">
|
||||
{{ t('nav.agents_players') }}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, computed, onMounted, onBeforeUnmount } from 'vue';
|
||||
import { ref, computed, onMounted, onActivated, onBeforeUnmount } from 'vue';
|
||||
|
||||
defineOptions({ name: 'AdminMatches' });
|
||||
import { useRoute } from 'vue-router';
|
||||
import { useAdminLocale } from '../composables/useAdminLocale';
|
||||
import { resolveFormError } from '../i18n/form-validation';
|
||||
@@ -121,6 +123,8 @@ onMounted(() => {
|
||||
}
|
||||
load({ restoreExpand: true });
|
||||
});
|
||||
// KeepAlive 激活时静默刷新,保持展开状态
|
||||
onActivated(() => { if (leagues.value.length > 0) void load({ keepExpand: true }); });
|
||||
onBeforeUnmount(persistListUiState);
|
||||
|
||||
function onPageChange(p: number) {
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted, onBeforeUnmount } from 'vue';
|
||||
import { ref, onMounted, onActivated, onBeforeUnmount } from 'vue';
|
||||
|
||||
defineOptions({ name: 'AdminMatchesOutrights' });
|
||||
import { useRoute } from 'vue-router';
|
||||
import { useAdminLocale } from '../composables/useAdminLocale';
|
||||
import api from '../api';
|
||||
@@ -97,6 +99,8 @@ onMounted(async () => {
|
||||
await load({ restoreExpand: true });
|
||||
await resolveExpandFromQuery();
|
||||
});
|
||||
// KeepAlive 激活时静默刷新
|
||||
onActivated(() => { if (leagues.value.length > 0) void load({ keepExpand: true }); });
|
||||
onBeforeUnmount(persistListUiState);
|
||||
|
||||
function onPageChange(p: number) {
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
<script setup lang="ts">
|
||||
import { computed, onMounted, ref } from 'vue';
|
||||
import { computed, onMounted, onActivated, ref } from 'vue';
|
||||
|
||||
defineOptions({ name: 'AdminStaffManage' });
|
||||
import { ElMessage, ElMessageBox } from 'element-plus';
|
||||
import api from '../api';
|
||||
import { useAdminLocale } from '../composables/useAdminLocale';
|
||||
@@ -249,6 +251,8 @@ onMounted(async () => {
|
||||
await loadRoles();
|
||||
await load();
|
||||
});
|
||||
// KeepAlive 激活时静默刷新
|
||||
onActivated(() => { if (rows.value.length > 0) void load(); });
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
||||
Reference in New Issue
Block a user