From 930326116ed6bbc68c64e9536f8ed5778f078aaf Mon Sep 17 00:00:00 2001 From: shaw Date: Tue, 30 Jun 2026 16:26:22 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E8=AE=A2=E9=98=85?= =?UTF-8?q?=E6=94=AF=E4=BB=98=E9=87=91=E9=A2=9D=E6=98=BE=E7=A4=BA=E9=94=99?= =?UTF-8?q?=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/views/user/PaymentView.vue | 26 ++++----------- .../views/user/__tests__/PaymentView.spec.ts | 33 ++++++++++--------- 2 files changed, 23 insertions(+), 36 deletions(-) diff --git a/frontend/src/views/user/PaymentView.vue b/frontend/src/views/user/PaymentView.vue index f77dc3a9c6..baa0cb244e 100644 --- a/frontend/src/views/user/PaymentView.vue +++ b/frontend/src/views/user/PaymentView.vue @@ -275,7 +275,7 @@ import { platformAccentBarClass, platformBadgeLightClass, platformBadgeClass, pl import SubscriptionPlanCard from '@/components/payment/SubscriptionPlanCard.vue' import PaymentStatusPanel from '@/components/payment/PaymentStatusPanel.vue' import Icon from '@/components/icons/Icon.vue' -import { DEFAULT_PAYMENT_CURRENCY, formatPaymentAmount, normalizePaymentCurrency } from '@/components/payment/currency' +import { formatPaymentAmount, normalizePaymentCurrency } from '@/components/payment/currency' import type { PaymentMethodOption } from '@/components/payment/PaymentMethodSelector.vue' import { buildPaymentErrorToastMessage, describePaymentScenarioError } from './paymentUx' import { hasWechatResumeQuery, parseWechatResumeRoute, stripWechatResumeQuery } from './paymentWechatResume' @@ -540,10 +540,6 @@ const localeCode = computed(() => { return undefined }) -interface PaymentAmountFormatOptions { - subscription?: boolean -} - function currencyFractionDigits(currency: string): number { try { return new Intl.NumberFormat(undefined, { @@ -567,22 +563,12 @@ function ceilPaymentAmount(value: number, currency: string): number { return Math.ceil(value * factor) / factor } -function subscriptionPaymentAmountForCurrency(value: number, currency: string): number { - if (currency !== DEFAULT_PAYMENT_CURRENCY) return value - return roundPaymentAmount(value / balanceRechargeMultiplier.value, currency) -} - -function subscriptionPaymentAmount(value: number): number { - return subscriptionPaymentAmountForCurrency(value, selectedCurrency.value) -} - -function formatSelectedPaymentAmount(value: number, options: PaymentAmountFormatOptions = {}): string { - const amount = options.subscription ? subscriptionPaymentAmount(value) : value - return formatPaymentAmount(amount, selectedCurrency.value, localeCode.value) +function formatSelectedPaymentAmount(value: number): string { + return formatPaymentAmount(value, selectedCurrency.value, localeCode.value) } function formatSelectedSubscriptionPaymentAmount(value: number): string { - return formatSelectedPaymentAmount(value, { subscription: true }) + return formatSelectedPaymentAmount(roundPaymentAmount(value, selectedCurrency.value)) } const methodOptions = computed(() => @@ -631,7 +617,7 @@ const canSubmit = computed(() => const subPaymentAmount = computed(() => { const price = selectedPlan.value?.price ?? 0 - return subscriptionPaymentAmount(price) + return roundPaymentAmount(price, selectedCurrency.value) }) const subFeeAmount = computed(() => { @@ -645,7 +631,7 @@ const subTotalAmount = computed(() => { }) function subscriptionTotalAmountForCurrency(value: number, currency: string): number { - const paymentAmount = subscriptionPaymentAmountForCurrency(value, currency) + const paymentAmount = roundPaymentAmount(value, currency) if (feeRate.value <= 0 || paymentAmount <= 0) return paymentAmount const fee = ceilPaymentAmount((paymentAmount * feeRate.value) / 100, currency) return roundPaymentAmount(paymentAmount + fee, currency) diff --git a/frontend/src/views/user/__tests__/PaymentView.spec.ts b/frontend/src/views/user/__tests__/PaymentView.spec.ts index d2c89c601d..3b16d42af1 100644 --- a/frontend/src/views/user/__tests__/PaymentView.spec.ts +++ b/frontend/src/views/user/__tests__/PaymentView.spec.ts @@ -236,28 +236,29 @@ async function mountSubscriptionConfirm(options: Parameters { - it('shows converted CNY pay amount for plan price, original price, and create button', async () => { + it('keeps subscription plan price independent from balance recharge multiplier', async () => { const wrapper = await mountSubscriptionConfirm({ checkout: { - balance_recharge_multiplier: 0.14, + balance_recharge_multiplier: 4, }, method: { currency: 'CNY', }, plan: { - price: 7.99, - original_price: 9.99, + price: 200, + original_price: 300, }, }) const text = wrapper.text() - const convertedPrice = formatPaymentAmount(57.07, 'CNY') - const convertedOriginalPrice = formatPaymentAmount(71.36, 'CNY') + const planPrice = formatPaymentAmount(200, 'CNY') + const originalPrice = formatPaymentAmount(300, 'CNY') + const convertedByRechargeMultiplier = formatPaymentAmount(50, 'CNY') - expect(text).toContain(convertedPrice) - expect(text).toContain(convertedOriginalPrice) - expect(text).not.toContain(formatPaymentAmount(7.99, 'CNY')) - expect(wrapper.findAll('button').some(button => button.text().includes(convertedPrice))).toBe(true) + expect(text).toContain(planPrice) + expect(text).toContain(originalPrice) + expect(text).not.toContain(convertedByRechargeMultiplier) + expect(wrapper.findAll('button').some(button => button.text().includes(planPrice))).toBe(true) }) it('keeps plan price when multiplier is not configured or payment currency is not CNY', async () => { @@ -293,10 +294,10 @@ describe('PaymentView subscription confirmation amounts', () => { expect(usdWrapper.text()).toContain(formatPaymentAmount(9.99, 'USD')) }) - it('adds fee rate after CNY multiplier conversion to match backend pay_amount', async () => { + it('adds fee rate to the direct subscription plan price to match backend pay_amount', async () => { const wrapper = await mountSubscriptionConfirm({ checkout: { - balance_recharge_multiplier: 0.14, + balance_recharge_multiplier: 4, recharge_fee_rate: 2.5, }, method: { @@ -308,11 +309,11 @@ describe('PaymentView subscription confirmation amounts', () => { }) const text = wrapper.text() - const convertedPrice = formatPaymentAmount(57.07, 'CNY') - const fee = formatPaymentAmount(1.43, 'CNY') - const total = formatPaymentAmount(58.5, 'CNY') + const price = formatPaymentAmount(7.99, 'CNY') + const fee = formatPaymentAmount(0.20, 'CNY') + const total = formatPaymentAmount(8.19, 'CNY') - expect(text).toContain(convertedPrice) + expect(text).toContain(price) expect(text).toContain(fee) expect(text).toContain(total) expect(wrapper.findAll('button').some(button => button.text().includes(total))).toBe(true)