From 55bbf27e8fa112d38e843a8eb2e8b1a9c9cd6eac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=BE=B7=E5=AE=87?= Date: Sun, 4 Oct 2026 17:12:55 +0800 Subject: [PATCH] =?UTF-8?q?fix(=E5=85=85=E5=80=BC=E5=BC=B9=E7=AA=97):=20?= =?UTF-8?q?=E5=BD=93=E5=89=8D=E6=A1=A3=E4=BD=8D=E6=94=B9=E4=BB=8E=E6=9C=AA?= =?UTF-8?q?=E8=BF=87=E6=BB=A4=E7=9B=AE=E5=BD=95=E8=A7=A3=E6=9E=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 有效会员的当前档位被后台临时禁用时,filter 后的 membershipPlans 查不到,状态卡退化成「会员」、按钮变「开通会员」,可在有效会员上重复开通(评审第 5 条) - 结算弹窗升级摘要的 currentPlan 同样取自过滤列表,禁用档位会丢「原套餐标准价」;改由父组件传入未过滤目录解析出的 currentPlan,并移除弹窗对 membership 的无用依赖(评审第 11 条) - 新增回归:active 会员 + 当前档 disabled 时仍显示「当前 Plus · 年付」、Max 提供「补差升级」,摘要保留「原套餐标准年价」 --- .../index.test.tsx | 44 +++++++++++++++++++ .../PlatformProfileRechargeModal/index.tsx | 17 ++++--- 2 files changed, 54 insertions(+), 7 deletions(-) diff --git a/packages/shared/src/components/PlatformProfileRechargeModal/index.test.tsx b/packages/shared/src/components/PlatformProfileRechargeModal/index.test.tsx index fbea85958..afb55f7f1 100644 --- a/packages/shared/src/components/PlatformProfileRechargeModal/index.test.tsx +++ b/packages/shared/src/components/PlatformProfileRechargeModal/index.test.tsx @@ -261,6 +261,50 @@ describe('PlatformProfileRechargeModal', () => { expect(onSubmitMembershipCheckout).toHaveBeenCalledWith('max', 'yearly'); }); + test('keeps an active member as member when their current plan is disabled', async () => { + const user = userEvent.setup(); + const onRequestMembershipQuote = vi.fn(); + + render( + , + ); + + // 状态卡仍认得当前档位,而不是退化成「会员」。 + expect(screen.getByText('当前 Plus · 年付')).toBeTruthy(); + // 有效会员看到的是补差升级,而不是可在有效会员上重复开通的「开通会员」。 + await user.click(screen.getByRole('button', { name: 'Max 年付 补差升级' })); + expect(onRequestMembershipQuote).toHaveBeenCalledWith('max'); + + const checkout = screen.getByRole('dialog', { name: '确认套餐变更' }); + // 即使原档位已禁用,升级摘要也要给出「原套餐标准年价」。 + expect(within(checkout).getByText('原套餐标准年价')).toBeTruthy(); + expect(within(checkout).getByText('¥990')).toBeTruthy(); + }); + test('shows a placeholder instead of the list price while the upgrade quote is loading', async () => { const user = userEvent.setup(); diff --git a/packages/shared/src/components/PlatformProfileRechargeModal/index.tsx b/packages/shared/src/components/PlatformProfileRechargeModal/index.tsx index c81eb11f6..e8bd6abea 100644 --- a/packages/shared/src/components/PlatformProfileRechargeModal/index.tsx +++ b/packages/shared/src/components/PlatformProfileRechargeModal/index.tsx @@ -936,7 +936,7 @@ function PlatformPointProductGrid({ function PlatformRechargeCheckoutDialog({ target, membershipPlans, - membership, + currentPlan, membershipQuote, isLoadingMembershipQuote, membershipQuoteError, @@ -949,7 +949,8 @@ function PlatformRechargeCheckoutDialog({ }: { target: PlatformProfileRechargeCheckoutTarget; membershipPlans: ProfileMembershipPlanRecord[]; - membership: ProfileMembership | null; + /** 会员当前档位;来自未过滤目录,档位被后台临时禁用时仍保留「原套餐标准价」。 */ + currentPlan: ProfileMembershipPlanRecord | null; membershipQuote: ProfileMembershipUpgradeQuote | null; isLoadingMembershipQuote: boolean; membershipQuoteError: string | null; @@ -1001,8 +1002,6 @@ function PlatformRechargeCheckoutDialog({ ? (plan?.yearPriceCents ?? 0) : (plan?.monthPriceCents ?? 0); const isUpgrade = target.mode === 'upgrade'; - const currentPlan = - membershipPlans.find((item) => item.plan === membership?.plan) ?? null; const productId = resolveMembershipProductId(target.plan, target.cycleKind); const submitting = submittingProductId === productId; const quoteForTarget = @@ -1317,10 +1316,14 @@ export function PlatformProfileRechargeModal({ () => center?.pointProducts ?? [], [center?.pointProducts], ); + // 当前档位必须从「未过滤目录」里查:会员有效期内若该档被后台临时禁用, + // 过滤后的 membershipPlans 查不到会把有效会员误判成非会员(状态卡丢标题、按钮变「开通会员」)。 const currentPlanRecord = useMemo( () => - membershipPlans.find((plan) => plan.plan === membership?.plan) ?? null, - [membership?.plan, membershipPlans], + (center?.membershipPlans ?? []).find( + (plan) => plan.plan === membership?.plan, + ) ?? null, + [center?.membershipPlans, membership?.plan], ); const [activeTab, setActiveTab] = useState('subscription'); @@ -1546,7 +1549,7 @@ export function PlatformProfileRechargeModal({