feat(imggen): фон питомца, обложки курсов, аватары и доска через ИИ
Питомец: кастомный фон (миграция 068 pet_bg_custom, POST /api/pet/bg/custom, карточка «Свой фон (ИИ)» в гардеробной, применение картинкой). Курсы: обложка-картинка (миграция 069 cover_image, генерация в модалке редактирования, рендер вместо эмодзи). Аватар: кнопка «Сгенерировать (ИИ)» в загрузке → кадрирование → модерация. Доска (classroom): кнопка-инструмент «Сгенерировать картинку (ИИ)». Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
+31
-1
@@ -449,6 +449,7 @@
|
||||
|
||||
<!-- Add section modal -->
|
||||
<script src="/js/api.js"></script>
|
||||
<script src="/js/imggen.js"></script>
|
||||
<script src="/js/sidebar.js"></script>
|
||||
<script>
|
||||
if (!LS.requireAuth()) throw new Error();
|
||||
@@ -548,7 +549,9 @@
|
||||
|
||||
document.getElementById('header-body').innerHTML = `
|
||||
${!course.isPublished ? '<span class="ch-draft-tag">Черновик</span><br><br>' : ''}
|
||||
<div class="ch-emoji">${course.coverEmoji || LS.icon('book-open',24)}</div>
|
||||
${course.coverImage
|
||||
? `<div class="ch-cover" style="width:100%;max-width:440px;height:160px;margin:0 auto 14px;border-radius:16px;background:center/cover url('${esc(course.coverImage)}');box-shadow:0 8px 24px rgba(0,0,0,.18)"></div>`
|
||||
: `<div class="ch-emoji">${course.coverEmoji || LS.icon('book-open',24)}</div>`}
|
||||
<div class="ch-subj ${SUBJ_CLASS[course.subjectSlug] || ''}">${esc(SUBJ_LABEL[course.subjectSlug] || course.subjectSlug)}</div>
|
||||
<div class="ch-title">${esc(course.title)}</div>
|
||||
${course.description ? `<div class="ch-desc">${esc(course.description)}</div>` : ''}
|
||||
@@ -862,6 +865,15 @@
|
||||
<option value="phys">Физика</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group" style="margin-top:12px">
|
||||
<label class="form-label">Обложка (картинка)</label>
|
||||
<div id="ec-cover-prev" style="${course.coverImage ? '' : 'display:none;'}height:120px;border-radius:12px;margin-bottom:8px;background:center/cover url('${LS.esc(course.coverImage || '')}')"></div>
|
||||
<input type="hidden" id="ec-cover" value="${LS.esc(course.coverImage || '')}" />
|
||||
<div style="display:flex;gap:8px;flex-wrap:wrap">
|
||||
<button type="button" class="btn-primary" id="ec-cover-gen" style="padding:8px 16px;min-height:auto;font-size:.82rem">Сгенерировать ИИ</button>
|
||||
<button type="button" class="btn-ghost" id="ec-cover-clear" style="padding:8px 16px;min-height:auto;${course.coverImage ? '' : 'display:none'}">Убрать</button>
|
||||
</div>
|
||||
</div>`;
|
||||
_editCourseModal = LS.modal({
|
||||
title: 'Редактировать курс', content: body, size: 'sm',
|
||||
@@ -871,6 +883,23 @@
|
||||
],
|
||||
});
|
||||
_editCourseModal.body.querySelector('#ec-subject').value = course.subjectSlug || '';
|
||||
const coverInput = _editCourseModal.body.querySelector('#ec-cover');
|
||||
const coverPrev = _editCourseModal.body.querySelector('#ec-cover-prev');
|
||||
const coverClear = _editCourseModal.body.querySelector('#ec-cover-clear');
|
||||
_editCourseModal.body.querySelector('#ec-cover-gen').onclick = () => {
|
||||
if (!LS.imagePromptModal) { LS.toast('Модуль генерации не загружен'); return; }
|
||||
LS.imagePromptModal({
|
||||
title: 'Обложка курса',
|
||||
placeholder: 'Обложка для курса «' + (course.title || '') + '»: яркая иллюстрация',
|
||||
useLabel: 'Поставить обложкой',
|
||||
onUse: (url) => {
|
||||
coverInput.value = url;
|
||||
coverPrev.style.cssText = "height:120px;border-radius:12px;margin-bottom:8px;background:center/cover url('" + url + "')";
|
||||
coverClear.style.display = '';
|
||||
},
|
||||
});
|
||||
};
|
||||
coverClear.onclick = () => { coverInput.value = ''; coverPrev.style.display = 'none'; coverClear.style.display = 'none'; };
|
||||
}
|
||||
async function doEditCourse() {
|
||||
const btn = document.getElementById('btn-do-edit-course');
|
||||
@@ -883,6 +912,7 @@
|
||||
title: document.getElementById('ec-title').value.trim(),
|
||||
description: document.getElementById('ec-desc').value.trim(),
|
||||
coverEmoji: document.getElementById('ec-emoji').value.trim(),
|
||||
coverImage: document.getElementById('ec-cover').value.trim(),
|
||||
subjectSlug: document.getElementById('ec-subject').value || null,
|
||||
}),
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user