mirror of
https://github.com/ChatGPTNextWeb/ChatGPT-Next-Web.git
synced 2025-11-17 14:33:41 +08:00
update login
This commit is contained in:
@@ -1,6 +1,5 @@
|
||||
import { NextRequest, NextResponse } from "next/server";
|
||||
import prisma from "@/lib/prisma";
|
||||
import { insertUser } from "@/lib/auth";
|
||||
import { getTokenLength } from "@/lib/utils";
|
||||
|
||||
async function handle(
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
|
||||
input {
|
||||
text-align: left !important
|
||||
}
|
||||
|
||||
|
||||
.ant-input {
|
||||
text-align: left !important
|
||||
}
|
||||
@@ -1,6 +1,5 @@
|
||||
"use client";
|
||||
|
||||
import "./users-table.modules.scss";
|
||||
import React, { Dispatch, SetStateAction, useEffect, useState } from "react";
|
||||
import { User } from "@prisma/client";
|
||||
import {
|
||||
|
||||
@@ -3,17 +3,79 @@
|
||||
import { signIn } from "next-auth/react";
|
||||
import React, { useState, useEffect, useRef, use } from "react";
|
||||
import { isName } from "@/lib/auth_list";
|
||||
import { Form, Input, InputRef } from "antd";
|
||||
import { UserOutlined, MailOutlined } from "@ant-design/icons";
|
||||
import type { FormProps } from "antd";
|
||||
import { SignInOptions } from "next-auth/react";
|
||||
|
||||
export default function UserLoginButton() {
|
||||
const [loading, setLoading] = useState(false);
|
||||
|
||||
const nameInput = useRef<HTMLInputElement>(null);
|
||||
const passwordInput = useRef<HTMLInputElement>(null);
|
||||
const [loginForm] = Form.useForm();
|
||||
const nameInput = useRef<InputRef>(null);
|
||||
const passwordInput = useRef<InputRef>(null);
|
||||
const emailInput = useRef<HTMLInputElement>(null);
|
||||
const [username, setUsername] = useState("");
|
||||
const [password, setPassword] = useState("");
|
||||
|
||||
const [error, setError] = useState(false);
|
||||
type FieldType = {
|
||||
username?: string;
|
||||
password?: string;
|
||||
email?: string;
|
||||
};
|
||||
const onFinish: FormProps<FieldType>["onFinish"] = (values) => {
|
||||
setLoading(true);
|
||||
let signInOptions: SignInOptions = {
|
||||
redirect: false,
|
||||
};
|
||||
let loginProvider = "";
|
||||
|
||||
if (values.email) {
|
||||
loginProvider = "email";
|
||||
signInOptions = { ...signInOptions, email: values.email };
|
||||
} else {
|
||||
loginProvider = "credentials";
|
||||
signInOptions = {
|
||||
...signInOptions,
|
||||
username: values.username,
|
||||
password: values.password ?? "",
|
||||
};
|
||||
}
|
||||
signIn(loginProvider, signInOptions).then((result) => {
|
||||
setLoading(false);
|
||||
if (!result?.error) {
|
||||
window.location.href =
|
||||
result?.url && result.url.includes("verify") ? result.url : "/";
|
||||
} else {
|
||||
const errorParts = result.error.split(",");
|
||||
if (errorParts.length > 1) {
|
||||
loginForm.setFields([
|
||||
{
|
||||
name: errorParts[0],
|
||||
errors: [errorParts[1]],
|
||||
},
|
||||
]);
|
||||
} else {
|
||||
loginForm.setFields([
|
||||
{
|
||||
name: "password",
|
||||
errors: [result.error],
|
||||
},
|
||||
]);
|
||||
}
|
||||
}
|
||||
console.log("response,", result);
|
||||
});
|
||||
|
||||
setLoading(false);
|
||||
console.log("Success:", values);
|
||||
};
|
||||
|
||||
const onFinishFailed: FormProps<FieldType>["onFinishFailed"] = (
|
||||
errorInfo,
|
||||
) => {
|
||||
console.log("Failed:", errorInfo);
|
||||
};
|
||||
|
||||
const handleNameComposition = (
|
||||
e: React.CompositionEvent<HTMLInputElement>,
|
||||
@@ -68,10 +130,11 @@ export default function UserLoginButton() {
|
||||
if (nameInput.current) {
|
||||
if (!isName(username)) {
|
||||
setError(true);
|
||||
nameInput.current.setCustomValidity("用户名校验失败");
|
||||
// nameInput
|
||||
// nameInput.current.setCustomValidity("用户名校验失败");
|
||||
} else {
|
||||
setError(false);
|
||||
nameInput.current.setCustomValidity("");
|
||||
// nameInput.current.setCustomValidity("");
|
||||
}
|
||||
}
|
||||
// console.log("username:", username);
|
||||
@@ -79,102 +142,176 @@ export default function UserLoginButton() {
|
||||
|
||||
return (
|
||||
<>
|
||||
{/*
|
||||
This example requires updating your template:
|
||||
|
||||
```
|
||||
<html class="h-full bg-white">
|
||||
<body class="h-full">
|
||||
```
|
||||
*/}
|
||||
|
||||
<div className="mt-10 sm:mx-auto sm:w-full sm:max-w-sm">
|
||||
<form
|
||||
<div className="mt-6 sm:mx-auto sm:w-full sm:max-w-sm">
|
||||
<Form
|
||||
className="space-y-6"
|
||||
action="#"
|
||||
method="POST"
|
||||
// action="#"
|
||||
// method="POST"
|
||||
autoComplete="off"
|
||||
onSubmit={onSubmitHandler}
|
||||
onFinish={onFinish}
|
||||
onFinishFailed={onFinishFailed}
|
||||
size="large"
|
||||
form={loginForm}
|
||||
id="login-form"
|
||||
// onSubmit={onSubmitHandler}
|
||||
>
|
||||
<div>
|
||||
<div className="mt-2">
|
||||
<input
|
||||
id="username"
|
||||
name="username"
|
||||
type="username"
|
||||
ref={nameInput}
|
||||
// value={username}
|
||||
onCompositionStart={(e) => e.preventDefault()}
|
||||
onCompositionEnd={handleNameComposition}
|
||||
onChange={onNameChange}
|
||||
// required
|
||||
placeholder="输入姓名、拼音或邮箱"
|
||||
className={`${
|
||||
loading
|
||||
? "cursor-not-allowed bg-stone-50 dark:bg-stone-800"
|
||||
: "bg-white hover:bg-stone-50 active:bg-stone-100 dark:bg-black dark:hover:border-white dark:hover:bg-black"
|
||||
} group my-2 flex h-10 w-full items-center justify-center space-x-2 rounded-md border border-stone-200 transition-colors duration-75 focus:outline-none dark:border-stone-700
|
||||
${
|
||||
error
|
||||
? "focus:invalid:border-red-500 focus:invalid:ring-red-500"
|
||||
: ""
|
||||
}
|
||||
`}
|
||||
/>
|
||||
<input
|
||||
id="password"
|
||||
name="password"
|
||||
type="password"
|
||||
ref={passwordInput}
|
||||
value={password}
|
||||
<Form.Item
|
||||
name="username"
|
||||
rules={[
|
||||
{
|
||||
validator: async (_, value) => {
|
||||
if (value && !isName(value)) {
|
||||
return Promise.reject(
|
||||
new Error("Invalid username format!"),
|
||||
);
|
||||
}
|
||||
const email_value = loginForm.getFieldValue("email");
|
||||
if (!value && !email_value) {
|
||||
return Promise.reject(
|
||||
new Error("Please input your username!"),
|
||||
);
|
||||
}
|
||||
if (value && email_value) {
|
||||
return Promise.reject(new Error("Field must be unique!"));
|
||||
}
|
||||
const password_value = loginForm.getFieldValue("password");
|
||||
if (!value && password_value) {
|
||||
return Promise.reject(
|
||||
new Error("Please input your username!"),
|
||||
);
|
||||
}
|
||||
},
|
||||
},
|
||||
]}
|
||||
>
|
||||
<Input
|
||||
// id="basic_username"
|
||||
// name="username"
|
||||
// type="username"
|
||||
// ref={nameInput}
|
||||
// // value={username}
|
||||
// onCompositionStart={(e) => e.preventDefault()}
|
||||
// onCompositionEnd={handleComposition}
|
||||
onChange={onPasswordChange}
|
||||
// onCompositionEnd={handleNameComposition}
|
||||
// onChange={onNameChange}
|
||||
// required
|
||||
placeholder="密码验证,测试阶段"
|
||||
className={`${
|
||||
loading
|
||||
? "cursor-not-allowed bg-stone-50 dark:bg-stone-800"
|
||||
: "bg-white hover:bg-stone-50 active:bg-stone-100 dark:bg-black dark:hover:border-white dark:hover:bg-black"
|
||||
} group my-2 flex h-10 w-full items-center justify-center space-x-2 rounded-md border border-stone-200 transition-colors duration-75 focus:outline-none dark:border-stone-700
|
||||
${
|
||||
error
|
||||
? "focus:invalid:border-red-500 focus:invalid:ring-red-500"
|
||||
: ""
|
||||
}
|
||||
`}
|
||||
autoComplete="off"
|
||||
prefix={<UserOutlined style={{ color: "rgba(0,0,0,.25)" }} />}
|
||||
placeholder="输入姓名、拼音或邮箱"
|
||||
className={
|
||||
"text-sm font-medium text-stone-600 dark:text-stone-400"
|
||||
}
|
||||
// className={`${
|
||||
// loading
|
||||
// ? "cursor-not-allowed bg-stone-50 dark:bg-stone-800"
|
||||
// : "bg-white hover:bg-stone-50 active:bg-stone-100 dark:bg-black dark:hover:border-white dark:hover:bg-black"
|
||||
// } group my-2 flex h-10 w-full items-center justify-center space-x-2 rounded-md border border-stone-200 transition-colors duration-75 focus:outline-none dark:border-stone-700
|
||||
// ${
|
||||
// error
|
||||
// ? "focus:invalid:border-red-500 focus:invalid:ring-red-500"
|
||||
// : ""
|
||||
// }
|
||||
// `}
|
||||
/>
|
||||
<input
|
||||
id="email"
|
||||
name="email"
|
||||
type="email"
|
||||
ref={emailInput}
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item<FieldType>
|
||||
// label="Password"
|
||||
name="password"
|
||||
rules={[
|
||||
{
|
||||
validator: async (_, value) => {
|
||||
if (value) {
|
||||
if (value.length < 6) {
|
||||
return Promise.reject(
|
||||
new Error("Password must be at least 6 characters!"),
|
||||
);
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
]}
|
||||
>
|
||||
<Input.Password
|
||||
// id="basic_password"
|
||||
// name="password"
|
||||
// type="password"
|
||||
// status={error ? "error" : ""}
|
||||
// ref={passwordInput}
|
||||
// value={password}
|
||||
// // onCompositionStart={(e) => e.preventDefault()}
|
||||
// // onCompositionEnd={handleComposition}
|
||||
// onChange={onPasswordChange}
|
||||
autoComplete="off"
|
||||
// // required
|
||||
placeholder="密码验证,测试阶段"
|
||||
className={
|
||||
"text-sm font-medium text-stone-600 dark:text-stone-400"
|
||||
}
|
||||
// className={`${
|
||||
// loading
|
||||
// ? "cursor-not-allowed bg-stone-50 dark:bg-stone-800"
|
||||
// : "bg-white hover:bg-stone-50 active:bg-stone-100 dark:bg-black dark:hover:border-white dark:hover:bg-black"
|
||||
// } group my-2 flex h-10 w-full items-center justify-center space-x-2 rounded-md border border-stone-200 transition-colors duration-75 focus:outline-none dark:border-stone-700
|
||||
// ${
|
||||
// error
|
||||
// ? "focus:invalid:border-red-500 focus:invalid:ring-red-500"
|
||||
// : ""
|
||||
// }
|
||||
// `}
|
||||
/>
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
name="email"
|
||||
rules={[
|
||||
{
|
||||
type: "email",
|
||||
message: "The input is not valid E-mail!",
|
||||
},
|
||||
{
|
||||
validator: async (_, value) => {
|
||||
const username_value = loginForm.getFieldValue("username");
|
||||
if (value && username_value) {
|
||||
return Promise.reject(new Error("Field must be unique!"));
|
||||
}
|
||||
},
|
||||
},
|
||||
]}
|
||||
>
|
||||
<Input
|
||||
// id="email"
|
||||
// name="email"
|
||||
// type="email"
|
||||
// ref={emailInput}
|
||||
// value={username}
|
||||
onCompositionStart={(e) => e.preventDefault()}
|
||||
// onCompositionStart={(e) => e.preventDefault()}
|
||||
// onCompositionEnd={handleComposition}
|
||||
// onChange={onNameChange}
|
||||
// required
|
||||
prefix={<MailOutlined style={{ color: "rgba(0,0,0,.25)" }} />}
|
||||
placeholder="邮箱验证,测试阶段"
|
||||
className={`${
|
||||
loading
|
||||
? "cursor-not-allowed bg-stone-50 dark:bg-stone-800"
|
||||
: "bg-white hover:bg-stone-50 active:bg-stone-100 dark:bg-black dark:hover:border-white dark:hover:bg-black"
|
||||
} group my-2 flex h-10 w-full items-center justify-center space-x-2 rounded-md border border-stone-200 transition-colors duration-75 focus:outline-none dark:border-stone-700
|
||||
${
|
||||
error
|
||||
? "focus:invalid:border-red-500 focus:invalid:ring-red-500"
|
||||
: ""
|
||||
}
|
||||
`}
|
||||
className={
|
||||
"text-sm font-medium text-stone-600 dark:text-stone-400"
|
||||
}
|
||||
// className={`${
|
||||
// loading
|
||||
// ? "cursor-not-allowed bg-stone-50 dark:bg-stone-800"
|
||||
// : "bg-white hover:bg-stone-50 active:bg-stone-100 dark:bg-black dark:hover:border-white dark:hover:bg-black"
|
||||
// } group my-2 flex h-10 w-full items-center justify-center space-x-2 rounded-md border border-stone-200 transition-colors duration-75 focus:outline-none dark:border-stone-700
|
||||
// ${
|
||||
// error
|
||||
// ? "focus:invalid:border-red-500 focus:invalid:ring-red-500"
|
||||
// : ""
|
||||
// }
|
||||
// `}
|
||||
/>
|
||||
{/*{error && <p className="mt-2 text-pink-600 text-sm">{error}</p>}*/}
|
||||
</div>
|
||||
</Form.Item>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<Form.Item>
|
||||
<button
|
||||
disabled={loading}
|
||||
// onClick={(e) => handleSubmit(e)}
|
||||
// onClick={() => loginForm.submit()}
|
||||
type="submit"
|
||||
className={`${
|
||||
loading
|
||||
@@ -184,8 +321,8 @@ export default function UserLoginButton() {
|
||||
>
|
||||
Sign in
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</Form.Item>
|
||||
</Form>
|
||||
</div>
|
||||
{/*</div>*/}
|
||||
</>
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
border: 0;
|
||||
border-top: 1px solid var(--color-separator);
|
||||
display: block;
|
||||
margin: 2rem auto 1rem;
|
||||
margin: 1rem auto 1rem;
|
||||
overflow: visible
|
||||
}
|
||||
|
||||
@@ -47,7 +47,7 @@
|
||||
}
|
||||
|
||||
.signin form input[type],.signin>div input[type] {
|
||||
margin-bottom: .5rem
|
||||
//margin-bottom: .5rem
|
||||
}
|
||||
|
||||
.signin form button,.signin>div button {
|
||||
@@ -73,7 +73,7 @@ html {
|
||||
.login-form {
|
||||
background-color: #fff;
|
||||
width: 350px;
|
||||
height: 500px;
|
||||
height: 550px;
|
||||
border-radius: 15px;
|
||||
|
||||
/* 定位到中心 */
|
||||
@@ -86,4 +86,12 @@ html {
|
||||
/* 毛玻璃 */
|
||||
backdrop-filter: blur(10px); /* 应用模糊效果 */
|
||||
background-color: rgba(255, 255, 255, 0.5); /* 半透明的白色背景 */
|
||||
}
|
||||
}
|
||||
|
||||
input {
|
||||
text-align: left !important
|
||||
}
|
||||
|
||||
#login-form input:-webkit-autofill {
|
||||
transition: background-color 5000s ease-in-out 0s;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user