index.tsx 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307
  1. import { useEffect, useState } from 'react'
  2. import { Tabs, Form, Input, Button } from 'antd'
  3. import type { TabsProps } from 'antd'
  4. import sso from '@src/lib/http/sso'
  5. import type { modalType, LoginTypeProps, RegisterType } from './types'
  6. import router from '@src/router/router'
  7. import styles from './index.module.css'
  8. import { debounce } from 'lodash'
  9. import { useSearchParams } from 'react-router-dom'
  10. const imgUrl = new URL('@assets/images/login_bg.png', import.meta.url).href
  11. export default function Login() {
  12. const [loginType, setLoginType] = useState<modalType>('login')
  13. const [activeTab, setActiveTab] = useState<string>('1')
  14. const [searchParams] = useSearchParams()
  15. function login() {
  16. if (searchParams.has('redirectUrl')) {
  17. router.navigate(decodeURIComponent(searchParams.get('redirectUrl') as string))
  18. }else{
  19. sessionStorage.removeItem('advertiserId')
  20. router.navigate('/')
  21. }
  22. }
  23. function editPassword() {
  24. setLoginType('register')
  25. }
  26. function backToLogin() {
  27. setLoginType('login')
  28. }
  29. function tabChange(tab: string) {
  30. setActiveTab(tab)
  31. }
  32. const items: TabsProps['items'] = [
  33. {
  34. key: '1',
  35. label: '账号登录',
  36. children: <AccountLogin activeTab={activeTab} onLogin={login} onEditPassword={editPassword}/>
  37. },
  38. // {
  39. // key: '2',
  40. // label: '短信登录',
  41. // children: <SMSlogin activeTab={activeTab} onLogin={login} onEditPassword={editPassword} />
  42. // }
  43. ]
  44. return (
  45. <div className={styles['login-contianer']}>
  46. <div className={styles['logo-banner']}>
  47. <div className={styles['logo-icon']}></div>
  48. <div className={styles['logo-title']}>
  49. AD <span>|</span> 优量圈
  50. </div>
  51. </div>
  52. <div className={styles['login-body']}>
  53. <div className={styles['login-bg']}>
  54. <img src={imgUrl} alt="" />
  55. </div>
  56. <div className={styles['login-box']}>
  57. {loginType === 'login' && <Tabs onChange={tabChange} defaultActiveKey="1" items={items} centered />}
  58. {loginType === 'register' && <Register backToLogin={backToLogin}/>}
  59. </div>
  60. </div>
  61. {/* <div className={styles['login-footer']}>
  62. <p>客服电话 0731-85679198、18974809627 | 客服邮箱:piaoquankefu@piaoquantv.com</p>
  63. <p>ICP备案:湘B2-20180063 | <span onClick={() => window.open('https://beian.miit.gov.cn/')}>湘ICP备16013107-06号</span> | <span onClick={() => window.open('https://beian.mps.gov.cn/#/query/webSearch')}>湘公网安备:43019002001624</span></p>
  64. </div> */}
  65. </div>
  66. )
  67. }
  68. // 密码登录
  69. function AccountLogin({ onLogin, activeTab }: LoginTypeProps) {
  70. const [form] = Form.useForm()
  71. useEffect(() => {
  72. form.resetFields()
  73. }, [activeTab])
  74. function login() {
  75. form.validateFields().then(res => {
  76. const { account, password } = res
  77. fetchLogin(account, password)
  78. })
  79. }
  80. function validator() {
  81. const account = form.getFieldValue('account')
  82. if (!account)
  83. return Promise.resolve()
  84. const phoneRegx = /^1[3456789]\d{9}$/
  85. const emailRegx = /^\w+@\w+(\.\w+)+$/
  86. if (phoneRegx.test(account) || emailRegx.test(account))
  87. return Promise.resolve()
  88. return Promise.reject('请输入合法账号')
  89. }
  90. const fetchLogin = debounce((account, password) => {
  91. sso.login(account, password).then(res => {
  92. res && onLogin()
  93. })
  94. }, 500)
  95. return (
  96. <div className={styles['account-login']}>
  97. <Form form={form}>
  98. <Form.Item name='account' validateTrigger='onBlur' rules={[{ required: true, message: '请输入手机号/邮箱', }, { validator }]}>
  99. <Input placeholder='请输入手机号/邮箱' allowClear />
  100. </Form.Item>
  101. <Form.Item name='password' rules={[{ required: true, message: '请输入密码' }]}>
  102. <Input.Password placeholder='请输入密码' allowClear />
  103. </Form.Item>
  104. <Form.Item name='loginBtn'>
  105. <Button type="primary" block onClick={login}>登录</Button>
  106. </Form.Item>
  107. </Form>
  108. {/* <p className={styles['forget-password']} onClick={onEditPassword}>忘记密码?</p> */}
  109. </div>
  110. )
  111. }
  112. // 短信登录
  113. // function SMSlogin({ onLogin, onEditPassword, activeTab }: LoginTypeProps) {
  114. // const [smsText, setSmsText] = useState('获取验证码')
  115. // const [verificationDisabled, setVerificationDisabled] = useState(false)
  116. // const [form] = Form.useForm()
  117. // useEffect(() => {
  118. // form.resetFields()
  119. // }, [activeTab])
  120. // function login() {
  121. // form.validateFields().then(res => {
  122. // const { verificationCode, phone } = res
  123. // fetchLogin(phone, verificationCode)
  124. // })
  125. // }
  126. // const fetchLogin = debounce((phone, verificationCode) => {
  127. // sso.loginBySendCode(phone, verificationCode).then(res => {
  128. // res && onLogin()
  129. // })
  130. // }, 500)
  131. // function verificationCode() {
  132. // form.validateFields(['phone']).then(res => {
  133. // const { phone } = res
  134. // sso.sendCode(phone).then(res => {
  135. // res && countdown()
  136. // })
  137. // })
  138. // }
  139. // function countdown() {
  140. // let count = 59
  141. // setVerificationDisabled(true)
  142. // setSmsText(`${count--}`)
  143. // const interval = setInterval(() => {
  144. // setSmsText(`${count--}`)
  145. // if (interval && count === 0) {
  146. // clearInterval(interval)
  147. // setVerificationDisabled(false)
  148. // setSmsText('获取验证码')
  149. // }
  150. // }, 1000)
  151. // }
  152. // function validator() {
  153. // const phone = form.getFieldValue('phone')
  154. // if (!phone)
  155. // return Promise.resolve()
  156. // const phoneRegx = /^1[3456789]\d{9}$/
  157. // if (phoneRegx.test(phone))
  158. // return Promise.resolve()
  159. // return Promise.reject('请输入合法手机号')
  160. // }
  161. // return (
  162. // <div className={styles['sms-login']}>
  163. // <Form form={form}>
  164. // <Form.Item name='phone' validateTrigger='onBlur' rules={[{ required: true, message: '请输入手机号' }, { validator }]}>
  165. // <Input placeholder='请输入手机号' allowClear />
  166. // </Form.Item>
  167. // <Form.Item name='verificationCode' rules={[{ required: true, message: '请输入验证码' }]}>
  168. // <div className={styles['msg-password']}>
  169. // <Input placeholder='请输入验证码' allowClear />
  170. // <Button type="primary" onClick={verificationCode} disabled={verificationDisabled}>
  171. // {smsText}
  172. // </Button>
  173. // </div>
  174. // </Form.Item>
  175. // <Form.Item name='loginBtn'>
  176. // <Button type="primary" block onClick={login}>登录</Button>
  177. // </Form.Item>
  178. // </Form>
  179. // <p className={styles['forget-password']} onClick={onEditPassword}>忘记密码?</p>
  180. // </div>
  181. // )
  182. // }
  183. // 忘记密码
  184. function Register({ backToLogin }: RegisterType) {
  185. const [smsText, setSmsText] = useState('获取验证码')
  186. const [verificationDisabled, setVerificationDisabled] = useState(false)
  187. const [form] = Form.useForm()
  188. useEffect(() => {
  189. form.resetFields()
  190. }, [])
  191. function submit() {
  192. form.validateFields().then(res => {
  193. const { phone, verificationCode, newPassword } = res
  194. fetchSubmit(phone, verificationCode, newPassword)
  195. })
  196. }
  197. const fetchSubmit = debounce((phone, verificationCode, newPassword) => {
  198. sso.forgotLoginPassword(phone, verificationCode, newPassword).then(res => {
  199. res && backToLogin()
  200. })
  201. }, 500)
  202. function verificationCode() {
  203. form.validateFields(['phone']).then(res => {
  204. const { phone } = res
  205. sso.sendCode(phone).then(res => {
  206. res && countdown()
  207. })
  208. })
  209. }
  210. function countdown() {
  211. let count = 59
  212. setVerificationDisabled(true)
  213. setSmsText(`${count--}`)
  214. const interval = setInterval(() => {
  215. setSmsText(`${count--}`)
  216. if (interval && count === 0) {
  217. clearInterval(interval)
  218. setVerificationDisabled(false)
  219. setSmsText('获取验证码')
  220. }
  221. }, 1000)
  222. }
  223. function validator() {
  224. const phone = form.getFieldValue('phone')
  225. if (!phone)
  226. return Promise.resolve()
  227. const phoneRegx = /^1[3456789]\d{9}$/
  228. const emailRegx = /^\w+@\w+(\.\w+)+$/
  229. if (phoneRegx.test(phone) || emailRegx.test(phone))
  230. return Promise.resolve()
  231. return Promise.reject('请输入合法手机号')
  232. }
  233. return (
  234. <div className={styles.register}>
  235. <div className={styles.title}>
  236. 忘记密码
  237. </div>
  238. <div className={styles['register-contianer']}>
  239. <Form form={form}>
  240. <Form.Item name='phone' validateTrigger='onBlur' rules={[{ required: true, message: '请输入手机号/邮箱' }, { validator }]}>
  241. <Input placeholder='请输入手机号/邮箱' allowClear />
  242. </Form.Item>
  243. <Form.Item name='verificationCode' rules={[{ required: true, message: '请输入验证码' }]}>
  244. <div className={styles['msg-password']}>
  245. <Input placeholder='请输入验证码' allowClear />
  246. <Button type="primary" onClick={verificationCode} disabled={verificationDisabled}>
  247. {smsText}
  248. </Button>
  249. </div>
  250. </Form.Item>
  251. <Form.Item name='newPassword' rules={[{ required: true, message: '请输入新密码' }]}>
  252. <Input.Password placeholder='请输入新密码' allowClear />
  253. </Form.Item>
  254. <Form.Item name='loginBtn'>
  255. <Button type="primary" block onClick={submit}>确认</Button>
  256. </Form.Item>
  257. <Form.Item name='backBtn'>
  258. <Button block onClick={backToLogin}>返回</Button>
  259. </Form.Item>
  260. </Form>
  261. </div>
  262. </div>
  263. )
  264. }