feat: support deepseek and openai-compatible providers

This commit is contained in:
liumangmang
2026-04-29 22:19:00 +08:00
parent 4ac755a7fe
commit 3555d19b26
13 changed files with 761 additions and 190 deletions
+39 -2
View File
@@ -63,6 +63,10 @@ function bindForms() {
const settingsForm = document.querySelector("#settings-form");
settingsForm.addEventListener("submit", onSaveSettings);
const settingsProvider = document.querySelector("#settings-provider");
if (settingsProvider) {
settingsProvider.addEventListener("change", () => updateSettingsProviderUI(settingsProvider.value));
}
const taskFilterBtn = document.querySelector("#btn-task-filter");
if (taskFilterBtn) {
@@ -870,6 +874,14 @@ function renderFileTable() {
async function loadSettings() {
try {
const data = await apiFetch("/api/settings");
document.querySelector("#settings-form [name='provider']").value = data.provider || "deepseek";
document.querySelector("#settings-form [name='apiKey']").value = "";
document.querySelector("#settings-form [name='openaiBaseUrl']").value = data.openaiBaseUrl || "";
document.querySelector("#settings-form [name='openaiApiKey']").value = data.openaiApiKey || "";
document.querySelector("#settings-form [name='openaiStageOneModel']").value =
data.openaiStageOneModel || "deepseek-v4-flash";
document.querySelector("#settings-form [name='openaiStageTwoModel']").value =
data.openaiStageTwoModel || "deepseek-v4-pro";
document.querySelector("#settings-form [name='outputDir']").value = data.outputDir || "";
state.defaultPresetId = data.defaultSvnPresetId || state.defaultPresetId;
const settingsPreset = document.querySelector("#settings-default-preset");
@@ -877,7 +889,8 @@ async function loadSettings() {
settingsPreset.value = state.defaultPresetId;
}
applyPresetToSvnForm(state.defaultPresetId);
document.querySelector("#settings-state").textContent = `API Key 状态:${data.apiKeyConfigured ? "已配置" : "未配置"}(来源:${data.apiKeySource}`;
updateSettingsProviderUI(data.provider || "deepseek");
renderSettingsState(data);
} catch (err) {
toast(err.message, true);
}
@@ -895,7 +908,8 @@ async function onSaveSettings(event) {
});
state.defaultPresetId = data.defaultSvnPresetId || state.defaultPresetId;
applyPresetToSvnForm(state.defaultPresetId);
document.querySelector("#settings-state").textContent = `API Key 状态:${data.apiKeyConfigured ? "已配置" : "未配置"}(来源:${data.apiKeySource}`;
updateSettingsProviderUI(data.provider || "deepseek");
renderSettingsState(data);
toast("设置保存成功");
} catch (err) {
toast(err.message, true);
@@ -909,6 +923,29 @@ function readForm(form) {
return Object.fromEntries(data.entries());
}
function updateSettingsProviderUI(provider) {
const isOpenAiCompatible = provider === "openai-compatible";
const groupedSection = document.querySelector("#openai-settings-group");
if (groupedSection) {
groupedSection.hidden = !isOpenAiCompatible;
}
document.querySelectorAll("#openai-api-key-group, #openai-stage-one-group, #openai-stage-two-group").forEach((node) => {
node.hidden = !isOpenAiCompatible;
});
}
function renderSettingsState(data) {
const stateEl = document.querySelector("#settings-state");
if (!stateEl) {
return;
}
if ((data.provider || "deepseek") === "openai-compatible") {
stateEl.textContent = `当前提供商:OpenAI兼容 | Base URL${data.openaiBaseUrl || "(未配置)"} | API Key${data.openaiApiKeyConfigured ? "已配置" : "未配置"} | Stage1${data.openaiStageOneModel || "-"} | Stage2${data.openaiStageTwoModel || "-"}`;
return;
}
stateEl.textContent = `当前提供商:DeepSeek | API Key 状态:${data.apiKeyConfigured ? "已配置" : "未配置"}(来源:${data.apiKeySource}`;
}
function setLoading(button, loading) {
if (!button) {
return;
@@ -345,11 +345,45 @@
</div>
<div class="card-body">
<form id="settings-form" class="form-layout">
<div class="form-group form-group-full">
<label for="settings-provider" class="form-label">AI 提供商</label>
<select name="provider" id="settings-provider" class="form-select">
<option value="deepseek">DeepSeek</option>
<option value="openai-compatible">OpenAI兼容</option>
</select>
</div>
<div class="form-group form-group-full">
<label for="api-key-input" class="form-label">DeepSeek API Key</label>
<input type="password" name="apiKey" id="api-key-input" class="form-input" placeholder="设置后将保存在当前进程内存">
</div>
<div class="form-group form-group-full" id="openai-settings-group" hidden>
<label for="openai-base-url" class="form-label">OpenAI兼容 Base URL</label>
<input type="text" name="openaiBaseUrl" id="openai-base-url" class="form-input" placeholder="例如 http://127.0.0.1:5001/v1">
</div>
<div class="form-group form-group-full" id="openai-api-key-group" hidden>
<label for="openai-api-key" class="form-label">OpenAI兼容 API Key</label>
<input type="password" name="openaiApiKey" id="openai-api-key" class="form-input" placeholder="设置后将保存在当前进程内存">
</div>
<div class="form-group" id="openai-stage-one-group" hidden>
<label for="openai-stage-one-model" class="form-label">第一阶段模型</label>
<select name="openaiStageOneModel" id="openai-stage-one-model" class="form-select">
<option value="deepseek-v4-flash">deepseek-v4-flash</option>
<option value="deepseek-v4-pro">deepseek-v4-pro</option>
</select>
</div>
<div class="form-group" id="openai-stage-two-group" hidden>
<label for="openai-stage-two-model" class="form-label">第二阶段模型</label>
<select name="openaiStageTwoModel" id="openai-stage-two-model" class="form-select">
<option value="deepseek-v4-pro">deepseek-v4-pro</option>
<option value="deepseek-v4-flash">deepseek-v4-flash</option>
</select>
</div>
<div class="form-group form-group-full">
<label for="default-preset" class="form-label">默认 SVN 项目</label>
<select name="defaultSvnPresetId" id="default-preset" class="form-select"></select>
+27 -1
View File
@@ -184,9 +184,35 @@
<article class="card form-card">
<h3>系统设置</h3>
<form id="settings-form" class="form-grid">
<label class="span-2">AI 提供商
<select name="provider" id="settings-provider">
<option value="deepseek">DeepSeek</option>
<option value="openai-compatible">OpenAI兼容</option>
</select>
</label>
<label class="span-2">DeepSeek API Key
<input type="password" name="apiKey" placeholder="设置后将保存在当前进程内存">
</label>
<div class="span-2" id="openai-settings-group" hidden>
<label class="span-2">OpenAI兼容 Base URL
<input type="text" name="openaiBaseUrl" placeholder="例如 http://127.0.0.1:5001/v1">
</label>
<label class="span-2">OpenAI兼容 API Key
<input type="password" name="openaiApiKey" placeholder="设置后将保存在当前进程内存">
</label>
<label>第一阶段模型
<select name="openaiStageOneModel">
<option value="deepseek-v4-flash">deepseek-v4-flash</option>
<option value="deepseek-v4-pro">deepseek-v4-pro</option>
</select>
</label>
<label>第二阶段模型
<select name="openaiStageTwoModel">
<option value="deepseek-v4-pro">deepseek-v4-pro</option>
<option value="deepseek-v4-flash">deepseek-v4-flash</option>
</select>
</label>
</div>
<label class="span-2">默认 SVN 项目
<select name="defaultSvnPresetId" id="settings-default-preset"></select>
</label>
@@ -205,6 +231,6 @@
</main>
</div>
<script src="/app.js?v=20260407_1811" defer></script>
<script src="/app.js?v=20260429_1808" defer></script>
</body>
</html>