From 8bdff06dcac0c3e38dc52dc96917406aec795261 Mon Sep 17 00:00:00 2001 From: xmdhs Date: Fri, 24 Nov 2023 23:34:50 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B3=A8=E5=86=8C=E9=AA=8C=E8=AF=81=E9=82=AE?= =?UTF-8?q?=E7=AE=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/apis/apis.ts | 5 +-- frontend/src/components/CheckInput.tsx | 4 ++- frontend/src/views/Register.tsx | 43 +++++++++++++++++++++++--- service/email/email.go | 9 ++++-- 4 files changed, 52 insertions(+), 9 deletions(-) diff --git a/frontend/src/apis/apis.ts b/frontend/src/apis/apis.ts index 76be4f4..fa53ba4 100644 --- a/frontend/src/apis/apis.ts +++ b/frontend/src/apis/apis.ts @@ -14,14 +14,15 @@ export async function login(email: string, password: string, captchaToken: strin return await apiGet(v) } -export async function register(email: string, username: string, password: string, captchaToken: string) { +export async function register(email: string, username: string, password: string, captchaToken: string, code: string) { const v = await fetch(root() + "/api/v1/user/reg", { method: "POST", body: JSON.stringify({ "Email": email, "Password": password, "Name": username, - "CaptchaToken": captchaToken + "CaptchaToken": captchaToken, + "EmailJwt": code, }) }) return await apiGet(v) diff --git a/frontend/src/components/CheckInput.tsx b/frontend/src/components/CheckInput.tsx index b0c08c7..e323714 100644 --- a/frontend/src/components/CheckInput.tsx +++ b/frontend/src/components/CheckInput.tsx @@ -1,6 +1,7 @@ import TextField from '@mui/material/TextField'; import { useState, useImperativeHandle, forwardRef } from 'react'; import type { TextFieldProps } from '@mui/material/TextField'; +import { useControllableValue } from 'ahooks'; export type refType = { verify: () => boolean @@ -15,7 +16,8 @@ type prop = { export const CheckInput = forwardRef(({ required, checkList, ...textFied }, ref) => { const [err, setErr] = useState(""); - const [value, setValue] = useState(""); + const [value, setValue] = useControllableValue(textFied); + const check = (value: string) => { if (required && (!value || value == "")) { diff --git a/frontend/src/views/Register.tsx b/frontend/src/views/Register.tsx index 79f2093..c5e1702 100644 --- a/frontend/src/views/Register.tsx +++ b/frontend/src/views/Register.tsx @@ -9,7 +9,7 @@ import LockOutlinedIcon from '@mui/icons-material/LockOutlined'; import Typography from '@mui/material/Typography'; import Container from '@mui/material/Container'; import { Link as RouterLink } from "react-router-dom"; -import { register } from '@/apis/apis' +import { getConfig, register } from '@/apis/apis' import CheckInput, { refType } from '@/components/CheckInput' import { useRef, useState } from 'react'; import Alert from '@mui/material/Alert'; @@ -22,6 +22,7 @@ import useTitle from '@/hooks/useTitle'; import { ApiErr } from '@/apis/error'; import { useSetAtom } from 'jotai'; import { token, user } from '@/store/store'; +import { useRequest } from 'ahooks'; export default function SignUp() { const [regErr, setRegErr] = useState(""); @@ -32,6 +33,38 @@ export default function SignUp() { useTitle("注册") const setToken = useSetAtom(token) const setUserInfo = useSetAtom(user) + const [code, setCode] = useState("") + const [email, setEmail] = useState("") + const [disableEmail, setDisableEmail] = useState(false) + + const u = new URL(location.href) + + React.useEffect(() => { + const e = u.searchParams.get("email") + if (!e || e == "") return + setEmail(e) + setDisableEmail(true) + }, [u.searchParams]) + + useRequest(getConfig, { + cacheKey: "/api/v1/config", + staleTime: 60000, + onError: e => { + console.warn(e) + setRegErr(String(e)) + }, + onSuccess: v => { + if (!v.NeedEmail) return + + const code = u.searchParams.get("code") + if (!code || code == "") { + navigate("/register_email") + return + } + setCode(code) + } + }) + const checkList = React.useRef>(new Map()) @@ -42,7 +75,6 @@ export default function SignUp() { if (loading) return const data = new FormData(event.currentTarget); const d = { - email: data.get('email')?.toString(), password: data.get('password')?.toString(), username: data.get("username")?.toString() } @@ -54,7 +86,7 @@ export default function SignUp() { return } setLoading(true) - register(d.email ?? "", d.username ?? "", d.password ?? "", captchaToken). + register(email ?? "", d.username ?? "", d.password ?? "", captchaToken, code). then(v => { if (!v) return setToken(v.token) @@ -71,7 +103,7 @@ export default function SignUp() { switch (v.code) { case 10: setRegErr("验证码错误") - return + return case 3: setRegErr("邮箱已存在") return @@ -116,6 +148,9 @@ export default function SignUp() { fullWidth name="email" label="邮箱" + value={email} + disabled={disableEmail} + onChange={v => setEmail(v.target.value)} autoComplete="email" ref={(dom) => { dom && checkList.current.set("1", dom) diff --git a/service/email/email.go b/service/email/email.go index 10d600d..a564bc7 100644 --- a/service/email/email.go +++ b/service/email/email.go @@ -118,11 +118,16 @@ func (e EmailService) SendVerifyUrl(ctx context.Context, email string, interval return fmt.Errorf("SendVerifyUrl: %w", err) } + q := url.Values{} + q.Set("code", code) + q.Set("email", email) + u := url.URL{ Host: host, Scheme: "http", - Path: "/register?code=" + url.QueryEscape(code), + Path: "/register", } + u.RawQuery = q.Encode() if e.config.WebBaseUrl != "" { webBase, err := url.Parse(e.config.WebBaseUrl) @@ -156,7 +161,7 @@ var ( func (e EmailService) VerifyJwt(email, jwtStr string) error { token, err := jwt.ParseWithClaims(jwtStr, &jwt.RegisteredClaims{}, func(t *jwt.Token) (interface{}, error) { - return e.pri.PublicKey, nil + return &e.pri.PublicKey, nil }) if err != nil { return fmt.Errorf("VerifyJwt: %w", err)