feat(lab-content-engine): phase 5 frontend — чип «Связано с программой»
Реальный фронт Ф5 (ранее ошибочно считал его сделанным параллельной сессией — его не было). _loadRelated(simId) в lab-glue.js: GET /api/lab/sims/:id/related, рендерит чипы-ссылки рядом с заголовком симуляции; контейнер #sim-related создаётся динамически (без правок lab.html/CSS). Вызов из openSim (lab-init.js). Тихо прячется при отсутствии связей/ошибке. Иконка — inline SVG .ic, без эмодзи. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -971,6 +971,58 @@
|
||||
});
|
||||
}
|
||||
|
||||
/* ── Контент-движок, Фаза 5: чип «Связано с программой» ──────────────────
|
||||
Подтягивает курикулумные связи симуляции (GET /api/lab/sims/:id/related) и
|
||||
рендерит чипы-ссылки рядом с заголовком симуляции. Самодостаточно: создаёт
|
||||
контейнер #sim-related динамически (без правок lab.html/CSS — меньше риск
|
||||
конфликта с параллельными сессиями). Тихо прячется, если связей нет/ошибка. */
|
||||
var _LAB_LINK_ICON = '<svg class="ic" viewBox="0 0 24 24" style="width:13px;height:13px;vertical-align:-2px"><path d="M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71"/><path d="M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71"/></svg>';
|
||||
function _labRelEsc(s) {
|
||||
return String(s == null ? '' : s).replace(/[&<>"']/g, function (c) {
|
||||
return { '&': '&', '<': '<', '>': '>', '"': '"', "'": ''' }[c];
|
||||
});
|
||||
}
|
||||
function _ensureRelatedHost() {
|
||||
var host = document.getElementById('sim-related');
|
||||
if (host) return host;
|
||||
host = document.createElement('div');
|
||||
host.id = 'sim-related';
|
||||
host.style.cssText = 'display:none;align-items:center;gap:6px;flex-wrap:wrap;margin-left:14px;min-width:0';
|
||||
var title = document.getElementById('sim-topbar-title');
|
||||
if (title && title.parentNode) title.parentNode.insertBefore(host, title.nextSibling);
|
||||
return host;
|
||||
}
|
||||
function _loadRelated(simId) {
|
||||
var host = _ensureRelatedHost();
|
||||
host.style.display = 'none';
|
||||
host.innerHTML = '';
|
||||
if (!window.LS || !LS.api) return;
|
||||
LS.api('/api/lab/sims/' + encodeURIComponent(simId) + '/related')
|
||||
.then(function (data) {
|
||||
var links = (data && data.links) || {};
|
||||
var all = [].concat(links.textbook || [], links.topic || [], links.kmap || [], links.question || []);
|
||||
if (!all.length) return;
|
||||
var chipBase = 'display:inline-flex;align-items:center;gap:4px;font-size:.72rem;padding:3px 9px;border-radius:999px;';
|
||||
var html = '<span style="font-size:.68rem;font-weight:700;color:var(--text-3);text-transform:uppercase;letter-spacing:.05em">'
|
||||
+ _LAB_LINK_ICON + ' Связано с программой</span>';
|
||||
all.forEach(function (l) {
|
||||
var label = _labRelEsc(l.label || (l.kind + ':' + l.ref_id));
|
||||
if (l.href) {
|
||||
html += '<a href="' + _labRelEsc(l.href) + '" title="Открыть в учебнике" style="' + chipBase
|
||||
+ 'background:rgba(155,93,229,.14);color:var(--violet);text-decoration:none;border:1px solid rgba(155,93,229,.32)">' + label + '</a>';
|
||||
} else {
|
||||
html += '<span style="' + chipBase
|
||||
+ 'background:rgba(255,255,255,.06);color:var(--text-2);border:1px solid rgba(255,255,255,.12)">' + label + '</span>';
|
||||
}
|
||||
});
|
||||
host.innerHTML = html;
|
||||
host.style.display = 'flex';
|
||||
if (window.lucide) lucide.createIcons();
|
||||
})
|
||||
.catch(function () { /* нет связей или ошибка — чип просто не показываем */ });
|
||||
}
|
||||
window._loadRelated = _loadRelated;
|
||||
|
||||
/* ── embed mode + auto-open from ?sim= ── */
|
||||
const _qp = new URLSearchParams(location.search);
|
||||
var _embedMode = _qp.get('embed') === '1';
|
||||
|
||||
@@ -119,6 +119,9 @@
|
||||
// load theory for this sim
|
||||
loadTheory(id.includes(':') ? id.split(':')[0] : id);
|
||||
|
||||
// Фаза 5: чип «Связано с программой» (курикулумные связи симуляции).
|
||||
if (typeof _loadRelated === 'function') _loadRelated(id.includes(':') ? id.split(':')[0] : id);
|
||||
|
||||
// ── Контент-движок (Фаза 1): диспетчеризация через реестр ──
|
||||
// Все каталожные симуляции зарегистрированы в _register-all.js.
|
||||
// Алиасы deep-link (magnetic/coulomb/thinlens/mirrors/refraction) нормализуем
|
||||
|
||||
Reference in New Issue
Block a user