add login and register
Change-Id: I268de3c72015b588e84a9d7d14df8d434b614509
diff --git a/src/app/user/login/login.scss b/src/app/user/login/login.scss
new file mode 100644
index 0000000..b028689
--- /dev/null
+++ b/src/app/user/login/login.scss
@@ -0,0 +1,53 @@
+//全局容器样式
+.login-container {
+ max-width: 1200px;
+ margin: 0 auto;
+ padding: 0 2rem;
+ //display: flex;
+ //flex-direction: column;
+ //justify-content: center;
+
+ .form-header {
+ //margin: auto;
+ display: flex;
+ justify-content: center;
+ font-size: 50px;
+ margin-bottom: 60px;
+ }
+
+ .form-field {
+ display: flex;
+ justify-content: center;
+ gap: 0.5rem;
+ margin-bottom: 50px;
+
+ .form-field-header {
+ width: 90px;
+ font-size: 30px;
+ color: rgba(63, 74, 73, 1);
+ margin-right: 50px;
+ }
+
+ input {
+ width: 400px;
+ padding: 0.75rem 1rem;
+ border-radius: 8px;
+ font-size: 1rem;
+ color: #2d3748;
+ }
+ }
+
+ .form-operation {
+ display: flex;
+ justify-content: center;
+ margin-top: 80px;
+
+ .form-operation-button {
+ width: 150px;
+ background: rgba(82, 102, 101, 1);
+ border: 1px solid rgba(82, 102, 101, 1);
+ border-radius: 20px;
+ margin-right: 25px;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/app/user/login/page.tsx b/src/app/user/login/page.tsx
index c48b626..a22cee0 100644
--- a/src/app/user/login/page.tsx
+++ b/src/app/user/login/page.tsx
@@ -1,12 +1,113 @@
'use client';
-import React from 'react';
+import React, { useRef, useState } from 'react';
+import { Button } from "primereact/button";
+// 输入框
+import { InputText } from "primereact/inputtext";
+// 消息提醒
+import { Toast } from 'primereact/toast';
+// 接口传输
+import axios from "axios";
+// 页面跳转
+import { useRouter } from "next/navigation";
+// 密码
+import { Password } from 'primereact/password';
+// 样式
+import './login.scss';
-const EmptyPage: React.FC = () => {
- return (
- <div className="p-d-flex p-jc-center p-ai-center" style={{ height: '100vh' }}>
- {"一个空页面"}
- </div>
- );
+export default function LoginPage() {
+ // 路由
+ const router = useRouter();
+ // 消息提醒
+ const toast = useRef<Toast>(null);
+
+ const [loginFormData, setLoginFormData] = useState({
+ username: '',
+ password: '',
+ })
+
+ // 获取userId
+ const fetchUserId = async () => {
+ try {
+ const response = await axios.get(process.env.PUBLIC_URL + `/user/getId`, {
+ params: { username: loginFormData.username , password: loginFormData.password }
+ });
+ console.log('用户id:', response.data)
+ localStorage.setItem("user", JSON.stringify({ Id: response.data }));
+ } catch (error) {
+ console.error('获取用户id失败:', error);
+ toast.current?.show({ severity: 'error', summary: 'Error', detail: '获取用户id失败' });
+ }
+ }
+
+ // 处理用户登录
+ const handleLogin = async () => {
+ try {
+ const postData = {
+ username: loginFormData.username,
+ password: loginFormData.password,
+ }
+ const response = await axios.post(process.env.PUBLIC_URL + `/user/login`, postData, {
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
+ validateStatus: (status) => true // 接受所有状态码
+ });
+
+ if (response.status === 200) {
+ console.log('用户登录成功');
+ toast.current?.show({ severity: 'success', summary: 'Success', detail: '登录成功' });
+ // 设置userId
+ fetchUserId()
+ router.push('/');
+ } else if (response.status === 406) {
+ console.log('用户名不存在');
+ toast.current?.show({ severity: 'error', summary: 'Error', detail: '用户名不存在' });
+ } else if (response.status === 408) {
+ console.error('密码错误');
+ toast.current?.show({ severity: 'error', summary: 'Error', detail: '密码错误' });
+ }
+
+ } catch (error) {
+ console.error('登录失败:', error);
+ toast.current?.show({ severity: 'error', summary: 'Error', detail: '登录失败' });
+ }
+ }
+
+ return (
+ <div className='login-container'>
+ <Toast ref={toast}></Toast>
+ <h1 className="form-header">登录</h1>
+ <div className="form-field">
+ <div className="form-field-header">
+ <label htmlFor="username">用户名</label>
+ </div>
+ <InputText
+ id="username"
+ value={loginFormData.username}
+ onChange={(e) => setLoginFormData(prev => ({
+ ...prev, // 复制顶层所有属性
+ username: e.target.value
+ }))}
+ className="w-full"
+ />
+ </div>
+ <div className="form-field">
+ <div className="form-field-header">
+ <label htmlFor="password">密码</label>
+ </div>
+ <Password
+ id="password"
+ value={loginFormData.password}
+ onChange={(e) => setLoginFormData(prev => ({
+ ...prev,
+ password: e.target.value
+ }))}
+ className="w-full"
+ toggleMask
+ />
+ </div>
+ <div className="form-operation">
+ <Button label="确定" onClick={handleLogin} className='form-operation-button'/>
+ <Button label="注册" onClick={() => router.push("/user/register")} className='form-operation-button'/>
+ </div>
+ </div>
+ )
};
-
-export default EmptyPage;
diff --git a/src/app/user/page.tsx b/src/app/user/page.tsx
index 5d36dc4..d534cd5 100644
--- a/src/app/user/page.tsx
+++ b/src/app/user/page.tsx
@@ -329,7 +329,7 @@
},
{
template: () => (
- <Button label="编辑悬赏" onClick={() => router.push(`/user/manage/resources/`)} />
+ <Button label="编辑悬赏" />
)
}
];
@@ -495,8 +495,6 @@
setSelectedGameplay([]);
// 重置资源封面
setResourcePictureUrl('');
- // 可以刷新资源列表
- // fetchResourceList();
}
} catch (error) {
console.error('资源上传失败:', error);
@@ -611,10 +609,6 @@
</div>
</TabPanel>
- {/*<TabPanel header="发布">*/}
-
- {/*</TabPanel>*/}
-
<TabPanel header="帖子">
{/*我的帖子*/}
<div className="homepage-item">
@@ -863,7 +857,6 @@
}));
setIngredient(e.value);
}}
- // onChange={(e: RadioButtonChangeEvent) => setIngredient(e.value)}
checked={ingredient === 'modPack'}
/>
<label htmlFor="ingredient2" className="ml-2">整合包</label>
@@ -883,7 +876,6 @@
}));
setIngredient(e.value);
}}
- // onChange={(e: RadioButtonChangeEvent) => setIngredient(e.value)}
checked={ingredient === 'mod'}
/>
<label htmlFor="ingredient3" className="ml-2">模组</label>
@@ -903,7 +895,6 @@
}));
setIngredient(e.value);
}}
- // onChange={(e: RadioButtonChangeEvent) => setIngredient(e.value)}
checked={ingredient === 'map'}
/>
<label htmlFor="ingredient4" className="ml-2">地图</label>
@@ -932,7 +923,6 @@
display="chip"
optionLabel="name"
placeholder="请选择资源标签"
- // maxSelectedLabels={3}
className="w-full md:w-20rem"
/>
</div>
@@ -964,12 +954,6 @@
auto
accept="image/*"
chooseLabel="上传资源封面"
-
- // accept="image/*"
- // maxFileSize={10000000000}
- // chooseLabel="选择资源封面"
- // className="w-full"
- // onUpload={onUpload}
/>
</div>
</div>
@@ -990,25 +974,9 @@
}
>
<div className="dialog-form">
- <span>
+ <span style={{marginBottom: "10px"}}>
确认是否删除该悬赏?
</span>
- {/*<div className="form-field">*/}
- {/* <div className="form-field-header">*/}
- {/* <label htmlFor="name">密码</label>*/}
- {/* </div>*/}
- {/* <Password*/}
- {/* id="passwrod"*/}
- {/* value={deleteResourceFormData.password}*/}
- {/* onChange={(e) => setDeleteResourceFormData(prev => ({*/}
- {/* ...prev,*/}
- {/* password: e.target.value*/}
- {/* }))}*/}
- {/* placeholder="请输入密码"*/}
- {/* className="w-full"*/}
- {/* toggleMask*/}
- {/* />*/}
- {/*</div>*/}
</div>
</Dialog>
diff --git a/src/app/user/register/page.tsx b/src/app/user/register/page.tsx
index c48b626..25f2bd0 100644
--- a/src/app/user/register/page.tsx
+++ b/src/app/user/register/page.tsx
@@ -1,12 +1,140 @@
'use client';
-import React from 'react';
+import React, { useRef, useState } from 'react';
+import { Button } from "primereact/button";
+// 输入框
+import { InputText } from "primereact/inputtext";
+// 消息提醒
+import { Toast } from 'primereact/toast';
+// 接口传输
+import axios from "axios";
+// 页面跳转
+import { useRouter } from "next/navigation";
+// 密码
+import { Password } from 'primereact/password';
+// 样式
+import './register.scss';
-const EmptyPage: React.FC = () => {
+export default function RegisterPage() {
+ // 路由
+ const router = useRouter();
+ // 消息提醒
+ const toast = useRef<Toast>(null);
+
+ const [registerFormData, setRegisterFormData] = useState({
+ username: '',
+ password: '',
+ confirmPassword: '',
+ invitationCode: '',
+ })
+
+
+ // 处理用户注册
+ const handleRegister = async () => {
+ try {
+ // 判断用户两次输入的密码是否一致
+ if (registerFormData.password != registerFormData.confirmPassword) {
+ console.error("两次输入的密码不一致,请重新输入");
+ toast.current?.show({severity: 'error', summary: 'Error', detail: '两次输入的密码不一致,请重新输入'});
+ return;
+ }
+
+ const postData = {
+ username: registerFormData.username,
+ password: registerFormData.password,
+ invitationCode: registerFormData.invitationCode,
+ }
+ const response = await axios.post(process.env.PUBLIC_URL + `/user/register`, postData, {
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
+ validateStatus: (status) => true // 接受所有状态码
+ });
+
+ if (response.status === 200) {
+ console.log('用户注册成功');
+ toast.current?.show({severity: 'success', summary: 'Success', detail: '注册成功'});
+ router.push('/user/login');
+ } else if (response.status === 412) {
+ console.log('用户名重复');
+ toast.current?.show({severity: 'error', summary: 'Error', detail: '用户名重复'});
+ } else if (response.status === 409) {
+ console.error('邀请码不存在');
+ toast.current?.show({severity: 'error', summary: 'Error', detail: '邀请码不存在'});
+ } else if (response.status === 410) {
+ console.error('邀请码已被使用');
+ toast.current?.show({severity: 'error', summary: 'Error', detail: '邀请码已被使用'});
+ }
+
+ } catch (error) {
+ console.error('注册失败:', error);
+ toast.current?.show({severity: 'error', summary: 'Error', detail: '注册失败'});
+ }
+ }
+
return (
- <div className="p-d-flex p-jc-center p-ai-center" style={{ height: '100vh' }}>
- {"一个空页面"}
- </div>
- );
+ <div className='register-container'>
+ <Toast ref={toast}></Toast>
+ <h1 className="form-header">注册</h1>
+ <div className="form-field">
+ <div className="form-field-header">
+ <label htmlFor="username">用户名</label>
+ </div>
+ <InputText
+ id="username"
+ value={registerFormData.username}
+ onChange={(e) => setRegisterFormData(prev => ({
+ ...prev, // 复制顶层所有属性
+ username: e.target.value
+ }))}
+ className="w-full"
+ />
+ </div>
+ <div className="form-field">
+ <div className="form-field-header">
+ <label htmlFor="password">设置密码</label>
+ </div>
+ <Password
+ id="password"
+ value={registerFormData.password}
+ onChange={(e) => setRegisterFormData(prev => ({
+ ...prev,
+ password: e.target.value
+ }))}
+ className="w-full"
+ toggleMask
+ />
+ </div>
+ <div className="form-field">
+ <div className="form-field-header">
+ <label htmlFor="confirmPassword">确认密码</label>
+ </div>
+ <Password
+ id="confirmPassword"
+ value={registerFormData.confirmPassword}
+ onChange={(e) => setRegisterFormData(prev => ({
+ ...prev,
+ confirmPassword: e.target.value
+ }))}
+ className="w-full"
+ toggleMask
+ />
+ </div>
+ <div className="form-field">
+ <div className="form-field-header">
+ <label htmlFor="invitationCode">邀请码</label>
+ </div>
+ <InputText
+ id="invitationCode"
+ value={registerFormData.invitationCode}
+ onChange={(e) => setRegisterFormData(prev => ({
+ ...prev, // 复制顶层所有属性
+ invitationCode: e.target.value
+ }))}
+ className="w-full"
+ />
+ </div>
+ <div className="form-operation">
+ <Button label="确定" onClick={handleRegister} className='form-operation-button'/>
+ <Button label="返回" onClick={() => router.push("/user/login")} className='form-operation-button'/>
+ </div>
+ </div>
+ )
};
-
-export default EmptyPage;
diff --git a/src/app/user/register/register.scss b/src/app/user/register/register.scss
new file mode 100644
index 0000000..9c9a77d
--- /dev/null
+++ b/src/app/user/register/register.scss
@@ -0,0 +1,53 @@
+//全局容器样式
+.register-container {
+ max-width: 1200px;
+ margin: 0 auto;
+ padding: 0 2rem;
+ //display: flex;
+ //flex-direction: column;
+ //justify-content: center;
+
+ .form-header {
+ //margin: auto;
+ display: flex;
+ justify-content: center;
+ font-size: 50px;
+ margin-bottom: 60px;
+ }
+
+ .form-field {
+ display: flex;
+ justify-content: center;
+ gap: 0.5rem;
+ margin-bottom: 50px;
+
+ .form-field-header {
+ width: 120px;
+ font-size: 30px;
+ color: rgba(63, 74, 73, 1);
+ margin-right: 50px;
+ }
+
+ input {
+ width: 400px;
+ padding: 0.75rem 1rem;
+ border-radius: 8px;
+ font-size: 1rem;
+ color: #2d3748;
+ }
+ }
+
+ .form-operation {
+ display: flex;
+ justify-content: center;
+ margin-top: 80px;
+
+ .form-operation-button {
+ width: 150px;
+ background: rgba(82, 102, 101, 1);
+ border: 1px solid rgba(82, 102, 101, 1);
+ border-radius: 20px;
+ margin-right: 25px;
+ }
+ }
+}
\ No newline at end of file