389 lines
11 KiB
TypeScript
389 lines
11 KiB
TypeScript
/** @format */
|
||
|
||
import {
|
||
GithubOutlined,
|
||
GitlabOutlined,
|
||
LockOutlined,
|
||
MobileOutlined,
|
||
QqOutlined,
|
||
UserOutlined,
|
||
WechatOutlined,
|
||
} from "@ant-design/icons";
|
||
import { ProFormCaptcha, ProFormCheckbox, ProFormText } from "@ant-design/pro-components";
|
||
import { Divider, Space, Tabs, message, Image, Alert, Form, Button } from "antd";
|
||
import { CSSProperties, useRef } from "react";
|
||
import { useState } from "react";
|
||
import logo from "@/assets/icons/schisandra.svg";
|
||
import qrCode from "@/assets/images/login_qrcode-landaiqing.jpg";
|
||
import styles from "./index.module.less";
|
||
import { observer } from "mobx-react";
|
||
import FooterComponent from "@/components/Footer";
|
||
import RotateCaptcha, { CaptchaInstance } from "react-rotate-captcha";
|
||
import { get, load, verify } from "@/api/captcha/index.ts";
|
||
import { oauthLogin } from "@/api/user";
|
||
// import useStore from '@/utils/store/useStore.tsx'
|
||
type LoginType = "account" | "phone";
|
||
|
||
const iconStyles: CSSProperties = {
|
||
color: "rgba(0, 0, 0, 0.2)",
|
||
fontSize: "18px",
|
||
verticalAlign: "middle",
|
||
cursor: "pointer",
|
||
};
|
||
|
||
export default observer(() => {
|
||
const [form] = Form.useForm();
|
||
const captcha = useRef<CaptchaInstance>(null);
|
||
const items = [
|
||
{
|
||
label: (
|
||
<span>
|
||
<UserOutlined />
|
||
账户登录
|
||
</span>
|
||
),
|
||
key: "account",
|
||
},
|
||
{
|
||
label: (
|
||
<span>
|
||
<MobileOutlined />
|
||
短信登录
|
||
</span>
|
||
),
|
||
key: "phone",
|
||
},
|
||
];
|
||
|
||
async function oAuthLogin(type: string) {
|
||
const res: any = await oauthLogin(type);
|
||
window.location.href = res.data;
|
||
}
|
||
|
||
const [loginType, setLoginType] = useState<LoginType>("account");
|
||
|
||
const onSubmit = async (formData: object) => {
|
||
console.log(formData);
|
||
};
|
||
return (
|
||
<RotateCaptcha get={get} load={load} verify={verify} limit={2} ref={captcha}>
|
||
<div className={styles.container}>
|
||
<div className={styles.content}>
|
||
<Space className={styles.content_content}>
|
||
<Space className={styles.login_content}>
|
||
<Space align="center" className={styles.mp_code}>
|
||
<Space direction="vertical" align="center">
|
||
<span className={styles.mp_code_title}>微信扫码登录</span>
|
||
<Image
|
||
preview={false}
|
||
height={210}
|
||
width={200}
|
||
className={styles.mp_code_img}
|
||
// src={generateMpRegCodeData.data?.qrCodeUrl}
|
||
src={qrCode}
|
||
/>
|
||
<Alert
|
||
// message={(<span>微信扫码<span>关注公众号</span></span>)}
|
||
description={
|
||
<div>
|
||
<span>
|
||
微信扫码
|
||
<span className={styles.mp_tips}>
|
||
关注公众号
|
||
</span>
|
||
</span>
|
||
<br />
|
||
登录更快更安全
|
||
</div>
|
||
}
|
||
// type="success"
|
||
showIcon={true}
|
||
className={styles.alert}
|
||
icon={<WechatOutlined />}
|
||
/>
|
||
</Space>
|
||
</Space>
|
||
<Form
|
||
form={form}
|
||
className={styles.login_form}
|
||
initialValues={{
|
||
autoLogin: true,
|
||
}}>
|
||
<Space direction="vertical" align="center">
|
||
<Space className={styles.logo}>
|
||
<img
|
||
alt="logo"
|
||
src={logo}
|
||
style={{ width: "44px", height: "44px" }}
|
||
/>
|
||
<span>五味子云存储</span>
|
||
</Space>
|
||
<div className={styles.subTitle}>随时随地分享你的美好瞬间</div>
|
||
</Space>
|
||
|
||
<Tabs
|
||
centered={true}
|
||
items={items}
|
||
activeKey={loginType}
|
||
onChange={(activeKey) =>
|
||
setLoginType(activeKey as LoginType)
|
||
}></Tabs>
|
||
|
||
{loginType === "account" && (
|
||
<>
|
||
<ProFormText
|
||
name="username"
|
||
fieldProps={{
|
||
size: "large",
|
||
prefix: <UserOutlined className={"prefixIcon"} />,
|
||
}}
|
||
placeholder={"请输入账号/邮箱/电话号码"}
|
||
rules={[
|
||
{
|
||
required: true,
|
||
message: "请输入用户名!",
|
||
},
|
||
]}
|
||
/>
|
||
<ProFormText.Password
|
||
name="password"
|
||
fieldProps={{
|
||
size: "large",
|
||
prefix: <LockOutlined className={"prefixIcon"} />,
|
||
}}
|
||
placeholder={"请输入密码"}
|
||
rules={[
|
||
{
|
||
required: true,
|
||
message: "请输入密码!",
|
||
},
|
||
{
|
||
pattern:
|
||
/^(?![0-9]+$)(?![a-zA-Z]+$)[0-9A-Za-z\\W]{6,18}$/,
|
||
message:
|
||
"密码长度需在6~18位字符,且必须包含字母和数字!",
|
||
},
|
||
]}
|
||
/>
|
||
{/*<ProFormText*/}
|
||
{/* addonAfter={CodeImg}*/}
|
||
{/* name='code'*/}
|
||
{/* fieldProps={{*/}
|
||
{/* size: 'large',*/}
|
||
{/* prefix: <BarcodeOutlined className={'prefixIcon'} />,*/}
|
||
{/* autoComplete: 'off',*/}
|
||
{/* }}*/}
|
||
{/* placeholder='请输入图形验证码'*/}
|
||
{/* rules={[*/}
|
||
{/* {*/}
|
||
{/* required: true,*/}
|
||
{/* message: '请输入图形验证码!',*/}
|
||
{/* },*/}
|
||
{/* {*/}
|
||
{/* pattern: /^[a-zA-Z0-9]{5}$/,*/}
|
||
{/* message: '图形验证码格式不正确',*/}
|
||
{/* },*/}
|
||
{/* ]}*/}
|
||
{/*/>*/}
|
||
</>
|
||
)}
|
||
{loginType === "phone" && (
|
||
<>
|
||
<ProFormText
|
||
fieldProps={{
|
||
size: "large",
|
||
prefix: <MobileOutlined className={"prefixIcon"} />,
|
||
autoComplete: "off",
|
||
}}
|
||
name="mobile"
|
||
placeholder={"请输入手机号"}
|
||
rules={[
|
||
{
|
||
required: true,
|
||
message: "请输入手机号!",
|
||
},
|
||
{
|
||
pattern: /^1\d{10}$/,
|
||
message: "手机号格式错误!",
|
||
},
|
||
]}
|
||
/>
|
||
{/*<ProFormText*/}
|
||
{/* addonAfter={CodeImg}*/}
|
||
{/* name='code'*/}
|
||
{/* fieldProps={{*/}
|
||
{/* size: 'large',*/}
|
||
{/* prefix: <BarcodeOutlined className={'prefixIcon'} />,*/}
|
||
{/* autoComplete: 'off',*/}
|
||
{/* }}*/}
|
||
{/* placeholder='请输入图形验证码'*/}
|
||
{/* rules={[*/}
|
||
{/* {*/}
|
||
{/* required: true,*/}
|
||
{/* message: '请输入图形验证码!',*/}
|
||
{/* },*/}
|
||
{/* {*/}
|
||
{/* pattern: /^[a-zA-Z0-9]{5}$/,*/}
|
||
{/* message: '图形验证码格式不正确',*/}
|
||
{/* },*/}
|
||
{/* ]}*/}
|
||
{/*/>*/}
|
||
<ProFormCaptcha
|
||
fieldProps={{
|
||
size: "large",
|
||
prefix: <LockOutlined className={"prefixIcon"} />,
|
||
}}
|
||
captchaProps={{
|
||
size: "large",
|
||
}}
|
||
placeholder={"请输入验证码"}
|
||
captchaTextRender={(timing, count) => {
|
||
if (timing) {
|
||
return `${count} ${"获取验证码"}`;
|
||
}
|
||
return "获取验证码";
|
||
}}
|
||
name="captcha"
|
||
rules={[
|
||
{
|
||
required: true,
|
||
message: "请输入验证码!",
|
||
},
|
||
]}
|
||
onGetCaptcha={async () => {
|
||
captcha.current!.open();
|
||
message.success("获取验证码成功!验证码为:1234");
|
||
}}
|
||
/>
|
||
</>
|
||
)}
|
||
<div style={{ marginBlockEnd: 14 }}>
|
||
<ProFormCheckbox noStyle name="autoLogin">
|
||
自动登录
|
||
</ProFormCheckbox>
|
||
<a style={{ float: "right" }}>忘记密码 </a>
|
||
</div>
|
||
|
||
<Button
|
||
type="primary"
|
||
block
|
||
size="large"
|
||
onClick={async () => {
|
||
let validateFields;
|
||
if (loginType === "account") {
|
||
validateFields = ["username", "password", "code"];
|
||
} else {
|
||
validateFields = ["mobile", "captcha", "code"];
|
||
}
|
||
|
||
await form
|
||
.validateFields(validateFields)
|
||
.then(async (values) => {
|
||
if (loginType === "account") {
|
||
captcha.current!.open();
|
||
}
|
||
await onSubmit(values as API.PhoneRegisterRequest);
|
||
})
|
||
.catch((errorInfo) => {
|
||
console.error(errorInfo);
|
||
});
|
||
}}>
|
||
登录
|
||
</Button>
|
||
|
||
<div
|
||
style={{
|
||
display: "flex",
|
||
justifyContent: "center",
|
||
alignItems: "center",
|
||
flexDirection: "column",
|
||
}}>
|
||
<Divider plain>
|
||
<span
|
||
style={{
|
||
color: "#CCC",
|
||
fontWeight: "normal",
|
||
fontSize: 14,
|
||
}}>
|
||
其他登录方式
|
||
</span>
|
||
</Divider>
|
||
<Space align="center" size={24}>
|
||
<div
|
||
style={{
|
||
display: "flex",
|
||
justifyContent: "center",
|
||
alignItems: "center",
|
||
flexDirection: "column",
|
||
height: 40,
|
||
width: 40,
|
||
border: "1px solid #D4D8DD",
|
||
borderRadius: "50%",
|
||
}}>
|
||
<QqOutlined
|
||
style={{ ...iconStyles, color: "#1677FF" }}
|
||
/>
|
||
</div>
|
||
<div
|
||
style={{
|
||
display: "flex",
|
||
justifyContent: "center",
|
||
alignItems: "center",
|
||
flexDirection: "column",
|
||
height: 40,
|
||
width: 40,
|
||
border: "1px solid #D4D8DD",
|
||
borderRadius: "50%",
|
||
}}>
|
||
<WechatOutlined
|
||
style={{ ...iconStyles, color: "#08a327" }}
|
||
/>
|
||
</div>
|
||
<div
|
||
style={{
|
||
display: "flex",
|
||
justifyContent: "center",
|
||
alignItems: "center",
|
||
flexDirection: "column",
|
||
height: 40,
|
||
width: 40,
|
||
border: "1px solid #D4D8DD",
|
||
borderRadius: "50%",
|
||
}}>
|
||
<GithubOutlined
|
||
style={{ ...iconStyles, color: "#333333" }}
|
||
/>
|
||
</div>
|
||
<div
|
||
style={{
|
||
display: "flex",
|
||
justifyContent: "center",
|
||
alignItems: "center",
|
||
flexDirection: "column",
|
||
height: 40,
|
||
width: 40,
|
||
border: "1px solid #D4D8DD",
|
||
borderRadius: "50%",
|
||
}}>
|
||
<GitlabOutlined
|
||
onClick={() => {
|
||
oAuthLogin("GITEE").then();
|
||
}}
|
||
style={{ ...iconStyles, color: "#FF6A10" }}
|
||
/>
|
||
</div>
|
||
</Space>
|
||
</div>
|
||
</Form>
|
||
<a href="/register" className={styles.go_to_register}>
|
||
<span>注册</span>
|
||
</a>
|
||
</Space>
|
||
</Space>
|
||
</div>
|
||
<FooterComponent></FooterComponent>
|
||
</div>
|
||
</RotateCaptcha>
|
||
);
|
||
});
|