diff --git a/frontend/desktop/package.json b/frontend/desktop/package.json index 5a3379fb9d6..ede5862733e 100644 --- a/frontend/desktop/package.json +++ b/frontend/desktop/package.json @@ -17,8 +17,10 @@ "postinstall": "pnpm gen:global && pnpm gen:region" }, "dependencies": { + "@alicloud/captcha20230305": "1.1.3", "@alicloud/dysmsapi20170525": "^2.0.24", "@alicloud/openapi-client": "^0.4.6", + "@alicloud/tea-typescript": "^1.8.0", "@alicloud/tea-util": "^1.4.7", "@chakra-ui/anatomy": "^2.2.1", "@chakra-ui/icons": "^2.1.1", diff --git a/frontend/desktop/src/components/signin/Captcha/index.tsx b/frontend/desktop/src/components/signin/Captcha/index.tsx new file mode 100644 index 00000000000..6188c6818ee --- /dev/null +++ b/frontend/desktop/src/components/signin/Captcha/index.tsx @@ -0,0 +1,109 @@ +import request from '@/services/request'; +import { useConfigStore } from '@/stores/config'; +import useScriptStore from '@/stores/script'; +import { Box, Button, ButtonProps, Link, LinkProps } from '@chakra-ui/react'; +import { delay } from 'lodash'; +import React, { + ReactElement, + forwardRef, + useEffect, + useId, + useImperativeHandle, + useRef, + useState +} from 'react'; +import { v4 } from 'uuid'; +export type TCaptchaInstance = { + getToken: () => Promise; + reset: () => void; +}; + +const HiddenCaptchaComponent = forwardRef(function HiddenCaptchaComponent(props, ref) { + const captchaElementRef = useRef(null); + const captchaInstanceRef = useRef(null); + const tokenRef = useRef(''); + const buttonRef = useRef(null); + const { authConfig } = useConfigStore(); + useImperativeHandle( + ref, + () => { + return { + getToken: async () => { + buttonRef.current?.click(); + await new Promise((res) => { + setTimeout(res, 1000); + }); + const token = tokenRef.current; + return token; + }, + reset() { + tokenRef.current = ''; + } + }; + }, + [] + ); + const { captchaIsLoaded } = useScriptStore(); + const [buttonId] = useState('captcha_button_pop'); + const [captchaId] = useState('captcha_' + v4().slice(0, 8)); + + // @ts-ignore + const getInstance = (instance) => { + captchaInstanceRef.current = instance; + }; + + const onBizResultCallback = () => {}; + useEffect(() => { + if (!captchaIsLoaded) return; + const initAliyunCaptchaOptions = { + SceneId: authConfig?.captcha.ali.sceneId, + prefix: authConfig?.captcha.ali.prefix, + mode: 'popup', + element: '#' + captchaId, + button: '#' + buttonId, + async captchaVerifyCallback(captchaToken: string) { + try { + tokenRef.current = captchaToken; + return { + captchaResult: true + }; + } catch (err) { + tokenRef.current = ''; + return { + captchaResult: false + }; + } + }, + onBizResultCallback: onBizResultCallback, + getInstance, + slideStyle: { + width: 360, + height: 40 + }, + immediate: false, + language: 'cn', + region: 'cn' + }; + + // @ts-ignore + window.initAliyunCaptcha(initAliyunCaptchaOptions); + + return () => { + captchaInstanceRef.current = null; + }; + }, [captchaIsLoaded]); + return ( + <> +