tiefen_space_web/app/auth/login/phonenumlogin/page.jsx

244 lines
7.1 KiB
React
Raw Normal View History

2024-01-03 01:07:16 +08:00
"use client";
import React, { useState, useEffect } from "react";
import { Form, Input, Toast, Checkbox } from "antd-mobile";
import { JSEncrypt } from "jsencrypt";
import { useRouter } from "next/navigation";
import { signIn } from "@/utils/auth";
import Link from "next/link";
import baseRequest from "@/utils/baseRequest";
import { generateSignature } from "@/utils/crypto";
2024-01-12 20:43:37 +08:00
import { getCookie } from "cookies-next";
2024-01-03 01:07:16 +08:00
export default function PhonenumLogin() {
const router = useRouter();
//保存区号、手机号、验证码
const [regionCode, setRegionCode] = useState("86");
const [mobilePhone, setMobilePhone] = useState("");
//重新获取验证码的计时器
const [isCounting, setIsCounting] = useState(false);
const [seconds, setSeconds] = useState(60);
useEffect(() => {
let interval;
if (isCounting && seconds > 0) {
interval = setInterval(() => {
setSeconds(seconds - 1);
}, 1000);
} else {
setIsCounting(false);
setSeconds(60);
clearInterval(interval);
}
return () => {
clearInterval(interval);
};
}, [isCounting, seconds]);
//点击获取验证码
const handleVerification = async () => {
//手机号校验
if (!mobilePhone.match(/^1[3456789]\d{9}$/)) {
Toast.show({
content: "手机号码格式错误",
});
return;
}
//开始倒计时
setIsCounting(true);
//对手机号进行RSA加密
const encrypt = new JSEncrypt();
encrypt.setPublicKey(process.env.NEXT_PUBLIC_RSA_KEY);
const mobile_phone = encrypt.encrypt(mobilePhone);
const base = baseRequest();
const signature = generateSignature({
mobile_phone: mobile_phone,
region_code: regionCode,
...base,
});
//发送短信验证码
try {
await fetch(`/api/veri_code/send?signature=${signature}`, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
mobile_phone: mobile_phone,
region_code: regionCode,
...base,
}),
});
} catch (error) {
console.error(error);
}
};
//设置checkbox
const [checked, setChecked] = useState(false);
//点击登录
const handleSubmit = async (value) => {
if (!checked) {
Toast.show({
content: "请先勾选同意《用户协议》与《隐私政策》",
});
return;
}
if (!value.mobile_phone) {
Toast.show({
content: "请填写手机号",
});
return;
}
if (!value.mobile_phone.match(/^1[3456789]\d{9}$/)) {
Toast.show({
content: "手机号码格式错误",
});
return;
}
if (!value.veri_code) {
Toast.show({
content: "请先输入正确的验证码",
});
return;
}
2024-01-12 20:43:37 +08:00
//读取邀请人
const inviter = getCookie("inviter");
2024-01-03 01:07:16 +08:00
//对手机号进行RSA加密
const encrypt = new JSEncrypt();
encrypt.setPublicKey(process.env.NEXT_PUBLIC_RSA_KEY);
const mobile_phone = encrypt.encrypt(value.mobile_phone);
const base = baseRequest();
const signature = generateSignature({
mobile_phone: mobile_phone,
region_code: regionCode,
veri_code: value.veri_code,
2024-01-12 22:38:29 +08:00
inviter: parseInt(inviter, 10),
2024-01-03 01:07:16 +08:00
...base,
});
//发送登录请求
try {
const response = await fetch(
`/api/login/login_by_veri_code?signature=${signature}`,
{
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
mobile_phone: mobile_phone,
region_code: regionCode,
veri_code: value.veri_code,
2024-01-12 22:44:00 +08:00
inviter: parseInt(inviter, 10),
2024-01-03 01:07:16 +08:00
...base,
}),
}
);
const data = await response.json();
if (data.ret === -1) {
Toast.show({
content: data.msg,
});
return;
}
//若已经设置了密码则直接登录
if (data.data.is_enabled) {
signIn(data);
router.back();
return;
}
//若没设置密码则前往设置密码
signIn(data);
const replacedString = mobile_phone.replace(/\+/g, "%2B");
router.replace(
`../setpassword?mobile_phone=${replacedString}&region_code=${regionCode}`
);
} catch (error) {
console.error(error);
}
};
return (
<section className="flex flex-1 flex-col">
<div className="flex flex-row justify-center">
<Form
style={{
"--border-top": "0",
"--border-bottom": "0",
"--border-inner": "0",
}}
layout="horizontal"
onFinish={handleSubmit}
>
<div className="w-96 p-4 bg-[#07050A]">
<div className="rounded-2xl overflow-hidden border-neutral border">
<Form.Item name="mobile_phone">
<div className="flex flex-row">
<p className="mr-4 text-white">+{regionCode}</p>
<Input
placeholder="请输入手机号"
clearable
type="number"
value={mobilePhone}
onChange={(value) => setMobilePhone(value)}
/>
</div>
</Form.Item>
<hr className="mx-4 border-neutral" />
<Form.Item
name="veri_code"
extra={
<button disabled={isCounting} onClick={handleVerification}>
<p className={isCounting ? "" : "text-primary"}>
{isCounting ? `(${seconds})重新发送` : "获取验证码"}
</p>
</button>
}
>
<div className="flex flex-row">
<p className="mr-4 text-white whitespace-nowrap">验证码</p>
<Input placeholder="请输入验证码" clearable type="number" />
</div>
</Form.Item>
</div>
<div className="flex justify-center mt-8 mb-4">
<Checkbox
style={{
"--icon-size": "18px",
"--font-size": "14px",
"--gap": "6px",
}}
checked={checked}
onChange={() => setChecked(!checked)}
>
<p className="text-gray-400 text-sm">
同意
<Link className="link text-primary" href="/doc/useragreement">
用户协议
</Link>
<Link className="link text-primary" href="/doc/privatypolicy">
隐私政策
</Link>
</p>
</Checkbox>
</div>
<div className="flex justify-center">
<button
type="submit"
className="btn btn-primary w-full text-base text-white font-medium"
>
登录
</button>
</div>
</div>
</Form>
</div>
</section>
);
}