mirror of
https://github.com/NoFxAiOS/nofx.git
synced 2026-07-10 06:20:58 +08:00
refactor: simplify config and remove unused database tables
- Remove system_config, beta_codes, signal_source tables and related code - Simplify config.go to only read from .env (APIServerPort, JWTSecret, RegistrationEnabled) - Remove GetCustomCoins, use all USDT perpetual contracts for WSMonitor - Add trader_equity_snapshots table for equity tracking - Remove signal source modal from frontend AITradersPage - Fix WSMonitor nil panic by restoring initialization in main.go
This commit is contained in:
@@ -30,10 +30,8 @@ import {
|
||||
Trash2,
|
||||
Plus,
|
||||
Users,
|
||||
AlertTriangle,
|
||||
BookOpen,
|
||||
HelpCircle,
|
||||
Radio,
|
||||
Pencil,
|
||||
} from 'lucide-react'
|
||||
import { confirmToast } from '../lib/notify'
|
||||
@@ -71,7 +69,6 @@ export function AITradersPage({ onTraderSelect }: AITradersPageProps) {
|
||||
const [showEditModal, setShowEditModal] = useState(false)
|
||||
const [showModelModal, setShowModelModal] = useState(false)
|
||||
const [showExchangeModal, setShowExchangeModal] = useState(false)
|
||||
const [showSignalSourceModal, setShowSignalSourceModal] = useState(false)
|
||||
const [editingModel, setEditingModel] = useState<string | null>(null)
|
||||
const [editingExchange, setEditingExchange] = useState<string | null>(null)
|
||||
const [editingTrader, setEditingTrader] = useState<any>(null)
|
||||
@@ -79,13 +76,6 @@ export function AITradersPage({ onTraderSelect }: AITradersPageProps) {
|
||||
const [allExchanges, setAllExchanges] = useState<Exchange[]>([])
|
||||
const [supportedModels, setSupportedModels] = useState<AIModel[]>([])
|
||||
const [supportedExchanges, setSupportedExchanges] = useState<Exchange[]>([])
|
||||
const [userSignalSource, setUserSignalSource] = useState<{
|
||||
coinPoolUrl: string
|
||||
oiTopUrl: string
|
||||
}>({
|
||||
coinPoolUrl: '',
|
||||
oiTopUrl: '',
|
||||
})
|
||||
|
||||
const { data: traders, mutate: mutateTraders, isLoading: isTradersLoading } = useSWR<TraderInfo[]>(
|
||||
user && token ? 'traders' : null,
|
||||
@@ -127,17 +117,6 @@ export function AITradersPage({ onTraderSelect }: AITradersPageProps) {
|
||||
setAllExchanges(exchangeConfigs)
|
||||
setSupportedModels(supportedModels)
|
||||
setSupportedExchanges(supportedExchanges)
|
||||
|
||||
// 加载用户信号源配置
|
||||
try {
|
||||
const signalSource = await api.getUserSignalSource()
|
||||
setUserSignalSource({
|
||||
coinPoolUrl: signalSource.coin_pool_url || '',
|
||||
oiTopUrl: signalSource.oi_top_url || '',
|
||||
})
|
||||
} catch (error) {
|
||||
console.log('📡 用户信号源配置暂未设置')
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Failed to load configs:', error)
|
||||
}
|
||||
@@ -717,24 +696,6 @@ export function AITradersPage({ onTraderSelect }: AITradersPageProps) {
|
||||
setShowExchangeModal(true)
|
||||
}
|
||||
|
||||
const handleSaveSignalSource = async (
|
||||
coinPoolUrl: string,
|
||||
oiTopUrl: string
|
||||
) => {
|
||||
try {
|
||||
await toast.promise(api.saveUserSignalSource(coinPoolUrl, oiTopUrl), {
|
||||
loading: '正在保存…',
|
||||
success: '保存成功',
|
||||
error: '保存失败',
|
||||
})
|
||||
setUserSignalSource({ coinPoolUrl, oiTopUrl })
|
||||
setShowSignalSourceModal(false)
|
||||
} catch (error) {
|
||||
console.error('Failed to save signal source:', error)
|
||||
toast.error(t('saveSignalSourceFailed', language))
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="space-y-4 md:space-y-6 animate-fade-in">
|
||||
{/* Header */}
|
||||
@@ -798,19 +759,6 @@ export function AITradersPage({ onTraderSelect }: AITradersPageProps) {
|
||||
{t('exchanges', language)}
|
||||
</button>
|
||||
|
||||
<button
|
||||
onClick={() => setShowSignalSourceModal(true)}
|
||||
className="px-3 md:px-4 py-2 rounded text-xs md:text-sm font-semibold transition-all hover:scale-105 flex items-center gap-1 md:gap-2 whitespace-nowrap"
|
||||
style={{
|
||||
background: '#2B3139',
|
||||
color: '#EAECEF',
|
||||
border: '1px solid #474D57',
|
||||
}}
|
||||
>
|
||||
<Radio className="w-3 h-3 md:w-4 md:h-4" />
|
||||
{t('signalSource', language)}
|
||||
</button>
|
||||
|
||||
<button
|
||||
onClick={() => setShowCreateModal(true)}
|
||||
disabled={
|
||||
@@ -834,54 +782,6 @@ export function AITradersPage({ onTraderSelect }: AITradersPageProps) {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 信号源配置警告 */}
|
||||
{traders &&
|
||||
traders.some((t) => t.use_coin_pool || t.use_oi_top) &&
|
||||
!userSignalSource.coinPoolUrl &&
|
||||
!userSignalSource.oiTopUrl && (
|
||||
<div
|
||||
className="rounded-lg px-4 py-3 flex items-start gap-3 animate-slide-in"
|
||||
style={{
|
||||
background: 'rgba(246, 70, 93, 0.1)',
|
||||
border: '1px solid rgba(246, 70, 93, 0.3)',
|
||||
}}
|
||||
>
|
||||
<AlertTriangle
|
||||
size={20}
|
||||
className="flex-shrink-0 mt-0.5"
|
||||
style={{ color: '#F6465D' }}
|
||||
/>
|
||||
<div className="flex-1">
|
||||
<div className="font-semibold mb-1" style={{ color: '#F6465D' }}>
|
||||
⚠️ {t('signalSourceNotConfigured', language)}
|
||||
</div>
|
||||
<div className="text-sm" style={{ color: '#848E9C' }}>
|
||||
<p className="mb-2">
|
||||
{t('signalSourceWarningMessage', language)}
|
||||
</p>
|
||||
<p>
|
||||
<strong>{t('solutions', language)}</strong>
|
||||
</p>
|
||||
<ul className="list-disc list-inside space-y-1 ml-2 mt-1">
|
||||
<li>点击"{t('signalSource', language)}"按钮配置API地址</li>
|
||||
<li>或在交易员配置中禁用"使用币种池"和"使用OI Top"</li>
|
||||
<li>或在交易员配置中设置自定义币种列表</li>
|
||||
</ul>
|
||||
</div>
|
||||
<button
|
||||
onClick={() => setShowSignalSourceModal(true)}
|
||||
className="mt-3 px-3 py-1.5 rounded text-sm font-semibold transition-all hover:scale-105"
|
||||
style={{
|
||||
background: '#F0B90B',
|
||||
color: '#000',
|
||||
}}
|
||||
>
|
||||
{t('configureSignalSourceNow', language)}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Configuration Status */}
|
||||
<div className="grid grid-cols-1 lg:grid-cols-2 gap-4 md:gap-6">
|
||||
{/* AI Models */}
|
||||
@@ -1304,17 +1204,6 @@ export function AITradersPage({ onTraderSelect }: AITradersPageProps) {
|
||||
language={language}
|
||||
/>
|
||||
)}
|
||||
|
||||
{/* Signal Source Configuration Modal */}
|
||||
{showSignalSourceModal && (
|
||||
<SignalSourceModal
|
||||
coinPoolUrl={userSignalSource.coinPoolUrl}
|
||||
oiTopUrl={userSignalSource.oiTopUrl}
|
||||
onSave={handleSaveSignalSource}
|
||||
onClose={() => setShowSignalSourceModal(false)}
|
||||
language={language}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -1364,141 +1253,6 @@ function Tooltip({
|
||||
)
|
||||
}
|
||||
|
||||
// Signal Source Configuration Modal Component
|
||||
function SignalSourceModal({
|
||||
coinPoolUrl,
|
||||
oiTopUrl,
|
||||
onSave,
|
||||
onClose,
|
||||
language,
|
||||
}: {
|
||||
coinPoolUrl: string
|
||||
oiTopUrl: string
|
||||
onSave: (coinPoolUrl: string, oiTopUrl: string) => void
|
||||
onClose: () => void
|
||||
language: Language
|
||||
}) {
|
||||
const [coinPool, setCoinPool] = useState(coinPoolUrl || '')
|
||||
const [oiTop, setOiTop] = useState(oiTopUrl || '')
|
||||
|
||||
const handleSubmit = (e: React.FormEvent) => {
|
||||
e.preventDefault()
|
||||
onSave(coinPool.trim(), oiTop.trim())
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50 p-4 overflow-y-auto">
|
||||
<div
|
||||
className="bg-gray-800 rounded-lg w-full max-w-lg relative my-8"
|
||||
style={{
|
||||
background: '#1E2329',
|
||||
maxHeight: 'calc(100vh - 4rem)',
|
||||
}}
|
||||
>
|
||||
<h3 className="text-xl font-bold mb-4" style={{ color: '#EAECEF' }}>
|
||||
{t('signalSourceConfig', language)}
|
||||
</h3>
|
||||
|
||||
<form onSubmit={handleSubmit} className="px-6 pb-6">
|
||||
<div
|
||||
className="space-y-4 overflow-y-auto"
|
||||
style={{ maxHeight: 'calc(100vh - 16rem)' }}
|
||||
>
|
||||
<div>
|
||||
<label
|
||||
className="block text-sm font-semibold mb-2"
|
||||
style={{ color: '#EAECEF' }}
|
||||
>
|
||||
COIN POOL URL
|
||||
</label>
|
||||
<input
|
||||
type="url"
|
||||
value={coinPool}
|
||||
onChange={(e) => setCoinPool(e.target.value)}
|
||||
placeholder="https://api.example.com/coinpool"
|
||||
className="w-full px-3 py-2 rounded"
|
||||
style={{
|
||||
background: '#0B0E11',
|
||||
border: '1px solid #2B3139',
|
||||
color: '#EAECEF',
|
||||
}}
|
||||
/>
|
||||
<div className="text-xs mt-1" style={{ color: '#848E9C' }}>
|
||||
{t('coinPoolDescription', language)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label
|
||||
className="block text-sm font-semibold mb-2"
|
||||
style={{ color: '#EAECEF' }}
|
||||
>
|
||||
OI TOP URL
|
||||
</label>
|
||||
<input
|
||||
type="url"
|
||||
value={oiTop}
|
||||
onChange={(e) => setOiTop(e.target.value)}
|
||||
placeholder="https://api.example.com/oitop"
|
||||
className="w-full px-3 py-2 rounded"
|
||||
style={{
|
||||
background: '#0B0E11',
|
||||
border: '1px solid #2B3139',
|
||||
color: '#EAECEF',
|
||||
}}
|
||||
/>
|
||||
<div className="text-xs mt-1" style={{ color: '#848E9C' }}>
|
||||
{t('oiTopDescription', language)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
className="p-4 rounded"
|
||||
style={{
|
||||
background: 'rgba(240, 185, 11, 0.1)',
|
||||
border: '1px solid rgba(240, 185, 11, 0.2)',
|
||||
}}
|
||||
>
|
||||
<div
|
||||
className="text-sm font-semibold mb-2"
|
||||
style={{ color: '#F0B90B' }}
|
||||
>
|
||||
ℹ️ {t('information', language)}
|
||||
</div>
|
||||
<div className="text-xs space-y-1" style={{ color: '#848E9C' }}>
|
||||
<div>{t('signalSourceInfo1', language)}</div>
|
||||
<div>{t('signalSourceInfo2', language)}</div>
|
||||
<div>{t('signalSourceInfo3', language)}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
className="flex gap-3 mt-6 pt-4 sticky bottom-0"
|
||||
style={{ background: '#1E2329' }}
|
||||
>
|
||||
<button
|
||||
type="button"
|
||||
onClick={onClose}
|
||||
className="flex-1 px-4 py-2 rounded text-sm font-semibold"
|
||||
style={{ background: '#2B3139', color: '#848E9C' }}
|
||||
>
|
||||
{t('cancel', language)}
|
||||
</button>
|
||||
<button
|
||||
type="submit"
|
||||
className="flex-1 px-4 py-2 rounded text-sm font-semibold"
|
||||
style={{ background: '#F0B90B', color: '#000' }}
|
||||
>
|
||||
{t('save', language)}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
// Model Configuration Modal Component
|
||||
function ModelConfigModal({
|
||||
allModels,
|
||||
|
||||
Reference in New Issue
Block a user