feat(redeem): 固定兑换链接 /redeem(输入订单号 → 状态分流 → 兑换)

- 路径式入口 `https://<域名>/redeem`(不带 #):主站是 HashRouter,
  故在 App.tsx 里早于 isWorkerSite() 插入独立 BrowserRouter 分支,
  主站与打手站路由均不受影响;Caddy 已有 try_files 兜底,无需改部署
- 页面按 7 种状态渲染:not_found / unpaid / cancelled / refunded /
  pending_certificate / redeemable / verified
  - not_found 保留用户输入的订单号,不清空
  - pending_certificate 只给显式「刷新」,不做自动轮询(公开限流接口,避免空转)
  - verified 只展示后端已掩码的券码,绝不渲染明文 certNo
  - confirm 不假设成功:一律按返回的 status 重渲染
- 纯函数抽到 utils/redeem.ts(无 React/antd、无 @ 别名),可直接跑单测
This commit is contained in:
yml2213
2026-10-09 12:01:35 +08:00
parent 080480f03b
commit 8c33ff62ec
7 changed files with 410 additions and 0 deletions
+19
View File
@@ -453,6 +453,25 @@
margin-bottom: 0;
}
/* ===== 兑换中心 (Redeem Page) ===== */
.redeem-page {
min-height: 100vh;
display: grid;
place-items: center;
padding: 32px 16px;
background: #f5f7fb;
}
.redeem-card {
width: min(520px, 100%);
}
.redeem-order-input {
flex: 1;
margin-bottom: 0;
}
/* ===== 买家页面响应式断点 ===== */
@media (max-width: 720px) {