up
This commit is contained in:
+69
-2
@@ -144,6 +144,15 @@
|
||||
padding: 3px 10px;
|
||||
border-radius: 20px;
|
||||
}
|
||||
header .model-select {
|
||||
max-width: 260px;
|
||||
cursor: pointer;
|
||||
outline: none;
|
||||
}
|
||||
header .model-select:disabled {
|
||||
opacity: .65;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
.header-actions {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
@@ -466,7 +475,9 @@
|
||||
{{ .Title }}
|
||||
</div>
|
||||
<div class="header-actions">
|
||||
<span class="model-badge">{{ .Model }}</span>
|
||||
<select id="modelSelect" class="model-badge model-select" title="切换 OpenAI 配置">
|
||||
<option value="{{ .OpenAIName }}">{{ .Model }}</option>
|
||||
</select>
|
||||
<button id="btnSearch" title="开启后,本轮提问会先联网搜索">联网搜索:关</button>
|
||||
<button id="btnPreset" title="设置预先提示词">预设</button>
|
||||
<button id="btnClear" title="开始新对话">新对话</button>
|
||||
@@ -531,6 +542,8 @@ let history = []; // {role, content, image_url?}
|
||||
let currentConvId = null;
|
||||
let pending = false;
|
||||
let webSearchEnabled = false;
|
||||
let openAIProfiles = [];
|
||||
let activeOpenAIName = '{{ .OpenAIName }}';
|
||||
let imageB64 = ''; // 当前待发送图片的 data URI
|
||||
let imageName = '';
|
||||
|
||||
@@ -542,6 +555,7 @@ const btnSend = document.getElementById('btnSend');
|
||||
const btnClear = document.getElementById('btnClear');
|
||||
const btnPreset = document.getElementById('btnPreset');
|
||||
const btnSearch = document.getElementById('btnSearch');
|
||||
const modelSelect = document.getElementById('modelSelect');
|
||||
const btnNewChat = document.getElementById('btnNewChat');
|
||||
const convList = document.getElementById('convList');
|
||||
const presetModal = document.getElementById('presetModal');
|
||||
@@ -615,6 +629,7 @@ function setInputDisabled(disabled) {
|
||||
inputBox.disabled = disabled;
|
||||
fileInput.disabled = disabled;
|
||||
btnSearch.disabled = disabled;
|
||||
modelSelect.disabled = disabled || openAIProfiles.length <= 1;
|
||||
}
|
||||
|
||||
function updateSearchButton() {
|
||||
@@ -622,6 +637,27 @@ function updateSearchButton() {
|
||||
btnSearch.textContent = webSearchEnabled ? '联网搜索:开' : '联网搜索:关';
|
||||
}
|
||||
|
||||
async function loadOpenAIProfiles() {
|
||||
const res = await fetch('/api/openai');
|
||||
if (!res.ok) {
|
||||
const err = await res.json().catch(() => ({ error: '加载模型配置失败' }));
|
||||
throw new Error(err.error || '加载模型配置失败');
|
||||
}
|
||||
const data = await res.json();
|
||||
openAIProfiles = Array.isArray(data.profiles) ? data.profiles : [];
|
||||
activeOpenAIName = data.active || activeOpenAIName;
|
||||
|
||||
modelSelect.innerHTML = '';
|
||||
for (const profile of openAIProfiles) {
|
||||
const opt = document.createElement('option');
|
||||
opt.value = profile.name;
|
||||
opt.textContent = `${profile.name} · ${profile.model}`;
|
||||
opt.selected = profile.name === activeOpenAIName;
|
||||
modelSelect.appendChild(opt);
|
||||
}
|
||||
modelSelect.disabled = pending || openAIProfiles.length <= 1;
|
||||
}
|
||||
|
||||
// ── 对话列表 ──────────────────────────────────────────────
|
||||
async function loadConversationList() {
|
||||
try {
|
||||
@@ -784,7 +820,12 @@ async function streamChat(messages, aiBubble, webSearch = false) {
|
||||
const res = await fetch('/api/chat', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ conversation_id: currentConvId, messages, web_search: webSearch }),
|
||||
body: JSON.stringify({
|
||||
conversation_id: currentConvId,
|
||||
messages,
|
||||
web_search: webSearch,
|
||||
openai_name: activeOpenAIName,
|
||||
}),
|
||||
});
|
||||
|
||||
if (!res.ok) {
|
||||
@@ -997,6 +1038,31 @@ btnSearch.addEventListener('click', () => {
|
||||
webSearchEnabled = !webSearchEnabled;
|
||||
updateSearchButton();
|
||||
});
|
||||
modelSelect.addEventListener('change', async () => {
|
||||
if (pending) {
|
||||
modelSelect.value = activeOpenAIName;
|
||||
return;
|
||||
}
|
||||
const nextName = modelSelect.value;
|
||||
const prevName = activeOpenAIName;
|
||||
try {
|
||||
const res = await fetch('/api/openai/active', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ name: nextName }),
|
||||
});
|
||||
if (!res.ok) {
|
||||
const err = await res.json().catch(() => ({ error: '切换模型失败' }));
|
||||
throw new Error(err.error || '切换模型失败');
|
||||
}
|
||||
const data = await res.json();
|
||||
activeOpenAIName = data.active;
|
||||
modelSelect.value = activeOpenAIName;
|
||||
} catch (e) {
|
||||
modelSelect.value = prevName;
|
||||
alert(e.message);
|
||||
}
|
||||
});
|
||||
btnNewChat.addEventListener('click', newConversation);
|
||||
btnClear.addEventListener('click', newConversation);
|
||||
btnPreset.addEventListener('click', openPresetModal);
|
||||
@@ -1016,6 +1082,7 @@ presetModal.addEventListener('click', e => {
|
||||
|
||||
// 自动聚焦 & 初始化
|
||||
updateSearchButton();
|
||||
loadOpenAIProfiles().catch(e => alert(e.message));
|
||||
loadConversationList();
|
||||
inputBox.focus();
|
||||
</script>
|
||||
|
||||
Reference in New Issue
Block a user