feat(core): Wave 3.5 前端 — 注册页/登录双态 + 邀请制 API 接线(认证定调:无邮箱)

scaffolding: types.ts 加 Invitation 类型;api.ts 加 listInvitations/createInvitation/revokeInvitation +
  register() 加 invite_code;route-config AuthMode "login"|"register" + /register 返回 register 态;
  App.tsx onModeChange 按 mode 切 /login↔/register URL
auth-screen.tsx(sub-agent):登录+注册双态(按 initialMode 渲染),去掉 /register→/login 强制改写;
  注册表单 = 团队名/用户名/密码/确认密码/邀请码(去邮箱!)+ 左价值点 + 协议勾选 + 一致性校验,
  有码提示「加入团队」无码「开新团队」;登录补第三方(微信/飞书+OR线)+ 切换行 + lead/mono;登录保持秒进
styles.css:仅加 .auth-* 注册态/第三方/切换行 CSS(restraint token)

验证: tsc 0 · build 0 · 走查 登录(无邮箱/第三方×2/切换/秒进698ms)+ 注册(5字段/0邮箱/0「邮箱」文案)
  + 切换态(URL→/register)全过 · 0 console error

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
seaislee1209
2026-06-19 12:41:36 +08:00
co-authored by Claude Opus 4.8
parent ba855cc219
commit c0a8582f3b
7 changed files with 648 additions and 25 deletions
+11 -1
View File
@@ -6,6 +6,7 @@ import type {
BillingTrend,
Ledger,
LoginSession,
Invitation,
ModelConfig,
Notification,
NotificationList,
@@ -105,7 +106,7 @@ async function request<T>(path: string, options: RequestInit = {}): Promise<T> {
}
export const api = {
register(payload: { username: string; password: string; email?: string; team_name?: string }) {
register(payload: { username: string; password: string; email?: string; team_name?: string; invite_code?: string }) {
return request<AuthPayload>("/api/auth/register/", { method: "POST", body: JSON.stringify(payload) });
},
login(payload: { username: string; password: string }) {
@@ -172,6 +173,15 @@ export const api = {
body: JSON.stringify({ password })
});
},
listInvitations() {
return request<Invitation[]>("/api/auth/team/invitations/");
},
createInvitation(payload: { role?: string; email?: string; monthly_credit_limit?: number | string }) {
return request<Invitation>("/api/auth/team/invitations/", { method: "POST", body: JSON.stringify(payload) });
},
revokeInvitation(id: string) {
return request<Invitation>(`/api/auth/team/invitations/${id}/revoke/`, { method: "POST" });
},
products() {
return request<Paginated<Product>>("/api/products/");
},