|
@@ -37,7 +37,7 @@ import {
|
|
|
isPasskeySupported,
|
|
isPasskeySupported,
|
|
|
} from '../../helpers';
|
|
} from '../../helpers';
|
|
|
import Turnstile from 'react-turnstile';
|
|
import Turnstile from 'react-turnstile';
|
|
|
-import { Button, Card, Divider, Form, Icon, Modal } from '@douyinfe/semi-ui';
|
|
|
|
|
|
|
+import { Button, Card, Checkbox, Divider, Form, Icon, Modal } from '@douyinfe/semi-ui';
|
|
|
import Title from '@douyinfe/semi-ui/lib/es/typography/title';
|
|
import Title from '@douyinfe/semi-ui/lib/es/typography/title';
|
|
|
import Text from '@douyinfe/semi-ui/lib/es/typography/text';
|
|
import Text from '@douyinfe/semi-ui/lib/es/typography/text';
|
|
|
import TelegramLoginButton from 'react-telegram-login';
|
|
import TelegramLoginButton from 'react-telegram-login';
|
|
@@ -84,6 +84,9 @@ const LoginForm = () => {
|
|
|
const [showTwoFA, setShowTwoFA] = useState(false);
|
|
const [showTwoFA, setShowTwoFA] = useState(false);
|
|
|
const [passkeySupported, setPasskeySupported] = useState(false);
|
|
const [passkeySupported, setPasskeySupported] = useState(false);
|
|
|
const [passkeyLoading, setPasskeyLoading] = useState(false);
|
|
const [passkeyLoading, setPasskeyLoading] = useState(false);
|
|
|
|
|
+ const [agreedToTerms, setAgreedToTerms] = useState(false);
|
|
|
|
|
+ const [hasUserAgreement, setHasUserAgreement] = useState(false);
|
|
|
|
|
+ const [hasPrivacyPolicy, setHasPrivacyPolicy] = useState(false);
|
|
|
|
|
|
|
|
const logo = getLogo();
|
|
const logo = getLogo();
|
|
|
const systemName = getSystemName();
|
|
const systemName = getSystemName();
|
|
@@ -103,6 +106,10 @@ const LoginForm = () => {
|
|
|
setTurnstileEnabled(true);
|
|
setTurnstileEnabled(true);
|
|
|
setTurnstileSiteKey(status.turnstile_site_key);
|
|
setTurnstileSiteKey(status.turnstile_site_key);
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+ // 从 status 获取用户协议和隐私政策的启用状态
|
|
|
|
|
+ setHasUserAgreement(status.user_agreement_enabled || false);
|
|
|
|
|
+ setHasPrivacyPolicy(status.privacy_policy_enabled || false);
|
|
|
}, [status]);
|
|
}, [status]);
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
useEffect(() => {
|
|
@@ -118,6 +125,10 @@ const LoginForm = () => {
|
|
|
}, []);
|
|
}, []);
|
|
|
|
|
|
|
|
const onWeChatLoginClicked = () => {
|
|
const onWeChatLoginClicked = () => {
|
|
|
|
|
+ if ((hasUserAgreement || hasPrivacyPolicy) && !agreedToTerms) {
|
|
|
|
|
+ showInfo(t('请先阅读并同意用户协议和隐私政策'));
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
setWechatLoading(true);
|
|
setWechatLoading(true);
|
|
|
setShowWeChatLoginModal(true);
|
|
setShowWeChatLoginModal(true);
|
|
|
setWechatLoading(false);
|
|
setWechatLoading(false);
|
|
@@ -157,6 +168,10 @@ const LoginForm = () => {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
async function handleSubmit(e) {
|
|
async function handleSubmit(e) {
|
|
|
|
|
+ if ((hasUserAgreement || hasPrivacyPolicy) && !agreedToTerms) {
|
|
|
|
|
+ showInfo(t('请先阅读并同意用户协议和隐私政策'));
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
if (turnstileEnabled && turnstileToken === '') {
|
|
if (turnstileEnabled && turnstileToken === '') {
|
|
|
showInfo('请稍后几秒重试,Turnstile 正在检查用户环境!');
|
|
showInfo('请稍后几秒重试,Turnstile 正在检查用户环境!');
|
|
|
return;
|
|
return;
|
|
@@ -208,6 +223,10 @@ const LoginForm = () => {
|
|
|
|
|
|
|
|
// 添加Telegram登录处理函数
|
|
// 添加Telegram登录处理函数
|
|
|
const onTelegramLoginClicked = async (response) => {
|
|
const onTelegramLoginClicked = async (response) => {
|
|
|
|
|
+ if ((hasUserAgreement || hasPrivacyPolicy) && !agreedToTerms) {
|
|
|
|
|
+ showInfo(t('请先阅读并同意用户协议和隐私政策'));
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
const fields = [
|
|
const fields = [
|
|
|
'id',
|
|
'id',
|
|
|
'first_name',
|
|
'first_name',
|
|
@@ -244,6 +263,10 @@ const LoginForm = () => {
|
|
|
|
|
|
|
|
// 包装的GitHub登录点击处理
|
|
// 包装的GitHub登录点击处理
|
|
|
const handleGitHubClick = () => {
|
|
const handleGitHubClick = () => {
|
|
|
|
|
+ if ((hasUserAgreement || hasPrivacyPolicy) && !agreedToTerms) {
|
|
|
|
|
+ showInfo(t('请先阅读并同意用户协议和隐私政策'));
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
setGithubLoading(true);
|
|
setGithubLoading(true);
|
|
|
try {
|
|
try {
|
|
|
onGitHubOAuthClicked(status.github_client_id);
|
|
onGitHubOAuthClicked(status.github_client_id);
|
|
@@ -255,6 +278,10 @@ const LoginForm = () => {
|
|
|
|
|
|
|
|
// 包装的OIDC登录点击处理
|
|
// 包装的OIDC登录点击处理
|
|
|
const handleOIDCClick = () => {
|
|
const handleOIDCClick = () => {
|
|
|
|
|
+ if ((hasUserAgreement || hasPrivacyPolicy) && !agreedToTerms) {
|
|
|
|
|
+ showInfo(t('请先阅读并同意用户协议和隐私政策'));
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
setOidcLoading(true);
|
|
setOidcLoading(true);
|
|
|
try {
|
|
try {
|
|
|
onOIDCClicked(status.oidc_authorization_endpoint, status.oidc_client_id);
|
|
onOIDCClicked(status.oidc_authorization_endpoint, status.oidc_client_id);
|
|
@@ -266,6 +293,10 @@ const LoginForm = () => {
|
|
|
|
|
|
|
|
// 包装的LinuxDO登录点击处理
|
|
// 包装的LinuxDO登录点击处理
|
|
|
const handleLinuxDOClick = () => {
|
|
const handleLinuxDOClick = () => {
|
|
|
|
|
+ if ((hasUserAgreement || hasPrivacyPolicy) && !agreedToTerms) {
|
|
|
|
|
+ showInfo(t('请先阅读并同意用户协议和隐私政策'));
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
setLinuxdoLoading(true);
|
|
setLinuxdoLoading(true);
|
|
|
try {
|
|
try {
|
|
|
onLinuxDOOAuthClicked(status.linuxdo_client_id);
|
|
onLinuxDOOAuthClicked(status.linuxdo_client_id);
|
|
@@ -283,6 +314,10 @@ const LoginForm = () => {
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
const handlePasskeyLogin = async () => {
|
|
const handlePasskeyLogin = async () => {
|
|
|
|
|
+ if ((hasUserAgreement || hasPrivacyPolicy) && !agreedToTerms) {
|
|
|
|
|
+ showInfo(t('请先阅读并同意用户协议和隐私政策'));
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
if (!passkeySupported) {
|
|
if (!passkeySupported) {
|
|
|
showInfo('当前环境无法使用 Passkey 登录');
|
|
showInfo('当前环境无法使用 Passkey 登录');
|
|
|
return;
|
|
return;
|
|
@@ -486,6 +521,44 @@ const LoginForm = () => {
|
|
|
</Button>
|
|
</Button>
|
|
|
</div>
|
|
</div>
|
|
|
|
|
|
|
|
|
|
+ {(hasUserAgreement || hasPrivacyPolicy) && (
|
|
|
|
|
+ <div className='mt-6'>
|
|
|
|
|
+ <Checkbox
|
|
|
|
|
+ checked={agreedToTerms}
|
|
|
|
|
+ onChange={(e) => setAgreedToTerms(e.target.checked)}
|
|
|
|
|
+ >
|
|
|
|
|
+ <Text size='small' className='text-gray-600'>
|
|
|
|
|
+ {t('我已阅读并同意')}
|
|
|
|
|
+ {hasUserAgreement && (
|
|
|
|
|
+ <>
|
|
|
|
|
+ <a
|
|
|
|
|
+ href='/user-agreement'
|
|
|
|
|
+ target='_blank'
|
|
|
|
|
+ rel='noopener noreferrer'
|
|
|
|
|
+ className='text-blue-600 hover:text-blue-800 mx-1'
|
|
|
|
|
+ >
|
|
|
|
|
+ {t('用户协议')}
|
|
|
|
|
+ </a>
|
|
|
|
|
+ </>
|
|
|
|
|
+ )}
|
|
|
|
|
+ {hasUserAgreement && hasPrivacyPolicy && t('和')}
|
|
|
|
|
+ {hasPrivacyPolicy && (
|
|
|
|
|
+ <>
|
|
|
|
|
+ <a
|
|
|
|
|
+ href='/privacy-policy'
|
|
|
|
|
+ target='_blank'
|
|
|
|
|
+ rel='noopener noreferrer'
|
|
|
|
|
+ className='text-blue-600 hover:text-blue-800 mx-1'
|
|
|
|
|
+ >
|
|
|
|
|
+ {t('隐私政策')}
|
|
|
|
|
+ </a>
|
|
|
|
|
+ </>
|
|
|
|
|
+ )}
|
|
|
|
|
+ </Text>
|
|
|
|
|
+ </Checkbox>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ )}
|
|
|
|
|
+
|
|
|
{!status.self_use_mode_enabled && (
|
|
{!status.self_use_mode_enabled && (
|
|
|
<div className='mt-6 text-center text-sm'>
|
|
<div className='mt-6 text-center text-sm'>
|
|
|
<Text>
|
|
<Text>
|
|
@@ -554,6 +627,44 @@ const LoginForm = () => {
|
|
|
prefix={<IconLock />}
|
|
prefix={<IconLock />}
|
|
|
/>
|
|
/>
|
|
|
|
|
|
|
|
|
|
+ {(hasUserAgreement || hasPrivacyPolicy) && (
|
|
|
|
|
+ <div className='pt-4'>
|
|
|
|
|
+ <Checkbox
|
|
|
|
|
+ checked={agreedToTerms}
|
|
|
|
|
+ onChange={(e) => setAgreedToTerms(e.target.checked)}
|
|
|
|
|
+ >
|
|
|
|
|
+ <Text size='small' className='text-gray-600'>
|
|
|
|
|
+ {t('我已阅读并同意')}
|
|
|
|
|
+ {hasUserAgreement && (
|
|
|
|
|
+ <>
|
|
|
|
|
+ <a
|
|
|
|
|
+ href='/user-agreement'
|
|
|
|
|
+ target='_blank'
|
|
|
|
|
+ rel='noopener noreferrer'
|
|
|
|
|
+ className='text-blue-600 hover:text-blue-800 mx-1'
|
|
|
|
|
+ >
|
|
|
|
|
+ {t('用户协议')}
|
|
|
|
|
+ </a>
|
|
|
|
|
+ </>
|
|
|
|
|
+ )}
|
|
|
|
|
+ {hasUserAgreement && hasPrivacyPolicy && t('和')}
|
|
|
|
|
+ {hasPrivacyPolicy && (
|
|
|
|
|
+ <>
|
|
|
|
|
+ <a
|
|
|
|
|
+ href='/privacy-policy'
|
|
|
|
|
+ target='_blank'
|
|
|
|
|
+ rel='noopener noreferrer'
|
|
|
|
|
+ className='text-blue-600 hover:text-blue-800 mx-1'
|
|
|
|
|
+ >
|
|
|
|
|
+ {t('隐私政策')}
|
|
|
|
|
+ </a>
|
|
|
|
|
+ </>
|
|
|
|
|
+ )}
|
|
|
|
|
+ </Text>
|
|
|
|
|
+ </Checkbox>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ )}
|
|
|
|
|
+
|
|
|
<div className='space-y-2 pt-2'>
|
|
<div className='space-y-2 pt-2'>
|
|
|
<Button
|
|
<Button
|
|
|
theme='solid'
|
|
theme='solid'
|
|
@@ -562,6 +673,7 @@ const LoginForm = () => {
|
|
|
htmlType='submit'
|
|
htmlType='submit'
|
|
|
onClick={handleSubmit}
|
|
onClick={handleSubmit}
|
|
|
loading={loginLoading}
|
|
loading={loginLoading}
|
|
|
|
|
+ disabled={(hasUserAgreement || hasPrivacyPolicy) && !agreedToTerms}
|
|
|
>
|
|
>
|
|
|
{t('继续')}
|
|
{t('继续')}
|
|
|
</Button>
|
|
</Button>
|