From 5f2d81d154478884fa723ae381bc202fd71d17b9 Mon Sep 17 00:00:00 2001 From: IanShaw027 <131567472+IanShaw027@users.noreply.github.com> Date: Sun, 28 Dec 2025 13:20:30 +0800 Subject: [PATCH] =?UTF-8?q?fix(frontend):=20=E4=BF=AE=E5=A4=8DUI=E6=94=B9?= =?UTF-8?q?=E8=BF=9B=E5=88=86=E6=94=AF=E4=B8=AD=E7=9A=84=E5=85=B3=E9=94=AE?= =?UTF-8?q?=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 修复RedeemView订阅刷新失败导致流程中断的问题 将订阅刷新隔离到独立try/catch,失败时仅显示警告 - 修复DataTable resize事件监听器泄漏问题 确保添加和移除使用同一个回调引用 - 修复订阅状态缓存导致强制刷新失效的问题 force=true时绕过activePromise缓存,clear()清空缓存 - 修复图表主题切换后颜色不更新的问题 添加图表ref并在主题切换时调用update()方法 --- frontend/src/components/common/DataTable.vue | 10 +++++++--- frontend/src/i18n/locales/en.ts | 3 ++- frontend/src/i18n/locales/zh.ts | 3 ++- frontend/src/stores/subscriptions.ts | 13 +++++++++---- frontend/src/views/user/DashboardView.vue | 19 ++++++++++++++++--- frontend/src/views/user/RedeemView.vue | 7 ++++++- 6 files changed, 42 insertions(+), 13 deletions(-) diff --git a/frontend/src/components/common/DataTable.vue b/frontend/src/components/common/DataTable.vue index 8abeee0c..9c250bc2 100644 --- a/frontend/src/components/common/DataTable.vue +++ b/frontend/src/components/common/DataTable.vue @@ -211,6 +211,7 @@ const checkActionsColumnWidth = () => { // 监听尺寸变化 let resizeObserver: ResizeObserver | null = null +let resizeHandler: (() => void) | null = null onMounted(() => { checkScrollable() @@ -223,17 +224,20 @@ onMounted(() => { resizeObserver.observe(tableWrapperRef.value) } else { // 降级方案:不支持 ResizeObserver 时使用 window resize - const handleResize = () => { + resizeHandler = () => { checkScrollable() checkActionsColumnWidth() } - window.addEventListener('resize', handleResize) + window.addEventListener('resize', resizeHandler) } }) onUnmounted(() => { resizeObserver?.disconnect() - window.removeEventListener('resize', checkScrollable) + if (resizeHandler) { + window.removeEventListener('resize', resizeHandler) + resizeHandler = null + } }) interface Props { diff --git a/frontend/src/i18n/locales/en.ts b/frontend/src/i18n/locales/en.ts index 3eb2fef3..285bb199 100644 --- a/frontend/src/i18n/locales/en.ts +++ b/frontend/src/i18n/locales/en.ts @@ -410,7 +410,8 @@ export default { subscriptionDays: '{days} days', days: ' days', codeRedeemSuccess: 'Code redeemed successfully!', - failedToRedeem: 'Failed to redeem code. Please check the code and try again.' + failedToRedeem: 'Failed to redeem code. Please check the code and try again.', + subscriptionRefreshFailed: 'Redeemed successfully, but failed to refresh subscription status.' }, // Profile diff --git a/frontend/src/i18n/locales/zh.ts b/frontend/src/i18n/locales/zh.ts index ca4ea7ac..1231ce54 100644 --- a/frontend/src/i18n/locales/zh.ts +++ b/frontend/src/i18n/locales/zh.ts @@ -406,7 +406,8 @@ export default { subscriptionDays: '{days} 天', days: '天', codeRedeemSuccess: '兑换成功!', - failedToRedeem: '兑换失败,请检查兑换码后重试。' + failedToRedeem: '兑换失败,请检查兑换码后重试。', + subscriptionRefreshFailed: '兑换成功,但订阅状态刷新失败。' }, // Profile diff --git a/frontend/src/stores/subscriptions.ts b/frontend/src/stores/subscriptions.ts index 2bda1e1a..58965914 100644 --- a/frontend/src/stores/subscriptions.ts +++ b/frontend/src/stores/subscriptions.ts @@ -48,7 +48,7 @@ export const useSubscriptionStore = defineStore('subscriptions', () => { } // Return in-flight request if exists (deduplication) - if (activePromise) { + if (activePromise && !force) { return activePromise } @@ -56,7 +56,7 @@ export const useSubscriptionStore = defineStore('subscriptions', () => { // Start new request loading.value = true - activePromise = subscriptionsAPI + const requestPromise = subscriptionsAPI .getActiveSubscriptions() .then((data) => { if (currentGeneration === requestGeneration) { @@ -71,10 +71,14 @@ export const useSubscriptionStore = defineStore('subscriptions', () => { throw error }) .finally(() => { - loading.value = false - activePromise = null + if (activePromise === requestPromise) { + loading.value = false + activePromise = null + } }) + activePromise = requestPromise + return activePromise } @@ -106,6 +110,7 @@ export const useSubscriptionStore = defineStore('subscriptions', () => { */ function clear() { requestGeneration++ + activePromise = null activeSubscriptions.value = [] loaded.value = false lastFetchedAt.value = null diff --git a/frontend/src/views/user/DashboardView.vue b/frontend/src/views/user/DashboardView.vue index 1288ac48..d660e1a0 100644 --- a/frontend/src/views/user/DashboardView.vue +++ b/frontend/src/views/user/DashboardView.vue @@ -336,6 +336,7 @@
@@ -400,7 +401,12 @@ {{ t('dashboard.tokenUsageTrend') }}
- +
diff --git a/frontend/src/views/user/RedeemView.vue b/frontend/src/views/user/RedeemView.vue index 7e35916d..6fa29c5b 100644 --- a/frontend/src/views/user/RedeemView.vue +++ b/frontend/src/views/user/RedeemView.vue @@ -548,7 +548,12 @@ const handleRedeem = async () => { // If subscription type, immediately refresh subscription status if (result.type === 'subscription') { - await subscriptionStore.fetchActiveSubscriptions(true) // force refresh + try { + await subscriptionStore.fetchActiveSubscriptions(true) // force refresh + } catch (error) { + console.error('Failed to refresh subscriptions after redeem:', error) + appStore.showWarning(t('redeem.subscriptionRefreshFailed')) + } } // Clear the input