From 04419b47e6cf8685742e1e55d4ba27481dee0b7d Mon Sep 17 00:00:00 2001 From: ZhouYongyou <128128010+zhouyongyou@users.noreply.github.com> Date: Sun, 2 Nov 2025 04:51:30 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E7=BC=96=E8=BE=91?= =?UTF-8?q?=E4=BA=A4=E6=98=93=E5=91=98=E6=97=B6=E3=80=8CAI=E6=A8=A1?= =?UTF-8?q?=E5=9E=8B=E9=85=8D=E7=BD=AE=E4=B8=8D=E5=AD=98=E5=9C=A8=E6=88=96?= =?UTF-8?q?=E6=9C=AA=E5=90=AF=E7=94=A8=E3=80=8D=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 问题: - 编辑交易员并修改系统提示词模板时,保存失败 - 错误提示:AI模型配置不存在或未启用 根本原因: 1. 后端 API 返回的 ai_model 被截断(admin_deepseek → deepseek) 2. 前端验证时找不到对应的模型 ID(enabledModels 存的是完整 ID) 3. API 缺少 system_prompt_template 字段 修复内容: - api/server.go: 移除 AI model ID 截断逻辑,返回完整 ID - api/server.go: 在 handleGetTraderConfig 中添加 system_prompt_template 字段 - web/src/types.ts: TraderConfigData 接口添加 system_prompt_template 字段 - web/src/components/AITradersPage.tsx: 添加 fallback 机制和详细日志 测试: - 编辑交易员 → 修改系统提示词模板 → 保存成功 - Console 输出验证日志,不再报错 --- api/server.go | 40 +++++++++++-------------- web/src/components/AITradersPage.tsx | 44 ++++++++++++++++++++++------ web/src/types.ts | 1 + 3 files changed, 53 insertions(+), 32 deletions(-) diff --git a/api/server.go b/api/server.go index ad16470a..a21dbb46 100644 --- a/api/server.go +++ b/api/server.go @@ -801,30 +801,24 @@ 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] - } - + // 返回完整的 AIModelID(如 "admin_deepseek"),不要截断 + // 前端需要完整 ID 来验证模型是否存在 result := map[string]interface{}{ - "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, + "trader_id": traderConfig.ID, + "trader_name": traderConfig.Name, + "ai_model": traderConfig.AIModelID, // 使用完整 ID + "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, + "system_prompt_template": traderConfig.SystemPromptTemplate, // 添加此字段 + "is_cross_margin": traderConfig.IsCrossMargin, + "use_coin_pool": traderConfig.UseCoinPool, + "use_oi_top": traderConfig.UseOITop, + "is_running": isRunning, } c.JSON(http.StatusOK, result) diff --git a/web/src/components/AITradersPage.tsx b/web/src/components/AITradersPage.tsx index d5937fb0..4f609a59 100644 --- a/web/src/components/AITradersPage.tsx +++ b/web/src/components/AITradersPage.tsx @@ -165,34 +165,60 @@ export function AITradersPage({ onTraderSelect }: AITradersPageProps) { if (!editingTrader) return; try { - const model = enabledModels?.find(m => m.id === data.ai_model_id); - const exchange = enabledExchanges?.find(e => e.id === data.exchange_id); - - if (!model) { - alert(t('modelConfigNotExist', language)); + // 1. 确保 ai_model_id 有值(使用 fallback) + const ai_model_id = data.ai_model_id || editingTrader.ai_model; + if (!ai_model_id) { + console.error('缺少 AI 模型配置', { data, editingTrader }); + alert('错误:缺少 AI 模型配置'); return; } + // 2. 确保 exchange_id 有值(使用 fallback) + const exchange_id = data.exchange_id || editingTrader.exchange_id; + if (!exchange_id) { + console.error('缺少交易所配置', { data, editingTrader }); + alert('错误:缺少交易所配置'); + return; + } + + // 3. 验证模型存在 + console.log('验证 AI 模型:', { ai_model_id, enabledModels: enabledModels?.map(m => m.id) }); + const model = enabledModels?.find(m => m.id === ai_model_id); + if (!model) { + console.error('找不到模型:', { + ai_model_id, + availableModels: enabledModels?.map(m => ({ id: m.id, name: m.name })) + }); + alert(`AI模型配置不存在或未启用: ${ai_model_id}\n\n可用的模型: ${enabledModels?.map(m => m.name).join(', ')}`); + return; + } + + // 4. 验证交易所存在 + const exchange = enabledExchanges?.find(e => e.id === exchange_id); if (!exchange) { + console.error('找不到交易所:', { exchange_id }); alert(t('exchangeConfigNotExist', language)); return; } - + + // 5. 构建请求(使用修正后的值) const request = { name: data.name, - ai_model_id: data.ai_model_id, - exchange_id: data.exchange_id, + ai_model_id: ai_model_id, // 使用修正后的值 + exchange_id: exchange_id, // 使用修正后的值 initial_balance: data.initial_balance, btc_eth_leverage: data.btc_eth_leverage, altcoin_leverage: data.altcoin_leverage, trading_symbols: data.trading_symbols, custom_prompt: data.custom_prompt, override_base_prompt: data.override_base_prompt, + system_prompt_template: data.system_prompt_template, // 添加此字段 is_cross_margin: data.is_cross_margin, use_coin_pool: data.use_coin_pool, use_oi_top: data.use_oi_top }; - + + console.log('保存交易员配置:', request); await api.updateTrader(editingTrader.trader_id, request); setShowEditModal(false); setEditingTrader(null); diff --git a/web/src/types.ts b/web/src/types.ts index e4ba1199..bcda735b 100644 --- a/web/src/types.ts +++ b/web/src/types.ts @@ -194,6 +194,7 @@ export interface TraderConfigData { trading_symbols: string; custom_prompt: string; override_base_prompt: boolean; + system_prompt_template: string; // 添加系统提示词模板字段 is_cross_margin: boolean; use_coin_pool: boolean; use_oi_top: boolean;