feat: 注册登录界面框架搭建完成
This commit is contained in:
@@ -1,243 +0,0 @@
|
||||
import {
|
||||
GithubOutlined,
|
||||
GitlabOutlined,
|
||||
LockOutlined,
|
||||
MobileOutlined,
|
||||
QqOutlined,
|
||||
UserOutlined,
|
||||
WechatOutlined,
|
||||
} from '@ant-design/icons'
|
||||
import {
|
||||
LoginFormPage,
|
||||
ProFormCaptcha,
|
||||
ProFormCheckbox,
|
||||
ProFormText,
|
||||
} from '@ant-design/pro-components'
|
||||
import { Divider, Space, Tabs, message, Button } from 'antd'
|
||||
import { CSSProperties } from 'react'
|
||||
import { useState } from 'react'
|
||||
import logo from '@/assets/icons/schisandra.svg'
|
||||
import background from '@/assets/images/background.png'
|
||||
import { observer } from 'mobx-react'
|
||||
// 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 store = useStore('user')
|
||||
|
||||
const items = [
|
||||
{ label: '账户密码登录', key: 'account' },
|
||||
{ label: '手机号登录', key: 'phone' },
|
||||
]
|
||||
const [loginType, setLoginType] = useState<LoginType>('account')
|
||||
|
||||
const onSubmit = async (formData: object) => {
|
||||
console.log(formData)
|
||||
}
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
backgroundColor: 'white',
|
||||
height: '100vh',
|
||||
width: '100vw',
|
||||
}}>
|
||||
<LoginFormPage
|
||||
onFinish={onSubmit}
|
||||
backgroundImageUrl={background}
|
||||
logo={logo}
|
||||
title='五味子云相册'
|
||||
subTitle='随时随地分享你的美好瞬间'
|
||||
activityConfig={{
|
||||
style: {
|
||||
boxShadow: '0px 0px 8px rgba(0, 0, 0, 0.2)',
|
||||
color: '#fff',
|
||||
borderRadius: 8,
|
||||
backgroundColor: '#1677FF',
|
||||
},
|
||||
title: '活动标题,可配置图片',
|
||||
subTitle: '活动介绍说明文字',
|
||||
action: (
|
||||
<Button
|
||||
size='large'
|
||||
style={{
|
||||
borderRadius: 20,
|
||||
background: '#fff',
|
||||
color: '#1677FF',
|
||||
width: 120,
|
||||
}}>
|
||||
去看看
|
||||
</Button>
|
||||
),
|
||||
}}
|
||||
actions={
|
||||
<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 style={{ ...iconStyles, color: '#FF6A10' }} />
|
||||
</div>
|
||||
</Space>
|
||||
</div>
|
||||
}>
|
||||
<Tabs
|
||||
centered
|
||||
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: '请输入密码!',
|
||||
},
|
||||
]}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
{loginType === 'phone' && (
|
||||
<>
|
||||
<ProFormText
|
||||
fieldProps={{
|
||||
size: 'large',
|
||||
prefix: <MobileOutlined className={'prefixIcon'} />,
|
||||
}}
|
||||
name='mobile'
|
||||
placeholder={'手机号'}
|
||||
rules={[
|
||||
{
|
||||
required: true,
|
||||
message: '请输入手机号!',
|
||||
},
|
||||
{
|
||||
pattern: /^1\d{10}$/,
|
||||
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 () => {
|
||||
message.success('获取验证码成功!验证码为:1234')
|
||||
}}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
<div style={{ marginBlockEnd: 24 }}>
|
||||
<ProFormCheckbox noStyle name='autoLogin'>
|
||||
自动登录
|
||||
</ProFormCheckbox>
|
||||
<a style={{ float: 'right' }}>忘记密码 </a>
|
||||
</div>
|
||||
</LoginFormPage>
|
||||
</div>
|
||||
)
|
||||
})
|
154
src/views/User/Login/index.less
Normal file
154
src/views/User/Login/index.less
Normal file
@@ -0,0 +1,154 @@
|
||||
|
||||
.container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
height: 100vh;
|
||||
width: 100vw;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.login_content {
|
||||
// margin-top: 40px;
|
||||
// position: relative;
|
||||
width: 782px;
|
||||
background-color: rgb(255, 255, 255);
|
||||
// height: 100%;
|
||||
overflow: hidden;
|
||||
box-shadow: rgb(0 0 0 / 15%) 0px 2px 15px;
|
||||
//float: right;
|
||||
//height: 538px;
|
||||
position: relative;
|
||||
padding: 30px 0 30px 0;
|
||||
|
||||
}
|
||||
|
||||
.go_to_register {
|
||||
cursor: pointer;
|
||||
height: 70px;
|
||||
width: 70px;
|
||||
background-image: url('@/assets/icons/corner_markers.svg');
|
||||
position: absolute;
|
||||
top: 0px;
|
||||
right: 0px;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.go_to_register span {
|
||||
font-size: 14px;
|
||||
color: rgb(255, 255, 255);
|
||||
font-weight: 500;
|
||||
position: relative;
|
||||
top: 10px;
|
||||
right: 7px;
|
||||
}
|
||||
|
||||
.lang {
|
||||
width: 100%;
|
||||
height: 40px;
|
||||
line-height: 44px;
|
||||
text-align: right;
|
||||
|
||||
:global(.ant-dropdown-trigger) {
|
||||
margin-right: 24px;
|
||||
}
|
||||
}
|
||||
|
||||
.content {
|
||||
//flex: 1;
|
||||
//padding: 32px 0;
|
||||
|
||||
//box-sizing: border-box;
|
||||
//margin: 60px auto;
|
||||
//display: flex;
|
||||
//align-items: center;
|
||||
//justify-content: center;
|
||||
//flex-direction: column;
|
||||
//height: 100vh;
|
||||
//overflow: auto;
|
||||
|
||||
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
.container {
|
||||
background-image: url('@/assets/images/background.png');
|
||||
background-size: cover;
|
||||
}
|
||||
|
||||
.content {
|
||||
padding: 32px 0 24px;
|
||||
}
|
||||
|
||||
.content img {
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
.icon {
|
||||
margin-left: 8px;
|
||||
color: rgba(0, 0, 0, 0.2);
|
||||
font-size: 24px;
|
||||
vertical-align: middle;
|
||||
cursor: pointer;
|
||||
transition: color 0.3s;
|
||||
|
||||
&:hover {
|
||||
color: aquamarine;
|
||||
}
|
||||
}
|
||||
|
||||
.mp_code {
|
||||
padding: 0px 60px;
|
||||
width: 361px;
|
||||
height: 490px;
|
||||
background-color: rgb(255, 255, 255);
|
||||
border-right: 0.5px solid rgb(196, 203, 215);
|
||||
}
|
||||
|
||||
.mp_code_title {
|
||||
margin-top: 50px;
|
||||
font-weight: 500;
|
||||
font-size: 24px;
|
||||
color: rgb(24, 24, 24)
|
||||
}
|
||||
|
||||
.mp_code_img {
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.alert {
|
||||
margin-top: 25px;
|
||||
width: 250px;
|
||||
padding: 5px;
|
||||
text-align: left;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.login_form {
|
||||
// height: 100%;
|
||||
// float: left;
|
||||
margin: 0;
|
||||
padding: 0 32px;
|
||||
}
|
||||
|
||||
.mp_tips {
|
||||
font-weight: bold;
|
||||
color: rgb(7, 221, 7);
|
||||
}
|
||||
|
||||
.logo span {
|
||||
position: relative;
|
||||
top: 2px;
|
||||
color: rgba(0, 0, 0, .85);
|
||||
font-weight: 600;
|
||||
font-size: 33px;
|
||||
}
|
||||
|
||||
.subTitle {
|
||||
margin-top: 12px;
|
||||
margin-bottom: 10px;
|
||||
color: rgba(0, 0, 0, .45);
|
||||
font-size: 14px;
|
||||
}
|
377
src/views/User/Login/index.tsx
Normal file
377
src/views/User/Login/index.tsx
Normal file
@@ -0,0 +1,377 @@
|
||||
import {
|
||||
BarcodeOutlined,
|
||||
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 } from 'react'
|
||||
import { useState } from 'react'
|
||||
import logo from '@/assets/icons/schisandra.svg'
|
||||
import qrCode from '@/assets/images/login_qrcode-landaiqing.jpg'
|
||||
import './index.less'
|
||||
import { observer } from 'mobx-react'
|
||||
// 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 [generateMpRegCodeData, setGenerateMpRegCodeData] = useState<API.GenerateMpRegCode>({})
|
||||
const [form] = Form.useForm()
|
||||
const [base64Code, setBase64Code] = useState<API.GenerateBase64Code>({ data: '' })
|
||||
const clickGetBase64CodeMethod = async () => {
|
||||
await getBase64CodeMethod()
|
||||
}
|
||||
const CodeImg = (
|
||||
<img
|
||||
src={'data:image/jpg;base64,' + base64Code.data}
|
||||
onClick={clickGetBase64CodeMethod}
|
||||
title='点击刷新'
|
||||
style={{ cursor: 'pointer', height: 40, width: 90 }}
|
||||
/>
|
||||
)
|
||||
const getBase64CodeMethod = async () => {}
|
||||
|
||||
const items = [
|
||||
{
|
||||
label: (
|
||||
<span>
|
||||
<UserOutlined />
|
||||
账户登录
|
||||
</span>
|
||||
),
|
||||
key: 'account',
|
||||
},
|
||||
{
|
||||
label: (
|
||||
<span>
|
||||
<MobileOutlined />
|
||||
短信登录
|
||||
</span>
|
||||
),
|
||||
key: 'phone',
|
||||
},
|
||||
]
|
||||
const [loginType, setLoginType] = useState<LoginType>('account')
|
||||
|
||||
const onSubmit = async (formData: object) => {
|
||||
console.log(formData)
|
||||
}
|
||||
return (
|
||||
<div className={'container'}>
|
||||
<div className={'content'}>
|
||||
<Space>
|
||||
<Space className={'login_content'}>
|
||||
<Space align='center' className={'mp_code'}>
|
||||
<Space direction='vertical' align='center'>
|
||||
<span className={'mp_code_title'}>微信扫码登录</span>
|
||||
<Image
|
||||
preview={false}
|
||||
height={210}
|
||||
width={200}
|
||||
className={'mp_code_img'}
|
||||
// src={generateMpRegCodeData.data?.qrCodeUrl}
|
||||
src={qrCode}
|
||||
/>
|
||||
<Alert
|
||||
// message={(<span>微信扫码<span>关注公众号</span></span>)}
|
||||
description={
|
||||
<div>
|
||||
<span>
|
||||
微信扫码
|
||||
<span className={'mp_tips'}>关注公众号</span>
|
||||
</span>
|
||||
<br />
|
||||
登录更快更安全
|
||||
</div>
|
||||
}
|
||||
// type="success"
|
||||
showIcon={true}
|
||||
className={'alert'}
|
||||
icon={<WechatOutlined />}
|
||||
/>
|
||||
</Space>
|
||||
</Space>
|
||||
<Form
|
||||
form={form}
|
||||
className={'login_form'}
|
||||
initialValues={{
|
||||
autoLogin: true,
|
||||
}}>
|
||||
<Space direction='vertical' align='center'>
|
||||
<Space className={'logo'}>
|
||||
<img
|
||||
alt='logo'
|
||||
src={logo}
|
||||
style={{ width: '44px', height: '44px' }}
|
||||
/>
|
||||
<span>五味子云相册</span>
|
||||
</Space>
|
||||
<div className={'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 () => {
|
||||
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) => {
|
||||
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
|
||||
style={{ ...iconStyles, color: '#FF6A10' }}
|
||||
/>
|
||||
</div>
|
||||
</Space>
|
||||
</div>
|
||||
</Form>
|
||||
<a href='/register' className={'go_to_register'}>
|
||||
<span>注册</span>
|
||||
</a>
|
||||
</Space>
|
||||
</Space>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
})
|
154
src/views/User/Register/index.less
Normal file
154
src/views/User/Register/index.less
Normal file
@@ -0,0 +1,154 @@
|
||||
|
||||
.container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
height: 100vh;
|
||||
width: 100vw;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.login_content {
|
||||
// margin-top: 40px;
|
||||
// position: relative;
|
||||
width: 782px;
|
||||
background-color: rgb(255, 255, 255);
|
||||
// height: 100%;
|
||||
overflow: hidden;
|
||||
box-shadow: rgb(0 0 0 / 15%) 0px 2px 15px;
|
||||
//float: right;
|
||||
//height: 538px;
|
||||
position: relative;
|
||||
padding: 30px 0 30px 0;
|
||||
|
||||
}
|
||||
|
||||
.go_to_register {
|
||||
cursor: pointer;
|
||||
height: 70px;
|
||||
width: 70px;
|
||||
background-image: url('@/assets/icons/corner_markers.svg');
|
||||
position: absolute;
|
||||
top: 0px;
|
||||
right: 0px;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.go_to_register span {
|
||||
font-size: 14px;
|
||||
color: rgb(255, 255, 255);
|
||||
font-weight: 500;
|
||||
position: relative;
|
||||
top: 10px;
|
||||
right: 7px;
|
||||
}
|
||||
|
||||
.lang {
|
||||
width: 100%;
|
||||
height: 40px;
|
||||
line-height: 44px;
|
||||
text-align: right;
|
||||
|
||||
:global(.ant-dropdown-trigger) {
|
||||
margin-right: 24px;
|
||||
}
|
||||
}
|
||||
|
||||
.content {
|
||||
//flex: 1;
|
||||
//padding: 32px 0;
|
||||
|
||||
//box-sizing: border-box;
|
||||
//margin: 60px auto;
|
||||
//display: flex;
|
||||
//align-items: center;
|
||||
//justify-content: center;
|
||||
//flex-direction: column;
|
||||
//height: 100vh;
|
||||
//overflow: auto;
|
||||
|
||||
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
.container {
|
||||
background-image: url('@/assets/images/background.png');
|
||||
background-size: cover;
|
||||
}
|
||||
|
||||
.content {
|
||||
padding: 32px 0 24px;
|
||||
}
|
||||
|
||||
.content img {
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
.icon {
|
||||
margin-left: 8px;
|
||||
color: rgba(0, 0, 0, 0.2);
|
||||
font-size: 24px;
|
||||
vertical-align: middle;
|
||||
cursor: pointer;
|
||||
transition: color 0.3s;
|
||||
|
||||
&:hover {
|
||||
color: aquamarine;
|
||||
}
|
||||
}
|
||||
|
||||
.mp_code {
|
||||
padding: 0px 60px;
|
||||
width: 361px;
|
||||
height: 490px;
|
||||
background-color: rgb(255, 255, 255);
|
||||
border-right: 0.5px solid rgb(196, 203, 215);
|
||||
}
|
||||
|
||||
.mp_code_title {
|
||||
margin-top: 50px;
|
||||
font-weight: 500;
|
||||
font-size: 24px;
|
||||
color: rgb(24, 24, 24)
|
||||
}
|
||||
|
||||
.mp_code_img {
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.alert {
|
||||
margin-top: 25px;
|
||||
width: 250px;
|
||||
padding: 5px;
|
||||
text-align: left;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.login_form {
|
||||
// height: 100%;
|
||||
// float: left;
|
||||
margin: 0;
|
||||
padding: 0 32px;
|
||||
}
|
||||
|
||||
.mp_tips {
|
||||
font-weight: bold;
|
||||
color: rgb(7, 221, 7);
|
||||
}
|
||||
|
||||
.logo span {
|
||||
position: relative;
|
||||
top: 2px;
|
||||
color: rgba(0, 0, 0, .85);
|
||||
font-weight: 600;
|
||||
font-size: 33px;
|
||||
}
|
||||
|
||||
.subTitle {
|
||||
margin-top: 12px;
|
||||
margin-bottom: 10px;
|
||||
color: rgba(0, 0, 0, .45);
|
||||
font-size: 14px;
|
||||
}
|
256
src/views/User/Register/index.tsx
Normal file
256
src/views/User/Register/index.tsx
Normal file
@@ -0,0 +1,256 @@
|
||||
import { BarcodeOutlined, LockOutlined, MobileOutlined, WechatOutlined } from '@ant-design/icons'
|
||||
import { ProFormCaptcha, ProFormText } from '@ant-design/pro-components'
|
||||
import { Space, Tabs, message, Image, Alert, Form, Button } from 'antd'
|
||||
import { useState } from 'react'
|
||||
import logo from '@/assets/icons/schisandra.svg'
|
||||
// import background from '@/assets/images/background.png'
|
||||
import qrCode from '@/assets/images/login_qrcode-landaiqing.jpg'
|
||||
import './index.less'
|
||||
import { observer } from 'mobx-react'
|
||||
// import useStore from '@/utils/store/useStore.tsx'
|
||||
type LoginType = 'phone'
|
||||
|
||||
export default observer(() => {
|
||||
const [generateMpRegCodeData, setGenerateMpRegCodeData] = useState<API.GenerateMpRegCode>({})
|
||||
const [form] = Form.useForm()
|
||||
const [base64Code, setBase64Code] = useState<API.GenerateBase64Code>({ data: '' })
|
||||
const clickGetBase64CodeMethod = async () => {
|
||||
await getBase64CodeMethod()
|
||||
}
|
||||
const CodeImg = (
|
||||
<img
|
||||
src={'data:image/jpg;base64,' + base64Code.data}
|
||||
onClick={clickGetBase64CodeMethod}
|
||||
title='点击刷新'
|
||||
style={{ cursor: 'pointer', height: 40, width: 90 }}
|
||||
/>
|
||||
)
|
||||
const getBase64CodeMethod = async () => {}
|
||||
|
||||
const items = [
|
||||
{
|
||||
key: 'phone',
|
||||
label: (
|
||||
<span>
|
||||
<MobileOutlined />
|
||||
手机号注册
|
||||
</span>
|
||||
),
|
||||
},
|
||||
]
|
||||
const [loginType, setLoginType] = useState<LoginType>('phone')
|
||||
|
||||
const onSubmit = async (formData: object) => {
|
||||
console.log(formData)
|
||||
}
|
||||
return (
|
||||
<div className={'container'}>
|
||||
<div className={'content'}>
|
||||
<Space>
|
||||
<Space className={'login_content'}>
|
||||
<Space align='center' className={'mp_code'}>
|
||||
<Space direction='vertical' align='center'>
|
||||
<span className={'mp_code_title'}>微信扫码登录</span>
|
||||
<Image
|
||||
preview={false}
|
||||
height={210}
|
||||
width={200}
|
||||
className={'mp_code_img'}
|
||||
// src={generateMpRegCodeData.data?.qrCodeUrl}
|
||||
src={qrCode}
|
||||
/>
|
||||
<Alert
|
||||
// message={(<span>微信扫码<span>关注公众号</span></span>)}
|
||||
description={
|
||||
<div>
|
||||
<span>
|
||||
微信扫码
|
||||
<span className={'mp_tips'}>关注公众号</span>
|
||||
</span>
|
||||
<br />
|
||||
登录更快更安全
|
||||
</div>
|
||||
}
|
||||
// type="success"
|
||||
showIcon={true}
|
||||
className={'alert'}
|
||||
icon={<WechatOutlined />}
|
||||
/>
|
||||
</Space>
|
||||
</Space>
|
||||
<Form
|
||||
form={form}
|
||||
className={'login_form'}
|
||||
initialValues={{
|
||||
autoLogin: true,
|
||||
}}>
|
||||
<Space direction='vertical' align='center'>
|
||||
<Space className={'logo'}>
|
||||
<img
|
||||
alt='logo'
|
||||
src={logo}
|
||||
style={{ width: '44px', height: '44px' }}
|
||||
/>
|
||||
<span>五味子云相册</span>
|
||||
</Space>
|
||||
<div className={'subTitle'}>随时随地分享你的美好瞬间</div>
|
||||
</Space>
|
||||
|
||||
<Tabs
|
||||
centered={true}
|
||||
items={items}
|
||||
activeKey={loginType}
|
||||
onChange={(activeKey) =>
|
||||
setLoginType(activeKey as LoginType)
|
||||
}></Tabs>
|
||||
|
||||
<>
|
||||
<ProFormText
|
||||
fieldProps={{
|
||||
size: 'large',
|
||||
prefix: <MobileOutlined className={'prefixIcon'} />,
|
||||
autoComplete: 'off',
|
||||
}}
|
||||
name='phone'
|
||||
placeholder='请输入手机号!'
|
||||
rules={[
|
||||
{
|
||||
required: true,
|
||||
message: '请输入手机号!',
|
||||
},
|
||||
{
|
||||
pattern: /^1\d{10}$/,
|
||||
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.Password
|
||||
name='confirmPassword'
|
||||
dependencies={['password']}
|
||||
fieldProps={{
|
||||
size: 'large',
|
||||
prefix: <LockOutlined className={'prefixIcon'} />,
|
||||
}}
|
||||
placeholder='请再次确认密码'
|
||||
rules={[
|
||||
{
|
||||
required: true,
|
||||
message: '请再次确认密码!',
|
||||
},
|
||||
({ getFieldValue }) => ({
|
||||
validator(_, value) {
|
||||
if (!value || getFieldValue('password') === value) {
|
||||
return Promise.resolve()
|
||||
}
|
||||
return Promise.reject(
|
||||
new Error('两次输入的密码不一致!'),
|
||||
)
|
||||
},
|
||||
}),
|
||||
]}
|
||||
/>
|
||||
|
||||
<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 () => {
|
||||
message.success('获取验证码成功!验证码为:1234')
|
||||
}}
|
||||
/>
|
||||
</>
|
||||
<Button
|
||||
type='primary'
|
||||
block
|
||||
size='large'
|
||||
onClick={async () => {
|
||||
const validateFields = [
|
||||
'phone',
|
||||
'username',
|
||||
'password',
|
||||
'captcha',
|
||||
'code',
|
||||
'confirmPassword',
|
||||
]
|
||||
await form
|
||||
.validateFields(validateFields)
|
||||
.then(async (values) => {
|
||||
await onSubmit(values as API.PhoneRegisterRequest)
|
||||
})
|
||||
.catch((errorInfo) => {
|
||||
console.error(errorInfo)
|
||||
})
|
||||
}}>
|
||||
注册
|
||||
</Button>
|
||||
</Form>
|
||||
<a href='/' className={'go_to_register'}>
|
||||
<span>登录</span>
|
||||
</a>
|
||||
</Space>
|
||||
</Space>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
})
|
Reference in New Issue
Block a user