feat(textbooks): инжект task-панелей §31-36 в physics_9_ch4.html
Жалоба: 'каждому параграфу там [в монолите] есть задачи, тут нет'.
В монолите physics_9.html — отдельный tab-tasks блок содержит 36 ptab-pN
панелей (~1.3 KB каждая) со scaffold'ом score-bar/prog-wrap/nav-dots/
taskArea/feedback/summary. Сами задачи (TASKS_P31..P36) рендерятся в
taskAreapN через goToTask('pN', i).
migrate_phys9_tasks.cjs:
- Извлекает ptab-p31..p36 из монолита (clean emoji + FA<i>)
- Внутри каждого build_pN в ch4 после theory body добавляет <div class='wg'>
с заголовком 'Задачи §N · Тренажёр §N' и вставляет ptab HTML
- Через 80 мс после render вызывает goToTask('pN', 0) → рендерит первую
задачу из TASKS_PN
Не делаю это для §1-30: TASKS_P1..P30 не определены в монолите
(там было решение делать тренажёры только для главы 'Законы сохранения').
This commit is contained in:
@@ -1072,6 +1072,39 @@ function build_p31(){
|
||||
box.innerHTML = html;
|
||||
renderMath(box);
|
||||
wireReadBtn('p31');
|
||||
// === Задачи §31 — task panel (auto-injected from monolith) ===
|
||||
const tasksBlock = document.createElement('div');
|
||||
tasksBlock.className = 'wg';
|
||||
tasksBlock.style.marginTop = '20px';
|
||||
tasksBlock.innerHTML = '<div class="wg-header"><span class="wg-badge">Задачи</span><div class="wg-title">Тренажёр §31</div></div>' + `<div id="ptab-p31">
|
||||
<div class="score-bar">
|
||||
<div class="chip chip-ok"> <span id="okp31">0</span></div>
|
||||
<div class="chip chip-tot"><span id="curp31">0</span> / <span id="maxp31">12</span></div>
|
||||
<button class="btn btn-ghost" onclick="resetTasks('p31')" style="padding:6px 13px;font-size:.74rem"> Заново</button>
|
||||
</div>
|
||||
<div class="prog-wrap"><div class="prog-fill" id="progp31" style="width:0%"></div></div>
|
||||
<div class="nav-dots" id="navDotsp31"></div>
|
||||
<div id="taskAreap31"></div>
|
||||
<div class="feedback" id="fbp31"></div>
|
||||
<div style="display:flex;gap:10px;margin-top:10px;justify-content:flex-end">
|
||||
<button class="btn btn-next" id="nextBtnp31" onclick="nextTask('p31')" style="display:none"> Следующая</button>
|
||||
</div>
|
||||
<div class="summary" id="sump31">
|
||||
<h2>§31 — готово!</h2>
|
||||
<div class="big-score" id="sumScorep31"></div>
|
||||
<div class="sum-grade" id="sumGradep31"></div>
|
||||
<div class="sum-btns">
|
||||
<button class="btn btn-pri" onclick="resetTasks('p31')"> Ещё раз</button>
|
||||
<button class="btn btn-ghost" onclick="setParaTab('p32')">→ §32</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>`;
|
||||
box.appendChild(tasksBlock);
|
||||
// Auto-render first task
|
||||
setTimeout(() => {
|
||||
try { if (typeof goToTask === 'function') goToTask('p31', 0); }
|
||||
catch(e) { console.warn('p31 goToTask:', e.message); }
|
||||
}, 80);
|
||||
}
|
||||
|
||||
function build_p32(){
|
||||
@@ -1265,6 +1298,39 @@ function build_p32(){
|
||||
box.innerHTML = html;
|
||||
renderMath(box);
|
||||
wireReadBtn('p32');
|
||||
// === Задачи §32 — task panel (auto-injected from monolith) ===
|
||||
const tasksBlock = document.createElement('div');
|
||||
tasksBlock.className = 'wg';
|
||||
tasksBlock.style.marginTop = '20px';
|
||||
tasksBlock.innerHTML = '<div class="wg-header"><span class="wg-badge">Задачи</span><div class="wg-title">Тренажёр §32</div></div>' + `<div id="ptab-p32" style="display:none">
|
||||
<div class="score-bar">
|
||||
<div class="chip chip-ok"> <span id="okp32">0</span></div>
|
||||
<div class="chip chip-tot"><span id="curp32">0</span> / <span id="maxp32">12</span></div>
|
||||
<button class="btn btn-ghost" onclick="resetTasks('p32')" style="padding:6px 13px;font-size:.74rem"> Заново</button>
|
||||
</div>
|
||||
<div class="prog-wrap"><div class="prog-fill" id="progp32" style="width:0%"></div></div>
|
||||
<div class="nav-dots" id="navDotsp32"></div>
|
||||
<div id="taskAreap32"></div>
|
||||
<div class="feedback" id="fbp32"></div>
|
||||
<div style="display:flex;gap:10px;margin-top:10px;justify-content:flex-end">
|
||||
<button class="btn btn-next" id="nextBtnp32" onclick="nextTask('p32')" style="display:none"> Следующая</button>
|
||||
</div>
|
||||
<div class="summary" id="sump32">
|
||||
<h2>§32 — готово!</h2>
|
||||
<div class="big-score" id="sumScorep32"></div>
|
||||
<div class="sum-grade" id="sumGradep32"></div>
|
||||
<div class="sum-btns">
|
||||
<button class="btn btn-pri" onclick="resetTasks('p32')"> Ещё раз</button>
|
||||
<button class="btn btn-ghost" onclick="setParaTab('p33')">→ §33</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>`;
|
||||
box.appendChild(tasksBlock);
|
||||
// Auto-render first task
|
||||
setTimeout(() => {
|
||||
try { if (typeof goToTask === 'function') goToTask('p32', 0); }
|
||||
catch(e) { console.warn('p32 goToTask:', e.message); }
|
||||
}, 80);
|
||||
}
|
||||
|
||||
function build_p33(){
|
||||
@@ -1524,6 +1590,39 @@ function build_p33(){
|
||||
box.innerHTML = html;
|
||||
renderMath(box);
|
||||
wireReadBtn('p33');
|
||||
// === Задачи §33 — task panel (auto-injected from monolith) ===
|
||||
const tasksBlock = document.createElement('div');
|
||||
tasksBlock.className = 'wg';
|
||||
tasksBlock.style.marginTop = '20px';
|
||||
tasksBlock.innerHTML = '<div class="wg-header"><span class="wg-badge">Задачи</span><div class="wg-title">Тренажёр §33</div></div>' + `<div id="ptab-p33" style="display:none">
|
||||
<div class="score-bar">
|
||||
<div class="chip chip-ok"> <span id="okp33">0</span></div>
|
||||
<div class="chip chip-tot"><span id="curp33">0</span> / <span id="maxp33">8</span></div>
|
||||
<button class="btn btn-ghost" onclick="resetTasks('p33')" style="padding:6px 13px;font-size:.74rem"> Заново</button>
|
||||
</div>
|
||||
<div class="prog-wrap"><div class="prog-fill" id="progp33" style="width:0%"></div></div>
|
||||
<div class="nav-dots" id="navDotsp33"></div>
|
||||
<div id="taskAreap33"></div>
|
||||
<div class="feedback" id="fbp33"></div>
|
||||
<div style="display:flex;gap:10px;margin-top:10px;justify-content:flex-end">
|
||||
<button class="btn btn-next" id="nextBtnp33" onclick="nextTask('p33')" style="display:none"> Следующая</button>
|
||||
</div>
|
||||
<div class="summary" id="sump33">
|
||||
<h2>§33 — готово!</h2>
|
||||
<div class="big-score" id="sumScorep33"></div>
|
||||
<div class="sum-grade" id="sumGradep33"></div>
|
||||
<div class="sum-btns">
|
||||
<button class="btn btn-pri" onclick="resetTasks('p33')"> Ещё раз</button>
|
||||
<button class="btn btn-ghost" onclick="setParaTab('p34')">→ §34</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>`;
|
||||
box.appendChild(tasksBlock);
|
||||
// Auto-render first task
|
||||
setTimeout(() => {
|
||||
try { if (typeof goToTask === 'function') goToTask('p33', 0); }
|
||||
catch(e) { console.warn('p33 goToTask:', e.message); }
|
||||
}, 80);
|
||||
}
|
||||
|
||||
function build_p34(){
|
||||
@@ -1811,6 +1910,39 @@ Eп₂ = <span id="ep2val" style="color:#7c3aed">1000</span> Дж
|
||||
box.innerHTML = html;
|
||||
renderMath(box);
|
||||
wireReadBtn('p34');
|
||||
// === Задачи §34 — task panel (auto-injected from monolith) ===
|
||||
const tasksBlock = document.createElement('div');
|
||||
tasksBlock.className = 'wg';
|
||||
tasksBlock.style.marginTop = '20px';
|
||||
tasksBlock.innerHTML = '<div class="wg-header"><span class="wg-badge">Задачи</span><div class="wg-title">Тренажёр §34</div></div>' + `<div id="ptab-p34" style="display:none">
|
||||
<div class="score-bar">
|
||||
<div class="chip chip-ok"> <span id="okp34">0</span></div>
|
||||
<div class="chip chip-tot"><span id="curp34">0</span> / <span id="maxp34">9</span></div>
|
||||
<button class="btn btn-ghost" onclick="resetTasks('p34')" style="padding:6px 13px;font-size:.74rem"> Заново</button>
|
||||
</div>
|
||||
<div class="prog-wrap"><div class="prog-fill" id="progp34" style="width:0%"></div></div>
|
||||
<div class="nav-dots" id="navDotsp34"></div>
|
||||
<div id="taskAreap34"></div>
|
||||
<div class="feedback" id="fbp34"></div>
|
||||
<div style="display:flex;gap:10px;margin-top:10px;justify-content:flex-end">
|
||||
<button class="btn btn-next" id="nextBtnp34" onclick="nextTask('p34')" style="display:none"> Следующая</button>
|
||||
</div>
|
||||
<div class="summary" id="sump34">
|
||||
<h2>§34 — готово!</h2>
|
||||
<div class="big-score" id="sumScorep34"></div>
|
||||
<div class="sum-grade" id="sumGradep34"></div>
|
||||
<div class="sum-btns">
|
||||
<button class="btn btn-pri" onclick="resetTasks('p34')"> Ещё раз</button>
|
||||
<button class="btn btn-ghost" onclick="setParaTab('p35')">→ §35</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>`;
|
||||
box.appendChild(tasksBlock);
|
||||
// Auto-render first task
|
||||
setTimeout(() => {
|
||||
try { if (typeof goToTask === 'function') goToTask('p34', 0); }
|
||||
catch(e) { console.warn('p34 goToTask:', e.message); }
|
||||
}, 80);
|
||||
}
|
||||
|
||||
function build_p35(){
|
||||
@@ -1932,6 +2064,39 @@ function build_p35(){
|
||||
box.innerHTML = html;
|
||||
renderMath(box);
|
||||
wireReadBtn('p35');
|
||||
// === Задачи §35 — task panel (auto-injected from monolith) ===
|
||||
const tasksBlock = document.createElement('div');
|
||||
tasksBlock.className = 'wg';
|
||||
tasksBlock.style.marginTop = '20px';
|
||||
tasksBlock.innerHTML = '<div class="wg-header"><span class="wg-badge">Задачи</span><div class="wg-title">Тренажёр §35</div></div>' + `<div id="ptab-p35" style="display:none">
|
||||
<div class="score-bar">
|
||||
<div class="chip chip-ok"> <span id="okp35">0</span></div>
|
||||
<div class="chip chip-tot"><span id="curp35">0</span> / <span id="maxp35">8</span></div>
|
||||
<button class="btn btn-ghost" onclick="resetTasks('p35')" style="padding:6px 13px;font-size:.74rem"> Заново</button>
|
||||
</div>
|
||||
<div class="prog-wrap"><div class="prog-fill" id="progp35" style="width:0%"></div></div>
|
||||
<div class="nav-dots" id="navDotsp35"></div>
|
||||
<div id="taskAreap35"></div>
|
||||
<div class="feedback" id="fbp35"></div>
|
||||
<div style="display:flex;gap:10px;margin-top:10px;justify-content:flex-end">
|
||||
<button class="btn btn-next" id="nextBtnp35" onclick="nextTask('p35')" style="display:none"> Следующая</button>
|
||||
</div>
|
||||
<div class="summary" id="sump35">
|
||||
<h2>§35 — готово!</h2>
|
||||
<div class="big-score" id="sumScorep35"></div>
|
||||
<div class="sum-grade" id="sumGradep35"></div>
|
||||
<div class="sum-btns">
|
||||
<button class="btn btn-pri" onclick="resetTasks('p35')"> Ещё раз</button>
|
||||
<button class="btn btn-ghost" onclick="setParaTab('p36')">→ §36</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>`;
|
||||
box.appendChild(tasksBlock);
|
||||
// Auto-render first task
|
||||
setTimeout(() => {
|
||||
try { if (typeof goToTask === 'function') goToTask('p35', 0); }
|
||||
catch(e) { console.warn('p35 goToTask:', e.message); }
|
||||
}, 80);
|
||||
}
|
||||
|
||||
function build_p36(){
|
||||
@@ -2083,6 +2248,39 @@ $\\dfrac{mv_0^2}{2} + 0 = 0 + mgh_{\\max}$</span></li>
|
||||
box.innerHTML = html;
|
||||
renderMath(box);
|
||||
wireReadBtn('p36');
|
||||
// === Задачи §36 — task panel (auto-injected from monolith) ===
|
||||
const tasksBlock = document.createElement('div');
|
||||
tasksBlock.className = 'wg';
|
||||
tasksBlock.style.marginTop = '20px';
|
||||
tasksBlock.innerHTML = '<div class="wg-header"><span class="wg-badge">Задачи</span><div class="wg-title">Тренажёр §36</div></div>' + `<div id="ptab-p36" style="display:none">
|
||||
<div class="score-bar">
|
||||
<div class="chip chip-ok"> <span id="okp36">0</span></div>
|
||||
<div class="chip chip-tot"><span id="curp36">0</span> / <span id="maxp36">8</span></div>
|
||||
<button class="btn btn-ghost" onclick="resetTasks('p36')" style="padding:6px 13px;font-size:.74rem"> Заново</button>
|
||||
</div>
|
||||
<div class="prog-wrap"><div class="prog-fill" id="progp36" style="width:0%"></div></div>
|
||||
<div class="nav-dots" id="navDotsp36"></div>
|
||||
<div id="taskAreap36"></div>
|
||||
<div class="feedback" id="fbp36"></div>
|
||||
<div style="display:flex;gap:10px;margin-top:10px;justify-content:flex-end">
|
||||
<button class="btn btn-next" id="nextBtnp36" onclick="nextTask('p36')" style="display:none"> Следующая</button>
|
||||
</div>
|
||||
<div class="summary" id="sump36">
|
||||
<h2>§36 — готово!</h2>
|
||||
<div class="big-score" id="sumScorep36"></div>
|
||||
<div class="sum-grade" id="sumGradep36"></div>
|
||||
<div class="sum-btns">
|
||||
<button class="btn btn-pri" onclick="resetTasks('p36')"> Ещё раз</button>
|
||||
<button class="btn btn-ghost" onclick="setParaTab('hard')">→ Сложные</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>`;
|
||||
box.appendChild(tasksBlock);
|
||||
// Auto-render first task
|
||||
setTimeout(() => {
|
||||
try { if (typeof goToTask === 'function') goToTask('p36', 0); }
|
||||
catch(e) { console.warn('p36 goToTask:', e.message); }
|
||||
}, 80);
|
||||
}
|
||||
|
||||
function build_final4(){
|
||||
|
||||
Reference in New Issue
Block a user