mirror of
https://github.com/GiriNeko/YesPlayMusic.git
synced 2025-12-16 13:17:46 +00:00
feat: 支持二维码登录 (#1443)
* fix: 使用replaceAll和正则来替换HTTPOnly * feat: 支持二维码登录 * fix: 不使用replaceAll * refactor: 使用react-query重写二维码登录 * refactor: 用useMemo来计算 qrCodeUrl * update * update * update * update
This commit is contained in:
parent
9f890072d3
commit
4d7bc14827
2 changed files with 86 additions and 27 deletions
|
|
@ -1,10 +1,16 @@
|
||||||
import md5 from 'md5'
|
import md5 from 'md5'
|
||||||
import QRCode from 'qrcode'
|
import QRCode from 'qrcode'
|
||||||
import { Fragment } from 'react'
|
import { Fragment } from 'react'
|
||||||
import {loginWithEmail, loginWithPhone} from '@/api/auth'
|
import {
|
||||||
|
checkLoginQrCodeStatus,
|
||||||
|
fetchLoginQrCodeKey,
|
||||||
|
loginWithEmail,
|
||||||
|
loginWithPhone,
|
||||||
|
} from '@/api/auth'
|
||||||
import SvgIcon from '@/components/SvgIcon'
|
import SvgIcon from '@/components/SvgIcon'
|
||||||
import { state } from '@/store'
|
import { state } from '@/store'
|
||||||
import { setCookies } from '@/utils/cookie'
|
import { setCookies } from '@/utils/cookie'
|
||||||
|
import { useInterval } from 'react-use'
|
||||||
|
|
||||||
enum Method {
|
enum Method {
|
||||||
QRCODE = 'qrcode',
|
QRCODE = 'qrcode',
|
||||||
|
|
@ -196,25 +202,24 @@ const LoginWithEmail = () => {
|
||||||
const navigate = useNavigate()
|
const navigate = useNavigate()
|
||||||
|
|
||||||
const doLogin = useMutation(
|
const doLogin = useMutation(
|
||||||
() => {
|
() =>
|
||||||
return loginWithEmail({
|
loginWithEmail({
|
||||||
email: email.trim(),
|
email: email.trim(),
|
||||||
md5_password: md5(password.trim())
|
md5_password: md5(password.trim()),
|
||||||
})
|
}),
|
||||||
|
{
|
||||||
|
onSuccess: result => {
|
||||||
|
if (result?.code !== 200) {
|
||||||
|
toast(`Login failed: ${result.code}`)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
saveCookie(result.cookie)
|
||||||
|
navigate(-1)
|
||||||
},
|
},
|
||||||
{
|
onError: error => {
|
||||||
onSuccess: result => {
|
toast(`Login failed: ${error}`)
|
||||||
if (result?.code !== 200) {
|
},
|
||||||
toast(`Login failed: ${result.code}`)
|
}
|
||||||
return
|
|
||||||
}
|
|
||||||
saveCookie(result.cookie)
|
|
||||||
navigate(-1)
|
|
||||||
},
|
|
||||||
onError: error => {
|
|
||||||
toast(`Login failed: ${error}`)
|
|
||||||
},
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const handleLogin = () => {
|
const handleLogin = () => {
|
||||||
|
|
@ -226,7 +231,11 @@ const LoginWithEmail = () => {
|
||||||
toast.error('Please enter password')
|
toast.error('Please enter password')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (email.match(/^[^\s@]+@(126|163|yeah|188|vip\.163|vip\.126)\.(com|net)$/) == null){
|
if (
|
||||||
|
email.match(
|
||||||
|
/^[^\s@]+@(126|163|yeah|188|vip\.163|vip\.126)\.(com|net)$/
|
||||||
|
) == null
|
||||||
|
) {
|
||||||
toast.error('Please use netease email')
|
toast.error('Please use netease email')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
@ -304,10 +313,61 @@ const LoginWithPhone = () => {
|
||||||
|
|
||||||
// Login with QRCode
|
// Login with QRCode
|
||||||
const LoginWithQRCode = () => {
|
const LoginWithQRCode = () => {
|
||||||
const [qrCodeUrl, setQrCodeUrl] = useState('dasdasfa')
|
const [qrCodeMessage, setQrCodeMessage] = useState('扫码登录')
|
||||||
const [qrCodeImage, setQrCodeImage] = useState('')
|
const [qrCodeImage, setQrCodeImage] = useState('')
|
||||||
useMemo(async () => {
|
|
||||||
try {
|
const navigate = useNavigate()
|
||||||
|
|
||||||
|
const {
|
||||||
|
data: key = { code: 200, data: { code: 200, unikey: 'Not Ready' } },
|
||||||
|
status: keyStatus,
|
||||||
|
refetch: refetchKey,
|
||||||
|
} = useQuery(
|
||||||
|
'qrCodeKey',
|
||||||
|
async () => {
|
||||||
|
const result = await fetchLoginQrCodeKey()
|
||||||
|
if (result.data.code !== 200) {
|
||||||
|
throw Error(`Failed to fetch QR code key: ${result.data.code}`)
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
},
|
||||||
|
{
|
||||||
|
retry: true,
|
||||||
|
retryDelay: 500,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
useInterval(async () => {
|
||||||
|
if (keyStatus !== 'success') return
|
||||||
|
const qrCodeStatus = await checkLoginQrCodeStatus({ key: key.data.unikey })
|
||||||
|
switch (qrCodeStatus.code) {
|
||||||
|
case 800:
|
||||||
|
refetchKey()
|
||||||
|
break
|
||||||
|
case 801:
|
||||||
|
setQrCodeMessage('等待扫码')
|
||||||
|
break
|
||||||
|
case 802:
|
||||||
|
setQrCodeMessage('等待确认')
|
||||||
|
break
|
||||||
|
case 803:
|
||||||
|
if (qrCodeStatus.cookie === undefined) {
|
||||||
|
toast('checkLoginQrCodeStatus returned 803 without cookie')
|
||||||
|
break
|
||||||
|
}
|
||||||
|
saveCookie(qrCodeStatus.cookie)
|
||||||
|
navigate(-1)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}, 1000)
|
||||||
|
|
||||||
|
const qrCodeUrl = useMemo(
|
||||||
|
() => `https://music.163.com/login?codekey=${key.data.unikey}`,
|
||||||
|
[key]
|
||||||
|
)
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const updateImage = async () => {
|
||||||
const image = await QRCode.toDataURL(qrCodeUrl, {
|
const image = await QRCode.toDataURL(qrCodeUrl, {
|
||||||
width: 1024,
|
width: 1024,
|
||||||
margin: 0,
|
margin: 0,
|
||||||
|
|
@ -317,11 +377,10 @@ const LoginWithQRCode = () => {
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
setQrCodeImage(image)
|
setQrCodeImage(image)
|
||||||
} catch (err) {
|
|
||||||
console.error(err)
|
|
||||||
}
|
}
|
||||||
|
updateImage()
|
||||||
}, [qrCodeUrl])
|
}, [qrCodeUrl])
|
||||||
const qrCodeMessage = 'test'
|
|
||||||
return (
|
return (
|
||||||
<div className='flex flex-col items-center justify-center'>
|
<div className='flex flex-col items-center justify-center'>
|
||||||
<div className='rounded-3xl border p-6 dark:border-gray-700'>
|
<div className='rounded-3xl border p-6 dark:border-gray-700'>
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import Cookies from 'js-cookie'
|
import Cookies from 'js-cookie'
|
||||||
|
|
||||||
export function setCookies(string: string) {
|
export function setCookies(string: string) {
|
||||||
const cookies = string.replace('HTTPOnly', '').split(';;')
|
const cookies = string.replace(/;.*?HTTPOnly.*?;/g, ';;').split(';;')
|
||||||
cookies.map(cookie => {
|
cookies.map(cookie => {
|
||||||
const cookieKeyValue = cookie.split(';')[0].split('=')
|
const cookieKeyValue = cookie.split(';')[0].split('=')
|
||||||
const [key, value] = cookieKeyValue
|
const [key, value] = cookieKeyValue
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue