Resolve merge conflicts in AITradersPage.tsx

- Fixed import statement conflict (using 'type Language')
- Merged exchange configuration logic preserving support for multiple exchange types
- Kept comprehensive form handling for Binance, Hyperliquid, Aster, and OKX exchanges
- Updated security warning messages to use proper translation keys
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: tinkle-community <tinklefund@gmail.com>
This commit is contained in:
icy
2025-11-01 19:01:44 +08:00
15 changed files with 753 additions and 381 deletions

View File

@@ -235,9 +235,10 @@ type ExchangeConfig struct {
type UpdateModelConfigRequest struct {
Models map[string]struct {
Enabled bool `json:"enabled"`
APIKey string `json:"api_key"`
CustomAPIURL string `json:"custom_api_url"`
Enabled bool `json:"enabled"`
APIKey string `json:"api_key"`
CustomAPIURL string `json:"custom_api_url"`
CustomModelName string `json:"custom_model_name"`
} `json:"models"`
}
@@ -612,16 +613,23 @@ func (s *Server) handleUpdateModelConfigs(c *gin.Context) {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
// 更新每个模型的配置
for modelID, modelData := range req.Models {
err := s.database.UpdateAIModel(userID, modelID, modelData.Enabled, modelData.APIKey, modelData.CustomAPIURL)
err := s.database.UpdateAIModel(userID, modelID, modelData.Enabled, modelData.APIKey, modelData.CustomAPIURL, modelData.CustomModelName)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": fmt.Sprintf("更新模型 %s 失败: %v", modelID, err)})
return
}
}
// 重新加载该用户的所有交易员,使新配置立即生效
err := s.traderManager.LoadUserTraders(s.database, userID)
if err != nil {
log.Printf("⚠️ 重新加载用户交易员到内存失败: %v", err)
// 这里不返回错误,因为模型配置已经成功更新到数据库
}
log.Printf("✓ AI模型配置已更新: %+v", req.Models)
c.JSON(http.StatusOK, gin.H{"message": "模型配置已更新"})
}
@@ -649,7 +657,7 @@ func (s *Server) handleUpdateExchangeConfigs(c *gin.Context) {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
// 更新每个交易所的配置
for exchangeID, exchangeData := range req.Exchanges {
err := s.database.UpdateExchange(userID, exchangeID, exchangeData.Enabled, exchangeData.APIKey, exchangeData.SecretKey, exchangeData.Testnet, exchangeData.HyperliquidWalletAddr, exchangeData.AsterUser, exchangeData.AsterSigner, exchangeData.AsterPrivateKey)
@@ -658,7 +666,14 @@ func (s *Server) handleUpdateExchangeConfigs(c *gin.Context) {
return
}
}
// 重新加载该用户的所有交易员,使新配置立即生效
err := s.traderManager.LoadUserTraders(s.database, userID)
if err != nil {
log.Printf("⚠️ 重新加载用户交易员到内存失败: %v", err)
// 这里不返回错误,因为交易所配置已经成功更新到数据库
}
log.Printf("✓ 交易所配置已更新: %+v", req.Exchanges)
c.JSON(http.StatusOK, gin.H{"message": "交易所配置已更新"})
}
@@ -725,12 +740,21 @@ func (s *Server) handleTraderList(c *gin.Context) {
}
}
// AIModelID 应该已经是 provider如 "deepseek"),直接使用
// 如果是旧数据格式(如 "admin_deepseek"),提取 provider 部分
aiModelID := trader.AIModelID
// 兼容旧数据:如果包含下划线,提取最后一部分作为 provider
if strings.Contains(aiModelID, "_") {
parts := strings.Split(aiModelID, "_")
aiModelID = parts[len(parts)-1]
}
result = append(result, map[string]interface{}{
"trader_id": trader.ID,
"trader_name": trader.Name,
"ai_model": trader.AIModelID,
"exchange_id": trader.ExchangeID,
"is_running": isRunning,
"trader_id": trader.ID,
"trader_name": trader.Name,
"ai_model": aiModelID,
"exchange_id": trader.ExchangeID,
"is_running": isRunning,
"initial_balance": trader.InitialBalance,
})
}
@@ -763,21 +787,30 @@ func (s *Server) handleGetTraderConfig(c *gin.Context) {
}
}
// AIModelID 应该已经是 provider如 "deepseek"),直接使用
// 如果是旧数据格式(如 "admin_deepseek"),提取 provider 部分
aiModelID := traderConfig.AIModelID
// 兼容旧数据:如果包含下划线,提取最后一部分作为 provider
if strings.Contains(aiModelID, "_") {
parts := strings.Split(aiModelID, "_")
aiModelID = parts[len(parts)-1]
}
result := map[string]interface{}{
"trader_id": traderConfig.ID,
"trader_name": traderConfig.Name,
"ai_model": traderConfig.AIModelID,
"exchange_id": traderConfig.ExchangeID,
"initial_balance": traderConfig.InitialBalance,
"btc_eth_leverage": traderConfig.BTCETHLeverage,
"altcoin_leverage": traderConfig.AltcoinLeverage,
"trading_symbols": traderConfig.TradingSymbols,
"custom_prompt": traderConfig.CustomPrompt,
"trader_id": traderConfig.ID,
"trader_name": traderConfig.Name,
"ai_model": aiModelID,
"exchange_id": traderConfig.ExchangeID,
"initial_balance": traderConfig.InitialBalance,
"btc_eth_leverage": traderConfig.BTCETHLeverage,
"altcoin_leverage": traderConfig.AltcoinLeverage,
"trading_symbols": traderConfig.TradingSymbols,
"custom_prompt": traderConfig.CustomPrompt,
"override_base_prompt": traderConfig.OverrideBasePrompt,
"is_cross_margin": traderConfig.IsCrossMargin,
"use_coin_pool": traderConfig.UseCoinPool,
"use_oi_top": traderConfig.UseOITop,
"is_running": isRunning,
"is_cross_margin": traderConfig.IsCrossMargin,
"use_coin_pool": traderConfig.UseCoinPool,
"use_oi_top": traderConfig.UseOITop,
"is_running": isRunning,
}
c.JSON(http.StatusOK, result)