From a2b14860c2777ef4857d8e55049f732bc65cfc1e Mon Sep 17 00:00:00 2001 From: wanghuixian Date: Wed, 25 Mar 2026 02:09:15 +0000 Subject: [PATCH] Optimize cloud billing data loading - Add loading state flags to prevent concurrent API calls - Implement debounce for statistics and details data loading (100ms) - Skip watch callbacks during component initialization - Reduce unnecessary API requests when filters change rapidly --- .gitignore | 1 + src/pages/CloudBilling/Billing.vue | 28 ++++++++++++++++++++++++++-- 2 files changed, 27 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index 600a076..1dc12a7 100644 --- a/.gitignore +++ b/.gitignore @@ -91,3 +91,4 @@ temp/ # AI/IDE directories .cursor/ +.agents/ diff --git a/src/pages/CloudBilling/Billing.vue b/src/pages/CloudBilling/Billing.vue index ce3a4e1..634d025 100644 --- a/src/pages/CloudBilling/Billing.vue +++ b/src/pages/CloudBilling/Billing.vue @@ -537,6 +537,11 @@ const detailsProviderId = ref('') const detailsAccountId = ref('') const showPreviewModal = ref(false) const selectedBilling = ref(null) +const isInitializing = ref(true) + +// Prevent multiple concurrent calls +let isStatsLoading = false +let isDetailsLoading = false // Initialize date range: details tab default is last 3 days (from 3 days ago to today) const initDateRange = () => { @@ -574,6 +579,9 @@ const loadProviders = async () => { // Load statistics const loadStatistics = async () => { + if (isStatsLoading) return + + isStatsLoading = true statsLoading.value = true try { const params = {} @@ -615,6 +623,7 @@ const loadStatistics = async () => { statistics.value = null } finally { statsLoading.value = false + isStatsLoading = false } } @@ -678,6 +687,9 @@ const loadDailyBillingData = async () => { // Load billing details const loadBillings = async (query = '') => { + if (isDetailsLoading) return + + isDetailsLoading = true detailsLoading.value = true try { const params = {} @@ -797,6 +809,7 @@ const loadBillings = async (query = '') => { billings.value = [] } finally { detailsLoading.value = false + isDetailsLoading = false } } @@ -804,6 +817,14 @@ const { debouncedFn: debouncedSearch } = useDebounce((query) => { loadBillings(query) }, 300) +const { debouncedFn: debouncedLoadStatistics } = useDebounce(() => { + loadStatistics() +}, 100) + +const { debouncedFn: debouncedLoadBillings } = useDebounce(() => { + loadBillings(searchQuery.value) +}, 100) + const handleSearch = (query) => { searchQuery.value = query debouncedSearch(query) @@ -833,20 +854,23 @@ watch(activeTab, (newTab) => { // Watch statistics filter changes for real-time updates watch([statsPeriodType, statsSelectedPeriod, statsSelectedYear, statsProviderId, statsAccountId], () => { + if (isInitializing.value) return if (activeTab.value === 'statistics') { - loadStatistics() + debouncedLoadStatistics() } }) // Watch details filter changes watch([detailsStartDate, detailsEndDate, detailsProviderId, detailsAccountId], () => { + if (isInitializing.value) return if (activeTab.value === 'details') { - loadBillings(searchQuery.value) + debouncedLoadBillings() } }) onMounted(() => { initDateRange() + isInitializing.value = false loadProviders() loadStatistics() })