Skip to content

feat: 集成 Cloudflare Turnstile + 按设计稿重构登录后页面 - #32

Merged
BSTester merged 1 commit into
mainfrom
feat/turnstile-and-postlogin-refactor
Aug 15, 2026
Merged

feat: 集成 Cloudflare Turnstile + 按设计稿重构登录后页面#32
BSTester merged 1 commit into
mainfrom
feat/turnstile-and-postlogin-refactor

Conversation

@BSTester

Copy link
Copy Markdown
Owner

改动

1. Cloudflare Turnstile 替换图形验证码

  • 后端:新增 web/backend/turnstile.py(siteverify 校验,默认用官方测试密钥始终通过,方便联调);auth_routes 的 login/register/email-code 流程用 Turnstile 替换 captcha 校验;移除 /api/auth/captcha/new,新增 /api/auth/turnstile/sitekey
  • 前端:新增 Turnstile.tsx 组件(显式渲染、可 reset、dark 主题);LoginForm/RegisterForm 去掉图形验证码,改挂 Turnstile;apiClient/useAuth 统一传 turnstile_token;删除 CaptchaImage
  • 默认使用 Cloudflare 测试密钥(sitekey 1x00000000000000000000AA / secret 1x0000000000000000000000000000000AA),生产环境用环境变量 TURNSTILE_SITE_KEY / TURNSTILE_SECRET_KEY 覆盖。

