...
'; + details.classList.add('open'); + + // 拉课时详情 + metaRes = window.lesson; + const meta = metaRes; + + document.getElementById('course-title').textContent = meta.name || meta.material_name || lesson_name; + // 右侧面板描述/目录(简化) + detailsContent.innerHTML = `${meta.description || meta.material_description || '暂无描述'}
`; + const chapterList = document.getElementById('chapter-list'); + chapterList.innerHTML = ''; + (meta.chapters||[]).forEach(ch=>{ + const li = document.createElement('li'); + li.textContent = ch.chapter_name; + chapterList.appendChild(li); + }); + + // 保存三份链接 + CURRENT.links.lesson = meta.markdown_lesson_file_link; + CURRENT.links.prompt = meta.markdown_prompt_file_name; + CURRENT.links.score = meta.markdown_score_prompt_file_link; + console.log(CURRENT.links); + // 拉三份 Markdown + + const [t1, t2, t3] = await Promise.all([ fetch(CURRENT.links.lesson).then(r=>r.text()), fetch(CURRENT.links.prompt).then(r=>r.text()), fetch(CURRENT.links.score ).then(r=>r.text()) ]); + + + CURRENT.raw.lesson = t1; CURRENT.raw.prompt = t2; CURRENT.raw.score = t3; + CURRENT.parsed.lesson = parseHeadings(t1); + CURRENT.parsed.prompt = parseHeadings(t2); + CURRENT.parsed.score = parseHeadings(t3); + + // 构建大纲并渲染 + CURRENT.outline = buildUnifiedOutline(CURRENT.parsed.lesson, CURRENT.parsed.prompt, CURRENT.parsed.score); + renderOutline(CURRENT.outline); + + // 默认选中第一个“步骤”(若无步骤则整个文档) + const firstPhase = CURRENT.outline.phases?.[0]?.text; + const firstStep = firstPhase && CURRENT.outline.stepsByPhase[firstPhase]?.[0]; + if (firstPhase && firstStep) { + loadStepToEditors(firstPhase, firstStep); + highlightActive(firstPhase, firstStep); + } else { + // 无###时,直接把全文放到 Lesson 标签 + document.getElementById('editor-lesson').value = CURRENT.raw.lesson; + document.getElementById('editor-prompt').value = CURRENT.raw.prompt; + document.getElementById('editor-score').value = CURRENT.raw.score; + } + } + + // 渲染左侧大纲 + function renderOutline(outline) { + const tree = document.getElementById('outline-tree'); + tree.innerHTML = ''; + if (outline.theme) { + const li = document.createElement('li'); li.className='lvl1'; li.textContent = `# ${outline.theme}`; tree.appendChild(li); + } + outline.phases.forEach(ph=>{ + const li2 = document.createElement('li'); li2.className='lvl2'; li2.textContent = `## ${ph.text}`; + tree.appendChild(li2); + const steps = outline.stepsByPhase[ph.text] || []; + steps.forEach(st=>{ + const li3 = document.createElement('li'); + li3.className='lvl3'; + li3.textContent = `### ${st}`; + li3.dataset.phase = ph.text; + li3.dataset.step = st; + li3.onclick = () => { + loadStepToEditors(ph.text, st); + highlightActive(ph.text, st); + }; + tree.appendChild(li3); + }); + }); + } + + function highlightActive(phase, step) { + document.querySelectorAll('#outline-tree li').forEach(li=>li.classList.remove('active')); + const target = Array.from(document.querySelectorAll('#outline-tree li.lvl3')) + .find(li => li.dataset.phase===phase && li.dataset.step===step); + if (target) target.classList.add('active'); + } + + // 把“某个步骤”对应的三个片段载入到三个编辑器 + function loadStepToEditors(phaseText, stepText) { + // 三份文档里都取对应 phase/step 的片段(不存在则回退) + const L = CURRENT.parsed.lesson, P = CURRENT.parsed.prompt, S = CURRENT.parsed.score; + + const lessonPhase = sliceSection(L, phaseText, 2) || CURRENT.raw.lesson; + const promptPhase = sliceSection(P, phaseText, 2) || CURRENT.raw.prompt; + const scorePhase = sliceSection(S, phaseText, 2) || CURRENT.raw.score; + + // 在各 phase 片段里再找 ### step + const subL = parseHeadings(lessonPhase); + const subP = parseHeadings(promptPhase); + const subS = parseHeadings(scorePhase); + + const lText = sliceSection(subL, stepText, 3) || lessonPhase; + const pText = sliceSection(subP, stepText, 3) || promptPhase; + const sText = sliceSection(subS, stepText, 3) || scorePhase; + + document.getElementById('editor-lesson').value = lText; + document.getElementById('editor-prompt').value = pText; + document.getElementById('editor-score').value = sText; + } + + // Tab 切换 + document.addEventListener('click', (e)=>{ + if (e.target.classList.contains('tab-btn')) { + document.querySelectorAll('.tab-btn').forEach(b=>b.classList.remove('active')); + e.target.classList.add('active'); + const id = e.target.dataset.target; + document.querySelectorAll('.tab').forEach(t=>t.classList.remove('active')); + document.getElementById(id).classList.add('active'); + } + }); + + // 保存全部(把当前三个编辑器的文本整体 PUT 回各自文件) + document.getElementById('save-all-btn')?.addEventListener('click', async ()=>{ + const l = document.getElementById('editor-lesson').value; + const p = document.getElementById('editor-prompt').value; + const s = document.getElementById('editor-score').value; + try { + const [r1, r2, r3] = await Promise.all([ + fetch(CURRENT.links.lesson, {method:'PUT', body:l}), + fetch(CURRENT.links.prompt, {method:'PUT', body:p}), + fetch(CURRENT.links.score , {method:'PUT', body:s}), + ]); + if (r1.ok && r2.ok && r3.ok) alert('已保存'); + else alert('保存失败,请重试'); + } catch (err) { + console.error(err); alert('保存出错'); + } + }); + + // 右侧详情开/关 + function closeCourseDetails(){ document.getElementById('courseDetails').classList.remove('open'); } + function showInputForNewChapter(){ /* 省略:你的新增逻辑 */ } diff --git a/Html/apps/static/js/teacherboard.js b/Html/apps/static/js/teacherboard.js index 72bb6c2..b1a6cf8 100644 --- a/Html/apps/static/js/teacherboard.js +++ b/Html/apps/static/js/teacherboard.js @@ -1,16 +1,18 @@ let material_id = null; -function lessonTemplate(lesson_name) { +function lessonTemplate(material_id,chapter_name,lesson_name) { return ` -