diff --git a/store/trader.go b/store/trader.go index 5a813bc7..5f4f8fa5 100644 --- a/store/trader.go +++ b/store/trader.go @@ -197,8 +197,12 @@ func (s *TraderStore) UpdateCustomPrompt(userID, id string, customPrompt string, return err } -// Delete deletes trader +// Delete deletes trader and associated data func (s *TraderStore) Delete(userID, id string) error { + // Delete associated equity snapshots first + _, _ = s.db.Exec(`DELETE FROM trader_equity_snapshots WHERE trader_id = ?`, id) + + // Delete the trader _, err := s.db.Exec(`DELETE FROM traders WHERE id = ? AND user_id = ?`, id, userID) return err } diff --git a/web/src/components/AITradersPage.tsx b/web/src/components/AITradersPage.tsx index 53a90a4c..f07ee7dd 100644 --- a/web/src/components/AITradersPage.tsx +++ b/web/src/components/AITradersPage.tsx @@ -34,6 +34,8 @@ import { BookOpen, HelpCircle, Pencil, + UserPlus, + ExternalLink, } from 'lucide-react' import { confirmToast } from '../lib/notify' import { toast } from 'sonner' @@ -1611,6 +1613,16 @@ function ExchangeConfigModal({ (e) => e.id === selectedExchangeId ) + // 交易所注册链接配置 + const exchangeRegistrationLinks: Record = { + binance: { url: 'https://www.binance.com/join?ref=NOFXAI', hasReferral: true }, + okx: { url: 'https://www.okx.com/join/1865360', hasReferral: true }, + bybit: { url: 'https://partner.bybit.com/b/83856', hasReferral: true }, + hyperliquid: { url: 'https://app.hyperliquid.xyz/join/AITRADING', hasReferral: true }, + aster: { url: 'https://www.asterdex.com/en/referral/fdfc0e', hasReferral: true }, + lighter: { url: 'https://lighter.xyz', hasReferral: false }, + } + // 如果是编辑现有交易所,初始化表单数据 useEffect(() => { if (editingExchangeId && selectedExchange) { @@ -1918,6 +1930,35 @@ function ExchangeConfigModal({ + {/* 注册链接 */} + {exchangeRegistrationLinks[selectedExchange.id] && ( + +
+ + + {language === 'zh' ? '还没有交易所账号?点击注册' : "No exchange account? Register here"} + + {exchangeRegistrationLinks[selectedExchange.id].hasReferral && ( + + {language === 'zh' ? '折扣优惠' : 'Discount'} + + )} +
+ +
+ )} )} diff --git a/web/src/components/HeaderBar.tsx b/web/src/components/HeaderBar.tsx index 050529d9..0d4bed07 100644 --- a/web/src/components/HeaderBar.tsx +++ b/web/src/components/HeaderBar.tsx @@ -5,6 +5,7 @@ import { Menu, X, ChevronDown } from 'lucide-react' import { t, type Language } from '../i18n/translations' import { Container } from './Container' import { useSystemConfig } from '../hooks/useSystemConfig' +import { OFFICIAL_LINKS } from '../constants/branding' type Page = | 'competition' @@ -430,45 +431,77 @@ export default function HeaderBar({ )} - {/* Right Side - Original Navigation Items and Login */} -
- {/* Only show original navigation items on home page */} - {isHomePage && - [ - { key: 'features', label: t('features', language) }, - { key: 'howItWorks', label: t('howItWorks', language) }, - { key: 'GitHub', label: 'GitHub' }, - { key: 'community', label: t('community', language) }, - ].map((item) => ( - - {item.label} - - - ))} + {/* Right Side - Social Links and User Actions */} +
+ {/* Social Links - Always visible */} +
+ {/* GitHub */} + { + e.currentTarget.style.color = '#EAECEF' + e.currentTarget.style.background = 'rgba(255, 255, 255, 0.05)' + }} + onMouseLeave={(e) => { + e.currentTarget.style.color = '#848E9C' + e.currentTarget.style.background = 'transparent' + }} + title="GitHub" + > + + + + + {/* Twitter/X */} + { + e.currentTarget.style.color = '#1DA1F2' + e.currentTarget.style.background = 'rgba(29, 161, 242, 0.1)' + }} + onMouseLeave={(e) => { + e.currentTarget.style.color = '#848E9C' + e.currentTarget.style.background = 'transparent' + }} + title="Twitter" + > + + + + + {/* Telegram */} + { + e.currentTarget.style.color = '#0088cc' + e.currentTarget.style.background = 'rgba(0, 136, 204, 0.1)' + }} + onMouseLeave={(e) => { + e.currentTarget.style.color = '#848E9C' + e.currentTarget.style.background = 'transparent' + }} + title="Telegram" + > + + + + +
+ + {/* Divider */} +
{/* User Info and Actions */} {isLoggedIn && user ? ( @@ -932,28 +965,10 @@ export default function HeaderBar({ [ { key: 'features', label: t('features', language) }, { key: 'howItWorks', label: t('howItWorks', language) }, - { key: 'GitHub', label: 'GitHub' }, - { key: 'community', label: t('community', language) }, ].map((item) => ( @@ -961,6 +976,43 @@ export default function HeaderBar({ ))} + {/* Social Links - Mobile */} +
+ + + + + + + + + + + + + + + +
+ {/* Language Toggle */}
diff --git a/web/src/components/TraderConfigModal.tsx b/web/src/components/TraderConfigModal.tsx index d36f59d9..1b9a3449 100644 --- a/web/src/components/TraderConfigModal.tsx +++ b/web/src/components/TraderConfigModal.tsx @@ -3,7 +3,7 @@ import type { AIModel, Exchange, CreateTraderRequest, Strategy } from '../types' import { useLanguage } from '../contexts/LanguageContext' import { t } from '../i18n/translations' import { toast } from 'sonner' -import { Pencil, Plus, X as IconX, Sparkles } from 'lucide-react' +import { Pencil, Plus, X as IconX, Sparkles, ExternalLink, UserPlus } from 'lucide-react' import { httpClient } from '../lib/httpClient' // 提取下划线后面的名称部分 @@ -12,6 +12,16 @@ function getShortName(fullName: string): string { return parts.length > 1 ? parts[parts.length - 1] : fullName } +// 交易所注册链接配置 +const EXCHANGE_REGISTRATION_LINKS: Record = { + binance: { url: 'https://www.binance.com/join?ref=NOFXENG', hasReferral: true }, + okx: { url: 'https://www.okx.com/join/1865360', hasReferral: true }, + bybit: { url: 'https://partner.bybit.com/b/83856', hasReferral: true }, + hyperliquid: { url: 'https://app.hyperliquid.xyz/join/AITRADING', hasReferral: true }, + aster: { url: 'https://www.asterdex.com/en/referral/fdfc0e', hasReferral: true }, + lighter: { url: 'https://lighter.xyz', hasReferral: false }, +} + import type { TraderConfigData } from '../types' // 表单内部状态类型 @@ -272,6 +282,30 @@ export function TraderConfigModal({ ))} + {/* Exchange Registration Link */} + {formData.exchange_id && (() => { + // Exchange ID is the exchange type (e.g., "binance", "okx", "aster") + const exchangeType = formData.exchange_id.toLowerCase() + const regLink = EXCHANGE_REGISTRATION_LINKS[exchangeType] + if (!regLink) return null + return ( + + + 还没有交易所账号?点击注册 + {regLink.hasReferral && ( + + 折扣优惠 + + )} + + + ) + })()}
diff --git a/web/src/components/landing/AboutSection.tsx b/web/src/components/landing/AboutSection.tsx index 9ec4df0a..369f8171 100644 --- a/web/src/components/landing/AboutSection.tsx +++ b/web/src/components/landing/AboutSection.tsx @@ -1,7 +1,5 @@ import { motion } from 'framer-motion' -import { Shield, Target } from 'lucide-react' -import AnimatedSection from './AnimatedSection' -import Typewriter from '../Typewriter' +import { Terminal, Shield, Cpu, BarChart3 } from 'lucide-react' import { t, Language } from '../../i18n/translations' interface AboutSectionProps { @@ -9,119 +7,151 @@ interface AboutSectionProps { } export default function AboutSection({ language }: AboutSectionProps) { + const features = [ + { + icon: Shield, + title: language === 'zh' ? '完全自主控制' : 'Full Control', + desc: language === 'zh' ? '自托管,数据安全' : 'Self-hosted, data secure', + }, + { + icon: Cpu, + title: language === 'zh' ? '多 AI 支持' : 'Multi-AI Support', + desc: language === 'zh' ? 'DeepSeek, GPT, Claude...' : 'DeepSeek, GPT, Claude...', + }, + { + icon: BarChart3, + title: language === 'zh' ? '实时监控' : 'Real-time Monitor', + desc: language === 'zh' ? '可视化交易看板' : 'Visual trading dashboard', + }, + ] + return ( - -
-
+
+ {/* Background Decoration */} +
+ +
+
+ {/* Left Content */} - - + + {t('aboutNofx', language)} -

+

{t('whatIsNofx', language)}

-

- {t('nofxNotAnotherBot', language)}{' '} - {t('nofxDescription1', language)}{' '} - {t('nofxDescription2', language)} + +

+ {t('nofxNotAnotherBot', language)} {t('nofxDescription1', language)}

-

- {t('nofxDescription3', language)}{' '} - {t('nofxDescription4', language)}{' '} - {t('nofxDescription5', language)} -

- -
- -
-
-
+ {features.map((feature, index) => ( + - {t('youFullControl', language)} -
-
- {t('fullControlDesc', language)} -
-
-
+
+ +
+
+
+ {feature.title} +
+
+ {feature.desc} +
+
+
+ ))} +
-
+ {/* Right - Terminal */} +
- + {/* Terminal Header */} +
+
+
+
+
+
+ terminal +
+ + {/* Terminal Content */} +
+
$ git clone https://github.com/NoFxAiOS/nofx.git
+
$ cd nofx && chmod +x start.sh
+
$ ./start.sh start --build
+
+ ✓ {t('startupMessages1', language)} +
+
+ ✓ {t('startupMessages2', language)} +
+
+ ✓ {t('startupMessages3', language)} +
+ + + _ + +
-
+
- +
) } diff --git a/web/src/components/landing/CommunitySection.tsx b/web/src/components/landing/CommunitySection.tsx index af894469..c0975686 100644 --- a/web/src/components/landing/CommunitySection.tsx +++ b/web/src/components/landing/CommunitySection.tsx @@ -1,7 +1,8 @@ import { motion } from 'framer-motion' -import AnimatedSection from './AnimatedSection' +import { MessageCircle, Heart, Repeat2, ExternalLink } from 'lucide-react' +import { Language } from '../../i18n/translations' -interface CardProps { +interface TweetProps { quote: string authorName: string handle: string @@ -10,49 +11,94 @@ interface CardProps { delay: number } -function TestimonialCard({ quote, authorName, delay }: CardProps) { +function TweetCard({ quote, authorName, handle, avatarUrl, tweetUrl, delay }: TweetProps) { return ( - -

- "{quote}" -

-
+ {/* Header */} +
+
+ {authorName} +
+
+ {authorName} +
+
+ {handle} +
+
+
+ {/* X Logo */}
- - {authorName} - + + + +
- + + {/* Content */} +

+ {quote} +

+ + {/* Footer */} +
+
+ + Reply +
+
+ + Repost +
+
+ + Like +
+
+ +
+
+ ) } -export default function CommunitySection() { - const staggerContainer = { - animate: { transition: { staggerChildren: 0.1 } }, - } +interface CommunitySectionProps { + language?: Language +} - // 推特内容整合(保持原三列布局,超出自动换行) - const items: CardProps[] = [ +export default function CommunitySection({ language }: CommunitySectionProps) { + const tweets: TweetProps[] = [ { quote: - '前不久非常火的 AI 量化交易系统 NOF1,在 GitHub 上有人将其复刻并开源,这就是 NOFX 项目。基于 DeepSeek、Qwen 等大语言模型,打造的通用架构 AI 交易操作系统,完成了从决策、到交易、再到复盘的闭环。GitHub: https://github.com/NoFxAiOS/nofx', + '前不久非常火的 AI 量化交易系统 NOF1,在 GitHub 上有人将其复刻并开源,这就是 NOFX 项目。基于 DeepSeek、Qwen 等大语言模型,打造的通用架构 AI 交易操作系统,完成了从决策、到交易、再到复盘的闭环。', authorName: 'Michael Williams', handle: '@MichaelWil93725', avatarUrl: @@ -84,20 +130,61 @@ export default function CommunitySection() { ] return ( - -
+
+ {/* Background Decoration */} +
+ +
+ {/* Header */} - {items.map((item, idx) => ( - +

+ {language === 'zh' ? '社区声音' : 'Community Voices'} +

+

+ {language === 'zh' ? '看看大家怎么说' : 'See what others are saying'} +

+
+ + {/* Tweet Grid */} +
+ {tweets.map((tweet, idx) => ( + ))} +
+ + {/* CTA */} + + + + + + {language === 'zh' ? '关注我们的 X' : 'Follow us on X'} +
- +
) } diff --git a/web/src/components/landing/FeaturesSection.tsx b/web/src/components/landing/FeaturesSection.tsx index de5e8a1a..55bcbeb1 100644 --- a/web/src/components/landing/FeaturesSection.tsx +++ b/web/src/components/landing/FeaturesSection.tsx @@ -1,7 +1,5 @@ import { motion } from 'framer-motion' -import AnimatedSection from './AnimatedSection' -import { CryptoFeatureCard } from '../CryptoFeatureCard' -import { Code, Cpu, Lock, Rocket } from 'lucide-react' +import { Brain, Swords, BarChart3, Shield, Blocks, LineChart } from 'lucide-react' import { t, Language } from '../../i18n/translations' interface FeaturesSectionProps { @@ -9,84 +7,199 @@ interface FeaturesSectionProps { } export default function FeaturesSection({ language }: FeaturesSectionProps) { + const features = [ + { + icon: Brain, + title: language === 'zh' ? 'AI 策略编排引擎' : 'AI Strategy Orchestration', + desc: language === 'zh' + ? '支持 DeepSeek、GPT、Claude、Qwen 等多种大模型,自定义 Prompt 策略,AI 自主分析市场并做出交易决策' + : 'Support DeepSeek, GPT, Claude, Qwen and more. Custom prompts, AI autonomously analyzes markets and makes trading decisions', + highlight: true, + badge: language === 'zh' ? '核心能力' : 'Core', + }, + { + icon: Swords, + title: language === 'zh' ? '多 AI 竞技场' : 'Multi-AI Arena', + desc: language === 'zh' + ? '多个 AI 交易员同台竞技,实时 PnL 排行榜,自动优胜劣汰,让最强策略脱颖而出' + : 'Multiple AI traders compete in real-time, live PnL leaderboard, automatic survival of the fittest', + highlight: true, + badge: language === 'zh' ? '独创' : 'Unique', + }, + { + icon: LineChart, + title: language === 'zh' ? '专业量化数据' : 'Pro Quant Data', + desc: language === 'zh' + ? '集成 K线、技术指标、市场深度、资金费率、持仓量等专业量化数据,为 AI 决策提供全面信息' + : 'Integrated candlesticks, indicators, order book, funding rates, open interest - comprehensive data for AI decisions', + highlight: true, + badge: language === 'zh' ? '专业' : 'Pro', + }, + { + icon: Blocks, + title: language === 'zh' ? '多交易所支持' : 'Multi-Exchange Support', + desc: language === 'zh' + ? 'Binance、OKX、Bybit、Hyperliquid、Aster DEX,一套系统管理多个交易所' + : 'Binance, OKX, Bybit, Hyperliquid, Aster DEX - one system, multiple exchanges', + }, + { + icon: BarChart3, + title: language === 'zh' ? '实时可视化看板' : 'Real-time Dashboard', + desc: language === 'zh' + ? '交易监控、收益曲线、持仓分析、AI 决策日志,一目了然' + : 'Trade monitoring, PnL curves, position analysis, AI decision logs at a glance', + }, + { + icon: Shield, + title: language === 'zh' ? '开源自托管' : 'Open Source & Self-Hosted', + desc: language === 'zh' + ? '代码完全开源可审计,数据存储在本地,API 密钥不经过第三方' + : 'Fully open source, data stored locally, API keys never leave your server', + }, + ] + return ( - -
+
+ {/* Background */} +
+ +
+ {/* Header */} - - - - {t('coreFeatures', language)} - - -

+

{t('whyChooseNofx', language)}

-

- {t('openCommunityDriven', language)} +

+ {language === 'zh' + ? '不只是交易机器人,而是完整的 AI 交易操作系统' + : 'Not just a trading bot, but a complete AI trading operating system'}

-
- } - title={t('openSourceSelfHosted', language)} - description={t('openSourceDesc', language)} - features={[ - t('openSourceFeatures1', language), - t('openSourceFeatures2', language), - t('openSourceFeatures3', language), - t('openSourceFeatures4', language), - ]} - delay={0} - /> - } - title={t('multiAgentCompetition', language)} - description={t('multiAgentDesc', language)} - features={[ - t('multiAgentFeatures1', language), - t('multiAgentFeatures2', language), - t('multiAgentFeatures3', language), - t('multiAgentFeatures4', language), - ]} - delay={0.1} - /> - } - title={t('secureReliableTrading', language)} - description={t('secureDesc', language)} - features={[ - t('secureFeatures1', language), - t('secureFeatures2', language), - t('secureFeatures3', language), - t('secureFeatures4', language), - ]} - delay={0.2} - /> + {/* Features Grid */} +
+ {features.map((feature, index) => ( + + {/* Badge */} + {feature.badge && ( +
+ {feature.badge} +
+ )} + + {/* Icon */} + + + + + {/* Text */} +

+ {feature.title} +

+

+ {feature.desc} +

+ + {/* Hover Glow */} +
+ + ))}
+ + {/* Bottom Stats */} + + {[ + { value: '10+', label: language === 'zh' ? 'AI 模型支持' : 'AI Models' }, + { value: '5+', label: language === 'zh' ? '交易所集成' : 'Exchanges' }, + { value: '24/7', label: language === 'zh' ? '自动交易' : 'Auto Trading' }, + { value: '100%', label: language === 'zh' ? '开源免费' : 'Open Source' }, + ].map((stat) => ( +
+
+ {stat.value} +
+
+ {stat.label} +
+
+ ))} +
- +
) } diff --git a/web/src/components/landing/FooterSection.tsx b/web/src/components/landing/FooterSection.tsx index 158a6ab0..9575591b 100644 --- a/web/src/components/landing/FooterSection.tsx +++ b/web/src/components/landing/FooterSection.tsx @@ -1,180 +1,169 @@ +import { Github, Send, ExternalLink } from 'lucide-react' import { t, Language } from '../../i18n/translations' +import { OFFICIAL_LINKS } from '../../constants/branding' interface FooterSectionProps { language: Language } export default function FooterSection({ language }: FooterSectionProps) { + const links = { + social: [ + { name: 'GitHub', href: OFFICIAL_LINKS.github, icon: Github }, + { + name: 'X (Twitter)', + href: OFFICIAL_LINKS.twitter, + icon: () => ( + + + + ), + }, + { name: 'Telegram', href: OFFICIAL_LINKS.telegram, icon: Send }, + ], + resources: [ + { + name: language === 'zh' ? '文档' : 'Documentation', + href: 'https://github.com/NoFxAiOS/nofx/blob/main/README.md', + }, + { name: 'Issues', href: 'https://github.com/NoFxAiOS/nofx/issues' }, + { name: 'Pull Requests', href: 'https://github.com/NoFxAiOS/nofx/pulls' }, + ], + supporters: [ + { name: 'Aster DEX', href: 'https://www.asterdex.com/en/referral/fdfc0e' }, + { name: 'Binance', href: 'https://www.maxweb.red/join?ref=NOFXAI' }, + { name: 'Hyperliquid', href: 'https://hyperliquid.xyz/' }, + { + name: 'Amber.ac', + href: 'https://amber.ac/', + badge: language === 'zh' ? '战略投资' : 'Strategic', + }, + ], + } + return ( -