feat: support deepseek and openai-compatible providers
This commit is contained in:
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user