mirror of
https://github.com/NoFxAiOS/nofx.git
synced 2026-07-07 13:00:59 +08:00
fix: 修复删除模型/交易所时界面卡死问题并增强依赖检查 (#578)
* fix: 修复删除模型/交易所时界面卡死问题并增强依赖检查 ## 问题描述 1. 删除唯一的AI模型或交易所配置时,界面会卡死数秒 2. 删除后配置仍然显示在列表中 3. 可以删除被交易员使用的配置,导致数据不一致 ## 修复内容 ### 后端性能优化 (manager/trader_manager.go) - 将循环内的重复数据库查询移到循环外 - 减少N次重复查询(GetAIModels + GetExchanges)为1次查询 - 大幅减少锁持有时间,从数秒降至毫秒级 ### 前端显示修复 (web/src/components/AITradersPage.tsx) - 过滤显示列表,只显示真正配置过的模型/交易所(有apiKey的) - 删除后重新从后端获取最新数据,确保界面同步 ### 前端依赖检查 (web/src/components/AITradersPage.tsx) - 新增完整的依赖检查,包括停止状态的交易员 - 删除前检查是否有交易员使用该配置 - 显示使用该配置的交易员名称列表 - 阻止删除被使用的配置,保证数据一致性 ### 多语言支持 (web/src/i18n/translations.ts) - 添加依赖检查相关的中英文提示文本 - cannotDeleteModelInUse / cannotDeleteExchangeInUse - tradersUsing / pleaseDeleteTradersFirst ## 测试建议 1. 创建交易员后尝试删除其使用的模型/交易所,应显示警告并阻止删除 2. 删除未使用的模型/交易所,应立即从列表消失且界面不卡死 3. 刷新页面后,已删除的配置不应再出现 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: tinkle-community <tinklefund@gmail.com> * refactor: 重构删除配置函数减少重复代码 ## 重构内容 - 创建通用的 handleDeleteConfig 函数 - 使用配置对象模式处理模型和交易所的删除逻辑 - 消除 handleDeleteModelConfig 和 handleDeleteExchangeConfig 之间的重复代码 ## 重构效果 - 减少代码行数约 40% - 提高代码可维护性和可读性 - 便于未来添加新的配置类型 ## 功能保持不变 - 依赖检查逻辑完全相同 - 删除流程完全相同 - 用户体验完全相同 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: tinkle-community <tinklefund@gmail.com> --------- Co-authored-by: tinkle-community <tinklefund@gmail.com>
This commit is contained in:
@@ -762,7 +762,21 @@ func (tm *TraderManager) LoadUserTraders(database *config.Database, userID strin
|
||||
}
|
||||
}
|
||||
|
||||
// 为每个交易员获取AI模型和交易所配置
|
||||
// 🔧 性能优化:在循环外只查询一次AI模型和交易所配置
|
||||
// 避免在循环中重复查询相同的数据,减少数据库压力和锁持有时间
|
||||
aiModels, err := database.GetAIModels(userID)
|
||||
if err != nil {
|
||||
log.Printf("⚠️ 获取用户 %s 的AI模型配置失败: %v", userID, err)
|
||||
return fmt.Errorf("获取AI模型配置失败: %w", err)
|
||||
}
|
||||
|
||||
exchanges, err := database.GetExchanges(userID)
|
||||
if err != nil {
|
||||
log.Printf("⚠️ 获取用户 %s 的交易所配置失败: %v", userID, err)
|
||||
return fmt.Errorf("获取交易所配置失败: %w", err)
|
||||
}
|
||||
|
||||
// 为每个交易员加载配置
|
||||
for _, traderCfg := range traders {
|
||||
// 检查是否已经加载过这个交易员
|
||||
if _, exists := tm.traders[traderCfg.ID]; exists {
|
||||
@@ -770,12 +784,7 @@ func (tm *TraderManager) LoadUserTraders(database *config.Database, userID strin
|
||||
continue
|
||||
}
|
||||
|
||||
// 获取AI模型配置(使用该用户的配置)
|
||||
aiModels, err := database.GetAIModels(userID)
|
||||
if err != nil {
|
||||
log.Printf("⚠️ 获取用户 %s 的AI模型配置失败: %v", userID, err)
|
||||
continue
|
||||
}
|
||||
// 从已查询的列表中查找AI模型配置
|
||||
|
||||
var aiModelCfg *config.AIModelConfig
|
||||
// 优先精确匹配 model.ID(新版逻辑)
|
||||
@@ -806,13 +815,7 @@ func (tm *TraderManager) LoadUserTraders(database *config.Database, userID strin
|
||||
continue
|
||||
}
|
||||
|
||||
// 获取交易所配置(使用该用户的配置)
|
||||
exchanges, err := database.GetExchanges(userID)
|
||||
if err != nil {
|
||||
log.Printf("⚠️ 获取用户 %s 的交易所配置失败: %v", userID, err)
|
||||
continue
|
||||
}
|
||||
|
||||
// 从已查询的列表中查找交易所配置
|
||||
var exchangeCfg *config.ExchangeConfig
|
||||
for _, exchange := range exchanges {
|
||||
if exchange.ID == traderCfg.ExchangeID {
|
||||
|
||||
Reference in New Issue
Block a user