From f901f954d900787a44233338aab63ed1228fdefc Mon Sep 17 00:00:00 2001 From: tinkle-community Date: Sun, 14 Dec 2025 23:12:09 +0800 Subject: [PATCH] feat: comprehensive FAQ rewrite with navigation fix - Add HeaderBar to FAQ page for proper navigation - Rewrite FAQ with 9 categories and ~50 Q&A items - Add EN/ZH translations for all FAQ content - Remove China-specific references - Update AI model names (GPT-5.2) - Update description to include crypto and US stock markets --- web/src/App.tsx | 379 +++++++++++++------- web/src/data/faqData.ts | 379 +++++++++++++------- web/src/i18n/translations.ts | 665 +++++++++++++++++++++-------------- 3 files changed, 896 insertions(+), 527 deletions(-) diff --git a/web/src/App.tsx b/web/src/App.tsx index 3a7df202..cbf4d1b3 100644 --- a/web/src/App.tsx +++ b/web/src/App.tsx @@ -59,18 +59,26 @@ function getModelDisplayName(modelId: string): string { } // Helper function to get exchange display name from exchange ID (UUID) -function getExchangeDisplayNameFromList(exchangeId: string | undefined, exchanges: Exchange[] | undefined): string { +function getExchangeDisplayNameFromList( + exchangeId: string | undefined, + exchanges: Exchange[] | undefined +): string { if (!exchangeId) return 'Unknown' - const exchange = exchanges?.find(e => e.id === exchangeId) + const exchange = exchanges?.find((e) => e.id === exchangeId) if (!exchange) return exchangeId.substring(0, 8).toUpperCase() + '...' const typeName = exchange.exchange_type?.toUpperCase() || exchange.name - return exchange.account_name ? `${typeName} - ${exchange.account_name}` : typeName + return exchange.account_name + ? `${typeName} - ${exchange.account_name}` + : typeName } // Helper function to get exchange type from exchange ID (UUID) - for TradingView charts -function getExchangeTypeFromList(exchangeId: string | undefined, exchanges: Exchange[] | undefined): string { +function getExchangeTypeFromList( + exchangeId: string | undefined, + exchanges: Exchange[] | undefined +): string { if (!exchangeId) return 'BINANCE' - const exchange = exchanges?.find(e => e.id === exchangeId) + const exchange = exchanges?.find((e) => e.id === exchangeId) if (!exchange) return 'BINANCE' // Default to BINANCE for charts return exchange.exchange_type?.toUpperCase() || 'BINANCE' } @@ -288,7 +296,52 @@ function App() { return } if (route === '/faq') { - return + return ( +
+ { + if (page === 'competition') { + window.history.pushState({}, '', '/competition') + setRoute('/competition') + setCurrentPage('competition') + } else if (page === 'traders') { + window.history.pushState({}, '', '/traders') + setRoute('/traders') + setCurrentPage('traders') + } else if (page === 'trader') { + window.history.pushState({}, '', '/dashboard') + setRoute('/dashboard') + setCurrentPage('trader') + } else if (page === 'faq') { + window.history.pushState({}, '', '/faq') + setRoute('/faq') + } else if (page === 'backtest') { + window.history.pushState({}, '', '/backtest') + setRoute('/backtest') + setCurrentPage('backtest') + } else if (page === 'strategy') { + window.history.pushState({}, '', '/strategy') + setRoute('/strategy') + setCurrentPage('strategy') + } else if (page === 'debate') { + window.history.pushState({}, '', '/debate') + setRoute('/debate') + setCurrentPage('debate') + } + }} + /> + +
+ ) } if (route === '/reset-password') { return @@ -453,7 +506,13 @@ function App() { /> {/* Main Content */} -
+
{currentPage === 'competition' ? ( ) : currentPage === 'traders' ? ( @@ -498,101 +557,118 @@ function App() {
{/* Footer - Hidden on debate page */} - {currentPage !== 'debate' && } + + )} ) } @@ -633,7 +709,9 @@ function TraderDetailsPage({ exchanges?: Exchange[] }) { const [closingPosition, setClosingPosition] = useState(null) - const [selectedChartSymbol, setSelectedChartSymbol] = useState(undefined) + const [selectedChartSymbol, setSelectedChartSymbol] = useState< + string | undefined + >(undefined) const [chartUpdateKey, setChartUpdateKey] = useState(0) const chartSectionRef = useRef(null) @@ -641,9 +719,10 @@ function TraderDetailsPage({ const handleClosePosition = async (symbol: string, side: string) => { if (!selectedTraderId) return - const confirmMsg = language === 'zh' - ? `确定要平仓 ${symbol} ${side === 'LONG' ? '多仓' : '空仓'} 吗?` - : `Are you sure you want to close ${symbol} ${side === 'LONG' ? 'LONG' : 'SHORT'} position?` + const confirmMsg = + language === 'zh' + ? `确定要平仓 ${symbol} ${side === 'LONG' ? '多仓' : '空仓'} 吗?` + : `Are you sure you want to close ${symbol} ${side === 'LONG' ? 'LONG' : 'SHORT'} position?` const confirmed = await confirmToast(confirmMsg, { title: language === 'zh' ? '确认平仓' : 'Confirm Close', @@ -656,14 +735,21 @@ function TraderDetailsPage({ setClosingPosition(symbol) try { await api.closePosition(selectedTraderId, symbol, side) - notify.success(language === 'zh' ? '平仓成功' : 'Position closed successfully') + notify.success( + language === 'zh' ? '平仓成功' : 'Position closed successfully' + ) // 使用 SWR mutate 刷新数据而非重新加载页面 await Promise.all([ mutate(`positions-${selectedTraderId}`), mutate(`account-${selectedTraderId}`), ]) } catch (err: unknown) { - const errorMsg = err instanceof Error ? err.message : (language === 'zh' ? '平仓失败' : 'Failed to close position') + const errorMsg = + err instanceof Error + ? err.message + : language === 'zh' + ? '平仓失败' + : 'Failed to close position' notify.error(errorMsg) } finally { setClosingPosition(null) @@ -828,7 +914,10 @@ function TraderDetailsPage({ style={{ color: '#EAECEF' }} > @@ -876,7 +965,7 @@ function TraderDetailsPage({ > {getModelDisplayName( selectedTrader.ai_model.split('_').pop() || - selectedTrader.ai_model + selectedTrader.ai_model )} @@ -884,7 +973,10 @@ function TraderDetailsPage({ Exchange:{' '} - {getExchangeDisplayNameFromList(selectedTrader.exchange_id, exchanges)} + {getExchangeDisplayNameFromList( + selectedTrader.exchange_id, + exchanges + )} @@ -961,7 +1053,10 @@ function TraderDetailsPage({ traderId={selectedTrader.trader_id} selectedSymbol={selectedChartSymbol} updateKey={chartUpdateKey} - exchangeId={getExchangeTypeFromList(selectedTrader.exchange_id, exchanges)} + exchangeId={getExchangeTypeFromList( + selectedTrader.exchange_id, + exchanges + )} /> @@ -1004,25 +1099,46 @@ function TraderDetailsPage({ {language === 'zh' ? '操作' : 'Action'} - + {language === 'zh' ? '入场价' : 'Entry'} - + {language === 'zh' ? '标记价' : 'Mark'} - + {language === 'zh' ? '数量' : 'Qty'} - + {language === 'zh' ? '价值' : 'Value'} - + {language === 'zh' ? '杠杆' : 'Lev.'} - + {language === 'zh' ? '未实现盈亏' : 'uPnL'} - + {language === 'zh' ? '强平价' : 'Liq.'} @@ -1037,7 +1153,10 @@ function TraderDetailsPage({ setChartUpdateKey(Date.now()) // Smooth scroll to chart with ref if (chartSectionRef.current) { - chartSectionRef.current.scrollIntoView({ behavior: 'smooth', block: 'start' }) + chartSectionRef.current.scrollIntoView({ + behavior: 'smooth', + block: 'start', + }) } }} > @@ -1050,13 +1169,13 @@ function TraderDetailsPage({ style={ pos.side === 'long' ? { - background: 'rgba(14, 203, 129, 0.1)', - color: '#0ECB81', - } + background: 'rgba(14, 203, 129, 0.1)', + color: '#0ECB81', + } : { - background: 'rgba(246, 70, 93, 0.1)', - color: '#F6465D', - } + background: 'rgba(246, 70, 93, 0.1)', + color: '#F6465D', + } } > {t( @@ -1069,12 +1188,17 @@ function TraderDetailsPage({