diff --git a/.dockerignore b/.dockerignore index 53d0019..cf14beb 100644 --- a/.dockerignore +++ b/.dockerignore @@ -7,4 +7,12 @@ Makefile docs .eslintcache .gocache -/web/node_modules \ No newline at end of file +/web/node_modules +.claude +.plans +current-page* +models-page* +pricing-page.png +login-page +scripts +relay/helper/price_test.go \ No newline at end of file diff --git a/web/src/components/auth/LoginForm.jsx b/web/src/components/auth/LoginForm.jsx index 82dba4e..0feb33c 100644 --- a/web/src/components/auth/LoginForm.jsx +++ b/web/src/components/auth/LoginForm.jsx @@ -17,8 +17,8 @@ along with this program. If not, see . For commercial licensing, please contact support@quantumnous.com */ -import React, { useContext, useEffect, useMemo, useRef, useState } from 'react'; -import { Link, useNavigate, useSearchParams } from 'react-router-dom'; +import React, { useCallback, useContext, useEffect, useMemo, useRef, useState } from 'react'; +import { Link, useLocation, useNavigate, useSearchParams } from 'react-router-dom'; import { UserContext } from '../../context/User'; import { StatusContext } from '../../context/Status'; import { @@ -69,6 +69,7 @@ import { SiDiscord } from 'react-icons/si'; const LoginForm = () => { let navigate = useNavigate(); + const location = useLocation(); const { t } = useTranslation(); const githubButtonTextKeyByState = { idle: '使用 GitHub 继续', @@ -113,6 +114,15 @@ const LoginForm = () => { const githubButtonText = t(githubButtonTextKeyByState[githubButtonState]); const [customOAuthLoading, setCustomOAuthLoading] = useState({}); + const navigateAfterLogin = useCallback(() => { + const from = location.state?.from; + if (from && from.pathname) { + navigate(from.pathname + (from.search || '')); + } else { + navigate('/console'); + } + }, [location.state, navigate]); + const logo = getLogo(); const systemName = getSystemName(); @@ -198,7 +208,7 @@ const LoginForm = () => { localStorage.setItem('user', JSON.stringify(data)); setUserData(data); updateAPI(); - navigate('/'); + navigateAfterLogin(); showSuccess(t('登录成功!')); setShowWeChatLoginModal(false); } else { @@ -255,7 +265,7 @@ const LoginForm = () => { centered: true, }); } - navigate('/console'); + navigateAfterLogin(); } else { showError(message); } @@ -300,7 +310,7 @@ const LoginForm = () => { showSuccess(t('登录成功!')); setUserData(data); updateAPI(); - navigate('/'); + navigateAfterLogin(); } else { showError(message); } @@ -456,7 +466,7 @@ const LoginForm = () => { setUserData(finish.data); updateAPI(); showSuccess(t('登录成功!')); - navigate('/console'); + navigateAfterLogin(); } else { showError(finish.message || t('Passkey 登录失败,请重试')); } @@ -491,7 +501,7 @@ const LoginForm = () => { setUserData(data); updateAPI(); showSuccess(t('登录成功!')); - navigate('/console'); + navigateAfterLogin(); }; // 返回登录页面 diff --git a/web/src/components/topup/RechargeCard.jsx b/web/src/components/topup/RechargeCard.jsx index 7be1b97..b3e3f18 100644 --- a/web/src/components/topup/RechargeCard.jsx +++ b/web/src/components/topup/RechargeCard.jsx @@ -102,6 +102,7 @@ const RechargeCard = ({ const initialTabSetRef = useRef(false); const showAmountSkeleton = useMinimumLoadingTime(amountLoading); const [activeTab, setActiveTab] = useState('topup'); + const [amountWarning, setAmountWarning] = useState(''); const shouldShowSubscription = !subscriptionLoading && subscriptionPlans.length > 0; @@ -255,18 +256,26 @@ const RechargeCard = ({ onChange={async (displayValue) => { const rawValue = needsConvert ? Math.round(displayValue / curRate) : displayValue; if (rawValue && rawValue >= 1) { + if (rawValue < minTopUp) { + setAmountWarning(t('金额过小,最低需充值') + displayMin + ' ' + curSymbol); + } else { + setAmountWarning(''); + } setTopUpCount(rawValue); setSelectedPreset(null); await getAmount(rawValue); + } else { + setAmountWarning(t('金额过小,最低需充值') + displayMin + ' ' + curSymbol); } }} onBlur={(e) => { const displayVal = parseInt(e.target.value); const rawVal = needsConvert ? Math.round(displayVal / curRate) : displayVal; if (!rawVal || rawVal < 1) { - setTopUpCount(1); - getAmount(1); + setTopUpCount(minTopUp); + getAmount(minTopUp); } + setAmountWarning(''); }} formatter={(value) => (value ? `${value}` : '')} parser={(value) => @@ -275,26 +284,33 @@ const RechargeCard = ({ suffix={curSymbol} style={{ width: '100%' }} extraText={ - - } - > - - {t('实付金额:')} - - {renderAmount()} - - - + <> + {amountWarning && ( +
+ {amountWarning} +
+ )} + + } + > + + {t('实付金额:')} + + {renderAmount()} + + + + } /> ); @@ -436,6 +452,7 @@ const RechargeCard = ({ bodyStyle={{ padding: '12px' }} onClick={() => { selectPresetAmount(preset); + setAmountWarning(''); onlineFormApiRef.current?.setValue( 'topUpCount', needsConvert ? Math.round(preset.value * pRate) : preset.value,