|
@@ -5,14 +5,19 @@ import useRequest from '@ahooksjs/use-request'
|
|
|
// @ts-ignore
|
|
|
import wx from 'weixin-js-sdk'
|
|
|
|
|
|
-import { Col, Row, Card, Input, Button, Select, Form, message } from 'antd'
|
|
|
-import { WechatOutlined } from '@ant-design/icons'
|
|
|
+import { Col, Row, Divider, Input, Button, Select, Form, message, Checkbox, TabsProps, Tabs } from 'antd'
|
|
|
+import { WechatOutlined, SafetyCertificateOutlined } from '@ant-design/icons'
|
|
|
+
|
|
|
+import { ReactComponent as LoginMobile } from 'assets/login_mobile.svg'
|
|
|
+import { ReactComponent as LoginPassword } from 'assets/login_passwode.svg'
|
|
|
|
|
|
import { Login2pService } from './Login2p.service'
|
|
|
import { useLogin2p } from './Login2pContext'
|
|
|
+import SetUpPassword from './components/SetUpPassword'
|
|
|
import { useMedia } from 'Context/Media/MediaContext'
|
|
|
import styles from '../styles/NewPage.module.scss'
|
|
|
|
|
|
+import type { CheckboxProps } from 'antd'
|
|
|
const { Option } = Select
|
|
|
|
|
|
const Login2p: React.FC = () => {
|
|
@@ -23,19 +28,33 @@ const Login2p: React.FC = () => {
|
|
|
const wechatToken = new URLSearchParams(useLocation().search).get('smtoken')
|
|
|
const next = new URLSearchParams(useLocation().search).get('next')
|
|
|
const [isDisabled, setIsDisabled] = useState<boolean>(false)
|
|
|
- const [captchaBtnText, setCaptchaBtnText] = useState<string>('发送验证码')
|
|
|
+ const [isSelectAuthor, setIsSelectAuthor] = useState<boolean>(false)
|
|
|
+ const [isSetPassword, setIsSetPassword] = useState<boolean>(false)
|
|
|
+ const [isBindMobile, setIsBindMobile] = useState<number>(0)
|
|
|
+ const [encryptionPhone, setEncryptionPhone] = useState<string>('')
|
|
|
+
|
|
|
+ const [captchaBtnText, setCaptchaBtnText] = useState<string>('获取验证码')
|
|
|
+ const [tabsAct, setTabsAct] = useState<string>('1')
|
|
|
const [phoneArea, setPhoneArea] = useState<number>(86)
|
|
|
const colSpanBlank = { xs: 1, sm: 1, md: 4, lg: 4, xl: 8 }
|
|
|
const colSpanForm = { xs: 22, sm: 22, md: 16, lg: 16, xl: 8 }
|
|
|
- const colPadding = media.isSmallMax === media.isBigMax ? '150px 0px 0px ' : '20px 0px'
|
|
|
+ const colPadding = media.isSmallMax === media.isBigMax ? '20px 0px 0px ' : '20px 0px'
|
|
|
const phoneAreaList = [
|
|
|
{ id: 86, optionName: '中国(+86)', regText: /^1\d{10}$/ },
|
|
|
{ id: 853, optionName: '中国澳门(+853)', regText: /^6\d{7}$/ },
|
|
|
{ id: 852, optionName: '中国香港(+852)', regText: /^[569]\d{3}\-?\d{4}$/ },
|
|
|
{ id: 61, optionName: '澳大利亚(+61)', regText: /^4\d{8}$/ },
|
|
|
{ id: 65, optionName: '新加坡(+65)', regText: /^[89]\d{7}$/ },
|
|
|
- { id: 1, optionName: '美国(+001)', regText: /^[2-9]\d{2}[2-9](?!11)\d{6}$/ },
|
|
|
- { id: 81, optionName: '日本(+81)', regText: /^\d{1,4}[ \-]?\d{1,4}[ \-]?\d{4}$/ },
|
|
|
+ {
|
|
|
+ id: 1,
|
|
|
+ optionName: '美国(+001)',
|
|
|
+ regText: /^[2-9]\d{2}[2-9](?!11)\d{6}$/
|
|
|
+ },
|
|
|
+ {
|
|
|
+ id: 81,
|
|
|
+ optionName: '日本(+81)',
|
|
|
+ regText: /^\d{1,4}[ \-]?\d{1,4}[ \-]?\d{4}$/
|
|
|
+ },
|
|
|
{ id: 44, optionName: '英国(+44)', regText: /^\+?[0-9,\-,\s]{5,20}$/ },
|
|
|
{ id: 886, optionName: '中国台湾(+886)', regText: /^[0][9]\d{8}$/ }
|
|
|
]
|
|
@@ -60,9 +79,23 @@ const Login2p: React.FC = () => {
|
|
|
)
|
|
|
}
|
|
|
}
|
|
|
+ // 设置、修改密码
|
|
|
+ const setUpPasswordHandlern = () => {
|
|
|
+ setIsBindMobile(1)
|
|
|
+ setIsSetPassword(true)
|
|
|
+ }
|
|
|
const handleLoginegByCode = (value: any) => {
|
|
|
+ setEncryptionPhone(value.phone_number)
|
|
|
login2p
|
|
|
- .login2pByCode(value.phone_number, value.code, next ? next : '/', wechatToken ? wechatToken : undefined)
|
|
|
+ .login2pByCode(
|
|
|
+ value.phone_number,
|
|
|
+ value.code,
|
|
|
+ tabsAct,
|
|
|
+ value.password,
|
|
|
+ next ? next : '/',
|
|
|
+ wechatToken ? wechatToken : undefined,
|
|
|
+ setUpPasswordHandlern
|
|
|
+ )
|
|
|
.then(r => undefined)
|
|
|
}
|
|
|
|
|
@@ -83,37 +116,85 @@ const Login2p: React.FC = () => {
|
|
|
}, 1000)
|
|
|
setTimeout(() => {
|
|
|
setIsDisabled(false)
|
|
|
- setCaptchaBtnText('发送验证码')
|
|
|
+ setCaptchaBtnText('获取验证码')
|
|
|
clearInterval(captchaCountdown)
|
|
|
}, 60000)
|
|
|
getLoginCode(phoneArea.toString(), form.getFieldValue('phone_number'))
|
|
|
}
|
|
|
-
|
|
|
+ // 是否选择了我是作者
|
|
|
+ const onCheckboxChange: CheckboxProps['onChange'] = e => {
|
|
|
+ setIsSelectAuthor(e.target.checked)
|
|
|
+ }
|
|
|
React.useEffect(checkLogin, [])
|
|
|
|
|
|
+ const items: TabsProps['items'] = [
|
|
|
+ {
|
|
|
+ key: '1',
|
|
|
+ label: <span>验证码登录</span>,
|
|
|
+ children: <></>
|
|
|
+ },
|
|
|
+
|
|
|
+ {
|
|
|
+ key: '2',
|
|
|
+ label: <span>密码登录</span>,
|
|
|
+ children: <></>
|
|
|
+ }
|
|
|
+ ]
|
|
|
+ // 点击了tabs的change
|
|
|
+ const onChange = (key: string) => {
|
|
|
+ setTabsAct(key)
|
|
|
+ }
|
|
|
+
|
|
|
+ // 阅读协议
|
|
|
+ const handleOpenWord = (path: string) => {
|
|
|
+ window.open(path)
|
|
|
+ }
|
|
|
+ // 点击了设置、修改密码
|
|
|
+ const setUpPasswordClickHandlern = () => {
|
|
|
+ setIsSetPassword(true)
|
|
|
+ }
|
|
|
return (
|
|
|
- <Row gutter={24} style={{ width: '100%' }}>
|
|
|
- {/*0-780px*/}
|
|
|
- {/*780px-1280px*/}
|
|
|
- {/*1280px-max*/}
|
|
|
- <Col {...colSpanBlank} />
|
|
|
- <Col
|
|
|
- {...colSpanForm}
|
|
|
- style={{
|
|
|
- padding: colPadding,
|
|
|
- fontSize: '18px'
|
|
|
- }}
|
|
|
- >
|
|
|
- <Card>
|
|
|
- <Form form={form} onFinish={handleLoginegByCode}>
|
|
|
- <div className={styles['login-title']}>验证码登录</div>
|
|
|
- <Form.Item style={{ marginBottom: '5px' }}>
|
|
|
- <p style={{ lineHeight: '24px', fontSize: '16px' }}>手机号</p>
|
|
|
- <Form.Item name="phone_number" rules={[{ required: true, message: 'Please input your phone number!' }]}>
|
|
|
- <Input
|
|
|
- addonBefore={
|
|
|
+ <>
|
|
|
+ <div className={styles['login-content-bg-img']}>
|
|
|
+ {!media.isSmallMax && (
|
|
|
+ <img
|
|
|
+ src="https://hzstatic.hzinsights.com/yx_xcx/web/login_log.png"
|
|
|
+ alt=""
|
|
|
+ className={styles['login-log-img']}
|
|
|
+ />
|
|
|
+ )}
|
|
|
+ <div className={`${media.isSmallMax ? styles['login-content-box-mobile'] : styles['login-content-box']}`}>
|
|
|
+ {!media.isSmallMax && (
|
|
|
+ <>
|
|
|
+ <div>
|
|
|
+ <Checkbox onChange={onCheckboxChange} value={isSelectAuthor}>
|
|
|
+ 我是专栏作者
|
|
|
+ </Checkbox>
|
|
|
+ </div>
|
|
|
+ {!isSelectAuthor ? (
|
|
|
+ <div className={styles['login-title']}>验证码登录</div>
|
|
|
+ ) : (
|
|
|
+ <Tabs defaultActiveKey={'1'} items={items} onChange={onChange} style={{ marginTop: 10 }} />
|
|
|
+ )}
|
|
|
+ </>
|
|
|
+ )}
|
|
|
+ <div className={styles['login-columncenter-content']}>
|
|
|
+ <Form form={form} onFinish={handleLoginegByCode}>
|
|
|
+ <Form.Item style={{ marginBottom: '5px' }}>
|
|
|
+ {/* <p style={{ lineHeight: '24px', fontSize: '16px' }}>手机号</p> */}
|
|
|
+ <Form.Item
|
|
|
+ name="phone_number"
|
|
|
+ rules={[
|
|
|
+ {
|
|
|
+ required: true,
|
|
|
+ message: 'Please input your phone number!'
|
|
|
+ }
|
|
|
+ ]}
|
|
|
+ >
|
|
|
+ <div className={styles['input-content']}>
|
|
|
<Select
|
|
|
defaultValue={phoneArea}
|
|
|
+ className="select-input"
|
|
|
onChange={value => {
|
|
|
setPhoneArea(value)
|
|
|
}}
|
|
@@ -124,49 +205,108 @@ const Login2p: React.FC = () => {
|
|
|
</Option>
|
|
|
))}
|
|
|
</Select>
|
|
|
- }
|
|
|
- placeholder="请输入手机号"
|
|
|
- />
|
|
|
+ <Input
|
|
|
+ className="mobile-phone-input"
|
|
|
+ prefix={<LoginMobile style={{ width: 15 }} />}
|
|
|
+ placeholder="请输入手机号"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ </Form.Item>
|
|
|
</Form.Item>
|
|
|
- </Form.Item>
|
|
|
- <Form.Item style={{ marginBottom: '5px' }}>
|
|
|
- <p style={{ lineHeight: '24px', fontSize: '16px' }}>验证码</p>
|
|
|
- <Form.Item>
|
|
|
- <Form.Item
|
|
|
- name={'code'}
|
|
|
- style={{ width: '65%', display: 'inline-block' }}
|
|
|
- rules={[{ required: true, message: 'Please input Captcha!' }]}
|
|
|
- >
|
|
|
- <Input placeholder="请输入验证码" />
|
|
|
+ {tabsAct === '1' || !isSelectAuthor ? (
|
|
|
+ <Form.Item style={{ marginBottom: '5px' }}>
|
|
|
+ {/* <p style={{ lineHeight: '24px', fontSize: '16px' }}>验证码</p> */}
|
|
|
+ <Form.Item name={'code'} rules={[{ required: true, message: 'Please input Captcha!' }]}>
|
|
|
+ <div className={styles['input-content']}>
|
|
|
+ <Input
|
|
|
+ className="mobile-code-input"
|
|
|
+ prefix={<SafetyCertificateOutlined style={{ color: '#E37318', fontSize: 20 }} />}
|
|
|
+ placeholder="请输入验证码"
|
|
|
+ />
|
|
|
+ <Button
|
|
|
+ onClick={getVCodeData}
|
|
|
+ style={{ width: 160, marginLeft: '12px' }}
|
|
|
+ loading={loadingVCode}
|
|
|
+ disabled={isDisabled}
|
|
|
+ className="custom-style-bottom-code"
|
|
|
+ >
|
|
|
+ {captchaBtnText}
|
|
|
+ </Button>
|
|
|
+ </div>
|
|
|
+ </Form.Item>
|
|
|
+ </Form.Item>
|
|
|
+ ) : (
|
|
|
+ <Form.Item style={{ marginBottom: '-19px' }}>
|
|
|
+ {/* <p style={{ lineHeight: '24px', fontSize: '16px' }}>验证码</p> */}
|
|
|
+ <Form.Item>
|
|
|
+ <div className={styles['input-content']}>
|
|
|
+ <Form.Item
|
|
|
+ name="password"
|
|
|
+ style={{ width: '100%', display: 'inline-block' }}
|
|
|
+ rules={[{ required: true, message: 'Please input Password!' }]}
|
|
|
+ >
|
|
|
+ <Input.Password
|
|
|
+ style={{ height: 60 }}
|
|
|
+ prefix={<LoginPassword style={{ width: 20 }} />}
|
|
|
+ placeholder="请输入密码"
|
|
|
+ />
|
|
|
+ </Form.Item>
|
|
|
+ </div>
|
|
|
+ <div className={styles['input-set-password-forget']}>
|
|
|
+ <span onClick={setUpPasswordClickHandlern}>设置密码/忘记密码</span>
|
|
|
+ </div>
|
|
|
+ </Form.Item>
|
|
|
</Form.Item>
|
|
|
- <Button onClick={getVCodeData} style={{ width: '35%' }} loading={loadingVCode} disabled={isDisabled}>
|
|
|
- {captchaBtnText}
|
|
|
+ )}
|
|
|
+
|
|
|
+ <Form.Item>
|
|
|
+ <Button type="primary" block htmlType="submit" className="custom-style-bottom">
|
|
|
+ 登录
|
|
|
</Button>
|
|
|
</Form.Item>
|
|
|
- </Form.Item>
|
|
|
- <Form.Item>
|
|
|
- <Button type="primary" block htmlType="submit">
|
|
|
- 验证码登录
|
|
|
- </Button>
|
|
|
- </Form.Item>
|
|
|
- <Form.Item style={{ textAlign: 'center' }}>
|
|
|
- <Button
|
|
|
- icon={<WechatOutlined style={{ color: '#60C84D' }} />}
|
|
|
- onClick={() =>
|
|
|
- login2p.loginWechatLaunch(
|
|
|
- `${process.env.REACT_APP_URL}login2p/wechat?next=${next ? next : encodeURIComponent('/')}`
|
|
|
- )
|
|
|
- }
|
|
|
- shape="circle"
|
|
|
- size="large"
|
|
|
- style={{ paddingTop: '7px' }}
|
|
|
- ></Button>
|
|
|
- </Form.Item>
|
|
|
- </Form>
|
|
|
- </Card>
|
|
|
- </Col>
|
|
|
- <Col {...colSpanBlank} />
|
|
|
- </Row>
|
|
|
+
|
|
|
+ <div className={styles['custom-style-divider']}>
|
|
|
+ <Divider className={styles['divider-line']}>
|
|
|
+ <span className={styles['divider-text']}>其他登陆方式</span>
|
|
|
+ </Divider>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <Form.Item style={{ textAlign: 'center' }}>
|
|
|
+ <Button
|
|
|
+ icon={<WechatOutlined style={{ color: '#60C84D', fontSize: 38 }} />}
|
|
|
+ onClick={() =>
|
|
|
+ login2p.loginWechatLaunch(
|
|
|
+ `${process.env.REACT_APP_URL}login2p/wechat?next=${next ? next : encodeURIComponent('/')}`
|
|
|
+ )
|
|
|
+ }
|
|
|
+ shape="circle"
|
|
|
+ size="large"
|
|
|
+ style={{ paddingTop: '7px', width: 64, height: 64 }}
|
|
|
+ ></Button>
|
|
|
+ </Form.Item>
|
|
|
+ <div className="buymodel-checkbox-wrapper m-t-md">
|
|
|
+ <span>登录即代表您阅读并同意</span>
|
|
|
+ <span className="buymodel-text-orange" onClick={handleOpenWord.bind(this, '/material/license')}>
|
|
|
+ 《研选平台服务协议》
|
|
|
+ </span>
|
|
|
+ <span className="buymodel-text-orange" onClick={handleOpenWord.bind(this, '/material/policy')}>
|
|
|
+ 《研选平台隐私政策》
|
|
|
+ </span>
|
|
|
+ </div>
|
|
|
+ </Form>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <SetUpPassword
|
|
|
+ visible={isSetPassword}
|
|
|
+ isBindMobile={isBindMobile}
|
|
|
+ encryptionPhone={encryptionPhone}
|
|
|
+ phoneAreaCode={phoneArea}
|
|
|
+ onCancelPassword={() => {
|
|
|
+ setIsSetPassword(false)
|
|
|
+ }}
|
|
|
+ />
|
|
|
+ </>
|
|
|
)
|
|
|
}
|
|
|
|