-
-
-
- setUsername(e.target.value)}
- placeholder="请输入用户名"
- autoComplete="username"
- onKeyDown={(e) => e.key === "Enter" && handleRegister()}
- />
-
-
-
- setNickname(e.target.value)}
- placeholder="请输入昵称"
- autoComplete="nickname"
- onKeyDown={(e) => e.key === "Enter" && handleRegister()}
- />
-
-
-
- setPassword(e.target.value)}
- type="password"
- placeholder="请输入密码(至少 8 位)"
- autoComplete="new-password"
- onKeyDown={(e) => e.key === "Enter" && handleRegister()}
- />
-
-
-
- setEmail(e.target.value)}
- placeholder="请输入电子邮箱"
- autoComplete="email"
- onKeyDown={(e) => e.key === "Enter" && handleRegister()}
- />
-
- {emailRegisterEnabled && (
-
-
-
- setCode(e.target.value)}
- placeholder="请输入 6 位邮箱验证码"
- maxLength={6}
- className="flex-1"
- onKeyDown={(e) => e.key === "Enter" && handleRegister()}
- />
-
-
+
-
-
-
-
- Already have an account?{" "}
-
- Sign in
-
-
-
-
+
+ 已经有账号?{" "}
+
+ 返回登录
+
+
+
)
}
diff --git a/frontend/components/auth/register-page.tsx b/frontend/components/auth/register-page.tsx
index cba9b374..755bda44 100644
--- a/frontend/components/auth/register-page.tsx
+++ b/frontend/components/auth/register-page.tsx
@@ -1,25 +1,12 @@
"use client"
-import {motion} from "motion/react"
import {RegisterForm} from "@/components/auth/register-form"
-import {AuroraBackground} from "@/components/ui/aurora-background"
+import {AuthShell} from "@/components/auth/auth-shell"
export function RegisterPage() {
return (
-
-
-
-
-
+
+
+
)
}
diff --git a/frontend/components/providers/title-updater.tsx b/frontend/components/providers/title-updater.tsx
new file mode 100644
index 00000000..54281001
--- /dev/null
+++ b/frontend/components/providers/title-updater.tsx
@@ -0,0 +1,36 @@
+"use client"
+
+import {useQuery} from '@tanstack/react-query'
+import {useEffect} from 'react'
+import services from '@/lib/services'
+import {usePathname} from 'next/navigation'
+
+export function SiteTitleUpdater() {
+ const pathname = usePathname()
+ const publicConfigQuery = useQuery({
+ queryKey: ["public-config"],
+ queryFn: () => services.config.getPublicConfig(),
+ })
+
+ useEffect(() => {
+ const siteName = publicConfigQuery.data?.site_name || "Wavelet Platform"
+
+ // Determine the page suffix based on path
+ let suffix = ""
+ if (pathname === "/login") {
+ suffix = " - 登录"
+ } else if (pathname === "/register") {
+ suffix = " - 注册"
+ } else if (pathname.startsWith("/admin")) {
+ suffix = " - 后台管理"
+ } else if (pathname === "/home") {
+ suffix = " - 控制台"
+ } else if (pathname === "/") {
+ suffix = ""
+ }
+
+ document.title = `${siteName}${suffix}`
+ }, [publicConfigQuery.data?.site_name, pathname])
+
+ return null
+}
diff --git a/frontend/components/ui/button.tsx b/frontend/components/ui/button.tsx
index 64ec63c8..b7826d93 100644
--- a/frontend/components/ui/button.tsx
+++ b/frontend/components/ui/button.tsx
@@ -1,8 +1,8 @@
import * as React from "react"
-import { Slot } from "@radix-ui/react-slot"
-import { cva, type VariantProps } from "class-variance-authority"
+import {Slot} from "@radix-ui/react-slot"
+import {cva, type VariantProps} from "class-variance-authority"
-import { cn } from "@/lib/utils"
+import {cn} from "@/lib/utils"
const buttonVariants = cva(
"cursor-pointer inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive",
@@ -10,6 +10,7 @@ const buttonVariants = cva(
variants: {
variant: {
default: "bg-primary text-primary-foreground hover:bg-primary/90",
+ auth: "bg-foreground text-background hover:bg-foreground/90",
destructive:
"bg-destructive text-white hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60",
outline:
diff --git a/frontend/proxy.ts b/frontend/proxy.ts
index 4bb0d6a3..f692e4cd 100644
--- a/frontend/proxy.ts
+++ b/frontend/proxy.ts
@@ -103,7 +103,7 @@ export function proxy(request: NextRequest) {
}
/* 页面请求:公共路由放行 */
- const publicRoutes = ['/', '/login', '/callback', '/privacy', '/terms']
+ const publicRoutes = ['/', '/login', '/register', '/callback', '/privacy', '/terms']
const publicPrefixes = ['/docs/', '/epay/']
if (publicRoutes.includes(pathname) || publicPrefixes.some(p => pathname.startsWith(p))) {
diff --git a/internal/apps/user/errs.go b/internal/apps/user/errs.go
index fabd3f71..c8ed94a0 100644
--- a/internal/apps/user/errs.go
+++ b/internal/apps/user/errs.go
@@ -5,43 +5,43 @@
package user
const (
- errBindParamsFailed = "参数绑定失败"
- errInvalidParams = "无效的参数"
- errPasswordLoginDisabled = "管理员关闭了密码登录" //nolint:gosec // false positive: this is an error message, not hardcoded credentials
- errUsernameOrPasswordWrong = "用户名或密码错误" //nolint:gosec // false positive: this is an error message, not hardcoded credentials
- errLoginEmailMissing = "该账号未绑定邮箱,请联系管理员绑定邮箱后再登录"
- errNeedEmailCodePrefix = "need_email_code:"
- errSMTPInvalidUseTempCodePrefix = "smtp_invalid:"
- errSMTPInvalidUseTempCode = "smtp 配置无效,使用临时码登录"
- errEmailCodeInvalidOrExpired = "验证码错误或已过期"
- errSaveSessionFailed = "无法保存会话信息,请重试"
- errRegistrationDisabled = "管理员关闭了注册"
- errPasswordTooShort = "密码长度不能少于 8 位" //nolint:gosec // false positive: this is an error message, not hardcoded credentials
- errEmailOrCodeRequired = "邮箱或验证码未填写"
- errNewPasswordTooShort = "新密码长度不能少于 8 位" //nolint:gosec // false positive: this is an error message, not hardcoded credentials
- errLoginRequired = "请先登录"
- errUserNotFound = "未找到该用户"
- errOldPasswordIncorrect = "原密码不正确" //nolint:gosec // false positive: this is an error message, not hardcoded credentials
- errPasswordEncryptFailed = "密码加密失败,请重试" //nolint:gosec // false positive: this is an error message, not hardcoded credentials
- errEmailRequired = "邮箱地址不能为空"
- errUnsupportedEmailScene = "不支持的验证场景"
- errEmailAlreadyRegistered = "该邮箱已被注册"
- errEmailCodeCooldown = "验证码发送频繁,请稍后再试"
- errEmailFormatInvalid = "邮箱格式不正确"
- errEmailAlreadyBound = "该邮箱已被其他账号绑定"
- errRenderEmailTemplateFailed = "渲染验证邮件模板失败:%w"
- errGenerateEmailCodeFailed = "生成验证码失败,请重试"
- errDispatchEmailTaskFailed = "投递验证邮件发送任务失败,请重试"
- errTokenNameRequired = "令牌名称不能为空" //nolint:gosec // false positive: this is an error message, not hardcoded credentials
- errAccessTokenLimitReached = "已达到访问令牌最大创建数量限制" //nolint:gosec // false positive: this is an error message, not hardcoded credentials
- errGenerateTokenFailed = "生成令牌失败" //nolint:gosec // false positive: this is an error message, not hardcoded credentials
- errInvalidTokenID = "无效的令牌ID" //nolint:gosec // false positive: this is an error message, not hardcoded credentials
- errTokenNotFoundOrForbidden = "令牌不存在或无权操作" //nolint:gosec // false positive: this is an error message, not hardcoded credentials
- errAdminTokenRequiresAdmin = "只有管理员才能创建具有管理员权限的令牌" //nolint:gosec // false positive: this is an error message, not hardcoded credentials
- errTaskPayloadRequired = "任务参数不能为空"
- errInvalidJSONFormat = "无效的 JSON 格式: %w"
- errEmailTaskFieldsRequired = "to、subject、body 不能为空"
- errParseEmailPayloadFailed = "解析邮件发送参数失败: %w"
- errSMTPConfigIncomplete = "系统 SMTP 邮件服务配置不完整"
- errSendMailFailed = "发送邮件失败: %w"
+ errBindParamsFailed = "参数绑定失败"
+ errInvalidParams = "无效的参数"
+ errPasswordLoginDisabled = "管理员关闭了密码登录" //nolint:gosec // false positive: this is an error message, not hardcoded credentials
+ errUsernameOrPasswordWrong = "用户名或密码错误" //nolint:gosec // false positive: this is an error message, not hardcoded credentials
+ errLoginEmailMissing = "该账号未绑定邮箱,请联系管理员绑定邮箱后再登录"
+ errNeedEmailCodePrefix = "need_email_code:"
+ errSMTPInvalidUseTempCodePrefix = "smtp_invalid:"
+ errSMTPInvalidUseTempCode = "smtp 配置无效,使用临时码登录"
+ errEmailCodeInvalidOrExpired = "验证码错误或已过期"
+ errSaveSessionFailed = "无法保存会话信息,请重试"
+ errRegistrationDisabled = "管理员关闭了注册"
+ errPasswordTooShort = "密码长度不能少于 8 位" //nolint:gosec // false positive: this is an error message, not hardcoded credentials
+ errEmailOrCodeRequired = "邮箱或验证码未填写"
+ errNewPasswordTooShort = "新密码长度不能少于 8 位" //nolint:gosec // false positive: this is an error message, not hardcoded credentials
+ errLoginRequired = "请先登录"
+ errUserNotFound = "未找到该用户"
+ errOldPasswordIncorrect = "原密码不正确" //nolint:gosec // false positive: this is an error message, not hardcoded credentials
+ errPasswordEncryptFailed = "密码加密失败,请重试" //nolint:gosec // false positive: this is an error message, not hardcoded credentials
+ errEmailRequired = "邮箱地址不能为空"
+ errUnsupportedEmailScene = "不支持的验证场景"
+ errEmailAlreadyRegistered = "该邮箱已被注册"
+ errEmailCodeCooldown = "验证码发送频繁,请稍后再试"
+ errEmailFormatInvalid = "邮箱格式不正确"
+ errEmailAlreadyBound = "该邮箱已被其他账号绑定"
+ errRenderEmailTemplateFailed = "渲染验证邮件模板失败:%w"
+ errGenerateEmailCodeFailed = "生成验证码失败,请重试"
+ errDispatchEmailTaskFailed = "投递验证邮件发送任务失败,请重试"
+ errTokenNameRequired = "令牌名称不能为空" //nolint:gosec // false positive: this is an error message, not hardcoded credentials
+ errAccessTokenLimitReached = "已达到访问令牌最大创建数量限制" //nolint:gosec // false positive: this is an error message, not hardcoded credentials
+ errGenerateTokenFailed = "生成令牌失败" //nolint:gosec // false positive: this is an error message, not hardcoded credentials
+ errInvalidTokenID = "无效的令牌ID" //nolint:gosec // false positive: this is an error message, not hardcoded credentials
+ errTokenNotFoundOrForbidden = "令牌不存在或无权操作" //nolint:gosec // false positive: this is an error message, not hardcoded credentials
+ errAdminTokenRequiresAdmin = "只有管理员才能创建具有管理员权限的令牌" //nolint:gosec // false positive: this is an error message, not hardcoded credentials
+ errTaskPayloadRequired = "任务参数不能为空"
+ errInvalidJSONFormat = "无效的 JSON 格式: %w"
+ errEmailTaskFieldsRequired = "to、subject、body 不能为空"
+ errParseEmailPayloadFailed = "解析邮件发送参数失败: %w"
+ errSMTPConfigIncomplete = "系统 SMTP 邮件服务配置不完整"
+ errSendMailFailed = "发送邮件失败: %w"
)