diff --git a/index.html b/index.html index 2361a56..31d6c86 100644 --- a/index.html +++ b/index.html @@ -179,6 +179,19 @@ a{color:inherit} .back-link:hover{color:var(--ink)} .section-title{font-size:13px;font-weight:700;text-transform:uppercase;letter-spacing:.05em;color:var(--gray-500);margin:6px 0 12px} +.devbar{display:flex;align-items:center;gap:8px;flex-wrap:wrap;margin-bottom:14px;padding:12px;background:var(--cyan-50);border-radius:10px} +.devlbl{font-size:13px;color:var(--gray-500);font-weight:600} +details.edu{border:1px solid var(--gray-200);border-radius:10px;padding:0;margin-bottom:10px;overflow:hidden} +details.edu summary{padding:13px 16px;font-weight:700;font-size:15px;cursor:pointer;list-style:none;background:var(--gray-100)} +details.edu summary::-webkit-details-marker{display:none} +details.edu[open] summary{border-bottom:1px solid var(--gray-200)} +details.edu .edu-body{padding:14px 16px;font-size:14px;color:var(--gray-500)} +details.edu .edu-body b{color:var(--ink)} +details.edu .edu-body li{margin-bottom:6px} +.iv-line{padding:11px 0;border-bottom:1px solid var(--gray-100)} +.iv-line:last-child{border-bottom:none} +.iv-line b{font-size:14px} +.iv-line .iv-meta{font-size:12px;color:var(--gray-500);margin-top:2px} .stat-line{display:flex;justify-content:space-between;padding:8px 0;border-bottom:1px solid var(--gray-100);font-size:14px} .stat-line:last-child{border-bottom:none} @@ -225,7 +238,7 @@ a{color:inherit} "use strict"; /* ============ ДАННЫЕ (localStorage как «БД») ============ */ -var STORE_KEY = "copd_monitor_v1"; +var STORE_KEY = "copd_monitor_v2"; function seed(){ var now = Date.now(); @@ -276,6 +289,10 @@ function seed(){ ], entries:[ entry("p3",1,8,{spo2:88,sys:142,dia:90,hr:112,rr:26,mmrc:3,cat:[3,3,2,4,4,3,2,3],meds:{"m1@08:00":{taken:false}},note:"усилилась одышка, мокрота гнойная"}) + ], + interventions:[ + {ts:Date.now()-3600000*3, text:"Связался с пациентом. Усилить О₂ до 3 л/мин, начать преднизолон 30 мг/сут 5 дней, резервный амоксиклав."}, + {ts:Date.now()-3600000*26, text:"Пациент в красной зоне. Повторить SpO₂ через 30 мин, при <88% — госпитализация."} ] }, { @@ -532,6 +549,30 @@ function renderPatient(){ app.appendChild(emptyCard("Пока нет записей. Нажмите «Новая запись», чтобы начать.")); } + // Образование и самопомощь + var edu = el("div","card"); + edu.appendChild(el("h3","","📚 Образование и самопомощь",{"style":"margin-bottom:14px"})); + edu.appendChild(el("div","muted","Краткие рекомендации при ХОБЛ. Нажмите, чтобы раскрыть.",{"style":"margin-bottom:12px"})); + edu.appendChild(eduBlock("🌬 Дыхательная гимнастика", + "
  • Диафрагмальное дыхание: одна рука на животе, вдох через нос — живот надувается; выдох через рот медленно.
  • "+ + "
  • Дыхание через сжатые губы: вдох носом 2 сек, выдох через губы трубочкой 4 сек. Удлиняйте выдох.
  • "+ + "
  • Выполняйте 5–10 минут 3–4 раза в день, особенно при одышке.
  • ")); + edu.appendChild(eduBlock("💊 Техника ингаляции", + "
  • Встряхните ДАИ, снимите колпачок, выдохните мимо ингалятора.
  • "+ + "
  • Обхватите мундштук губами, начинайте вдох и нажмите на баллончик одновременно.
  • "+ + "
  • Продолжайте медленный глубокий вдох 3–5 сек, задержите дыхание на 10 сек.
  • "+ + "
  • После ингаляции ГКС — прополощите рот водой.
  • ")); + edu.appendChild(eduBlock("🚦 План действий (светофор)", + "
  • 🟢 Зелёная зона: всё как обычно — базисная терапия, дневник.
  • "+ + "
  • 🟡 Жёлтая зона: SpO₂ 90–94% — спасатель, контроль, связаться с медсестрой.
  • "+ + "
  • 🔴 Красная зона: SpO₂ <90% — кислород, бронхолитик, положение, вызов скорой.
  • ")); + edu.appendChild(eduBlock("🚑 Когда вызывать скорую", + "
  • SpO₂ < 88% держится более 5 минут или нарастает одышка.
  • "+ + "
  • Одышка в покое не уменьшается через 15–20 минут после бронхолитика.
  • "+ + "
  • Спутанность сознания, синюшность губ, боли в груди.
  • "+ + "
  • Температура > 38,5 °C с нарастающей одышкой.
  • ")); + app.appendChild(edu); + // История if(p.entries.length){ var hc = el("div","card"); @@ -560,6 +601,12 @@ function bpZone(s,d){ } function mmrcTxt(m){ return ["одышки нет","при быстрой ходьбе","иду медленнее","останавливаюсь ~100м","не могу выйти из дома"][m]||"—"; } +function eduBlock(title, html){ + var d=el("details","edu"); + d.innerHTML=''+title+'
    '; + return d; +} + function renderMedsCard(p, entry, showActions){ var c = el("div","card"); c.appendChild(el("h3","","💊 Базисные препараты",{"style":"margin-bottom:6px"})); @@ -595,6 +642,21 @@ function markMed(p, med, time){ save(state); render(); toast("Приём отмечен: "+med.name); } +/* mock-чтение с прибора (имитация Bluetooth) */ +function readDevice(kind){ + if(kind==="oxy"){ + var v = 88+Math.floor(Math.random()*9); // 88–96 + var hr = 64+Math.floor(Math.random()*42); // 64–105 + $("#spo2").value=v; $("#hr").value=hr; + toast("Пульсоксиметр: SpO₂ "+v+"%, ЧСС "+hr); + } else { + var s=116+Math.floor(Math.random()*34); // 116–149 + var d=74+Math.floor(Math.random()*20); // 74–93 + $("#bpSys").value=s; $("#bpDia").value=d; + toast("Тонометр: АД "+s+"/"+d); + } +} + function historyTable(p){ var t = el("table","hist"); var thead = el("thead"); thead.innerHTML='ДатаSpO₂АДЧССЧДДmMRCCATЗона'; @@ -633,6 +695,15 @@ function openDiaryModal(p){ // Жизненные показатели body.appendChild(el("div","section-title","Показатели")); + // приборы (mock Bluetooth) + var devBar = el("div","devbar"); + devBar.appendChild(el("span","devlbl","📡 Считать с прибора:")); + var bOxy = el("button","btn ghost sm","🩸 Пульсоксиметр"); + bOxy.onclick=function(){ readDevice("oxy"); }; + var bBp = el("button","btn ghost sm","🩺 Тонометр"); + bBp.onclick=function(){ readDevice("bp"); }; + devBar.appendChild(bOxy); devBar.appendChild(bBp); + body.appendChild(devBar); var fg = el("div","form-grid"); fg.appendChild(field('spo2','number','🩸 Сатурация (SpO₂)','90',true,"%, 50–100")); fg.appendChild(bpField()); @@ -890,6 +961,37 @@ function openPatientDetail(id){ } else { app.appendChild(emptyCard("Нет записей по пациенту.")); } + + // вмешательства и назначения врача + app.appendChild(interventionsCard(p)); +} + +function interventionsCard(p){ + var c=el("div","card"); + c.appendChild(el("h3","","📝 Вмешательства и назначения врача",{"style":"margin-bottom:14px"})); + if(!p.interventions) p.interventions=[]; + if(p.interventions.length){ + p.interventions.slice().reverse().forEach(function(iv){ + var row=el("div","iv-line"); + row.innerHTML=''+iv.text+'
    '+fmtTime(iv.ts)+'
    '; + c.appendChild(row); + }); + } else { + c.appendChild(el("div","muted","Пока нет записей.",{"style":"margin-bottom:12px"})); + } + var ta=el("textarea","input"); ta.id="ivText"; ta.rows=2; ta.placeholder="Записать вмешательство/назначение (напр.: «Усилить О₂ до 3 л/мин, добавить преднизолон 30 мг»)"; ta.style.marginBottom="10px"; ta.style.width="100%"; + c.appendChild(ta); + var btn=el("button","btn sm","Добавить запись"); + btn.onclick=function(){ addIntervention(p); }; + c.appendChild(btn); + return c; +} +function addIntervention(p){ + var ta=$("#ivText"); var t=(ta&&ta.value||"").trim(); + if(!t){ toast("Введите текст вмешательства"); return; } + if(!p.interventions) p.interventions=[]; + p.interventions.push({ts:Date.now(), text:t}); + save(state); openPatientDetail(p.id); toast("Вмешательство записано"); } function trendCard(p){