diff --git a/controller/github.go b/controller/github.go index 7097356db..79f27bca3 100644 --- a/controller/github.go +++ b/controller/github.go @@ -44,7 +44,7 @@ func getGitHubUserInfoByCode(code string) (*GitHubUser, error) { req.Header.Set("Content-Type", "application/json") req.Header.Set("Accept", "application/json") client := http.Client{ - Timeout: 5 * time.Second, + Timeout: 20 * time.Second, } res, err := client.Do(req) if err != nil { diff --git a/web/src/components/auth/LoginForm.jsx b/web/src/components/auth/LoginForm.jsx index 28d58987f..356bab873 100644 --- a/web/src/components/auth/LoginForm.jsx +++ b/web/src/components/auth/LoginForm.jsx @@ -17,7 +17,7 @@ along with this program. If not, see . For commercial licensing, please contact support@quantumnous.com */ -import React, { useContext, useEffect, useState } from 'react'; +import React, { useContext, useEffect, useRef, useState } from 'react'; import { Link, useNavigate, useSearchParams } from 'react-router-dom'; import { UserContext } from '../../context/User'; import { @@ -87,6 +87,9 @@ const LoginForm = () => { const [agreedToTerms, setAgreedToTerms] = useState(false); const [hasUserAgreement, setHasUserAgreement] = useState(false); const [hasPrivacyPolicy, setHasPrivacyPolicy] = useState(false); + const [githubButtonText, setGithubButtonText] = useState('使用 GitHub 继续'); + const [githubButtonDisabled, setGithubButtonDisabled] = useState(false); + const githubTimeoutRef = useRef(null); const logo = getLogo(); const systemName = getSystemName(); @@ -116,6 +119,12 @@ const LoginForm = () => { isPasskeySupported() .then(setPasskeySupported) .catch(() => setPasskeySupported(false)); + + return () => { + if (githubTimeoutRef.current) { + clearTimeout(githubTimeoutRef.current); + } + }; }, []); useEffect(() => { @@ -267,7 +276,20 @@ const LoginForm = () => { showInfo(t('请先阅读并同意用户协议和隐私政策')); return; } + if (githubButtonDisabled) { + return; + } setGithubLoading(true); + setGithubButtonDisabled(true); + setGithubButtonText(t('正在跳转 GitHub...')); + if (githubTimeoutRef.current) { + clearTimeout(githubTimeoutRef.current); + } + githubTimeoutRef.current = setTimeout(() => { + setGithubLoading(false); + setGithubButtonText(t('请求超时,请刷新页面后重新发起 GitHub 登录')); + setGithubButtonDisabled(true); + }, 20000); try { onGitHubOAuthClicked(status.github_client_id); } finally { @@ -444,8 +466,9 @@ const LoginForm = () => { icon={} onClick={handleGitHubClick} loading={githubLoading} + disabled={githubButtonDisabled} > - {t('使用 GitHub 继续')} + {githubButtonText} )} diff --git a/web/src/components/auth/RegisterForm.jsx b/web/src/components/auth/RegisterForm.jsx index 436a7b6b8..29eca627e 100644 --- a/web/src/components/auth/RegisterForm.jsx +++ b/web/src/components/auth/RegisterForm.jsx @@ -17,7 +17,7 @@ along with this program. If not, see . For commercial licensing, please contact support@quantumnous.com */ -import React, { useContext, useEffect, useState } from 'react'; +import React, { useContext, useEffect, useRef, useState } from 'react'; import { Link, useNavigate } from 'react-router-dom'; import { API, @@ -85,6 +85,9 @@ const RegisterForm = () => { const [agreedToTerms, setAgreedToTerms] = useState(false); const [hasUserAgreement, setHasUserAgreement] = useState(false); const [hasPrivacyPolicy, setHasPrivacyPolicy] = useState(false); + const [githubButtonText, setGithubButtonText] = useState('使用 GitHub 继续'); + const [githubButtonDisabled, setGithubButtonDisabled] = useState(false); + const githubTimeoutRef = useRef(null); const logo = getLogo(); const systemName = getSystemName(); @@ -128,6 +131,14 @@ const RegisterForm = () => { return () => clearInterval(countdownInterval); // Clean up on unmount }, [disableButton, countdown]); + useEffect(() => { + return () => { + if (githubTimeoutRef.current) { + clearTimeout(githubTimeoutRef.current); + } + }; + }, []); + const onWeChatLoginClicked = () => { setWechatLoading(true); setShowWeChatLoginModal(true); @@ -232,7 +243,20 @@ const RegisterForm = () => { }; const handleGitHubClick = () => { + if (githubButtonDisabled) { + return; + } setGithubLoading(true); + setGithubButtonDisabled(true); + setGithubButtonText(t('正在跳转 GitHub...')); + if (githubTimeoutRef.current) { + clearTimeout(githubTimeoutRef.current); + } + githubTimeoutRef.current = setTimeout(() => { + setGithubLoading(false); + setGithubButtonText(t('请求超时,请刷新页面后重新发起 GitHub 登录')); + setGithubButtonDisabled(true); + }, 20000); try { onGitHubOAuthClicked(status.github_client_id); } finally { @@ -347,8 +371,9 @@ const RegisterForm = () => { icon={} onClick={handleGitHubClick} loading={githubLoading} + disabled={githubButtonDisabled} > - {t('使用 GitHub 继续')} + {githubButtonText} )} diff --git a/web/src/i18n/locales/en.json b/web/src/i18n/locales/en.json index 4cbe216d1..0d4614ecf 100644 --- a/web/src/i18n/locales/en.json +++ b/web/src/i18n/locales/en.json @@ -2109,6 +2109,8 @@ "请填写完整的产品信息": "Please fill in complete product information", "产品ID已存在": "Product ID already exists", "统一的": "The Unified", - "大模型接口网关": "LLM API Gateway" + "大模型接口网关": "LLM API Gateway", + "正在跳转 GitHub...": "Redirecting to GitHub...", + "请求超时,请刷新页面后重新发起 GitHub 登录": "Request timed out, please refresh and restart GitHub login" } } diff --git a/web/src/i18n/locales/fr.json b/web/src/i18n/locales/fr.json index ef593e0bd..fd310d259 100644 --- a/web/src/i18n/locales/fr.json +++ b/web/src/i18n/locales/fr.json @@ -2089,6 +2089,8 @@ "默认测试模型": "Modèle de test par défaut", "默认补全倍率": "Taux de complétion par défaut", "统一的": "La Passerelle", - "大模型接口网关": "API LLM Unifiée" + "大模型接口网关": "API LLM Unifiée", + "正在跳转 GitHub...": "Redirection vers GitHub...", + "请求超时,请刷新页面后重新发起 GitHub 登录": "Délai dépassé, veuillez actualiser la page puis relancer la connexion GitHub" } } diff --git a/web/src/i18n/locales/ja.json b/web/src/i18n/locales/ja.json index 67d3c79b6..28590bb62 100644 --- a/web/src/i18n/locales/ja.json +++ b/web/src/i18n/locales/ja.json @@ -2080,6 +2080,8 @@ "默认测试模型": "デフォルトテストモデル", "默认补全倍率": "デフォルト補完倍率", "统一的": "統合型", - "大模型接口网关": "LLM APIゲートウェイ" + "大模型接口网关": "LLM APIゲートウェイ", + "正在跳转 GitHub...": "GitHub にリダイレクトしています...", + "请求超时,请刷新页面后重新发起 GitHub 登录": "タイムアウトしました。ページをリロードして GitHub ログインをやり直してください" } } diff --git a/web/src/i18n/locales/ru.json b/web/src/i18n/locales/ru.json index 5adc1deb7..67d4663f8 100644 --- a/web/src/i18n/locales/ru.json +++ b/web/src/i18n/locales/ru.json @@ -2098,6 +2098,8 @@ "默认测试模型": "Модель для тестирования по умолчанию", "默认补全倍率": "Коэффициент вывода по умолчанию", "统一的": "Единый", - "大模型接口网关": "Шлюз API LLM" + "大模型接口网关": "Шлюз API LLM", + "正在跳转 GitHub...": "Перенаправление на GitHub...", + "请求超时,请刷新页面后重新发起 GitHub 登录": "Время ожидания истекло, обновите страницу и снова запустите вход через GitHub" } } diff --git a/web/src/i18n/locales/zh.json b/web/src/i18n/locales/zh.json index e1bde4b99..63772d8d7 100644 --- a/web/src/i18n/locales/zh.json +++ b/web/src/i18n/locales/zh.json @@ -2071,6 +2071,8 @@ "默认测试模型": "默认测试模型", "默认补全倍率": "默认补全倍率", "Creem 介绍": "Creem 是一个简单的支付处理平台,支持固定金额产品销售,以及订阅销售。", - "Creem Setting Tips": "Creem 只支持预设的固定金额产品,这产品以及价格需要提前在Creem网站内创建配置,所以不支持自定义动态金额充值。在Creem端配置产品的名字以及价格,获取Product Id 后填到下面的产品,在new-api为该产品设置充值额度,以及展示价格。" + "Creem Setting Tips": "Creem 只支持预设的固定金额产品,这产品以及价格需要提前在Creem网站内创建配置,所以不支持自定义动态金额充值。在Creem端配置产品的名字以及价格,获取Product Id 后填到下面的产品,在new-api为该产品设置充值额度,以及展示价格。", + "正在跳转 GitHub...": "正在跳转 GitHub...", + "请求超时,请刷新页面后重新发起 GitHub 登录": "请求超时,请刷新页面后重新发起 GitHub 登录" } }