/** * settings.js — 设置页(系统提示词 + 模板正文 + LLM 参数) * 所有配置持久化到 SQLite,通过 /api/prompts 读写 */ const SettingsPage = { state: { template: 'simple', configs: null, // 从 API 加载的配置(含自定义值) llmParams: null, // LLM 参数 systemPrompt: '', // 系统提示词(编辑框值,空=使用默认) templateText: '', // 模板正文(编辑框值,空=使用默认) saveStatus: '', // 保存状态提示 loading: true, error: null, }, render() { if (this.state.loading) { return `

设置

${UI.spinner(20)}加载配置中...
`; } if (this.state.error) { return `

设置

${UI.errorState(this.state.error, 'SettingsPage.init()')}
`; } const tpl = TEMPLATES.find(t => t.value === this.state.template); const llm = this.state.llmParams || {}; return `

设置

配置系统提示词、问答模板和 LLM 参数,所有设置持久化到数据库。

定义 AI 的角色和基本行为。留空使用默认值。

${TEMPLATES.map(t => ` `).join('')}

自定义模板正文,必须包含 {context}{question} 占位符。留空使用预设模板。

查看预设模板参考(当前: ${tpl?.label || ''})
${this._escapeHtml(PROMPT_DEFAULTS['template_' + this.state.template] || '')}
LLM 参数
${llm.temperature ?? 0.3}

Thinking 开启时,AI 会先思考再回答(可折叠查看)。Max Tokens 是总 token 上限(含 thinking)。

`; }, async init() { await this.loadConfigs(); }, async loadConfigs() { this.state.loading = true; const content = document.getElementById('content'); if (content) content.innerHTML = this.render(); try { const resp = await API.get('/api/prompts'); this.state.configs = resp.data.configs; this.state.llmParams = resp.data.llm_params; // 系统提示词:直接显示数据库值(空则用默认值填充) this.state.systemPrompt = this.state.configs.system_prompt || PROMPT_DEFAULTS.system_prompt; // 当前模板正文:直接显示数据库值(空则用默认值填充) this._loadTemplateText(); this.state.loading = false; this.state.error = null; if (content) content.innerHTML = this.render(); } catch (e) { this.state.loading = false; this.state.error = e.message; if (content) content.innerHTML = this.render(); } }, _loadTemplateText() { const tplKey = `template_${this.state.template}`; this.state.templateText = this.state.configs[tplKey] || PROMPT_DEFAULTS[tplKey]; }, setTemplate(t) { this.state.template = t; if (this.state.configs) this._loadTemplateText(); const content = document.getElementById('content'); content.innerHTML = this.render(); }, // ===== 系统提示词 ===== async saveSystemPrompt(val) { this.state.systemPrompt = val; this._showSaveStatus('保存中...'); try { await API.put('/api/prompts', { system_prompt: val }); this._showSaveStatus('已保存'); } catch (e) { this._showSaveStatus('保存失败'); } }, async resetSystemPrompt() { this.state.systemPrompt = ''; this._showSaveStatus('重置中...'); try { await API.put('/api/prompts', { system_prompt: '' }); const el = document.getElementById('settings-system-prompt'); if (el) el.value = ''; this._showSaveStatus('已恢复默认'); } catch (e) { this._showSaveStatus('重置失败'); } }, // ===== 模板正文 ===== async saveTemplateText(val) { this.state.templateText = val; this._showSaveStatus('保存中...'); try { const body = {}; body[`template_${this.state.template}`] = val; await API.put('/api/prompts', body); this._showSaveStatus('已保存'); } catch (e) { this._showSaveStatus('保存失败'); } }, async resetTemplateText() { this.state.templateText = ''; this._showSaveStatus('重置中...'); try { const body = {}; body[`template_${this.state.template}`] = ''; await API.put('/api/prompts', body); const el = document.getElementById('settings-template-text'); if (el) el.value = ''; this._showSaveStatus('已恢复默认'); } catch (e) { this._showSaveStatus('重置失败'); } }, // ===== LLM 参数 ===== async saveLLMParam(key, value) { this._showSaveStatus('保存中...'); try { const body = {}; body[key] = String(value); await API.put('/api/prompts', body); this._showSaveStatus('已保存'); // 重新加载参数 const resp = await API.get('/api/prompts'); this.state.llmParams = resp.data.llm_params; } catch (e) { this._showSaveStatus('保存失败'); } }, // ===== 工具方法 ===== _showSaveStatus(msg) { this.state.saveStatus = msg; const el = document.getElementById('settings-save-status'); if (el) { el.textContent = msg; el.style.opacity = '1'; setTimeout(() => { el.style.opacity = '0'; }, 2000); } }, _escapeHtml(text) { if (!text) return ''; const div = document.createElement('div'); div.textContent = text; return div.innerHTML; }, };