lk
2 months ago
4 changed files with 270 additions and 190 deletions
-
307src/components/captcha/SlideCapt.tsx
-
49src/pages/use/login/index.tsx
-
70src/pages/use/password/retrieve.tsx
-
34src/pages/use/register/index.tsx
@ -1,160 +1,163 @@ |
|||||
import React, { forwardRef, memo, useCallback, useEffect, useState, useImperativeHandle } from "react"; |
|
||||
import { Popover, message } from "antd"; |
|
||||
import GoCaptcha from "go-captcha-react"; |
|
||||
import { SlideCaptchaCheckData } from "./types.ts"; |
|
||||
import { SlideData, SlidePoint } from "go-captcha-react/dist/components/Slide/meta/data"; |
|
||||
import { SlideConfig } from "go-captcha-react/dist/components/Slide/meta/config"; |
|
||||
import { Props } from "go-captcha-react/dist/components/Button"; |
|
||||
import { useStyle } from "./style.ts"; |
|
||||
|
import React, { forwardRef, memo, useCallback, useEffect, useState, useImperativeHandle } from 'react' |
||||
|
import { Popover, message } from 'antd' |
||||
|
import GoCaptcha from 'go-captcha-react' |
||||
|
import { SlideCaptchaCheckData } from './types.ts' |
||||
|
import { SlideData, SlidePoint } from 'go-captcha-react/dist/components/Slide/meta/data' |
||||
|
import { SlideConfig } from 'go-captcha-react/dist/components/Slide/meta/config' |
||||
|
import { useStyle } from './style.ts' |
||||
|
import {Props} from "@/global"; |
||||
|
|
||||
export interface SlideCaptProps { |
export interface SlideCaptProps { |
||||
api: { |
api: { |
||||
getCaptcha: () => Promise<any>; |
|
||||
checkCaptcha: (params: SlideCaptchaCheckData) => Promise<any>; |
|
||||
}; |
|
||||
config?: SlideConfig; |
|
||||
value?: string; |
|
||||
onChange?: (value?: string) => void; |
|
||||
|
getCaptcha: () => Promise<any>, |
||||
|
checkCaptcha: (params: SlideCaptchaCheckData) => Promise<any>, |
||||
|
}, |
||||
|
config?: SlideConfig |
||||
|
value?: string |
||||
|
onChange?: (value?: string) => void |
||||
} |
} |
||||
|
|
||||
export type SlideCaptRef = { |
export type SlideCaptRef = { |
||||
reset: () => void; |
|
||||
}; |
|
||||
|
|
||||
const SlideCapt = forwardRef<SlideCaptRef | undefined, SlideCaptProps>( |
|
||||
({ config, api, value, onChange }: SlideCaptProps, ref) => { |
|
||||
const { styles } = useStyle(); |
|
||||
const [open, setOpen] = useState(false); |
|
||||
const [state, setState] = useState<Props>({}); |
|
||||
const [data, setData] = useState<SlideData>(); |
|
||||
const [innerKey, setKey] = useState(value); |
|
||||
|
|
||||
const fetchCaptcha = useCallback(() => { |
|
||||
return api.getCaptcha().then((res) => { |
|
||||
if (res.code === 0) { |
|
||||
const data = res.data; |
|
||||
setKey(data["captcha_key"] || ""); |
|
||||
setData({ |
|
||||
image: data["image_base64"] || "", |
|
||||
thumb: data["tile_base64"] || "", |
|
||||
thumbX: data["tile_x"] || 0, |
|
||||
thumbY: data["tile_y"] || 0, |
|
||||
thumbWidth: data["tile_width"] || 0, |
|
||||
thumbHeight: data["tile_height"] || 0, |
|
||||
}); |
|
||||
} |
|
||||
}); |
|
||||
}, [api.getCaptcha, setData]); |
|
||||
|
|
||||
const refresh = useCallback(() => { |
|
||||
fetchCaptcha(); |
|
||||
}, [fetchCaptcha]); |
|
||||
|
|
||||
const confirm = useCallback( |
|
||||
(point: SlidePoint, clear: (fn?: any) => void) => { |
|
||||
api |
|
||||
.checkCaptcha({ |
|
||||
point: [point.x, point.y].join(","), |
|
||||
key: innerKey!, |
|
||||
}) |
|
||||
.then((res) => { |
|
||||
// console.log(res)
|
|
||||
if (res.code === 0 && res.data.is_ok) { |
|
||||
message.success(`验证成功`); |
|
||||
|
|
||||
//验证成功,onChange通知出去,外部需要key做为校验
|
|
||||
onChange?.(innerKey); |
|
||||
|
|
||||
setState((prevState) => ({ |
|
||||
...prevState, |
|
||||
type: "success", |
|
||||
title: "校验成功", |
|
||||
})); |
|
||||
setOpen(false); |
|
||||
} else { |
|
||||
message.error("验证失败"); |
|
||||
setState((prevState) => ({ |
|
||||
...prevState, |
|
||||
type: "error", |
|
||||
title: "点击进行校验", |
|
||||
})); |
|
||||
} |
|
||||
setTimeout(() => { |
|
||||
clear(); |
|
||||
fetchCaptcha(); |
|
||||
}, 1000); |
|
||||
}) |
|
||||
.catch(() => { |
|
||||
setTimeout(() => { |
|
||||
clear(); |
|
||||
fetchCaptcha(); |
|
||||
}, 1000); |
|
||||
}); |
|
||||
}, |
|
||||
[api.checkCaptcha, setData, state, setState, setOpen, innerKey, onChange, fetchCaptcha], |
|
||||
); |
|
||||
|
|
||||
useImperativeHandle(ref, () => { |
|
||||
return { |
|
||||
reset() { |
|
||||
setState((prevState) => ({ |
|
||||
...prevState, |
|
||||
type: "default", |
|
||||
title: "点击进行校验", |
|
||||
})); |
|
||||
setKey(undefined); |
|
||||
onChange?.(undefined); |
|
||||
refresh(); |
|
||||
}, |
|
||||
}; |
|
||||
}, [fetchCaptcha, setState, setKey]); |
|
||||
|
|
||||
useEffect(() => { |
|
||||
if (open) { |
|
||||
fetchCaptcha(); |
|
||||
|
reset: () => void |
||||
|
} |
||||
|
|
||||
|
|
||||
|
const SlideCapt = forwardRef<SlideCaptRef | undefined, SlideCaptProps>(( |
||||
|
{ |
||||
|
config, |
||||
|
api, |
||||
|
value, |
||||
|
onChange, |
||||
|
}: SlideCaptProps, ref) => { |
||||
|
|
||||
|
const { styles } = useStyle() |
||||
|
const [ open, setOpen ] = useState(false) |
||||
|
const [ state, setState ] = useState<Props>({}) |
||||
|
const [ data, setData ] = useState<SlideData>() |
||||
|
const [ innerKey, setKey ] = useState(value) |
||||
|
|
||||
|
const fetchCaptcha = useCallback(() => { |
||||
|
|
||||
|
return api.getCaptcha().then(res => { |
||||
|
if (res.code === 0) { |
||||
|
const data = res.data |
||||
|
setKey(data['captcha_key'] || '') |
||||
|
setData({ |
||||
|
image: data['image_base64'] || '', |
||||
|
thumb: data['tile_base64'] || '', |
||||
|
thumbX: data['tile_x'] || 0, |
||||
|
thumbY: data['tile_y'] || 0, |
||||
|
thumbWidth: data['tile_width'] || 0, |
||||
|
thumbHeight: data['tile_height'] || 0, |
||||
|
}) |
||||
} |
} |
||||
}, [open]); |
|
||||
|
|
||||
return ( |
|
||||
<div className={styles.container}> |
|
||||
<Popover |
|
||||
content={ |
|
||||
<GoCaptcha.Slide |
|
||||
config={{ |
|
||||
width: 300, |
|
||||
height: 217, |
|
||||
showTheme: false, |
|
||||
verticalPadding: 5, |
|
||||
horizontalPadding: 5, |
|
||||
...config, |
|
||||
}} |
|
||||
style={{ color: "red" }} |
|
||||
data={data!} |
|
||||
events={{ |
|
||||
refresh, |
|
||||
confirm, |
|
||||
close: () => { |
|
||||
setOpen(false); |
|
||||
}, |
|
||||
}} |
|
||||
/> |
|
||||
} |
|
||||
open={open} |
|
||||
onOpenChange={setOpen} |
|
||||
forceRender={true} |
|
||||
trigger="click" |
|
||||
> |
|
||||
<GoCaptcha.Button |
|
||||
title={"点击进行校验"} |
|
||||
{...state} |
|
||||
clickEvent={() => { |
|
||||
setOpen(true); |
|
||||
}} |
|
||||
/> |
|
||||
</Popover> |
|
||||
</div> |
|
||||
); |
|
||||
}, |
|
||||
); |
|
||||
|
|
||||
export default memo(SlideCapt); |
|
||||
|
}) |
||||
|
|
||||
|
|
||||
|
}, [ api.getCaptcha, setData ]) |
||||
|
|
||||
|
const refresh = useCallback(() => { |
||||
|
fetchCaptcha() |
||||
|
}, [ fetchCaptcha ]) |
||||
|
|
||||
|
const confirm = useCallback((point: SlidePoint, clear: (fn?: any) => void) => { |
||||
|
|
||||
|
api.checkCaptcha({ |
||||
|
point: [ point.x, point.y ].join(','), |
||||
|
key: innerKey! |
||||
|
}).then(res => { |
||||
|
// console.log(res)
|
||||
|
if (res.code === 0 && res.data.is_ok) { |
||||
|
message.success(`验证成功`) |
||||
|
|
||||
|
//验证成功,onChange通知出去,外部需要key做为校验
|
||||
|
onChange?.(innerKey) |
||||
|
|
||||
|
setState(prevState => ({ |
||||
|
...prevState, type: 'success', title: '校验成功', |
||||
|
})) |
||||
|
setOpen(false) |
||||
|
} else { |
||||
|
message.error('验证失败') |
||||
|
setState(prevState => ({ |
||||
|
...prevState, type: 'error', title: '点击进行校验', |
||||
|
})) |
||||
|
} |
||||
|
setTimeout(() => { |
||||
|
clear() |
||||
|
fetchCaptcha() |
||||
|
}, 1000) |
||||
|
|
||||
|
}).catch(() => { |
||||
|
setTimeout(() => { |
||||
|
clear() |
||||
|
fetchCaptcha() |
||||
|
}, 1000) |
||||
|
}) |
||||
|
|
||||
|
}, [ api.checkCaptcha, setData, state, setState, setOpen, innerKey, onChange, fetchCaptcha ]) |
||||
|
|
||||
|
useImperativeHandle(ref, () => { |
||||
|
return { |
||||
|
reset() { |
||||
|
setState(prevState => ({ |
||||
|
...prevState, type: 'default', title: '点击进行校验', |
||||
|
})) |
||||
|
setKey(undefined) |
||||
|
onChange?.(undefined) |
||||
|
refresh() |
||||
|
} |
||||
|
} |
||||
|
}, [ fetchCaptcha, setState, setKey ]) |
||||
|
|
||||
|
useEffect(() => { |
||||
|
|
||||
|
if (open) { |
||||
|
fetchCaptcha() |
||||
|
} |
||||
|
|
||||
|
}, [ open ]) |
||||
|
|
||||
|
return ( |
||||
|
<div className={styles.container}> |
||||
|
<Popover |
||||
|
content={ |
||||
|
<GoCaptcha.Slide |
||||
|
config={{ |
||||
|
width: 300, |
||||
|
height: 217, |
||||
|
showTheme: false, |
||||
|
verticalPadding: 5, |
||||
|
horizontalPadding: 5, |
||||
|
...config, |
||||
|
}} |
||||
|
style={{ color: 'red' }} |
||||
|
data={data!} |
||||
|
events={{ |
||||
|
refresh, |
||||
|
confirm, |
||||
|
close: () => { |
||||
|
setOpen(false) |
||||
|
} |
||||
|
}} |
||||
|
/> |
||||
|
} |
||||
|
open={open} |
||||
|
onOpenChange={setOpen} |
||||
|
forceRender={true} |
||||
|
trigger="click"> |
||||
|
<GoCaptcha.Button |
||||
|
title={'点击进行校验'} |
||||
|
{...state} |
||||
|
clickEvent={ |
||||
|
() => { |
||||
|
setOpen(true) |
||||
|
} |
||||
|
}/> |
||||
|
</Popover> |
||||
|
</div> |
||||
|
) |
||||
|
}) |
||||
|
|
||||
|
export default memo(SlideCapt) |
Write
Preview
Loading…
Cancel
Save
Reference in new issue