Files
pyisu/frontend/src/views/courseBuilder.js
2026-03-13 14:39:43 +08:00

144 lines
7.8 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { currentUser } from '../components/auth.js';
// Import editors
import { loadVditor, initVditorEditor } from '../editors/vditorLoader.js';
// Import course-builder modules
import { courseStructure, currentCourseId, isEditMode, isDraftMode, setVditorInstance, getVditorInstance } from '../course-builder/State.js';
import { saveDraft, previewCourse, publishCourse, updateDraftsCount, showDraftsModal, loadDraftIntoEditor } from '../course-builder/DraftManager.js';
import { initCourseStructure, loadCourseForEditing, renderCourseStructure } from '../course-builder/StructureManager.js';
import { showMessage, updateBuilderTitle } from '../course-builder/CourseUI.js';
export { courseStructure, currentCourseId, isEditMode, isDraftMode };
export async function render() {
if (!currentUser) {
return `
<div class="auth-required">
<h2>Требуется авторизация</h2>
<p>Для доступа к конструктору курса необходимо войти в систему.</p>
<a href="/login" data-link>Войти</a>
</div>`;
}
return `
<div class="course-builder-page">
<div class="course-builder-container">
<h2>Конструктор курса</h2>
<p class="subtitle">Создайте новый курс с помощью редактора Markdown с поддержкой LaTeX</p>
<div class="course-form">
<div class="form-group">
<label for="course-title">Название курса</label>
<input type="text" id="course-title" placeholder="Введите название курса" required>
</div>
<div class="form-group">
<label for="course-description">Краткое описание</label>
<textarea id="course-description" placeholder="Краткое описание курса" rows="3"></textarea>
</div>
<div class="form-group">
<label for="course-level">Уровень сложности</label>
<select id="course-level">
<option value="beginner">Начальный</option>
<option value="intermediate">Средний</option>
<option value="advanced">Продвинутый</option>
</select>
</div>
<div class="course-structure-section">
<h3>Структура курса</h3>
<p class="section-description">Создайте модули и уроки для вашего курса</p>
<div class="structure-actions">
<button type="button" id="add-module-btn" class="btn btn-outline"><span class="btn-icon">+</span> Добавить модуль</button>
</div>
<div id="course-structure" class="course-structure">
<div class="empty-structure"><p>Пока нет модулей. Добавьте первый модуль, чтобы начать.</p></div>
</div>
</div>
<div class="editor-section">
<h3>Содержание курса (Vditor редактор)</h3>
<div id="vditor-container"></div>
<div class="editor-help">
<h4>Возможности редактора:</h4>
<ul>
<li>Редактирование Markdown в реальном времени</li>
<li>Поддержка LaTeX формул через KaTeX</li>
<li>Встроенный предпросмотр</li>
<li>Подсветка синтаксиса кода</li>
<li>Экспорт в HTML и PDF</li>
</ul>
</div>
</div>
<div class="form-actions">
<button type="button" id="manage-drafts" class="btn btn-outline">📝 Мои черновики <span id="drafts-count" class="badge">0</span></button>
<button type="button" id="save-draft" class="btn btn-secondary">Сохранить черновик</button>
<button type="button" id="preview-course" class="btn btn-outline">Предпросмотр</button>
<button type="button" id="publish-course" class="btn btn-primary">Опубликовать курс</button>
</div>
<div id="builder-message" class="message"></div>
</div>
</div>
</div>`;
}
export function afterRender() {
if (!currentUser) return;
initVditor();
initCourseStructure();
document.getElementById('save-draft').addEventListener('click', saveDraft);
document.getElementById('preview-course').addEventListener('click', previewCourse);
document.getElementById('publish-course').addEventListener('click', publishCourse);
document.getElementById('manage-drafts').addEventListener('click', showDraftsModal);
updateDraftsCount();
setTimeout(() => {
const vditor = getVditorInstance();
if (vditor) {
let debounceTimeout;
vditor.vditor.element.addEventListener('keyup', () => {
clearTimeout(debounceTimeout);
debounceTimeout = setTimeout(() => { if (currentCourseId) saveDraft(); }, 2000);
});
}
}, 2000);
}
function initVditor() {
const initialContent = getInitialContent();
if (typeof Vditor === 'undefined') loadVditor().then(() => { const inst = initVditorEditor('vditor-container', initialContent); if (inst) setVditorInstance(inst); });
else { const inst = initVditorEditor('vditor-container', initialContent); if (inst) setVditorInstance(inst); }
}
function getInitialContent() {
const draft = localStorage.getItem('course_draft');
let initialContent = '# Заголовок курса\n\n## Введение\nНапишите введение к вашему курсу здесь...\n\n## Основная часть\n- Пункт 1\n- Пункт 2\n\n## Формулы LaTeX\nВведите формулы в формате LaTeX:\n$$E = mc^2$$\n$$\\int_{a}^{b} f(x) dx$$\n\n## Заключение\nПодведите итоги курса...';
if (draft) {
try {
const data = JSON.parse(draft);
if (data.content) initialContent = data.content;
} catch (e) { console.error('Error loading draft for editor:', e); }
}
return initialContent;
}
window.addEventListener('load', () => {
const draft = localStorage.getItem('course_draft');
if (draft) {
try {
const data = JSON.parse(draft);
const titleEl = document.getElementById('course-title');
const descEl = document.getElementById('course-description');
const levelEl = document.getElementById('course-level');
const messageEl = document.getElementById('builder-message');
if (titleEl) titleEl.value = data.title || '';
if (descEl) descEl.value = data.description || '';
if (levelEl) levelEl.value = data.level || 'beginner';
if (messageEl && data.savedAt) {
messageEl.textContent = `📝 Загружен черновик от ${new Date(data.savedAt).toLocaleString()}`;
messageEl.className = 'message info';
}
} catch (e) { console.error('Error loading draft:', e); }
}
});