Интерфейс врача: отчёты (сегментация+охват), протокол светофор, каталог базисной терапии и назначение пациенту
This commit is contained in:
parent
175b6181b5
commit
54b9bf8816
268
index.html
268
index.html
@ -255,6 +255,7 @@ function seed(){
|
|||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
role:"patient",
|
role:"patient",
|
||||||
|
staffTab:"patients",
|
||||||
currentPatient:"p1",
|
currentPatient:"p1",
|
||||||
patients:[
|
patients:[
|
||||||
{
|
{
|
||||||
@ -339,6 +340,75 @@ var ZONE_TXT = {
|
|||||||
red:{t:"Ухудшение", d:"Срочно! Выполните рекомендации и вызовите скорую при необходимости."}
|
red:{t:"Ухудшение", d:"Срочно! Выполните рекомендации и вызовите скорую при необходимости."}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* ============ ПРОТОКОЛ «СВЕТОФОР» (расширенные действия) ============ */
|
||||||
|
var ZONE_PROTOCOL = {
|
||||||
|
green:{
|
||||||
|
title:"🟢 Зелёная зона — стабилен",
|
||||||
|
crit:"SpO₂ ≥ 95% · ЧДД 12–20/мин · ЧСС 60–100 уд/мин · CAT не растёт · нет гнойной мокроты",
|
||||||
|
patient:["Продолжать базисную терапию строго по схеме","Вести дневник 2–3 раза в день","Принимать препараты по расписанию, не пропускать","Дыхательная гимнастика и регулярная физическая активность","Вакцинация (грипп, пневмококк) по графику"],
|
||||||
|
staff:["Рутинное наблюдение, просмотр динамики 1–2 раза в неделю","Контроль adherence и техники ингаляции","Плановый осмотр 1 раз в 1–3 месяца, спирометрия, CAT","Обучение и поддержка самопомощи"],
|
||||||
|
esc:"Эскалации не требуется"
|
||||||
|
},
|
||||||
|
yellow:{
|
||||||
|
title:"🟡 Жёлтая зона — внимание",
|
||||||
|
crit:"SpO₂ 90–94% · ЧДД 21–24/мин · ЧСС 101–110 уд/мин · CAT вырос на ≥2 балла · нарастание одышки",
|
||||||
|
patient:["Применить спасательный бронхолитик (сальбутамол 2–4 вдоха / небулайзер)","Проверить и при необходимости усилить О₂ по схеме","Контроль SpO₂ каждые 15–30 минут","Усилить контроль до 3–4 замеров/день","Связаться с медсестрой в течение дня","Начать резервный ГКС/антибиотик по плану врача при гнойной мокроте"],
|
||||||
|
staff:["Связаться с пациентом в течение дня","Оценить adherence и технику ингаляции","Коррекция терапии: усилить бронхолитик, рассмотреть ИГКС","Контроль через 24–48 часов","Информировать лечащего врача при отсутствии эффекта"],
|
||||||
|
esc:"Нет эффекта за 24–48ч → красная зона, рассмотреть госпитализацию"
|
||||||
|
},
|
||||||
|
red:{
|
||||||
|
title:"🔴 Красная зона — ухудшение",
|
||||||
|
crit:"SpO₂ < 90% · ЧДД > 24/мин · ЧСС > 110 уд/мин · резкая одышка в покое · гнойная мокрота · лихорадка",
|
||||||
|
patient:["Увеличить поток О₂ по схеме","Бронхолитик через небулайзер/ДАИ (сальбутамол ± ипратропий)","Положение ортопноэ, дыхание через сжатые губы","Старт системной терапии по плану: ГКС ± антибиотик","Вызвать скорую при SpO₂<88% >5мин или нарастании одышки"],
|
||||||
|
staff:["Срочный контакт с пациентом, решение о госпитализации/вызове бригады","Назначить/скорректировать системную терапию (ГКС, антибиотики, О₂)","Контроль через 1–4 часа","Передача информации лечащему врачу и оформление вмешательства","Подготовка к госпитализации при нарастании РДС"],
|
||||||
|
esc:"Экстренная госпитализация: SpO₂<88%, ЧДД>30, спутанность сознания, цианоз, загрудинные боли"
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/* ============ КАТАЛОГ БАЗИСНОЙ ТЕРАПИИ ХОБЛ (для назначения врачом) ============ */
|
||||||
|
var MED_CATALOG = [
|
||||||
|
{grp:"Купирование (короткодействующие)", items:[
|
||||||
|
{id:"salbutamol", name:"Сальбутамол (ДАИ/небулайзер)", dt:["по потребности"]},
|
||||||
|
{id:"fenoterol", name:"Фенотерол (Беротек)", dt:["по потребности"]},
|
||||||
|
{id:"ipratropium", name:"Ипратропия бромид (Атровент)", dt:["по потребности"]},
|
||||||
|
{id:"ipra_feno", name:"Ипратропий/Фенотерол (Беродуал)", dt:["по потребности"]}
|
||||||
|
]},
|
||||||
|
{grp:"ЛАМА (длиннодействующие М-холинолитики)", items:[
|
||||||
|
{id:"tiotropium", name:"Тиотропий (Спирива)", dt:["08:00"]},
|
||||||
|
{id:"glycopyrronium", name:"Гликопирроний (Сибри)", dt:["08:00"]},
|
||||||
|
{id:"aclidinium", name:"Аклидиний (Эклира)", dt:["08:00","20:00"]},
|
||||||
|
{id:"umeclidinium", name:"Умеклидиний (Инкруз)", dt:["08:00"]}
|
||||||
|
]},
|
||||||
|
{grp:"ЛАБА (длиннодействующие β2-агонисты)", items:[
|
||||||
|
{id:"indacaterol", name:"Индакатерол (Онбрез)", dt:["08:00"]},
|
||||||
|
{id:"olodaterol", name:"Олодатерол (Стриворди)", dt:["08:00"]},
|
||||||
|
{id:"salmeterol", name:"Сальметерол (Серевент)", dt:["08:00","20:00"]},
|
||||||
|
{id:"formoterol", name:"Формотерол (Форадил)", dt:["08:00","20:00"]}
|
||||||
|
]},
|
||||||
|
{grp:"ЛАМА/ЛАБА (комбинированные)", items:[
|
||||||
|
{id:"gly_ind", name:"Гликопирроний/Индакатерол (Ультибро)", dt:["08:00"]},
|
||||||
|
{id:"tio_olo", name:"Тиотропий/Олодатерол (Спиольто)", dt:["08:00"]},
|
||||||
|
{id:"ume_vil", name:"Умеклидиний/Вилинтерол (Аноро)", dt:["08:00"]}
|
||||||
|
]},
|
||||||
|
{grp:"ИГКС/ЛАБА (комбинированные)", items:[
|
||||||
|
{id:"bud_fm", name:"Будесонид/Формотерол (Симбикорт)", dt:["08:00","20:00"]},
|
||||||
|
{id:"flu_sal", name:"Флутиказон/Сальметерол (Серетид)", dt:["08:00","20:00"]},
|
||||||
|
{id:"flu_vil", name:"Флутиказон/Вилантерол (Релвар)", dt:["08:00"]},
|
||||||
|
{id:"bec_fm", name:"Беклометазон/Формотерол (Фостер)", dt:["08:00","20:00"]}
|
||||||
|
]},
|
||||||
|
{grp:"Тройная терапия (ИГКС/ЛАБА/ЛАМА)", items:[
|
||||||
|
{id:"flu_ume_vil", name:"Флутиказон/Умеклидиний/Вилантерол (Трео)", dt:["08:00"]},
|
||||||
|
{id:"bec_fm_gly", name:"Беклометазон/Формотерол/Гликопирроний (Trimbow)", dt:["08:00","20:00"]}
|
||||||
|
]},
|
||||||
|
{grp:"Прочее (ФДЭ-4, муколитики, макролиды, О₂)", items:[
|
||||||
|
{id:"roflumilast", name:"Рофлумиласт (Даксас) — ФДЭ-4", dt:["21:00"]},
|
||||||
|
{id:"nac", name:"N-ацетилцистеин (муколитик)", dt:["08:00","20:00"]},
|
||||||
|
{id:"erdosteine", name:"Эрдостеин (муколитик)", dt:["08:00","20:00"]},
|
||||||
|
{id:"azithromycin", name:"Азитромицин (профилактика обострений)", dt:["08:00"]},
|
||||||
|
{id:"o2_therapy", name:"Длительная О₂-терапия", dt:["15ч/сут 2л/мин"]}
|
||||||
|
]}
|
||||||
|
];
|
||||||
|
|
||||||
/* ============ CAT ВОПРОСЫ ============ */
|
/* ============ CAT ВОПРОСЫ ============ */
|
||||||
var CAT_Q = [
|
var CAT_Q = [
|
||||||
{q:"Кашель", a:"Я никогда не кашляю", b:"Я постоянно кашляю"},
|
{q:"Кашель", a:"Я никогда не кашляю", b:"Я постоянно кашляю"},
|
||||||
@ -354,7 +424,7 @@ function catLevel(s){ if(s<=9) return {t:"низкое влияние",c:"green"
|
|||||||
|
|
||||||
/* ============ УТИЛИТЫ ============ */
|
/* ============ УТИЛИТЫ ============ */
|
||||||
function $(sel,root){ return (root||document).querySelector(sel); }
|
function $(sel,root){ return (root||document).querySelector(sel); }
|
||||||
function el(tag,cls,html,opts){ var e=document.createElement(tag); if(cls)e.className=cls; if(html!=null && typeof html==="string")e.innerHTML=html; if(opts){ if(opts.style)e.setAttribute("style",opts.style); if(opts.text!=null)e.textContent=opts.text; } return e; }
|
function el(tag,cls,html,opts){ var e=document.createElement(tag); if(cls)e.className=cls; if(html!=null && typeof html==="string")e.innerHTML=html; else if(html!=null && typeof html==="object" && !opts){opts=html;} if(opts){ if(opts.style)e.setAttribute("style",opts.style); if(opts.text!=null)e.textContent=opts.text; } return e; }
|
||||||
function nowHHMM(){ var d=new Date(); return pad(d.getHours())+":"+pad(d.getMinutes()); }
|
function nowHHMM(){ var d=new Date(); return pad(d.getHours())+":"+pad(d.getMinutes()); }
|
||||||
function pad(n){ return (n<10?"0":"")+n; }
|
function pad(n){ return (n<10?"0":"")+n; }
|
||||||
function fmtTime(ts){ var d=new Date(ts); return pad(d.getDate())+"."+pad(d.getMonth()+1)+" "+pad(d.getHours())+":"+pad(d.getMinutes()); }
|
function fmtTime(ts){ var d=new Date(ts); return pad(d.getDate())+"."+pad(d.getMonth()+1)+" "+pad(d.getHours())+":"+pad(d.getMinutes()); }
|
||||||
@ -838,6 +908,68 @@ function saveEntry(p){
|
|||||||
toast("Запись сохранена. Зона: "+ZONE_TXT[z].t);
|
toast("Запись сохранена. Зона: "+ZONE_TXT[z].t);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ============ МОДАЛКА: НАЗНАЧЕНИЕ БАЗИСНОЙ ТЕРАПИИ ============ */
|
||||||
|
function openPrescribeModal(p){
|
||||||
|
var m=$("#modal"); m.innerHTML="";
|
||||||
|
var head=el("div","modal-head");
|
||||||
|
head.innerHTML='<h3>Назначить базисную терапию · '+p.name+'</h3>';
|
||||||
|
var close=el("button","modal-close","×"); close.onclick=closeModal;
|
||||||
|
head.appendChild(close); m.appendChild(head);
|
||||||
|
var body=el("div","modal-body");
|
||||||
|
body.appendChild(el("div","muted","Выберите препараты из каталога. Время приёма можно изменить. Уже назначенные отмечены.",{"style":"margin-bottom:14px"}));
|
||||||
|
|
||||||
|
MED_CATALOG.forEach(function(grp){
|
||||||
|
body.appendChild(el("div","section-title",grp.grp));
|
||||||
|
grp.items.forEach(function(it){
|
||||||
|
var exists=p.meds.some(function(mm){return mm.id===it.id;});
|
||||||
|
var row=el("div","med");
|
||||||
|
row.dataset.medId=it.id; row.dataset.medName=it.name;
|
||||||
|
var left=el("div","med-info");
|
||||||
|
left.innerHTML='<div class="med-name">'+it.name+(exists?' <span class="med-state taken" style="margin-left:6px">назначен</span>':'')+'</div>';
|
||||||
|
var te=el("div","med-time");
|
||||||
|
var ti=el("input","input"); ti.value=it.dt.join(", "); ti.style.maxWidth="220px"; ti.style.padding="7px 10px"; ti.style.fontSize="13px";
|
||||||
|
te.appendChild(el("span","med-pill","время"));
|
||||||
|
te.appendChild(ti);
|
||||||
|
left.appendChild(te);
|
||||||
|
row.appendChild(left);
|
||||||
|
var cb=el("input"); cb.type="checkbox"; cb.style.width="20px"; cb.style.height="20px";
|
||||||
|
if(exists){ cb.checked=true; cb.disabled=true; }
|
||||||
|
var lab=el("label","",{"style":"display:flex;align-items:center;gap:8px;font-size:14px;font-weight:600;cursor:pointer"});
|
||||||
|
lab.appendChild(cb); lab.appendChild(el("span","","Назначить"));
|
||||||
|
row.appendChild(lab);
|
||||||
|
body.appendChild(row);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
m.appendChild(body);
|
||||||
|
var foot=el("div","modal-foot");
|
||||||
|
var cancel=el("button","btn ghost","Отмена"); cancel.onclick=closeModal;
|
||||||
|
var saveBtn=el("button","btn","Сохранить назначения");
|
||||||
|
saveBtn.onclick=function(){ savePrescription(p, body); };
|
||||||
|
foot.appendChild(cancel); foot.appendChild(saveBtn);
|
||||||
|
m.appendChild(foot);
|
||||||
|
openModal();
|
||||||
|
}
|
||||||
|
|
||||||
|
function savePrescription(p, body){
|
||||||
|
var rows=body.querySelectorAll(".med");
|
||||||
|
var added=0;
|
||||||
|
for(var i=0;i<rows.length;i++){
|
||||||
|
var row=rows[i];
|
||||||
|
var cb=row.querySelector("input[type=checkbox]");
|
||||||
|
if(!cb || !cb.checked) continue;
|
||||||
|
var id=row.dataset.medId, name=row.dataset.medName;
|
||||||
|
if(p.meds.some(function(mm){return mm.id===id;})) continue;
|
||||||
|
var ti=row.querySelector(".med-time input");
|
||||||
|
var times=(ti&&ti.value||"").split(",").map(function(s){return s.trim();}).filter(Boolean);
|
||||||
|
if(!times.length) times=["08:00"];
|
||||||
|
p.meds.push({id:id, name:name, times:times});
|
||||||
|
added++;
|
||||||
|
}
|
||||||
|
save(state); closeModal(); openPatientDetail(p.id);
|
||||||
|
toast(added? "Добавлено препаратов: "+added : "Изменений нет");
|
||||||
|
}
|
||||||
|
|
||||||
/* ============ РЕНДЕР: МЕДРАБОТНИК ============ */
|
/* ============ РЕНДЕР: МЕДРАБОТНИК ============ */
|
||||||
function renderStaff(){
|
function renderStaff(){
|
||||||
// баннер
|
// баннер
|
||||||
@ -852,19 +984,136 @@ function renderStaff(){
|
|||||||
'</div>';
|
'</div>';
|
||||||
app.appendChild(banner);
|
app.appendChild(banner);
|
||||||
|
|
||||||
// список пациентов по зонам
|
// вкладки
|
||||||
|
var tabs=el("div","tabs");
|
||||||
|
[["patients","🩺 Пациенты"],["reports","📊 Отчёты"],["protocol","🚦 Протокол (светофор)"]].forEach(function(t){
|
||||||
|
var b=el("button","",t[1]);
|
||||||
|
if(state.staffTab===t[0]) b.classList.add("active");
|
||||||
|
b.onclick=function(){ state.staffTab=t[0]; save(state); render(); };
|
||||||
|
tabs.appendChild(b);
|
||||||
|
});
|
||||||
|
app.appendChild(tabs);
|
||||||
|
|
||||||
|
if(state.staffTab==="reports") renderStaffReports();
|
||||||
|
else if(state.staffTab==="protocol") renderStaffProtocol();
|
||||||
|
else renderStaffList();
|
||||||
|
}
|
||||||
|
|
||||||
|
function renderStaffList(){
|
||||||
var list=el("div","card");
|
var list=el("div","card");
|
||||||
list.appendChild(el("h3","","Пациенты по степени риска",{"style":"margin-bottom:14px"}));
|
list.appendChild(el("h3","","Пациенты по степени риска",{"style":"margin-bottom:14px"}));
|
||||||
var sorted=state.patients.slice().sort(function(a,b){
|
var sorted=state.patients.slice().sort(function(a,b){
|
||||||
var za=entryZone(a), zb=entryZone(b);
|
var za=entryZone(a), zb=entryZone(b);
|
||||||
return zoneRank(zb)-zoneRank(za);
|
return zoneRank(zb)-zoneRank(za);
|
||||||
});
|
});
|
||||||
sorted.forEach(function(p){
|
sorted.forEach(function(p){ list.appendChild(patientRow(p)); });
|
||||||
list.appendChild(patientRow(p));
|
|
||||||
});
|
|
||||||
app.appendChild(list);
|
app.appendChild(list);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ---- Отчёт: сегментация + охват ---- */
|
||||||
|
function renderStaffReports(){
|
||||||
|
var c=zoneCounts(); var n=state.patients.length;
|
||||||
|
// 1. Сегментация
|
||||||
|
var seg=el("div","card");
|
||||||
|
seg.appendChild(el("h3","","Отчёт по сегментации пациентов",{"style":"margin-bottom:14px"}));
|
||||||
|
var bars=el("div","",{"style":"margin-bottom:16px"});
|
||||||
|
[["red","Красная",c.red,"#EA3943"],["yellow","Жёлтая",c.yellow,"#F5A623"],["green","Зелёная",c.green,"#16C784"]].forEach(function(z){
|
||||||
|
var pct=n?Math.round(z[2]/n*100):0;
|
||||||
|
var row=el("div","",{"style":"margin-bottom:10px"});
|
||||||
|
row.innerHTML='<div style="display:flex;justify-content:space-between;font-size:14px;margin-bottom:4px"><span>'+z[1]+'</span><span><b>'+z[2]+'</b> ('+pct+'%)</span></div>';
|
||||||
|
var track=el("div","",{"style":"background:var(--gray-100);border-radius:6px;height:12px;overflow:hidden"});
|
||||||
|
var fill=el("div","",{"style":"background:"+z[3]+";height:100%;width:"+pct+"%"});
|
||||||
|
track.appendChild(fill); row.appendChild(track); bars.appendChild(row);
|
||||||
|
});
|
||||||
|
seg.appendChild(bars);
|
||||||
|
// таблица по зонам
|
||||||
|
["red","yellow","green"].forEach(function(z){
|
||||||
|
var ps=state.patients.filter(function(p){return entryZone(p)===z;});
|
||||||
|
if(!ps.length) return;
|
||||||
|
seg.appendChild(el("div","zone-chip "+z,'<span class="d"></span>'+ZONE_TXT[z].t+" — "+ps.length,{"style":"margin:10px 0 6px"}));
|
||||||
|
var lst=el("div","",{"style":"font-size:14px;color:var(--gray-500)"});
|
||||||
|
lst.innerHTML=ps.map(function(p){return p.name;}).join(" · ");
|
||||||
|
seg.appendChild(lst);
|
||||||
|
});
|
||||||
|
app.appendChild(seg);
|
||||||
|
|
||||||
|
// 2. Охват мониторингом
|
||||||
|
var cov=el("div","card");
|
||||||
|
cov.appendChild(el("h3","","Отчёт по охвату мониторингом",{"style":"margin-bottom:14px"}));
|
||||||
|
var now=Date.now(), H24=3600000*24, H48=3600000*48;
|
||||||
|
var active24=0, stale=0, noData=0, doseTaken=0, doseTotal=0, sumCat=0, catN=0;
|
||||||
|
var staleList=[];
|
||||||
|
state.patients.forEach(function(p){
|
||||||
|
var e=lastEntry(p);
|
||||||
|
if(!e){ noData++; staleList.push({p:p,d:"нет данных"}); return; }
|
||||||
|
var dt=now-e.ts;
|
||||||
|
if(dt<=H24) active24++; else { stale++; staleList.push({p:p,d:"последний замер "+fmtTime(e.ts)}); }
|
||||||
|
sumCat+=e.catTotal; catN++;
|
||||||
|
p.meds.forEach(function(m){ medStatus(m,e).forEach(function(s){ if(s.status!=="upcoming"){ doseTotal++; if(s.status==="taken") doseTaken++; } }); });
|
||||||
|
});
|
||||||
|
var tiles=el("div","grid4");
|
||||||
|
tiles.appendChild(statTile("Всего под наблюдением", n));
|
||||||
|
tiles.appendChild(statTile("Активны (замер ≤24ч)", active24, active24>=Math.ceil(n*0.6)?"green":"yellow"));
|
||||||
|
tiles.appendChild(statTile("Нет замеров >24ч", stale+noData, (stale+noData)?"red":"green"));
|
||||||
|
tiles.appendChild(statTile("Adherence препаратов", (doseTotal?Math.round(doseTaken/doseTotal*100):0)+"%", doseTotal&&doseTaken/doseTotal>=0.8?"green":"yellow"));
|
||||||
|
cov.appendChild(tiles);
|
||||||
|
var tiles2=el("div","grid4");
|
||||||
|
tiles2.appendChild(statTile("Средний CAT", catN?Math.round(sumCat/catN*10)/10:"—"));
|
||||||
|
tiles2.appendChild(statTile("В красной зоне", c.red, c.red?"red":"green"));
|
||||||
|
tiles2.appendChild(statTile("В жёлтой зоне", c.yellow, c.yellow?"yellow":"green"));
|
||||||
|
tiles2.appendChild(statTile("В зелёной зоне", c.green, "green"));
|
||||||
|
cov.appendChild(tiles2);
|
||||||
|
// список требующих внимания
|
||||||
|
if(staleList.length){
|
||||||
|
cov.appendChild(el("div","section-title","Требуют внимания (нет свежих замеров)"));
|
||||||
|
staleList.forEach(function(it){
|
||||||
|
var row=el("div","patient-row yellow");
|
||||||
|
row.onclick=function(){ openPatientDetail(it.p.id); };
|
||||||
|
row.innerHTML='<div class="avatar"></div><div class="info"><div class="name">'+it.p.name+'</div><div class="meta">'+it.d+'</div></div><span class="alert-flag amber">контакт</span>';
|
||||||
|
cov.appendChild(row);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
app.appendChild(cov);
|
||||||
|
}
|
||||||
|
function statTile(lbl,val,zone){
|
||||||
|
var cls=zone==="red"?"danger":zone==="yellow"?"warn":zone==="green"?"ok":"";
|
||||||
|
var t=el("div","vital-tile "+cls);
|
||||||
|
t.innerHTML='<div class="lbl">'+lbl+'</div><div class="val" style="font-size:22px">'+val+'</div>';
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---- Протокол «светофор» (расширенные действия) ---- */
|
||||||
|
function renderStaffProtocol(){
|
||||||
|
["red","yellow","green"].forEach(function(zkey){
|
||||||
|
var p=ZONE_PROTOCOL[zkey];
|
||||||
|
var cls=zkey==="red"?"r":zkey==="yellow"?"y":"g";
|
||||||
|
var card=el("div","zone "+cls);
|
||||||
|
card.style.marginBottom="18px";
|
||||||
|
var badge=zkey==="red"?"Красная зона":zkey==="yellow"?"Жёлтая зона":"Зелёная зона";
|
||||||
|
card.innerHTML='<span class="badge">'+badge+'</span><h3>'+p.title+'</h3>';
|
||||||
|
card.appendChild(el("div","thr","<b>Критерии:</b> "+p.crit));
|
||||||
|
card.appendChild(protoCol("Действия пациента", p.patient, "→", "var(--"+(zkey==="green"?"green":zkey==="yellow"?"amber":"red")+")"));
|
||||||
|
card.appendChild(protoCol("Действия медперсонала", p.staff, "✓", "var(--cyan)"));
|
||||||
|
var esc=el("div","act","<b>Эскалация:</b> "+p.esc);
|
||||||
|
card.appendChild(esc);
|
||||||
|
app.appendChild(card);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
function protoCol(title, items, mark, color){
|
||||||
|
var wrap=el("div","",{"style":"margin-bottom:12px"});
|
||||||
|
wrap.appendChild(el("div","",{style:"font-size:13px;font-weight:700;color:var(--gray-500);text-transform:uppercase;letter-spacing:.04em;margin-bottom:6px","text":title}));
|
||||||
|
var ul=el("ul","",{"style":"list-style:none;padding:0;margin:0"});
|
||||||
|
items.forEach(function(it){
|
||||||
|
var li=el("li","",{"style":"font-size:14px;padding:5px 0 5px 22px;position:relative","text":it});
|
||||||
|
li.style.setProperty("--mk",color);
|
||||||
|
li.innerHTML='<span style="position:absolute;left:0;color:'+color+';font-weight:800">'+mark+'</span>'+it;
|
||||||
|
ul.appendChild(li);
|
||||||
|
});
|
||||||
|
wrap.appendChild(ul);
|
||||||
|
return wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
function entryZone(p){ var e=lastEntry(p); return e?overallZone(e.spo2,e.hr,e.rr):"green"; }
|
function entryZone(p){ var e=lastEntry(p); return e?overallZone(e.spo2,e.hr,e.rr):"green"; }
|
||||||
function zoneCounts(){
|
function zoneCounts(){
|
||||||
var c={green:0,yellow:0,red:0};
|
var c={green:0,yellow:0,red:0};
|
||||||
@ -933,8 +1182,15 @@ function openPatientDetail(id){
|
|||||||
if(e.note){ pc.appendChild(el("div","muted","Заметка пациента: "+e.note,{"style":"margin-top:12px"})); }
|
if(e.note){ pc.appendChild(el("div","muted","Заметка пациента: "+e.note,{"style":"margin-top:12px"})); }
|
||||||
app.appendChild(pc);
|
app.appendChild(pc);
|
||||||
|
|
||||||
// препараты
|
// препараты + назначение терапии
|
||||||
app.appendChild(renderMedsCard(p, e, false));
|
app.appendChild(renderMedsCard(p, e, false));
|
||||||
|
var presc=el("div","card");
|
||||||
|
presc.style.display="flex";presc.style.alignItems="center";presc.style.justifyContent="space-between";presc.style.gap="12px";presc.style.flexWrap="wrap";
|
||||||
|
presc.innerHTML='<div><h3 style="font-size:17px">Базисная терапия</h3><div class="sub">Назначьте препараты из каталога — пациент увидит схему в своём кабинете</div></div>';
|
||||||
|
var pb=el("button","btn dark","+ Назначить терапию");
|
||||||
|
pb.onclick=function(){ openPrescribeModal(p); };
|
||||||
|
presc.appendChild(pb);
|
||||||
|
app.appendChild(presc);
|
||||||
|
|
||||||
// флаги / рекомендации
|
// флаги / рекомендации
|
||||||
var flags=buildFlags(e).concat(buildMedFlags(p));
|
var flags=buildFlags(e).concat(buildMedFlags(p));
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user