diff --git a/docs/BUG_HISTORY.md b/docs/BUG_HISTORY.md index 16f5d764..fb949440 100644 --- a/docs/BUG_HISTORY.md +++ b/docs/BUG_HISTORY.md @@ -2584,3 +2584,19 @@ - 相关记录:BUG-128、BUG-129、BUG-136、ERR-095、ERR-099、ERR-103 - 复发自:无 - 修复版本:待新 SHA 的 Release Gate 验证 + +## BUG-152 | 订单返回套餐后再次返回会重新进入订单页 + +- 状态:resolved(local candidate) +- 首次发现:2026-08-10 +- 最近更新:2026-08-10 +- 影响面:`/membership` 与 `/membership/orders` 的浏览器返回历史;支付、订单读取、兑换与 production 未改动。 +- 用户现象:从套餐与会员页进入订单记录,点击返回套餐页后,再点击套餐页返回,会再次进入订单记录页,形成往返循环。 +- 触发条件:套餐页用普通 Link 将订单页压入历史记录,订单页返回时又用普通 Link 将套餐页再次压入历史记录。 +- 根因:订单页的“返回套餐与会员”是返回语义,却使用了默认 push 导航,历史栈变成 `套餐页 → 订单页 → 套餐页`。 +- 修复:订单页返回 Link 使用 Next.js 原生 `replace`,将当前订单页历史项替换为套餐页;套餐页再次返回时回到进入套餐前的原入口。 +- 验证:聚焦 membership 合同测试锁定返回 Link 的 `replace` 语义;前端生产构建 `next build --webpack` 通过;`git diff --check` 通过。未 push、deploy 或触碰 production。 +- 防复发:固定目标的“返回上级页”不能再次 push 当前上级页;会员页回归测试持续锁定订单页返回的 replace 语义。 +- 相关记录:无 +- 复发自:无 +- 修复版本:本地候选提交(未 push / deploy) diff --git a/frontend/src/app/globals.css b/frontend/src/app/globals.css index 388c561f..719e05d0 100644 --- a/frontend/src/app/globals.css +++ b/frontend/src/app/globals.css @@ -749,6 +749,7 @@ button:disabled { cursor: default; opacity: .45; } .avatar-randomize { justify-self: start; } .avatar-notice { margin-top: var(--space-4); } .redeem-modal { width: min(100%, 420px); } +.paywall-modal { width: min(100%, 480px); } .logout-modal { width: min(100%, 400px); } .account-modal h2, .auth-panel h1, .admin-header h1 { font-family: var(--font-display); font-weight: 400; letter-spacing: -.5px; text-wrap: balance; } .account-modal h2 { margin: 0; font-size: var(--type-display-sm); letter-spacing: -.025em; } @@ -758,6 +759,14 @@ button:disabled { cursor: default; opacity: .45; } .redeem-balance span { color: var(--color-ink-secondary); font-size: var(--type-caption); } .redeem-balance strong { color: var(--color-ink); font-size: var(--type-title-lg); font-variant-numeric: tabular-nums; font-weight: 400; } .account-redeem-form { padding-top: var(--space-5); } +.paywall-intro { display: flex; align-items: flex-start; gap: var(--space-4); padding-bottom: var(--space-5); } +.paywall-mark { width: 44px; height: 44px; display: grid; flex: 0 0 auto; place-items: center; border-radius: 50%; background: var(--color-action-soft); color: var(--color-action); } +.paywall-mark svg { width: 20px; height: 20px; } +.paywall-intro b { display: block; color: var(--color-ink); font-family: var(--font-display); font-size: var(--type-title-md); font-weight: 400; } +.paywall-intro p { margin: var(--space-1) 0 0; color: var(--color-ink-secondary); font-size: var(--type-body-sm); line-height: 1.6; text-wrap: pretty; } +.paywall-footer { display: flex; align-items: center; justify-content: space-between; gap: var(--space-4); margin-top: var(--space-6); padding-top: var(--space-5); border-top: 1px solid var(--color-border); } +.paywall-footer span { color: var(--color-ink-secondary); font-size: var(--type-caption); } +.paywall-footer > a, .paywall-footer > button { flex: 0 0 auto; text-decoration: none; } .logout-copy { margin: 0; color: var(--color-ink-secondary); font-size: var(--type-body-md); line-height: 1.6; text-wrap: pretty; } .dialog-actions { display: flex; justify-content: flex-end; gap: var(--space-2); margin-top: var(--space-6); } .sheet-section { border-bottom: 1px solid var(--color-border); padding: var(--space-6) 0; border-color: var(--color-border); } @@ -910,6 +919,8 @@ input:not([class^="ant-"]):not([class*=" ant-"]):not(.ant-picker input):disabled .starter-content span { font-size: var(--type-title-sm); } .account-modal h2 { font-size: var(--type-title-lg); } .account-redeem-form > div { grid-template-columns: 1fr; } + .paywall-footer { align-items: stretch; flex-direction: column; } + .paywall-footer > a, .paywall-footer > button { width: 100%; } .dialog-actions { flex-direction: column-reverse; } .dialog-actions > button { width: 100%; } .auth-story { min-height: 220px; padding: var(--space-6) var(--space-5); } diff --git a/frontend/src/app/membership/orders/page.tsx b/frontend/src/app/membership/orders/page.tsx index 2384fb73..3a65ab97 100644 --- a/frontend/src/app/membership/orders/page.tsx +++ b/frontend/src/app/membership/orders/page.tsx @@ -84,7 +84,7 @@ export default function MembershipOrdersPage() {
填写兑换码,解锁后续咨询、生时校正与完整解读。
+