feat(assistant): форма добавления провайдера свёрнута по умолчанию

Раскрывается кнопкой «+ Добавить провайдера» (и автоматически при «Изм.»),
сворачивается после сохранения/отмены. Окно компактнее в обычном режиме.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Maxim Dolgolyov
2026-06-04 20:58:14 +03:00
parent 4172569ff7
commit f748e074fd
+16 -11
View File
@@ -84,15 +84,18 @@
'<div class="asst-prov" id="asst-prov"></div>' +
'<div id="asst-ptest" class="asst-ptest"></div>' +
'<hr style="border:none;border-top:1px solid var(--border,#e2e8f0);margin:6px 0 2px">' +
'<div style="font-weight:800;font-size:.86rem" id="asst-fhead">Добавить провайдера</div>' +
'<div class="asst-flabel">Пресет</div>' +
'<select id="asst-preset" style="' + IN + '"><option value="">— выбрать провайдера —</option>' + presets.map(function (p, i) { return '<option value="' + i + '">' + esc(p.name) + '</option>'; }).join('') + '</select>' +
'<div class="asst-flabel">Название</div><input id="asst-name" placeholder="напр. Kilo основной" style="' + IN + '" />' +
'<div class="asst-flabel">URL (chat/completions)</div><input id="asst-url" placeholder="https://…/chat/completions" style="' + IN + '" />' +
'<div id="asst-kbox" style="display:none"><div class="asst-flabel">Модель Kilo (бесплатные)</div><select id="asst-kmodels" style="' + IN + '"></select></div>' +
'<div class="asst-flabel">Модель</div><input id="asst-model" placeholder="model-id" style="' + IN + '" />' +
'<div class="asst-flabel">API-ключ</div><input id="asst-key" type="password" autocomplete="off" placeholder="ключ" style="' + IN + '" />' +
'<div style="display:flex;gap:8px;flex-wrap:wrap;margin-top:4px"><button id="asst-save" class="asst-ib primary" style="padding:8px 16px">Сохранить провайдера</button><button id="asst-cancel" class="asst-ib" style="display:none;padding:8px 16px">Отмена</button></div>';
'<button id="asst-ftoggle" class="asst-ib" style="align-self:flex-start;padding:7px 13px;display:inline-flex;align-items:center;gap:6px"><svg viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round"><path d="M12 5v14M5 12h14"/></svg>Добавить провайдера</button>' +
'<div id="asst-form" style="display:none;flex-direction:column;gap:9px;margin-top:2px;padding:13px;border:1px dashed var(--border,#e2e8f0);border-radius:12px">' +
'<div style="font-weight:800;font-size:.86rem" id="asst-fhead">Новый провайдер</div>' +
'<div class="asst-flabel">Пресет</div>' +
'<select id="asst-preset" style="' + IN + '"><option value="">— выбрать провайдера —</option>' + presets.map(function (p, i) { return '<option value="' + i + '">' + esc(p.name) + '</option>'; }).join('') + '</select>' +
'<div class="asst-flabel">Название</div><input id="asst-name" placeholder="напр. Kilo основной" style="' + IN + '" />' +
'<div class="asst-flabel">URL (chat/completions)</div><input id="asst-url" placeholder="https://…/chat/completions" style="' + IN + '" />' +
'<div id="asst-kbox" style="display:none"><div class="asst-flabel">Модель Kilo (бесплатные)</div><select id="asst-kmodels" style="' + IN + '"></select></div>' +
'<div class="asst-flabel">Модель</div><input id="asst-model" placeholder="model-id" style="' + IN + '" />' +
'<div class="asst-flabel">API-ключ</div><input id="asst-key" type="password" autocomplete="off" placeholder="ключ" style="' + IN + '" />' +
'<div style="display:flex;gap:8px;flex-wrap:wrap;margin-top:4px"><button id="asst-save" class="asst-ib primary" style="padding:8px 16px">Сохранить провайдера</button><button id="asst-cancel" class="asst-ib" style="padding:8px 16px">Отмена</button></div>' +
'</div>';
host.appendChild(pc);
// ── Настройки/статистика ──
@@ -137,7 +140,8 @@
'</div></div>';
}).join('');
function clearForm() { editingId = null; Q('#asst-fhead').textContent = 'Добавить провайдера'; Q('#asst-name').value = ''; Q('#asst-url').value = ''; Q('#asst-model').value = ''; Q('#asst-key').value = ''; Q('#asst-key').placeholder = 'ключ'; Q('#asst-cancel').style.display = 'none'; toggleKilo(); }
function openForm(show) { Q('#asst-form').style.display = show ? 'flex' : 'none'; }
function clearForm() { editingId = null; Q('#asst-fhead').textContent = 'Новый провайдер'; Q('#asst-preset').value = ''; Q('#asst-name').value = ''; Q('#asst-url').value = ''; Q('#asst-model').value = ''; Q('#asst-key').value = ''; Q('#asst-key').placeholder = 'ключ'; toggleKilo(); openForm(false); }
function toggleKilo() {
var isKilo = /kilocode\.ai/.test(Q('#asst-url').value || '');
Q('#asst-kbox').style.display = isKilo ? '' : 'none';
@@ -163,7 +167,7 @@
editingId = id; Q('#asst-fhead').textContent = 'Изменить: ' + (p.name || '');
Q('#asst-name').value = p.name || ''; Q('#asst-url').value = p.url || ''; Q('#asst-model').value = p.model || '';
Q('#asst-key').value = ''; Q('#asst-key').placeholder = p.hasKey ? 'ключ сохранён — введите новый, чтобы заменить' : 'ключ';
Q('#asst-cancel').style.display = ''; toggleKilo(); Q('#asst-name').focus();
toggleKilo(); openForm(true); Q('#asst-form').scrollIntoView({ behavior: 'smooth', block: 'nearest' }); Q('#asst-name').focus();
} else if (act === 'test') {
var res = Q('#asst-ptest'); res.innerHTML = 'Проверяю…';
try { var r = await LS.adminTestAssistant({ id: id }); res.innerHTML = r && r.ok ? '<span style="color:#059652">✓ Работает (' + esc(r.model || '') + '): ' + esc(String(r.sample || 'ответ получен')) + '</span>' : '<span style="color:#e0335e">✗ ' + esc(String((r && (r.error || ('HTTP ' + r.status))) || 'ошибка').slice(0, 200)) + '</span>'; } catch (e) { res.innerHTML = '<span style="color:#e0335e">✗ ' + esc(e.message || 'ошибка') + '</span>'; }
@@ -172,6 +176,7 @@
});
// форма
Q('#asst-ftoggle').addEventListener('click', function () { var open = Q('#asst-form').style.display !== 'none'; if (open) { clearForm(); } else { clearForm(); openForm(true); Q('#asst-name').focus(); } });
Q('#asst-preset').addEventListener('change', function () { var p = presets[Number(this.value)]; if (p) { Q('#asst-url').value = p.url; Q('#asst-model').value = p.model; if (!Q('#asst-name').value) Q('#asst-name').value = p.name; toggleKilo(); } });
Q('#asst-url').addEventListener('input', toggleKilo);
Q('#asst-kmodels').addEventListener('change', function () { Q('#asst-model').value = this.value; });