/** * 系统配置管理模块 JavaScript * 提供系统配置的查看和编辑功能 */ (function() { 'use strict'; // 引用全局的翻译函数 // 翻译函数由 i18n-helper.js 提供 // 模块私有状态 let container = null; let registrationConfig = null; let llmConfig = { api_key: null, base_url: null, model_name: null }; // 系统配置管理模块 const SystemConfigManagement = { init: function(containerElement) { container = containerElement; this.initEventListeners(); // 等待 i18next 初始化完成后再加载数据 const loadData = () => { this.loadRegistrationSettings(); this.loadLlmSettings(); }; // 检查 i18next 是否已可用(通过测试一个翻译键) const checkI18nReady = () => { if (window.i18next && window.i18next.t) { try { const test = window.i18next.t('common.loading'); // 如果翻译键正常工作(返回值不是键名本身),开始加载数据 if (test && test !== 'common.loading') { loadData(); return true; } } catch (e) { // i18next 还没准备好 } } return false; }; // 立即检查一次 if (checkI18nReady()) { return; } // 等待 i18next 初始化 const checkI18n = setInterval(() => { if (checkI18nReady()) { clearInterval(checkI18n); } }, 100); // 超时保护(10秒后强制加载) setTimeout(() => { clearInterval(checkI18n); console.warn('i18next initialization timeout or check failed, loading data anyway'); loadData(); }, 10000); }, initEventListeners: function() { // 编辑注册设置按钮 const editRegistrationBtn = container.querySelector('#editRegistrationBtn'); if (editRegistrationBtn) { editRegistrationBtn.addEventListener('click', () => { this.showEditRegistrationModal(); }); } // 编辑 LLM 配置按钮 const editLlmConfigBtn = container.querySelector('#editLlmConfigBtn'); if (editLlmConfigBtn) { editLlmConfigBtn.addEventListener('click', () => { this.showEditLlmConfigModal(); }); } // 测试 LLM 连接按钮 const testLlmBtn = container.querySelector('#testLlmConnectionBtn'); if (testLlmBtn) { testLlmBtn.addEventListener('click', () => { this.testLlmConnection(); }); } }, loadRegistrationSettings: async function() { try { registrationConfig = await apiGet('/system-configs/allow_registration'); this.renderRegistrationValue(); } catch (error) { // 如果配置不存在,创建默认配置 if (error.status === 404) { try { registrationConfig = await apiPut('/system-configs/allow_registration', { value: 'true', description: t('system.allowRegistrationDefaultDesc') }); this.renderRegistrationValue(); } catch (createError) { console.error('创建默认注册设置失败:', createError); showError(t('system.createDefaultFailed') + ' ' + (createError.message || t('messages.unknownError'))); } } else { console.error('加载注册设置失败:', error); showError(t('system.loadRegistrationFailed') + ' ' + (error.message || t('messages.unknownError'))); } // 显示默认值 const valueDisplay = container.querySelector('#registrationValueDisplay'); if (valueDisplay && !registrationConfig) { valueDisplay.innerHTML = `${t('common.failed')}`; } } }, renderRegistrationValue: function() { const valueDisplay = container.querySelector('#registrationValueDisplay'); if (!valueDisplay || !registrationConfig) return; const value = registrationConfig.value || 'true'; const isEnabled = value.toLowerCase() === 'true' || value === '1' || value.toLowerCase() === 'yes'; valueDisplay.innerHTML = ` ${isEnabled ? t('system.configEnabled') : t('system.configDisabled')} (${escapeHtml(value)}) `; }, showEditRegistrationModal: function() { const currentValue = registrationConfig ? registrationConfig.value : 'true'; const isEnabled = currentValue.toLowerCase() === 'true' || currentValue === '1' || currentValue.toLowerCase() === 'yes'; const title = t('system.editRegistrationTitle'); const content = `
`; openModal(title, content, async () => { await this.saveRegistrationSettings(); }); }, saveRegistrationSettings: async function() { const value = document.getElementById('registrationValue').value; const description = document.getElementById('registrationDescription').value.trim(); if (!value) { showError(t('system.selectRegistrationValue')); return; } try { const updateData = { value: value, description: description || t('system.allowRegistrationDefaultDesc') }; registrationConfig = await apiPut('/system-configs/allow_registration', updateData); showSuccess(t('system.registrationUpdateSuccess')); closeModal(); this.renderRegistrationValue(); } catch (error) { console.error('保存注册设置失败:', error); showError(t('system.registrationSaveFailed') + ' ' + (error.message || t('messages.unknownError'))); } }, // ==================== LLM 配置管理 ==================== const LLM_DEFAULTS = { base_url: 'http://43.159.131.233:3001/v1', model_name: 'gpt-5.1', }; loadLlmSettings: async function() { const keys = [ { field: 'api_key', key: 'llm_api_key', displayId: 'llmApiKeyDisplay' }, { field: 'base_url', key: 'llm_base_url', displayId: 'llmBaseUrlDisplay' }, { field: 'model_name', key: 'llm_model_name', displayId: 'llmModelNameDisplay' } ]; for (const { field, key, displayId } of keys) { try { const config = await apiGet(`/system-configs/${key}`); llmConfig[field] = config.value; } catch (error) { if (error.status === 404) { llmConfig[field] = LLM_DEFAULTS[field] || null; } else { console.error(`加载 LLM 配置 ${key} 失败:`, error); } } this.renderLlmConfigValue(field, displayId); } }, renderLlmConfigValue: function(field, displayId) { const valueDisplay = container.querySelector(`#${displayId}`); if (!valueDisplay) return; const value = llmConfig[field]; if (!value) { valueDisplay.innerHTML = `${t('system.llmConfigNotSet')}`; } else if (field === 'api_key') { // API Key 脱敏显示 const masked = value.length > 8 ? value.substring(0, 4) + '****' + value.substring(value.length - 4) : '****'; valueDisplay.innerHTML = `${escapeHtml(masked)}`; } else { valueDisplay.innerHTML = `${escapeHtml(value)}`; } }, showEditLlmConfigModal: function() { const title = t('system.editLlmConfigTitle'); const content = ` `; openModal(title, content, async () => { await this.saveLlmSettings(); }); }, saveLlmSettings: async function() { const apiKey = document.getElementById('llmApiKeyInput').value.trim(); const baseUrl = document.getElementById('llmBaseUrlInput').value.trim(); const modelName = document.getElementById('llmModelNameInput').value.trim(); const configs = [ { field: 'api_key', key: 'llm_api_key', value: apiKey, description: 'LLM API Key' }, { field: 'base_url', key: 'llm_base_url', value: baseUrl, description: 'LLM API Base URL' }, { field: 'model_name', key: 'llm_model_name', value: modelName, description: 'LLM Model Name' } ]; try { for (const config of configs) { if (config.value) { await apiPut(`/system-configs/${config.key}`, { value: config.value, description: config.description }); llmConfig[config.field] = config.value; } } showSuccess(t('system.llmConfigUpdateSuccess')); closeModal(); // 刷新显示 this.renderLlmConfigValue('api_key', 'llmApiKeyDisplay'); this.renderLlmConfigValue('base_url', 'llmBaseUrlDisplay'); this.renderLlmConfigValue('model_name', 'llmModelNameDisplay'); } catch (error) { console.error('保存 LLM 配置失败:', error); showError(t('system.llmConfigSaveFailed') + ' ' + (error.message || t('messages.unknownError'))); } }, testLlmConnection: async function() { const btn = container.querySelector('#testLlmConnectionBtn'); const resultSpan = container.querySelector('#llmTestResult'); if (!btn || !resultSpan) return; btn.disabled = true; btn.querySelector('span').textContent = t('system.testingConnection') || '测试中...'; resultSpan.textContent = ''; resultSpan.style.color = '#666'; try { const currentLang = (window.i18next && window.i18next.language) || 'zh'; const lang = currentLang.startsWith('zh') ? 'zh' : 'en'; const res = await apiPost(`/analysis/test-llm-connection?lang=${lang}`); if (res.success) { resultSpan.style.color = '#2e7d32'; resultSpan.textContent = '✓ ' + res.message; } else { resultSpan.style.color = '#c62828'; resultSpan.textContent = '✗ ' + res.message; } } catch (error) { resultSpan.style.color = '#c62828'; resultSpan.textContent = '✗ ' + t('system.testConnectionFailed') + ': ' + (error.message || t('messages.unknownError')); } finally { btn.disabled = false; btn.querySelector('span').textContent = t('system.testConnection') || '测试连接'; } } }; // 导出到全局 window.SystemConfigManagement = SystemConfigManagement; })();