document.addEventListener('DOMContentLoaded', async () => { try { const response = await fetch('/api/config/defaults'); const result = await response.json(); if (result.success && result.config) { const config = result.config; if (config.brain) { if (config.brain.username) { document.getElementById('brainUsername').value = config.brain.username; } if (config.brain.password) { document.getElementById('brainPassword').value = config.brain.password; } } if (config.llm) { if (config.llm.api_key) { document.getElementById('llmApiKey').value = config.llm.api_key; } if (config.llm.base_url) { document.getElementById('llmBaseUrl').value = config.llm.base_url; } if (config.llm.model) { document.getElementById('llmModel').value = config.llm.model; } } if (config.transformer) { if (config.transformer.top_n_datafield) { document.getElementById('topNDatafield').value = config.transformer.top_n_datafield; } if (config.transformer.data_type) { document.getElementById('dataType').value = config.transformer.data_type; } } } } catch (error) { console.error('加载默认配置失败:', error); } }); const form = document.getElementById('transformerForm'); const submitBtn = document.getElementById('submitBtn'); const downloadBtn = document.getElementById('downloadBtn'); const loginAndFetchBtn = document.getElementById('loginAndFetchBtn'); const testLLMBtn = document.getElementById('testLLMBtn'); const regionSelect = document.getElementById('region'); const delaySelect = document.getElementById('delay'); const universeSelect = document.getElementById('universe'); const dataTypeSelect = document.getElementById('dataType'); const categoryButtons = document.getElementById('category-buttons'); let optionsData = {}; dataTypeSelect.addEventListener('change', function() { if (this.value === 'VECTOR') { if (!confirm("请确保您输入的原型Alpha中正确地使用了vector operator,否则极容易造成数据类型错误!")) { this.value = 'MATRIX'; } } }); loginAndFetchBtn.addEventListener('click', async () => { const username = document.getElementById('brainUsername').value.trim(); const password = document.getElementById('brainPassword').value; if (!username || !password) { alert('请先填写BRAIN用户名和密码'); return; } loginAndFetchBtn.disabled = true; loginAndFetchBtn.textContent = '正在登录...'; try { const response = await fetch('/api/transformer/login-and-fetch-options', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ username, password }) }); const result = await response.json(); if (result.success) { optionsData = result.options; populateRegionSelect(); regionSelect.disabled = false; if (result.categories) { populateCategoryButtons(result.categories); } loginAndFetchBtn.textContent = '登录成功'; } else { alert('登录失败: ' + result.error); loginAndFetchBtn.disabled = false; loginAndFetchBtn.textContent = '登录BRAIN并获取选项'; } } catch (error) { alert('登录出错: ' + error.message); loginAndFetchBtn.disabled = false; loginAndFetchBtn.textContent = '登录BRAIN并获取选项'; } }); testLLMBtn.addEventListener('click', async () => { const apiKey = document.getElementById('llmApiKey').value.trim(); const baseUrl = document.getElementById('llmBaseUrl').value.trim(); const model = document.getElementById('llmModel').value.trim(); if (!apiKey || !baseUrl || !model) { alert('请先填写完整的 LLM 配置'); return; } testLLMBtn.disabled = true; testLLMBtn.textContent = '测试中...'; testLLMBtn.classList.remove('btn-success', 'btn-error'); try { const response = await fetch('/api/test-llm', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ llm_api_key: apiKey, llm_base_url: baseUrl, llm_model: model }) }); const result = await response.json(); if (result.success) { testLLMBtn.textContent = '连接成功'; testLLMBtn.classList.add('btn-success'); } else { testLLMBtn.textContent = '连接失败'; testLLMBtn.classList.add('btn-error'); } } catch (error) { testLLMBtn.textContent = '连接失败'; testLLMBtn.classList.add('btn-error'); } finally { testLLMBtn.disabled = false; } }); function populateRegionSelect() { while (regionSelect.options.length > 1) { regionSelect.remove(1); } const regions = Object.keys(optionsData); regions.forEach(region => { const option = document.createElement('option'); option.value = region; option.textContent = region; regionSelect.appendChild(option); }); } function populateCategoryButtons(categories) { categories.forEach(category => { const btn = document.createElement('button'); btn.type = 'button'; btn.dataset.value = category.id || category; btn.textContent = category.name || category; btn.onclick = function() { toggleCategory(this); }; btn.className = 'btn'; btn.style.cssText = 'padding: 4px 12px; font-size: 11px;'; categoryButtons.appendChild(btn); }); } function toggleCategory(btn) { const allBtn = document.getElementById('cat-all'); const isAllBtn = (btn === allBtn); if (isAllBtn) { allBtn.style.backgroundColor = '#000080'; allBtn.style.color = 'white'; const otherBtns = categoryButtons.querySelectorAll('button:not(#cat-all)'); otherBtns.forEach(b => { b.style.backgroundColor = '#c0c0c0'; b.style.color = 'black'; }); } else { if (btn.style.backgroundColor === 'rgb(0, 0, 128)') { btn.style.backgroundColor = '#c0c0c0'; btn.style.color = 'black'; } else { btn.style.backgroundColor = '#000080'; btn.style.color = 'white'; } const anySelected = categoryButtons.querySelectorAll('button:not(#cat-all)'); let hasSelected = false; anySelected.forEach(b => { if (b.style.backgroundColor === 'rgb(0, 0, 128)') { hasSelected = true; } }); if (hasSelected) { allBtn.style.backgroundColor = '#c0c0c0'; allBtn.style.color = 'black'; } else { allBtn.style.backgroundColor = '#000080'; allBtn.style.color = 'white'; } } } regionSelect.addEventListener('change', () => { const selectedRegion = regionSelect.value; delaySelect.innerHTML = ''; universeSelect.innerHTML = ''; delaySelect.disabled = true; universeSelect.disabled = true; if (selectedRegion && optionsData[selectedRegion]) { const delays = Object.keys(optionsData[selectedRegion]); delays.forEach(delay => { const option = document.createElement('option'); option.value = delay; option.textContent = delay; delaySelect.appendChild(option); }); delaySelect.disabled = false; } }); delaySelect.addEventListener('change', () => { const selectedRegion = regionSelect.value; const selectedDelay = delaySelect.value; universeSelect.innerHTML = ''; universeSelect.disabled = true; if (selectedRegion && selectedDelay && optionsData[selectedRegion][selectedDelay]) { const universes = optionsData[selectedRegion][selectedDelay]; universes.forEach(universe => { const option = document.createElement('option'); option.value = universe; option.textContent = universe; universeSelect.appendChild(option); }); universeSelect.disabled = false; } }); form.addEventListener('submit', async (e) => { e.preventDefault(); const formData = { alpha_id: document.getElementById('alphaId').value.trim(), llm_api_key: document.getElementById('llmApiKey').value.trim(), llm_base_url: document.getElementById('llmBaseUrl').value.trim(), llm_model: document.getElementById('llmModel').value.trim(), brain_username: document.getElementById('brainUsername').value.trim(), brain_password: document.getElementById('brainPassword').value.trim(), top_n_datafield: parseInt(document.getElementById('topNDatafield').value) || 50, max_retries: parseInt(document.getElementById('maxRetries').value) || 20, data_type: document.getElementById('dataType').value || 'MATRIX' }; const region = document.getElementById('region').value; const delay = document.getElementById('delay').value; const universe = document.getElementById('universe').value; if (region) formData.user_region = region; if (delay) formData.user_delay = parseInt(delay); if (universe) formData.user_universe = universe; const allBtn = document.getElementById('cat-all'); let selectedCategories = []; if (allBtn.style.backgroundColor !== 'rgb(0, 0, 128)') { const categoryBtns = categoryButtons.querySelectorAll('button:not(#cat-all)'); categoryBtns.forEach(btn => { if (btn.style.backgroundColor === 'rgb(0, 0, 128)') { selectedCategories.push(btn.dataset.value); } }); if (selectedCategories.length > 0) { formData.user_category = selectedCategories; } } submitBtn.disabled = true; submitBtn.textContent = '处理中...'; try { const response = await fetch('/api/generate', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(formData) }); const result = await response.json(); if (result.success) { const successCount = result.expressions_success ? result.expressions_success.length : 0; const candidateCount = result.candidates ? result.candidates.length : 0; const errorCount = result.expressions_error ? result.expressions_error.length : 0; // 显示下载按钮 downloadBtn.style.display = 'block'; downloadBtn.textContent = '下载结果 (' + successCount + '成功, ' + candidateCount + '候选)'; downloadBtn.onclick = function() { const alphaId = document.getElementById('alphaId').value.trim(); window.location.href = '/api/download/' + alphaId; }; } else { downloadBtn.style.display = 'none'; downloadBtn.textContent = '下载结果 (ZIP)'; } } catch (error) { downloadBtn.style.display = 'none'; downloadBtn.textContent = '下载结果 (ZIP)'; } finally { submitBtn.disabled = false; submitBtn.textContent = '生成变种'; } });