fix(story-summary): refine vector api settings UX

This commit is contained in:
2026-04-03 16:27:15 +08:00
parent af7e0f689d
commit 7b921b80e0
2 changed files with 186 additions and 116 deletions

View File

@@ -303,6 +303,18 @@ All checks passed. Beginning incremental extraction...
custom: { url: '', needKey: true, canFetch: true } custom: { url: '', needKey: true, canFetch: true }
}; };
function setStatusText(el, message, kind = '') {
if (!el) return;
el.textContent = message || '';
el.style.color = kind === 'error'
? '#ef4444'
: kind === 'success'
? '#22c55e'
: kind === 'loading'
? '#f59e0b'
: '';
}
const SECTION_META = { const SECTION_META = {
keywords: { title: '编辑关键词', hint: '每行一个关键词,格式:关键词|权重(核心/重要/一般)' }, keywords: { title: '编辑关键词', hint: '每行一个关键词,格式:关键词|权重(核心/重要/一般)' },
events: { title: '编辑事件时间线', hint: '编辑时,每个事件要素都应完整' }, events: { title: '编辑事件时间线', hint: '编辑时,每个事件要素都应完整' },
@@ -530,7 +542,19 @@ All checks passed. Beginning incremental extraction...
$(`${prefix}-api-connect-status`).classList.toggle('hidden', !pv.canFetch); $(`${prefix}-api-connect-status`).classList.toggle('hidden', !pv.canFetch);
const urlInput = $(`${prefix}-api-url`); const urlInput = $(`${prefix}-api-url`);
if (urlInput && !urlInput.value && pv.url) urlInput.value = pv.url; if (urlInput) {
if (provider === 'custom') {
urlInput.readOnly = false;
urlInput.placeholder = 'https://your-openai-compatible-api/v1';
} else {
urlInput.value = pv.url || '';
urlInput.readOnly = true;
urlInput.placeholder = pv.url || '';
if (config.vector?.[`${prefix}Api`]) {
config.vector[`${prefix}Api`].url = pv.url || '';
}
}
}
} }
async function fetchVectorModels(prefix) { async function fetchVectorModels(prefix) {
@@ -786,6 +810,8 @@ All checks passed. Beginning incremental extraction...
}; };
$('btn-test-vector-api').onclick = () => { $('btn-test-vector-api').onclick = () => {
$('btn-test-vector-api').disabled = true;
setStatusText($('embedding-api-connect-status'), '测试中...', 'loading');
saveConfig(); // 先保存新 Key 到 localStorage saveConfig(); // 先保存新 Key 到 localStorage
postMsg('VECTOR_TEST_ONLINE', { postMsg('VECTOR_TEST_ONLINE', {
provider: getVectorConfig().embeddingApi.provider, provider: getVectorConfig().embeddingApi.provider,
@@ -795,10 +821,17 @@ All checks passed. Beginning incremental extraction...
['l0', 'embedding', 'rerank'].forEach(prefix => { ['l0', 'embedding', 'rerank'].forEach(prefix => {
$(`${prefix}-api-provider`).onchange = e => { $(`${prefix}-api-provider`).onchange = e => {
const oldProvider = config.vector[`${prefix}Api`]?.provider || 'siliconflow';
const pv = VECTOR_PROVIDER_DEFAULTS[e.target.value] || VECTOR_PROVIDER_DEFAULTS.custom; const pv = VECTOR_PROVIDER_DEFAULTS[e.target.value] || VECTOR_PROVIDER_DEFAULTS.custom;
const target = config.vector[`${prefix}Api`] ||= { modelCache: [] }; const target = config.vector[`${prefix}Api`] ||= { modelCache: [] };
if (e.target.value === 'custom') {
if (target.url === (VECTOR_PROVIDER_DEFAULTS[oldProvider]?.url || '')) {
target.url = '';
}
} else {
target.url = pv.url || '';
}
target.provider = e.target.value; target.provider = e.target.value;
if (!target.url && pv.url) target.url = pv.url;
if (!pv.canFetch) target.modelCache = []; if (!pv.canFetch) target.modelCache = [];
updateVectorProviderUI(prefix, e.target.value); updateVectorProviderUI(prefix, e.target.value);
}; };
@@ -854,6 +887,16 @@ All checks passed. Beginning incremental extraction...
postMsg('REQUEST_ANCHOR_STATS'); postMsg('REQUEST_ANCHOR_STATS');
} }
function updateVectorOnlineStatus(status, message) {
const btn = $('btn-test-vector-api');
if (btn) btn.disabled = false;
setStatusText(
$('embedding-api-connect-status'),
message || '',
status === 'error' ? 'error' : status === 'success' ? 'success' : 'loading'
);
}
function initSummaryIOUI() { function initSummaryIOUI() {
$('btn-copy-summary').onclick = () => { $('btn-copy-summary').onclick = () => {
$('btn-copy-summary').disabled = true; $('btn-copy-summary').disabled = true;
@@ -1956,7 +1999,7 @@ All checks passed. Beginning incremental extraction...
break; break;
case 'VECTOR_ONLINE_STATUS': case 'VECTOR_ONLINE_STATUS':
updateOnlineStatus(d.status, d.message); updateVectorOnlineStatus(d.status, d.message);
break; break;
case 'VECTOR_STATS': case 'VECTOR_STATS':

View File

@@ -429,124 +429,151 @@
<input type="number" id="vector-l0-concurrency" min="1" max="50" step="1" value="10"> <input type="number" id="vector-l0-concurrency" min="1" max="50" step="1" value="10">
<div class="settings-hint" style="margin-bottom:16px;">默认 10。免费账号可调低到 1-3线路稳定时可自行调高。</div> <div class="settings-hint" style="margin-bottom:16px;">默认 10。免费账号可调低到 1-3线路稳定时可自行调高。</div>
<div class="settings-section-title" style="margin-bottom:8px;">L0 锚点提取模型</div> <details class="settings-collapse" id="l0-api-collapse" style="margin-bottom:12px;">
<div class="settings-row"> <summary class="settings-collapse-header">
<div class="settings-field"> <span>L0 锚点提取模型</span>
<label>渠道</label> <svg class="collapse-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<select id="l0-api-provider"> <polyline points="6 9 12 15 18 9"></polyline>
<option value="siliconflow">硅基流动</option> </svg>
<option value="openrouter">OpenRouter</option> </summary>
<option value="custom">自定义</option> <div class="settings-collapse-content">
</select> <div class="settings-row">
<div class="settings-field">
<label>渠道</label>
<select id="l0-api-provider">
<option value="siliconflow">硅基流动</option>
<option value="openrouter">OpenRouter</option>
<option value="custom">自定义</option>
</select>
</div>
</div>
<div class="settings-row" id="l0-api-url-row">
<div class="settings-field full">
<label>API URL</label>
<input type="text" id="l0-api-url" placeholder="https://api.siliconflow.cn/v1">
</div>
</div>
<div class="settings-row" id="l0-api-key-row">
<div class="settings-field full">
<label>API KEY</label>
<input type="password" id="l0-api-key" placeholder="sk-xxx">
</div>
</div>
<div class="settings-row" id="l0-api-model-manual-row">
<div class="settings-field full">
<label>模型名</label>
<input type="text" id="l0-api-model-text" placeholder="可手动填写,如 Qwen/Qwen3-8B">
</div>
</div>
<div class="settings-row hidden" id="l0-api-model-select-row">
<div class="settings-field full">
<label>已拉取模型</label>
<select id="l0-api-model-select"><option value="">请选择</option></select>
</div>
</div>
<div class="settings-btn-row" id="l0-api-connect-row" style="margin-bottom:8px;">
<button class="btn btn-sm" id="l0-btn-connect" style="flex:1">连接 / 拉取模型列表</button>
</div>
<div class="settings-hint" id="l0-api-connect-status" style="margin-bottom:16px;"></div>
</div> </div>
</div> </details>
<div class="settings-row" id="l0-api-url-row">
<div class="settings-field full">
<label>API URL</label>
<input type="text" id="l0-api-url" placeholder="https://api.siliconflow.cn/v1">
</div>
</div>
<div class="settings-row" id="l0-api-key-row">
<div class="settings-field full">
<label>API KEY</label>
<input type="password" id="l0-api-key" placeholder="sk-xxx">
</div>
</div>
<div class="settings-row" id="l0-api-model-manual-row">
<div class="settings-field full">
<label>模型名</label>
<input type="text" id="l0-api-model-text" placeholder="可手动填写,如 Qwen/Qwen3-8B">
</div>
</div>
<div class="settings-row hidden" id="l0-api-model-select-row">
<div class="settings-field full">
<label>已拉取模型</label>
<select id="l0-api-model-select"><option value="">请选择</option></select>
</div>
</div>
<div class="settings-btn-row" id="l0-api-connect-row" style="margin-bottom:8px;">
<button class="btn btn-sm" id="l0-btn-connect" style="flex:1">连接 / 拉取模型列表</button>
</div>
<div class="settings-hint" id="l0-api-connect-status" style="margin-bottom:16px;"></div>
<div class="settings-section-title" style="margin-bottom:8px;">Embedding 模型</div> <details class="settings-collapse" id="embedding-api-collapse" style="margin-bottom:12px;">
<div class="settings-row"> <summary class="settings-collapse-header">
<div class="settings-field"> <span>Embedding 模型</span>
<label>渠道</label> <svg class="collapse-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<select id="embedding-api-provider"> <polyline points="6 9 12 15 18 9"></polyline>
<option value="siliconflow">硅基流动</option> </svg>
<option value="custom">自定义</option> </summary>
</select> <div class="settings-collapse-content">
<div class="settings-row">
<div class="settings-field">
<label>渠道</label>
<select id="embedding-api-provider">
<option value="siliconflow">硅基流动</option>
<option value="custom">自定义</option>
</select>
</div>
</div>
<div class="settings-row" id="embedding-api-url-row">
<div class="settings-field full">
<label>API URL</label>
<input type="text" id="embedding-api-url" placeholder="https://api.siliconflow.cn/v1">
</div>
</div>
<div class="settings-row" id="embedding-api-key-row">
<div class="settings-field full">
<label>API KEY</label>
<input type="password" id="embedding-api-key" placeholder="sk-xxx">
</div>
</div>
<div class="settings-row" id="embedding-api-model-manual-row">
<div class="settings-field full">
<label>模型名</label>
<input type="text" id="embedding-api-model-text" placeholder="如 BAAI/bge-m3">
</div>
</div>
<div class="settings-row hidden" id="embedding-api-model-select-row">
<div class="settings-field full">
<label>已拉取模型</label>
<select id="embedding-api-model-select"><option value="">请选择</option></select>
</div>
</div>
<div class="settings-btn-row" id="embedding-api-connect-row" style="margin-bottom:8px;">
<button class="btn btn-sm" id="embedding-btn-connect" style="flex:1">连接 / 拉取模型列表</button>
<button class="btn btn-sm" id="btn-test-vector-api" style="flex:1">测试 Embedding</button>
</div>
<div class="settings-hint" id="embedding-api-connect-status" style="margin-bottom:16px;"></div>
</div> </div>
</div> </details>
<div class="settings-row" id="embedding-api-url-row">
<div class="settings-field full">
<label>API URL</label>
<input type="text" id="embedding-api-url" placeholder="https://api.siliconflow.cn/v1">
</div>
</div>
<div class="settings-row" id="embedding-api-key-row">
<div class="settings-field full">
<label>API KEY</label>
<input type="password" id="embedding-api-key" placeholder="sk-xxx">
</div>
</div>
<div class="settings-row" id="embedding-api-model-manual-row">
<div class="settings-field full">
<label>模型名</label>
<input type="text" id="embedding-api-model-text" placeholder="如 BAAI/bge-m3">
</div>
</div>
<div class="settings-row hidden" id="embedding-api-model-select-row">
<div class="settings-field full">
<label>已拉取模型</label>
<select id="embedding-api-model-select"><option value="">请选择</option></select>
</div>
</div>
<div class="settings-btn-row" id="embedding-api-connect-row" style="margin-bottom:8px;">
<button class="btn btn-sm" id="embedding-btn-connect" style="flex:1">连接 / 拉取模型列表</button>
<button class="btn btn-sm" id="btn-test-vector-api" style="flex:1">测试 Embedding</button>
</div>
<div class="settings-hint" id="embedding-api-connect-status" style="margin-bottom:16px;"></div>
<div class="settings-section-title" style="margin-bottom:8px;">Rerank 模型</div> <details class="settings-collapse" id="rerank-api-collapse">
<div class="settings-row"> <summary class="settings-collapse-header">
<div class="settings-field"> <span>Rerank 模型</span>
<label>渠道</label> <svg class="collapse-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<select id="rerank-api-provider"> <polyline points="6 9 12 15 18 9"></polyline>
<option value="siliconflow">硅基流动</option> </svg>
<option value="custom">自定义</option> </summary>
</select> <div class="settings-collapse-content">
<div class="settings-row">
<div class="settings-field">
<label>渠道</label>
<select id="rerank-api-provider">
<option value="siliconflow">硅基流动</option>
<option value="custom">自定义</option>
</select>
</div>
</div>
<div class="settings-row" id="rerank-api-url-row">
<div class="settings-field full">
<label>API URL</label>
<input type="text" id="rerank-api-url" placeholder="https://api.siliconflow.cn/v1">
</div>
</div>
<div class="settings-row" id="rerank-api-key-row">
<div class="settings-field full">
<label>API KEY</label>
<input type="password" id="rerank-api-key" placeholder="sk-xxx">
</div>
</div>
<div class="settings-row" id="rerank-api-model-manual-row">
<div class="settings-field full">
<label>模型名</label>
<input type="text" id="rerank-api-model-text" placeholder="如 BAAI/bge-reranker-v2-m3">
</div>
</div>
<div class="settings-row hidden" id="rerank-api-model-select-row">
<div class="settings-field full">
<label>已拉取模型</label>
<select id="rerank-api-model-select"><option value="">请选择</option></select>
</div>
</div>
<div class="settings-btn-row" id="rerank-api-connect-row">
<button class="btn btn-sm" id="rerank-btn-connect" style="flex:1">连接 / 拉取模型列表</button>
</div>
<div class="settings-hint" id="rerank-api-connect-status"></div>
</div> </div>
</div> </details>
<div class="settings-row" id="rerank-api-url-row">
<div class="settings-field full">
<label>API URL</label>
<input type="text" id="rerank-api-url" placeholder="https://api.siliconflow.cn/v1">
</div>
</div>
<div class="settings-row" id="rerank-api-key-row">
<div class="settings-field full">
<label>API KEY</label>
<input type="password" id="rerank-api-key" placeholder="sk-xxx">
</div>
</div>
<div class="settings-row" id="rerank-api-model-manual-row">
<div class="settings-field full">
<label>模型名</label>
<input type="text" id="rerank-api-model-text" placeholder="如 BAAI/bge-reranker-v2-m3">
</div>
</div>
<div class="settings-row hidden" id="rerank-api-model-select-row">
<div class="settings-field full">
<label>已拉取模型</label>
<select id="rerank-api-model-select"><option value="">请选择</option></select>
</div>
</div>
<div class="settings-btn-row" id="rerank-api-connect-row">
<button class="btn btn-sm" id="rerank-btn-connect" style="flex:1">连接 / 拉取模型列表</button>
</div>
<div class="settings-hint" id="rerank-api-connect-status"></div>
</div> </div>
</div> </div>
</div> </div>