|
class APIPanel { |
|
constructor() { |
|
|
|
if (window.apiPanelInstance) { |
|
console.warn('APIPanel: Instance already exists, returning existing one.'); |
|
return window.apiPanelInstance; |
|
} |
|
console.log('APIPanel: Creating new instance.'); |
|
|
|
|
|
this.providerSelect = document.getElementById('api-provider'); |
|
this.modelSelect = document.getElementById('api-model'); |
|
this.apiKeyInput = document.getElementById('api-key'); |
|
|
|
this.submitButton = document.querySelector('#api-panel .api-submit-btn'); |
|
|
|
|
|
if (!this.providerSelect || !this.modelSelect || !this.apiKeyInput || !this.submitButton) { |
|
console.error("APIPanel: One or more required DOM elements not found during construction."); |
|
} |
|
|
|
this.initialized = false; |
|
|
|
this.handleSubmit = this.handleSubmit.bind(this); |
|
this.updateModelOptions = this.updateModelOptions.bind(this); |
|
if (this.providerSelect && this.modelSelect) { |
|
this.updateModelOptions(); |
|
} |
|
|
|
window.apiPanelInstance = this; |
|
console.log('APIPanel: New instance created.'); |
|
} |
|
|
|
init() { |
|
if (this.initialized) { |
|
console.log('APIPanel: Listeners already initialized, skipping.'); |
|
return; |
|
} |
|
|
|
if (!this.providerSelect || !this.modelSelect || !this.apiKeyInput || !this.submitButton) { |
|
console.error("APIPanel: Cannot init listeners, required DOM elements missing."); |
|
return; |
|
} |
|
|
|
console.log('APIPanel: Initializing event listeners.'); |
|
this.setupEventListeners(); |
|
this.initialized = true; |
|
console.log('APIPanel: Event listeners initialized successfully.'); |
|
} |
|
|
|
setupEventListeners() { |
|
|
|
if (this.submitButton) { |
|
this.submitButton.removeEventListener('click', this.handleSubmit); |
|
|
|
this.submitButton.addEventListener('click', this.handleSubmit); |
|
console.log('APIPanel: Submit button listener attached.'); |
|
} |
|
|
|
|
|
if (this.providerSelect) { |
|
this.providerSelect.removeEventListener('change', this.updateModelOptions); |
|
this.providerSelect.addEventListener('change', this.updateModelOptions); |
|
console.log('APIPanel: Provider select listener attached.'); |
|
} |
|
} |
|
|
|
updateModelOptions() { |
|
if (!this.providerSelect || !this.modelSelect) { |
|
console.warn('APIPanel: DOM elements missing for updateModelOptions.'); |
|
return; |
|
} |
|
|
|
const provider = this.providerSelect.value; |
|
const models = { |
|
openai: ['gpt-3.5-turbo', 'gpt-4'], |
|
anthropic: ['claude-3-opus', 'claude-3-sonnet'], |
|
alibaba: ['qwen-turbo', 'qwen-max'], |
|
openrouter: ['gpt-4o-mini'] |
|
}; |
|
|
|
const currentModelValue = this.modelSelect.value; |
|
this.modelSelect.innerHTML = ''; |
|
|
|
if (models[provider] && models[provider].length > 0) { |
|
models[provider].forEach(model => { |
|
const option = document.createElement('option'); |
|
option.value = model; |
|
option.textContent = model; |
|
this.modelSelect.appendChild(option); |
|
}); |
|
|
|
if (models[provider].includes(currentModelValue)) { |
|
this.modelSelect.value = currentModelValue; |
|
} |
|
} else { |
|
|
|
const option = document.createElement('option'); |
|
option.textContent = 'No models available'; |
|
option.disabled = true; |
|
this.modelSelect.appendChild(option); |
|
} |
|
} |
|
|
|
handleSubmit(event) { |
|
|
|
event.preventDefault(); |
|
event.stopPropagation(); |
|
|
|
if (APIPanel.isSubmitting) { |
|
console.log('APIPanel: Submission in progress, ignoring duplicate click.'); |
|
return; |
|
} |
|
|
|
|
|
if (!this.providerSelect || !this.modelSelect || !this.apiKeyInput || !this.submitButton) { |
|
console.error("APIPanel: Cannot handle submit, critical elements missing."); |
|
alert(window.i18n?.get('internalError') ?? '内部错误,无法提交。'); |
|
return; |
|
} |
|
|
|
|
|
|
|
APIPanel.isSubmitting = true; |
|
this.submitButton.disabled = true; |
|
|
|
const resetButton = () => { |
|
APIPanel.isSubmitting = false; |
|
if (this.submitButton) { |
|
this.submitButton.disabled = false; |
|
} |
|
console.log('APIPanel: Submit button re-enabled.'); |
|
}; |
|
|
|
|
|
|
|
const provider = this.providerSelect.value; |
|
const model = this.modelSelect.value; |
|
const apiKey = this.apiKeyInput.value.trim(); |
|
|
|
|
|
if (!provider || !model || !apiKey) { |
|
const message = window.i18n?.get('fillAllFields') ?? '请填写所有字段!'; |
|
alert(message); |
|
resetButton(); |
|
return; |
|
} |
|
|
|
const requestData = { |
|
provider: provider, |
|
model: model, |
|
apiKey: apiKey |
|
}; |
|
|
|
console.log('APIPanel: Sending config data (key hidden):', { provider, model, apiKey: '***' }); |
|
|
|
|
|
fetch('/api/save-config', { |
|
method: 'POST', |
|
headers: { 'Content-Type': 'application/json' }, |
|
body: JSON.stringify(requestData) |
|
}) |
|
.then(response => { |
|
if (response.ok) { |
|
const message = window.i18n?.get('configSubmitted') ?? '配置已提交到服务器!'; |
|
alert(message); |
|
} else { |
|
|
|
response.text().then(text => { |
|
console.error('APIPanel: Submit failed.', response.status, text); |
|
const message = (window.i18n?.get('submitFailed') ?? '提交失败,请检查服务器状态。') + ` (Status: ${response.status})`; |
|
alert(message); |
|
}).catch(() => { |
|
console.error('APIPanel: Submit failed.', response.status); |
|
const message = (window.i18n?.get('submitFailed') ?? '提交失败,请检查服务器状态。') + ` (Status: ${response.status})`; |
|
alert(message); |
|
}); |
|
} |
|
}) |
|
.catch(error => { |
|
console.error('APIPanel: HTTP request failed:', error); |
|
const message = window.i18n?.get('networkError') ?? '提交失败,请检查网络连接。'; |
|
alert(message); |
|
}) |
|
.finally(() => { |
|
|
|
resetButton(); |
|
}); |
|
} |
|
} |
|
|
|
APIPanel.isSubmitting = false; |
|
window.APIPanel = APIPanel; |
|
|