feat(imggen): генерация картинок ИИ (FLUX.1) — ассистент, флэшкарты, редактор уроков
Бэкенд /api/imggen (status/generate, CF Workers AI, cooldown+дневной лимит). Переиспользуемый модал LS.imagePromptModal (js/imggen.js). Квантик: режим «Нарисовать» в чате (inline). Флэшкарты: кнопка «ИИ» в блоке картинки карточки. Редактор уроков: кнопка «Сгенерировать» в блоке изображения. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -490,7 +490,8 @@
|
||||
chatEl.innerHTML = '';
|
||||
_chat.forEach(function (m) {
|
||||
var d = msgEl(m.role);
|
||||
if (m.role === 'assistant') { d.innerHTML = '<div class="asst-rich"></div>'; renderRich(d.querySelector('.asst-rich'), m.content); }
|
||||
if (m.img) d.innerHTML = '<img src="' + m.img + '" alt="" style="width:100%;border-radius:10px;display:block">';
|
||||
else if (m.role === 'assistant') { d.innerHTML = '<div class="asst-rich"></div>'; renderRich(d.querySelector('.asst-rich'), m.content); }
|
||||
else d.textContent = m.content;
|
||||
chatEl.appendChild(d);
|
||||
});
|
||||
@@ -498,7 +499,7 @@
|
||||
}
|
||||
var FB_UP = '<svg class="ic" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M7 10v11"/><path d="M15 5.88 14 10h5.83a2 2 0 0 1 1.92 2.56l-2.33 8A2 2 0 0 1 17.5 22H4a2 2 0 0 1-2-2v-8a2 2 0 0 1 2-2h2.76a2 2 0 0 0 1.79-1.11L12 2a3.13 3.13 0 0 1 3 3.88Z"/></svg>';
|
||||
var FB_DOWN = '<svg class="ic" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" style="transform:rotate(180deg)"><path d="M7 10v11"/><path d="M15 5.88 14 10h5.83a2 2 0 0 1 1.92 2.56l-2.33 8A2 2 0 0 1 17.5 22H4a2 2 0 0 1-2-2v-8a2 2 0 0 1 2-2h2.76a2 2 0 0 0 1.79-1.11L12 2a3.13 3.13 0 0 1 3 3.88Z"/></svg>';
|
||||
var MODE_PH = { answer: 'Спроси что угодно: «объясни…», «как…»', hint: 'Задача, по которой нужна подсказка…', check: 'Вставь своё решение — проверю…' };
|
||||
var MODE_PH = { answer: 'Спроси что угодно: «объясни…», «как…»', hint: 'Задача, по которой нужна подсказка…', check: 'Вставь своё решение — проверю…', draw: 'Опиши картинку: «кот-учёный, плоская иллюстрация»' };
|
||||
function openAsk(prefill) {
|
||||
var sel = _lastSel, pc = getPageContext();
|
||||
var ctxBtns = '';
|
||||
@@ -512,7 +513,8 @@
|
||||
var modes = '<div class="asst-modes">' +
|
||||
'<button class="asst-mode on" data-m="answer">Ответ</button>' +
|
||||
'<button class="asst-mode" data-m="hint">Подсказка</button>' +
|
||||
'<button class="asst-mode" data-m="check">Проверить решение</button></div>';
|
||||
'<button class="asst-mode" data-m="check">Проверить решение</button>' +
|
||||
'<button class="asst-mode" data-m="draw">Нарисовать</button></div>';
|
||||
openBubble(
|
||||
'<div class="asst-name"><span class="asst-name-face">' + faceSVG('happy') + '</span>Спроси Квантика' +
|
||||
'<button class="asst-link" data-a="mem" style="float:right;font-weight:600;margin-right:24px">Память</button>' +
|
||||
@@ -580,9 +582,29 @@
|
||||
});
|
||||
}
|
||||
function srcUrl(s) { return '/textbook/' + s.slug + (s.ref ? '#sec-' + s.ref : ''); }
|
||||
function drawInChat(prompt, chatEl) {
|
||||
prompt = (prompt || '').trim();
|
||||
if (prompt.length < 3) return;
|
||||
_chat.push({ role: 'user', content: 'Нарисуй: ' + prompt });
|
||||
var u = msgEl('user'); u.textContent = 'Нарисуй: ' + prompt; chatEl.appendChild(u);
|
||||
var ph = msgEl('assistant'); ph.className += ' asst-msg-ph'; ph.textContent = 'Рисую картинку…'; chatEl.appendChild(ph);
|
||||
chatEl.scrollTop = chatEl.scrollHeight;
|
||||
LS.imageGen(prompt).then(function (r) {
|
||||
ph.remove();
|
||||
var d = msgEl('assistant');
|
||||
if (r && r.url) { d.innerHTML = '<img src="' + r.url + '" alt="" style="width:100%;border-radius:10px;display:block">'; _chat.push({ role: 'assistant', content: '[картинка]', img: r.url }); }
|
||||
else d.textContent = 'Не получилось нарисовать.';
|
||||
chatEl.appendChild(d); chatEl.scrollTop = chatEl.scrollHeight;
|
||||
}).catch(function (err) {
|
||||
ph.remove(); var d = msgEl('assistant');
|
||||
d.textContent = (err && err.data && err.data.error) || 'Не получилось нарисовать.';
|
||||
chatEl.appendChild(d); chatEl.scrollTop = chatEl.scrollHeight;
|
||||
});
|
||||
}
|
||||
function send(q, context, chatEl, mode) {
|
||||
q = (q || '').trim();
|
||||
if (q.length < 2) return;
|
||||
if (mode === 'draw') return drawInChat(q, chatEl);
|
||||
var history = _chat.slice(-6);
|
||||
_chat.push({ role: 'user', content: q });
|
||||
var u = msgEl('user'); u.textContent = q; chatEl.appendChild(u);
|
||||
|
||||
Reference in New Issue
Block a user