From 02eee39ddf18c22d420bfe9e5ff5c8ab8dde3ae1 Mon Sep 17 00:00:00 2001 From: wucm667 Date: Fri, 28 Aug 2026 16:54:33 +0800 Subject: [PATCH] fix(payment): show selected currency in recharge rate --- frontend/src/i18n/locales/en/misc.ts | 2 +- frontend/src/i18n/locales/zh/misc.ts | 2 +- frontend/src/views/user/PaymentView.vue | 2 +- .../views/user/__tests__/PaymentView.spec.ts | 43 ++++++++++++++++++- 4 files changed, 45 insertions(+), 4 deletions(-) diff --git a/frontend/src/i18n/locales/en/misc.ts b/frontend/src/i18n/locales/en/misc.ts index e8f5404f25..d8d0124d37 100644 --- a/frontend/src/i18n/locales/en/misc.ts +++ b/frontend/src/i18n/locales/en/misc.ts @@ -390,7 +390,7 @@ export default { amountTooLow: 'Minimum amount is {min}', amountTooHigh: 'Maximum amount is {max}', amountNoMethod: 'No payment method available for this amount', - rechargeRatePreview: 'Current rate: 1 CNY = {usd} USD', + rechargeRatePreview: 'Current rate: 1 {currency} = {usd} USD', refundReason: 'Refund Reason', refundReasonPlaceholder: 'Please describe your refund reason', stripeLoadFailed: 'Failed to load payment component. Please refresh and try again.', diff --git a/frontend/src/i18n/locales/zh/misc.ts b/frontend/src/i18n/locales/zh/misc.ts index 6a51408425..dd08354c0b 100644 --- a/frontend/src/i18n/locales/zh/misc.ts +++ b/frontend/src/i18n/locales/zh/misc.ts @@ -414,7 +414,7 @@ export default { amountTooLow: '最低金额为 {min}', amountTooHigh: '最高金额为 {max}', amountNoMethod: '该金额没有可用的支付方式', - rechargeRatePreview: '当前倍率:1 CNY = {usd} USD', + rechargeRatePreview: '当前倍率:1 {currency} = {usd} USD', refundReason: '退款原因', refundReasonPlaceholder: '请描述您的退款原因', stripeLoadFailed: '支付组件加载失败,请刷新页面重试', diff --git a/frontend/src/views/user/PaymentView.vue b/frontend/src/views/user/PaymentView.vue index c5df5981f7..127e16e8e8 100644 --- a/frontend/src/views/user/PaymentView.vue +++ b/frontend/src/views/user/PaymentView.vue @@ -80,7 +80,7 @@ ${{ creditedAmount.toFixed(2) }}

- {{ t('payment.rechargeRatePreview', { usd: balanceRechargeMultiplier.toFixed(2) }) }} + {{ t('payment.rechargeRatePreview', { currency: selectedCurrency, usd: balanceRechargeMultiplier.toFixed(2) }) }}

diff --git a/frontend/src/views/user/__tests__/PaymentView.spec.ts b/frontend/src/views/user/__tests__/PaymentView.spec.ts index a3d688d5a9..acc5828a6a 100644 --- a/frontend/src/views/user/__tests__/PaymentView.spec.ts +++ b/frontend/src/views/user/__tests__/PaymentView.spec.ts @@ -3,7 +3,10 @@ import { flushPromises, shallowMount } from '@vue/test-utils' import PaymentView from '../PaymentView.vue' import { PAYMENT_RECOVERY_STORAGE_KEY } from '@/components/payment/paymentFlow' import { formatPaymentAmount } from '@/components/payment/currency' +import AmountInput from '@/components/payment/AmountInput.vue' import SubscriptionPlanCard from '@/components/payment/SubscriptionPlanCard.vue' +import en from '@/i18n/locales/en' +import zh from '@/i18n/locales/zh' import type { CheckoutInfoResponse, MethodLimit, SubscriptionPlan } from '@/types/payment' const routeState = vi.hoisted(() => ({ @@ -22,6 +25,7 @@ const showInfo = vi.hoisted(() => vi.fn()) const showWarning = vi.hoisted(() => vi.fn()) const getCheckoutInfo = vi.hoisted(() => vi.fn()) const bridgeInvoke = vi.hoisted(() => vi.fn()) +const translate = vi.hoisted(() => vi.fn((key: string) => key)) vi.mock('vue-router', async () => { const actual = await vi.importActual('vue-router') @@ -41,7 +45,7 @@ vi.mock('vue-i18n', async () => { return { ...actual, useI18n: () => ({ - t: (key: string) => key, + t: translate, }), } }) @@ -292,6 +296,43 @@ describe('PaymentView subscription plan grid', () => { }) }) +describe('PaymentView recharge rate preview', () => { + it('uses the selected payment method currency in both locale templates', async () => { + translate.mockClear() + routeState.path = '/purchase' + routeState.query = {} + getCheckoutInfo.mockReset().mockResolvedValue(checkoutInfoFixture({ + balance_recharge_multiplier: 0.5, + methods: { + stripe: { + ...checkoutInfoFixture().data.methods.wxpay, + currency: 'USD', + }, + }, + })) + + const wrapper = shallowMount(PaymentView, { + global: { + stubs: { + AppLayout: { template: '
' }, + Teleport: true, + Transition: false, + }, + }, + }) + await flushPromises() + wrapper.getComponent(AmountInput).vm.$emit('update:modelValue', 10) + await flushPromises() + + expect(translate).toHaveBeenCalledWith('payment.rechargeRatePreview', { + currency: 'USD', + usd: '0.50', + }) + expect(en.payment.rechargeRatePreview).toBe('Current rate: 1 {currency} = {usd} USD') + expect(zh.payment.rechargeRatePreview).toBe('当前倍率:1 {currency} = {usd} USD') + }) +}) + describe('PaymentView subscription confirmation amounts', () => { it('shows converted CNY pay amount using the subscription rate, not the balance multiplier', async () => { const wrapper = await mountSubscriptionConfirm({