fix: preserve AI model API key when updating and add default URLs

Backend:
- Fix AIModelStore.Update to preserve existing API key when new key is empty
  (prevents clearing API key when adding a new model)
- Add default OI Top API URL to strategy config

Frontend:
- Add "Fill Default" buttons for Coin Pool, OI Top, and Quant Data URLs
- Pre-configured default URLs for all data sources
- Users can click to auto-fill with working defaults
This commit is contained in:
tinkle-community
2025-12-08 12:58:13 +08:00
parent 9c1a322901
commit 7a6e6f2d92
4 changed files with 83 additions and 20 deletions

View File

@@ -204,16 +204,25 @@ func (s *AIModelStore) firstEnabled(userID string) (*AIModel, error) {
}
// Update updates AI model, creates if not exists
// IMPORTANT: If apiKey is empty string, the existing API key will be preserved (not overwritten)
func (s *AIModelStore) Update(userID, id string, enabled bool, apiKey, customAPIURL, customModelName string) error {
// Try exact ID match first
var existingID string
err := s.db.QueryRow(`SELECT id FROM ai_models WHERE user_id = ? AND id = ? LIMIT 1`, userID, id).Scan(&existingID)
if err == nil {
encryptedAPIKey := s.encrypt(apiKey)
_, err = s.db.Exec(`
UPDATE ai_models SET enabled = ?, api_key = ?, custom_api_url = ?, custom_model_name = ?, updated_at = datetime('now')
WHERE id = ? AND user_id = ?
`, enabled, encryptedAPIKey, customAPIURL, customModelName, existingID, userID)
// If apiKey is empty, preserve the existing API key
if apiKey == "" {
_, err = s.db.Exec(`
UPDATE ai_models SET enabled = ?, custom_api_url = ?, custom_model_name = ?, updated_at = datetime('now')
WHERE id = ? AND user_id = ?
`, enabled, customAPIURL, customModelName, existingID, userID)
} else {
encryptedAPIKey := s.encrypt(apiKey)
_, err = s.db.Exec(`
UPDATE ai_models SET enabled = ?, api_key = ?, custom_api_url = ?, custom_model_name = ?, updated_at = datetime('now')
WHERE id = ? AND user_id = ?
`, enabled, encryptedAPIKey, customAPIURL, customModelName, existingID, userID)
}
return err
}
@@ -222,11 +231,19 @@ func (s *AIModelStore) Update(userID, id string, enabled bool, apiKey, customAPI
err = s.db.QueryRow(`SELECT id FROM ai_models WHERE user_id = ? AND provider = ? LIMIT 1`, userID, provider).Scan(&existingID)
if err == nil {
logger.Warnf("⚠️ Using legacy provider matching to update model: %s -> %s", provider, existingID)
encryptedAPIKey := s.encrypt(apiKey)
_, err = s.db.Exec(`
UPDATE ai_models SET enabled = ?, api_key = ?, custom_api_url = ?, custom_model_name = ?, updated_at = datetime('now')
WHERE id = ? AND user_id = ?
`, enabled, encryptedAPIKey, customAPIURL, customModelName, existingID, userID)
// If apiKey is empty, preserve the existing API key
if apiKey == "" {
_, err = s.db.Exec(`
UPDATE ai_models SET enabled = ?, custom_api_url = ?, custom_model_name = ?, updated_at = datetime('now')
WHERE id = ? AND user_id = ?
`, enabled, customAPIURL, customModelName, existingID, userID)
} else {
encryptedAPIKey := s.encrypt(apiKey)
_, err = s.db.Exec(`
UPDATE ai_models SET enabled = ?, api_key = ?, custom_api_url = ?, custom_model_name = ?, updated_at = datetime('now')
WHERE id = ? AND user_id = ?
`, enabled, encryptedAPIKey, customAPIURL, customModelName, existingID, userID)
}
return err
}

View File

@@ -191,7 +191,8 @@ func GetDefaultStrategyConfig(lang string) StrategyConfig {
CoinPoolLimit: 30,
CoinPoolAPIURL: "http://nofxaios.com:30006/api/ai500/list?auth=cm_568c67eae410d912c54c",
UseOITop: false,
OITopLimit: 0,
OITopLimit: 20,
OITopAPIURL: "http://nofxaios.com:30006/api/oi/top-ranking?limit=20&duration=1h&auth=cm_568c67eae410d912c54c",
},
Indicators: IndicatorConfig{
Klines: KlineConfig{