2. 按设计稿重构登录后系统页面

  • me/*(我的分析 / 订阅明细 / 账户偏好)改为设计稿的侧栏布局 AccountLayout(用户名片 + 纵向导航,窄屏横向滚动)。
  • admin/*(用户管理 / LLM 配置 / 系统默认 Provider)从旧 AppNavbar+Footer 切到新 SiteLayout,补齐设计稿页头(eyebrow + 标题 + 管理员徽章)。
  • 抽出 ResearchCard 到独立组件,修复页面模块导出非页面组件的 tsc 报错。

验证

  • tsc --noEmit:0 报错
  • next build:26 路由全部静态预渲染成功
  • vitest run:74/74 通过
  • e2e(新后端 + 测试密钥):GET /api/auth/turnstile/sitekey → 测试 key;POST /api/auth/captcha/new → 404;带 token 登录 → 放行人机验证后校验账密(401 用户名或密码错误);不带 token 登录 → 422 人机验证失败。

联调说明

当前用 Cloudflare 官方测试密钥,Turnstile widget 会显示但始终通过。要切到真实人机验证,在 .env 设置真实的 TURNSTILE_SITE_KEY / TURNSTILE_SECRET_KEYNEXT_PUBLIC_TURNSTILE_SITE_KEY 即可,前后端无需改代码。

- 登录/注册/邮箱验证码下发改用 Cloudflare Turnstile 人机验证组件,
  默认使用官方测试密钥(始终通过)方便联调;生产环境通过环境变量
  TURNSTILE_SITE_KEY / TURNSTILE_SECRET_KEY 覆盖
- 后端:新增 web/backend/turnstile.py 做 siteverify 校验;
  auth_routes 的 login/register/email-code 流程替换 captcha 校验,
  移除 /api/auth/captcha/new,新增 /api/auth/turnstile/sitekey
- 前端:新增 Turnstile 组件,LoginForm/RegisterForm 去掉图形验证码,
  apiClient/auth hook 统一传 turnstile_token;删除 CaptchaImage
- 登录后页面按设计稿重构:me/* 改为侧栏布局(AccountLayout),
  admin/* 从旧 AppNavbar 切到新 SiteLayout,补齐设计稿页头样式
- 抽出 ResearchCard 到独立组件,修复页面模块导出非页面组件的 tsc 报错

验证:tsc 0 报错;next build 26 路由全部预渲染;vitest 74/74 通过;
e2e:sitekey 返回测试 key,带 token 登录放行人机验证后校验账密,
缺 token 返回 422 人机验证失败

Co-authored-by: multica-agent <github@multica.ai>
Copilot AI lite review requested due to automatic review settings August 14, 2026 09:29

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

该 PR 在 FastAPI 后端鉴权链路Next.js 前端认证/登录后页面结构两端同步改造:用 Cloudflare Turnstile 替换原图形验证码,并按设计稿统一登录后个人区与管理后台的页面布局组件化复用。

Changes:

  • 后端新增 Turnstile 校验模块与 sitekey 下发接口,并将 login/register/email-code 流程从图形验证码切换为 Turnstile。
  • 前端新增 Turnstile 组件并改造登录/注册表单的鉴权参数传递;移除 CaptchaImage。
  • 登录后页面按设计稿重构:引入 AccountLayout、抽离 ResearchCard、admin 页面切换到 SiteLayout,并补齐所需图标子集。

Reviewed changes

Copilot reviewed 21 out of 21 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
web/frontend/src/lib/auth.tsx AuthContext 的 login/register/email-code 入参改为 turnstileToken
web/frontend/src/lib/apiClient.ts authAPI 改为传 turnstile_token,并新增获取 Turnstile sitekey 方法
web/frontend/src/components/site/ResearchCard.tsx 从 page 模块抽离可复用 ResearchCard,避免 Next 页面导出非页面组件
web/frontend/src/components/site/AccountLayout.tsx 新增登录后个人区侧栏布局(用户名片 + 导航 + 主内容区)
web/frontend/src/components/auth/Turnstile.tsx 新增 Turnstile 显式渲染组件,支持 reset 与失败提示
web/frontend/src/components/auth/RegisterForm.tsx 注册流程移除图形验证码,改用 Turnstile token + 邮箱验证码
web/frontend/src/components/auth/LoginForm.tsx 登录/邮箱验证码登录移除图形验证码,改用 Turnstile token
web/frontend/src/components/auth/CaptchaImage.tsx 删除旧图形验证码组件
web/frontend/src/app/page.tsx 首页改为引用抽离后的 ResearchCard
web/frontend/src/app/me/page.tsx “我的分析”切换到 AccountLayout,并调整操作按钮/文案
web/frontend/src/app/me/billing/page.tsx “订阅明细”切换到 AccountLayout,并补齐购买入口
web/frontend/src/app/me/preferences/page.tsx “账户偏好”切换到 AccountLayout,并修正设置入口为 Link
web/frontend/src/app/leaderboard/page.tsx 榜单页改为引用抽离后的 ResearchCard
web/frontend/src/app/admin/users/page.tsx 管理页从旧 AppNavbar/Footer 切换到 SiteLayout
web/frontend/src/app/admin/system-default-provider/page.tsx 管理页切换到 SiteLayout,并补齐设计稿标题/徽章结构
web/frontend/src/app/admin/llm-config/page.tsx 管理页切换到 SiteLayout,并补齐设计稿标题/徽章结构
web/frontend/public/lib/font-awesome/css/icons.subset.css 增补/调整图标子集以匹配新布局所需图标
web/backend/turnstile.py 新增 Turnstile siteverify 校验逻辑与测试密钥默认值
web/backend/schemas.py 请求体由 captcha_* 字段切换为 turnstile_token
web/backend/auth_routes.py 移除 /captcha/new,新增 /turnstile/sitekey,并在鉴权流程中使用 Turnstile 校验
.env.example 增加 Turnstile 相关环境变量示例(后端与 NEXT_PUBLIC 前端注入)

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment on lines +63 to 66
await authAPI.sendEmailCode(emailForCode, turnstileToken);

onShowToast('验证码已发送到您的邮箱', 'success');
setCountdown(60);
Comment on lines +62 to 65
await authAPI.sendEmailCodeForRegister(formData.email, turnstileToken);

onShowToast('验证码已发送到您的邮箱,请查收', 'success');
setCountdown(60);
Comment on lines +36 to +52
scriptLoadPromise = new Promise<void>((resolve, reject) => {
const existing = document.querySelector<HTMLScriptElement>(
`script[src="${SCRIPT_SRC}"]`,
);
if (existing) {
existing.addEventListener('load', () => resolve());
existing.addEventListener('error', () => reject(new Error('Turnstile script load failed')));
return;
}
const s = document.createElement('script');
s.src = SCRIPT_SRC;
s.async = true;
s.defer = true;
s.onload = () => resolve();
s.onerror = () => reject(new Error('Turnstile script load failed'));
document.head.appendChild(s);
});
Comment on lines +92 to +95
getTurnstileSiteKey: async () => {
try {
const response = await publicApiClient.get('/api/auth/turnstile/sitekey');
return response.data as { sitekey: string };
Comment thread web/backend/turnstile.py
Comment on lines +7 to +18
import os
from typing import Optional

import httpx

# Cloudflare 官方测试密钥(始终通过 / always passes)
# 详见 https://developers.cloudflare.com/turnstile/troubleshooting/testing/
_TEST_SECRET = "1x0000000000000000000000000000000AA"
_TEST_SITE_KEY = "1x00000000000000000000AA"

TURNSTILE_SECRET_KEY = os.getenv("TURNSTILE_SECRET_KEY", _TEST_SECRET)
TURNSTILE_SITE_KEY = os.getenv("TURNSTILE_SITE_KEY", _TEST_SITE_KEY)
@BSTester
BSTester merged commit 58f6f6d into main Aug 15, 2026
1 check passed
@BSTester
BSTester deleted the feat/turnstile-and-postlogin-refactor branch August 15, 2026 02:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants