diff --git a/index.html b/index.html index f2f2f71..d6f13aa 100644 --- a/index.html +++ b/index.html @@ -5,96 +5,123 @@ План ПБ 2026 — Казахтелеком
-

План ПБ 2026

-

АО «Казахтелеком»

+ +

План производственной безопасности 2026

- - - + + +
-
-
План ПБ 2026 -
-
- + @@ -106,53 +133,46 @@ var reg=["Центральный","Алматинский","Южный","Сев var st={wait:"Не начато",warn:"В процессе",late:"Просрочено",done:"Исполнено"}; var ms=["2026-01","2026-02","2026-03","2026-04","2026-05","2026-06","2026-07","2026-08","2026-09","2026-10","2026-11","2026-12"]; var mn=["Янв","Фев","Мар","Апр","Май","Июн","Июл","Авг","Сен","Окт","Ноя","Дек"]; +var titles={ev:"Мероприятия",an:"Аналитика",rp:"Отчётность",ai:"ИИ-помощник"}; function M(i){var p=ms[i].split("-");return mn[parseInt(p[1])-1]+" "+p[0]} function esc(s){return s.replace(/&/g,"&").replace(//g,">")} function nl(s){return esc(s).replace(/\n/g,"
")} function sb(s){var m={done:"g",warn:"a",late:"r",wait:"w"};return''+st[s]+''} function daysLeft(e){ - if(e.s==="done")return""; - if(e.s==="late")return'ПРОСРОЧЕНО'; + if(e.s==="done")return''; + if(e.s==="late")return'ПРОСРОЧЕНО'; var p=e.due.split(".");if(p.length!==3)return""; var d=new Date(parseInt(p[2]),parseInt(p[1])-1,parseInt(p[0])); var days=Math.round((d-new Date())/86400000); - if(days<0)return''+Math.abs(days)+' дн. просрочки'; - if(days<=7)return''+days+' дн.'; - if(days<=14)return''+days+' дн.'; - if(days<=30)return''+days+' дн.'; + if(days<0)return''+Math.abs(days)+' дн.'; + if(days<=7)return''+days+' дн.'; + if(days<=14)return''+days+' дн.'; + if(days<=30)return''+days+' дн.'; return days+' дн.'; } -function rowClass(e){ - if(e.s==="late")return"rd";if(e.s==="done")return""; - var p=e.due.split(".");if(p.length!==3)return""; - var d=new Date(parseInt(p[2]),parseInt(p[1])-1,parseInt(p[0])); - var days=Math.round((d-new Date())/86400000); - if(days<=14)return"rd";if(days<=30)return"am";return""; -} +function rowClass(e){if(e.s==="late")return"rd";if(e.s==="done")return"";var p=e.due.split(".");if(p.length!==3)return"";var d=new Date(parseInt(p[2]),parseInt(p[1])-1,parseInt(p[0]));var days=Math.round((d-new Date())/86400000);if(days<=14)return"rd";if(days<=30)return"am";return""} -var U={"curator@telecom.kz":{n:"Куратор",b:0,r:"cur"},"dpp@telecom.kz":{n:"Директор ДПБ",b:0,r:"br"},"ahmetov@telecom.kz":{n:"Ахметов К.Т.",b:6,r:"br"},"serikov@telecom.kz":{n:"Сериков А.М.",b:1,r:"br"},"nurlanov@telecom.kz":{n:"Нурланов Д.С.",b:8,r:"br"},"aliev@telecom.kz":{n:"Алиев Г.С.",b:4,r:"br"},"tulegenov@telecom.kz":{n:"Тулегенов Е.А.",b:2,r:"br"},"saparov@telecom.kz":{n:"Сапаров А.Д.",b:3,r:"br"},"maratov@telecom.kz":{n:"Маратов Ж.К.",b:5,r:"br"},"iskakov@telecom.kz":{n:"Искаков Р.Н.",b:7,r:"br"}}; -var cu=null,ev=null,cm=5,cr=0,esi=-1,ex={},chatHistory=[]; +var U={"curator@telecom.kz":{n:"Куратор ПБ",b:0,r:"cur"},"dpp@telecom.kz":{n:"Директор ДПБ",b:0,r:"br"},"ahmetov@telecom.kz":{n:"Ахметов К.Т.",b:6,r:"br"},"serikov@telecom.kz":{n:"Сериков А.М.",b:1,r:"br"},"nurlanov@telecom.kz":{n:"Нурланов Д.С.",b:8,r:"br"},"aliev@telecom.kz":{n:"Алиев Г.С.",b:4,r:"br"},"tulegenov@telecom.kz":{n:"Тулегенов Е.А.",b:2,r:"br"},"saparov@telecom.kz":{n:"Сапаров А.Д.",b:3,r:"br"},"maratov@telecom.kz":{n:"Маратов Ж.К.",b:5,r:"br"},"iskakov@telecom.kz":{n:"Искаков Р.Н.",b:7,r:"br"}}; +var cu=null,ev=null,cm=5,esi=-1,ex={},chatHistory=[]; -function getMD(id,ri,si){ri=ri||0;var k=si>=0?"sf_"+id+"_s"+si+"_r"+ri:"sf_"+id+"_r"+ri;var r=localStorage.getItem(k);return r?JSON.parse(r):{}} -function setMD(id,o,ri,si){ri=ri||0;var k=si>=0?"sf_"+id+"_s"+si+"_r"+ri:"sf_"+id+"_r"+ri;localStorage.setItem(k,JSON.stringify(o))} +function getMD(id,si){var k=si>=0?"sf_"+id+"_s"+si:"sf_"+id;var r=localStorage.getItem(k);return r?JSON.parse(r):{}} +function setMD(id,o,si){var k=si>=0?"sf_"+id+"_s"+si:"sf_"+id;localStorage.setItem(k,JSON.stringify(o))} function gsc(id){var r=localStorage.getItem("ss_"+id);return r?JSON.parse(r):[]} function ssc(id,a){localStorage.setItem("ss_"+id,JSON.stringify(a))} -// ===== AUTH ===== function doLogin(){var e=document.getElementById("lem").value.trim().toLowerCase();if(U[e]){cu={em:e,n:U[e].n,b:U[e].b,r:U[e].r};localStorage.setItem("su",JSON.stringify(cu));showApp()}else document.getElementById("lerr").style.display="block"} function doLogout(){localStorage.removeItem("su");cu=null;document.getElementById("loginBox").style.display="flex";document.getElementById("app").style.display="none"} -function showApp(){document.getElementById("loginBox").style.display="none";document.getElementById("app").style.display="block";document.getElementById("ul").innerHTML=""+cu.n+" · "+(cu.r==="cur"?"Все":br[cu.b]);loadEvents()} +function showApp(){document.getElementById("loginBox").style.display="none";document.getElementById("app").style.display="flex";document.getElementById("ul").textContent=cu.n;loadEvents()} -// ===== DATA ===== -function loadEvents(){var s=localStorage.getItem("se3");if(s){try{ev=JSON.parse(s);renderEv();return}catch(e){}}var x=new XMLHttpRequest();x.open("GET","data.json",true);x.onload=function(){if(x.status===200){try{ev=JSON.parse(x.responseText);saveEv()}catch(e){ev=[]}};renderEv()};x.onerror=function(){ev=[];renderEv()};x.send()} -function saveEv(){localStorage.setItem("se3",JSON.stringify(ev||[]))} +function loadEvents(){var s=localStorage.getItem("se4");if(s){try{ev=JSON.parse(s);renderEv();return}catch(e){}}var x=new XMLHttpRequest();x.open("GET","data.json",true);x.onload=function(){if(x.status===200){try{ev=JSON.parse(x.responseText);saveEv()}catch(e){ev=[]}};renderEv()};x.onerror=function(){ev=[];renderEv()};x.send()} +function saveEv(){localStorage.setItem("se4",JSON.stringify(ev||[]))} -// ===== TABS ===== function switchPg(n){ - document.querySelectorAll(".tab").forEach(function(t){t.classList.remove("on")}); + document.querySelectorAll(".sidebar nav a").forEach(function(a){a.classList.remove("on")}); document.querySelector('[data-pg="'+n+'"]').classList.add("on"); document.querySelectorAll(".pg").forEach(function(p){p.classList.remove("on")}); document.getElementById("pg-"+n).classList.add("on"); + document.getElementById("pageTitle").textContent=titles[n]; if(n==="ev")renderEv();else if(n==="an")renderAn();else if(n==="rp")renderRp();else if(n==="ai")renderAi(); } @@ -161,205 +181,135 @@ function toggleEx(id){ex[id]=!ex[id];renderEv()} function ts(id,si,chk){var s=gsc(id);if(chk&&s.indexOf(si)<0)s.push(si);else if(!chk)s=s.filter(function(x){return x!==si});ssc(id,s);var e=null;for(var i=0;i=0||br[e.b].toLowerCase().indexOf(sr2)>=0}); - if(bf)list=list.filter(function(e){return e.b===parseInt(bf)}); - nu(); - - var h="
"; - h+=""; - h+=""; - h+=""+list.length+" из "+all.length+"
"; - h+=""; + h+=""+list.length+" из "+all.length+"
МероприятиеОтветственныеРазделСрокОсталосьСтатус
"; list.forEach(function(e){ - var hs=e.sub&&e.sub.length; - var sc=e.sub?gsc(e.id):[]; - var sdd=hs?sc.length:0,stt=hs?e.sub.length:0; - var cl=rowClass(e); - h+=""; - if(hs&&ex[e.id])e.sub.forEach(function(sb,i){var ch=sc.indexOf(i)>=0;h+=""}); + if(hs&&ex[e.id])e.sub.forEach(function(sb,i){var ch=sc.indexOf(i)>=0;h+=""}); }); - h+="
МероприятиеОтветственныеРазделСрокОсталосьСтатус
"+e.id+""; - if(hs)h+=""+(ex[e.id]?'▼':'▶')+""; - h+=esc(e.t); - if(hs)h+=" ("+sdd+"/"+stt+")"; + var hs=e.sub&&e.sub.length,sc=e.sub?gsc(e.id):[],sdd=hs?sc.length:0,stt=hs?e.sub.length:0,cl=rowClass(e); + h+="
"+e.id+""; + if(hs)h+=""+(ex[e.id]?'▼':'▶')+""; + h+=esc(e.t);if(hs)h+=" ("+sdd+"/"+stt+")"; h+=""+nl(e.r)+""+sec[e.sec]+""+e.due+""+daysLeft(e)+""+sb(e.s)+"
"+sb.l+") "+esc(sb.t)+"
"+sb.l+") "+esc(sb.t)+"
"; - document.getElementById("pg-ev").innerHTML=h; + h+="
";document.getElementById("pg-ev").innerHTML=h; } // ===== ANALYTICS ===== function renderAn(){ - var all=ev||[]; - var done=all.filter(function(e){return e.s==="done"}); - var late=all.filter(function(e){return e.s==="late"}); - var warn=all.filter(function(e){return e.s==="warn"}); - var wait=all.filter(function(e){return e.s==="wait"}); + var all=ev||[],done=all.filter(function(e){return e.s==="done"}),late=all.filter(function(e){return e.s==="late"}),warn=all.filter(function(e){return e.s==="warn"}),wait=all.filter(function(e){return e.s==="wait"}); var dp=all.length?Math.round(done.length/all.length*100):0; - - var h="
Всего
"+all.length+"
Исполнено
"+done.length+"
"+dp+"%
В процессе
"+warn.length+"
Просрочено
"+late.length+"
Не начато
"+wait.length+"
"; - + var h="
"+all.length+"
Всего
"+done.length+"
Исполнено ("+dp+"%)
"+warn.length+"
В процессе
"+late.length+"
Просрочено
"+wait.length+"
Не начато
"; + // Chart + h+="

Динамика по кварталам

Q1 фактQ2 прогнозQ3 планQ4 цель
"; // Branch ranking - var brData=[]; - br.forEach(function(b,i){var it=all.filter(function(e){return e.b===i});var d=it.filter(function(e){return e.s==="done"}).length;var l=it.filter(function(e){return e.s==="late"}).length;var p=it.length?Math.round(d/it.length*100):0;brData.push({name:b,pct:p,done:d,total:it.length,late:l})}); - brData.sort(function(a,b){return a.pct-b.pct}); + var brData=[];br.forEach(function(b,i){var it=all.filter(function(e){return e.b===i});var d=it.filter(function(e){return e.s==="done"}).length;var l=it.filter(function(e){return e.s==="late"}).length;var p=it.length?Math.round(d/it.length*100):0;brData.push({name:b,pct:p,done:d,total:it.length,late:l})});brData.sort(function(a,b){return a.pct-b.pct}); h+="

Рейтинг филиалов

"; - brData.forEach(function(b){h+=""}); - h+="
ФилиалИсполнено%Просрочено
"+b.name+""+b.done+"/"+b.total+""+b.pct+"%"+(b.late?b.late:"—")+"
"; - + brData.forEach(function(b){h+=""+b.name+""+b.done+"/"+b.total+""+b.pct+"%"+(b.late?b.late:"—")+""});h+="
"; // TOP problems var problems=late.concat(all.filter(function(e){return e.s==="warn"&&e.p<30})).sort(function(a,b){return a.p-b.p}).slice(0,10); - if(problems.length){ - h+="

ТОП проблемных мероприятий

"; - problems.forEach(function(e){h+=""}); - h+="
МероприятиеФилиалСтатусСрок
"+e.id+""+esc(e.t.slice(0,80))+"..."+br[e.b]+""+sb(e.s)+""+daysLeft(e)+"
"; - } - - // Quantities - var tq=0,rq={0:0,1:0,2:0,3:0,4:0,5:0}; - all.forEach(function(e){reg.forEach(function(_,ri){var d=getMD(e.id,ri,-1);for(var k in d){if(d.hasOwnProperty(k)&&d[k]){tq+=d[k].qty||0;rq[ri]+=d[k].qty||0}if(e.sub)e.sub.forEach(function(si){var sd=getMD(e.id,ri,si);for(var sk in sd){if(sd.hasOwnProperty(sk)&&sd[sk]){tq+=sd[sk].qty||0;rq[ri]+=sd[sk].qty||0}}})}})}); - h+="

Количественные показатели

Всего единиц
"+tq+"
"; - reg.forEach(function(r,ri){if(rq[ri])h+="
"+r+"
"+rq[ri]+"
"}); - h+="
"; + if(problems.length){h+="

ТОП проблемных мероприятий

";problems.forEach(function(e){h+=""});h+="
МероприятиеФилиалСтатусСрок
"+e.id+""+esc(e.t.slice(0,80))+"..."+br[e.b]+""+sb(e.s)+""+daysLeft(e)+"
"} document.getElementById("pg-an").innerHTML=h; } // ===== NOTIFICATIONS ===== function toggleN(){nu();document.getElementById("nd").classList.toggle("on")} -function nu(){var all=ev||[],n=[],now=new Date(); - all.forEach(function(e){ - if(e.s==="late"){n.push({c:"🔴",m:"Просрочено: №"+e.id+" — "+e.t.slice(0,50)+"...",t:e.due});return} - if(e.s==="done")return; - var p=e.due.split(".");if(p.length===3){var d=new Date(parseInt(p[2]),parseInt(p[1])-1,parseInt(p[0]));var days=Math.round((d-now)/86400000); - if(days<=1&&days>=0)n.push({c:"🔴",m:"СРОЧНО! 1 день: №"+e.id,t:e.due}); - else if(days<=7)n.push({c:"🟠",m:"7 дн: №"+e.id+" — "+e.t.slice(0,40)+"...",t:e.due}); - else if(days<=14)n.push({c:"🟡",m:"14 дн: №"+e.id+" — "+e.t.slice(0,40)+"...",t:e.due}); - else if(days<=30)n.push({c:"🔵",m:"30 дн: №"+e.id+" — "+e.t.slice(0,40)+"...",t:e.due}); - } - }); - n.sort(function(a,b){var o={"🔴":0,"🟠":1,"🟡":2,"🔵":3};return(o[a.c]||9)-(o[b.c]||9)}); - var el=document.getElementById("nd"),c=document.getElementById("nc");c.textContent=n.length;c.style.display=n.length?"inline-block":"none"; - el.innerHTML=n.length?n.map(function(x){return"
"+x.c+" "+esc(x.m)+"Срок: "+x.t+"
"}).join(""):"
Нет уведомлений
"; -} +function nu(){var all=ev||[],n=[],now=new Date();all.forEach(function(e){if(e.s==="late"){n.push({c:"🔴",m:"Просрочено: №"+e.id+" — "+e.t.slice(0,45)+"...",t:e.due});return}if(e.s==="done")return;var p=e.due.split(".");if(p.length===3){var d=new Date(parseInt(p[2]),parseInt(p[1])-1,parseInt(p[0]));var days=Math.round((d-now)/86400000);if(days<=1&&days>=0)n.push({c:"🔴",m:"СРОЧНО! 1 день: №"+e.id,t:e.due});else if(days<=7)n.push({c:"🟠",m:"7 дн: №"+e.id+" — "+e.t.slice(0,35)+"...",t:e.due});else if(days<=14)n.push({c:"🟡",m:"14 дн: №"+e.id+" — "+e.t.slice(0,35)+"...",t:e.due});else if(days<=30)n.push({c:"🔵",m:"30 дн: №"+e.id+" — "+e.t.slice(0,35)+"...",t:e.due})}});n.sort(function(a,b){var o={"🔴":0,"🟠":1,"🟡":2,"🔵":3};return(o[a.c]||9)-(o[b.c]||9)}); + document.getElementById("nc").textContent=n.length;document.getElementById("nc").style.display=n.length?"inline-block":"none"; + document.getElementById("nd").innerHTML=n.length?n.map(function(x){return"
"+x.c+" "+esc(x.m)+"Срок: "+x.t+"
"}).join(""):"
Нет уведомлений
"} // ===== REPORTS ===== -function renderRp(){ - var b=0;for(var i=0;i"+M(i)+""; - h+="
"; - h+="

Хранилище: "+(b>1048576?(b/1048576).toFixed(1)+" МБ":(b/1024).toFixed(0)+" КБ")+"

"; - h+=" "; - h+=" "; - h+=" "; - h+=""; - document.getElementById("pg-rp").innerHTML=h; -} - -function dCSV(){var f=parseInt(document.getElementById("rf").value);var t=parseInt(document.getElementById("rt").value);var all=ev||[];var csv="\uFEFF№;Филиал;Мероприятие;Регион;Статус;Осталось;Срок\n";all.forEach(function(e){reg.forEach(function(_,ri){var d=getMD(e.id,ri,-1);var rep="";for(var i=f;i<=t;i++){var m=ms[i];if(d[m]&&d[m].report)rep+=M(i)+": "+d[m].report.replace(/"/g,'""')+"; "}csv+=e.id+";"+br[e.b]+";\""+e.t.replace(/"/g,'""')+"\";"+reg[ri]+";"+st[e.s]+";"+daysLeft(e).replace(/<[^>]*>/g,"")+";"+e.due+";\""+rep+"\"\n"})});var a=document.createElement("a");a.href=URL.createObjectURL(new Blob([csv]));a.download="otchet.csv";a.click()} - -function dHTML(){var f=parseInt(document.getElementById("rf").value);var t=parseInt(document.getElementById("rt").value);var all=ev||[];var h="Отчёт ПБ

Сводный отчёт ПБ

"; - all.forEach(function(e){var cl={done:"g",warn:"a",late:"r",wait:""}[e.s];h+="

"+e.id+". "+esc(e.t)+"

"+br[e.b]+" | "+sec[e.sec]+" | Срок: "+e.due+" | "+st[e.s]+"

"; - reg.forEach(function(_,ri){var d=getMD(e.id,ri,-1);for(var i=f;i<=t;i++){var m=ms[i];if(d[m]&&(d[m].report||(d[m].files&&d[m].files.length))){h+="
"+M(i)+" — "+reg[ri]+"";if(d[m].report)h+="

"+esc(d[m].report)+"

";if(d[m].qty)h+="

Количество: "+d[m].qty+"

"; - if(d[m].files&&d[m].files.length)h+="

📎 Файлы:
"+d[m].files.map(function(f2){return"📄 "+esc(f2.name)+" ("+(f2.size/1024).toFixed(0)+" КБ)"}).join("
")+"

";h+="
"}}}); - if(e.sub)e.sub.forEach(function(s,si){reg.forEach(function(_,ri){var sd=getMD(e.id,ri,si);for(var i=f;i<=t;i++){var m=ms[i];if(sd[m]&&(sd[m].report||(sd[m].files&&sd[m].files.length))){h+="
"+s.l+") "+esc(s.t.slice(0,50))+" — "+reg[ri]+" | "+M(i)+"";if(sd[m].report)h+="

"+esc(sd[m].report)+"

";if(sd[m].qty)h+="

Количество: "+sd[m].qty+"

"; - if(sd[m].files&&sd[m].files.length)h+="

📎 Файлы:
"+sd[m].files.map(function(f2){return"📄 "+esc(f2.name)+" ("+(f2.size/1024).toFixed(0)+" КБ)"}).join("
")+"

";h+="
"}}})});h+="
"}); - h+=""; - try{var a=document.createElement("a");a.href=URL.createObjectURL(new Blob(["\uFEFF"+h],{type:"text/html"}));a.download="otchet.html";a.click()}catch(e){alert("Отчёт слишком большой. Попробуйте меньший период.")}} - + h+="

Хранилище: "+(b>1048576?(b/1048576).toFixed(1)+" МБ":(b/1024).toFixed(0)+" КБ")+"

"; + h+=" "; + document.getElementById("pg-rp").innerHTML=h} +function dCSV(){var f=parseInt(document.getElementById("rf").value),t=parseInt(document.getElementById("rt").value),all=ev||[],csv="\uFEFF№;Филиал;Мероприятие;Статус;Осталось;Срок\n";all.forEach(function(e){csv+=e.id+";"+br[e.b]+";\""+e.t.replace(/"/g,'""')+"\";"+st[e.s]+";"+daysLeft(e).replace(/<[^>]*>/g,"")+";"+e.due+"\n"});var a=document.createElement("a");a.href=URL.createObjectURL(new Blob([csv]));a.download="otchet.csv";a.click()} +function dHTML(){var f=parseInt(document.getElementById("rf").value),t=parseInt(document.getElementById("rt").value),all=ev||[],h="Отчёт ПБ

Сводный отчёт ПБ

";all.forEach(function(e){var cl={done:"g",warn:"a",late:"r",wait:""}[e.s];h+="

"+e.id+". "+esc(e.t)+"

"+br[e.b]+" | "+sec[e.sec]+" | Срок: "+e.due+" | "+st[e.s]+"

";var d=getMD(e.id,-1);for(var i=f;i<=t;i++){var m=ms[i];if(d[m]&&d[m].report)h+="
"+M(i)+"

"+esc(d[m].report)+"

"}if(e.sub)e.sub.forEach(function(s,si){var sd=getMD(e.id,si);for(var i=f;i<=t;i++){var m=ms[i];if(sd[m]&&sd[m].report)h+="
"+s.l+") "+M(i)+"

"+esc(sd[m].report)+"

"}});h+="
"});h+="";try{var a=document.createElement("a");a.href=URL.createObjectURL(new Blob(["\uFEFF"+h],{type:"text/html"}));a.download="otchet.html";a.click()}catch(e){alert("Слишком большой отчёт")}} function exp(){var d={events:ev,date:new Date().toISOString(),files:{},sc:{}};for(var i=0;i
Просрочено
"+late.length+"
Всего
"+all.length+"
"; + var h="

🤖 ИИ-помощник по производственной безопасности

Анализ исполнения Плана мероприятий. Задайте вопрос — получу нужную информацию из системы.

"; + h+="
"+dp+"%
Выполнено
"+late.length+"
Просрочено
"+all.length+"
Всего мероприятий
"; - // Risk prediction - var now=new Date(),risks=[]; - all.forEach(function(e){if(e.s!=="done"&&e.s!=="late"){var p=e.due.split(".");if(p.length===3){var d=new Date(parseInt(p[2]),parseInt(p[1])-1,parseInt(p[0]));var days=Math.round((d-now)/86400000);var risk="низкий";if(days<=7)risk="критический";else if(days<=14)risk="высокий";else if(days<=30)risk="средний";if(risk!=="низкий")risks.push({e:e,risk:risk,days:days})}}}); - risks.sort(function(a,b){return a.days-b.days}); - if(risks.length){h+="

⚠️ Прогноз рисков

";risks.slice(0,10).forEach(function(r){var cl=r.risk==="критический"?"r":r.risk==="высокий"?"a":"w";h+=""});h+="
МероприятиеРискОсталось
"+r.e.id+""+esc(r.e.t.slice(0,60))+"..."+r.risk+""+r.days+" дн.
"} - h+="

Примеры: «просроченные», «риски», «отчёт за квартал», «статус пункта 25», «сводка для руководства»

"; + var now=new Date(),risks=[];all.forEach(function(e){if(e.s!=="done"&&e.s!=="late"){var p=e.due.split(".");if(p.length===3){var d=new Date(parseInt(p[2]),parseInt(p[1])-1,parseInt(p[0]));var days=Math.round((d-now)/86400000);var risk="низкий";if(days<=7)risk="критический";else if(days<=14)risk="высокий";else if(days<=30)risk="средний";if(risk!=="низкий")risks.push({e:e,risk:risk,days:days})}}});risks.sort(function(a,b){return a.days-b.days}); + if(risks.length){h+="

⚠️ Прогноз рисков невыполнения

";risks.slice(0,10).forEach(function(r){var cl=r.risk==="критический"?"r":r.risk==="высокий"?"a":"w";h+=""});h+="
МероприятиеУровень рискаОсталось дней
"+r.e.id+""+esc(r.e.t.slice(0,60))+"..."+r.risk+""+r.days+" дн.
"} + + h+="

Спросите: «просроченные», «риски», «сводка», «статус пункта 15», «рейтинг филиалов», «график», «отстающие», «документы», «сроки»

"; h+="
"+chatHistory.map(function(m){return"
"+m.text+"
"}).join("")+"
"; - h+="
"; + h+="
"; document.getElementById("pg-ai").innerHTML=h; } -function aiAsk(){ - var q=(document.getElementById("aiQ").value||"").trim().toLowerCase();if(!q)return;document.getElementById("aiQ").value=""; - chatHistory.push({role:"user",text:"Вы: "+esc(q)}); - var ans=aiAnswer(q);chatHistory.push({role:"bot",text:"🤖 ИИ: "+ans}); - renderAi();var el=document.getElementById("aiChat");if(el)el.scrollTop=el.scrollHeight; +function aiAsk(){var q=(document.getElementById("aiQ").value||"").trim().toLowerCase();if(!q)return;document.getElementById("aiQ").value="";chatHistory.push({role:"user",text:"Вы: "+esc(q)});chatHistory.push({role:"bot",text:"🤖 ИИ: "+aiAnswer(q)});renderAi();var el=document.getElementById("aiChat");if(el)el.scrollTop=el.scrollHeight} + +function aiAnswer(q){var all=ev||[],now=new Date(),late=all.filter(function(e){return e.s==="late"}),done=all.filter(function(e){return e.s==="done"}),warn=all.filter(function(e){return e.s==="warn"}),wait=all.filter(function(e){return e.s==="wait"}); + // Query routing + if(q.indexOf("просрочен")>=0||q.indexOf("просрочк")>=0||q.indexOf("сорван")>=0){if(!late.length)return"Просроченных мероприятий нет. План выполняется без отклонений.";var r="Просрочено "+late.length+" мероприятий:
";late.forEach(function(e){r+="• №"+e.id+" — "+esc(e.t.slice(0,80))+"...
Филиал: "+br[e.b]+", срок: "+e.due+"
"});r+="
Рекомендация: эскалировать руководителям филиалов, провести совещание.";return r} + if(q.indexOf("риск")>=0||q.indexOf("невыполнен")>=0||q.indexOf("угроз")>=0){var risks=[];all.forEach(function(e){if(e.s!=="done"&&e.s!=="late"){var p=e.due.split(".");if(p.length===3){var d=new Date(parseInt(p[2]),parseInt(p[1])-1,parseInt(p[0]));var days=Math.round((d-now)/86400000);if(days<=30)risks.push({e:e,days:days})}}});risks.sort(function(a,b){return a.days-b.days});if(!risks.length)return"Мероприятий с риском невыполнения в ближайшие 30 дней не выявлено.";var r="Выявлено "+risks.length+" мероприятий с риском:
";risks.slice(0,8).forEach(function(x){r+="• №"+x.e.id+" — "+x.days+" дн. — "+esc(x.e.t.slice(0,60))+"...
"});return r} + if(q.indexOf("статус")>=0||q.indexOf("пункт")>=0||q.indexOf("мероприятие")>=0){var num=q.match(/\d+/);if(num){var e=null;for(var i=0;i
Статус: "+st[e.s]+"
Филиал: "+br[e.b]+"
Срок: "+e.due+"
Осталось: "+daysLeft(e).replace(/<[^>]*>/g,"")+"
Ответственный: "+nl(e.r);if(e.sub){r+="
Подпункты: "+e.sub.length+" шт."}return r}return"Пункт №"+num[0]+" не найден в плане."}} + if(q.indexOf("сводка")>=0||q.indexOf("руководств")>=0||q.indexOf("правлен")>=0||q.indexOf("итог")>=0||q.indexOf("обзор")>=0){var dp=all.length?Math.round(done.length/all.length*100):0;var r="Сводка для руководства
• План выполнен на "+dp+"% ("+done.length+"/"+all.length+")
• В процессе: "+warn.length+"
• Не начато: "+wait.length+"
• Просрочено: "+late.length+"
";if(late.length)r+="
Требует внимания: эскалация просрочек.";else r+="
Ситуация под контролем.";return r} + if(q.indexOf("рейтинг")>=0||q.indexOf("филиал")>=0||q.indexOf("отста")>=0||q.indexOf("худш")>=0||q.indexOf("лучш")>=0){var brData=[];br.forEach(function(b,i){var it=all.filter(function(e){return e.b===i});var d=it.filter(function(e){return e.s==="done"}).length;var l=it.filter(function(e){return e.s==="late"}).length;brData.push({name:b,done:d,total:it.length,late:l,pct:it.length?Math.round(d/it.length*100):0})});brData.sort(function(a,b){return b.pct-a.pct});var r="Рейтинг филиалов:
";brData.forEach(function(b,i){r+=(i+1)+". "+b.name+" — "+b.pct+"% ("+b.done+"/"+b.total+(b.late?", просрочено: "+b.late:"")+")
"});return r} + if(q.indexOf("график")>=0||q.indexOf("диаграм")>=0||q.indexOf("динамик")>=0){return"График доступен на вкладке «Аналитика». Переключитесь для просмотра визуализации."} + if(q.indexOf("документ")>=0||q.indexOf("файл")>=0){var tf=0;all.forEach(function(e){var d=getMD(e.id,-1);for(var k in d)if(d.hasOwnProperty(k))tf+=(d[k].files||[]).length;if(e.sub)e.sub.forEach(function(si){var sd=getMD(e.id,si);for(var k in sd)if(sd.hasOwnProperty(k))tf+=(sd[k].files||[]).length})});return"Всего загружено "+tf+" документов. Детальная информация — на вкладке «Отчётность»."} + if(q.indexOf("срок")>=0||q.indexOf("дедлайн")>=0){var near=[];all.forEach(function(e){if(e.s!=="done"&&e.s!=="late"){var p=e.due.split(".");if(p.length===3){var d=new Date(parseInt(p[2]),parseInt(p[1])-1,parseInt(p[0]));var days=Math.round((d-now)/86400000);if(days<=14)near.push({e:e,days:days})}}});near.sort(function(a,b){return a.days-b.days});if(!near.length)return"Ближайших сроков исполнения в течение 14 дней нет.";var r="Ближайшие сроки (≤14 дней):
";near.forEach(function(x){r+="• №"+x.e.id+" — "+x.days+" дн. — "+esc(x.e.t.slice(0,50))+"...
"});return r} + if(q.indexOf("привет")>=0||q.indexOf("здрав")>=0)return"Здравствуйте! Я ИИ-помощник по производственной безопасности. Спросите о статусе мероприятий, просрочках, рисках, рейтинге филиалов или сводке для руководства."; + return"Я могу ответить на вопросы:
«просроченные» — список просрочек
«риски» — прогноз рисков невыполнения
«сводка» — сводка для руководства
«статус пункта N» — статус мероприятия
«рейтинг филиалов» — кто лучший/худший
«сроки» — ближайшие дедлайны
«документы» — статистика загрузок"; } -function aiAnswer(q){ - var all=ev||[],now=new Date(),late=all.filter(function(e){return e.s==="late"}),done=all.filter(function(e){return e.s==="done"}); - if(q.indexOf("просрочен")>=0||q.indexOf("просрочк")>=0){if(!late.length)return"Просроченных мероприятий нет.";return"Просрочено "+late.length+" мероприятий: "+late.map(function(e){return"№"+e.id+" ("+br[e.b]+", срок "+e.due+")"}).join("; ")+"."} - if(q.indexOf("риск")>=0||q.indexOf("невыполнен")>=0){var risks=[];all.forEach(function(e){if(e.s!=="done"&&e.s!=="late"){var p=e.due.split(".");if(p.length===3){var d=new Date(parseInt(p[2]),parseInt(p[1])-1,parseInt(p[0]));var days=Math.round((d-now)/86400000);if(days<=30)risks.push({e:e,days:days})}}});risks.sort(function(a,b){return a.days-b.days});if(!risks.length)return"Мероприятий с высоким риском невыполнения не выявлено.";return"Выявлено "+risks.length+" мероприятий с риском: "+risks.slice(0,5).map(function(r){return"№"+r.e.id+" ("+r.days+" дн)"}).join("; ")+"."} - if(q.indexOf("статус")>=0||q.indexOf("пункт")>=0){var num=q.match(/\d+/);if(num){var e=null;for(var i=0;i"+st[e.s]+". "+esc(e.t.slice(0,100))+"... Филиал: "+br[e.b]+". Срок: "+e.due+".";return"Пункт №"+num[0]+" не найден."}} - if(q.indexOf("сводка")>=0||q.indexOf("руководств")>=0||q.indexOf("правлен")>=0){var dp=all.length?Math.round(done.length/all.length*100):0;return"Краткая сводка:
• План выполнен на "+dp+"% ("+done.length+"/"+all.length+")
• Просрочено: "+late.length+" мероприятий
• "+(late.length?"Требуется эскалация просрочек":"Ситуация под контролем")} - if(q.indexOf("филиал")>=0){var brLate={};late.forEach(function(e){brLate[e.b]=(brLate[e.b]||0)+1});var worst=Object.keys(brLate).sort(function(a,b){return brLate[b]-brLate[a]})[0];if(worst>=0)return"Филиал с наибольшим числом просрочек: "+br[parseInt(worst)]+" ("+brLate[worst]+" просрочек).";return"Все филиалы без просрочек."} - if(q.indexOf("отчёт")>=0||q.indexOf("квартал")>=0)return"Перейдите на вкладку «Отчёты», выберите период и нажмите CSV или HTML. Используйте 💾 для бекапа."; - return"Я отвечаю на вопросы: «просроченные», «риски», «статус пункта N», «сводка», «филиалы», «отчёт»."; -} - -// ===== EDIT ===== -function oe(id,mi,ri,si){ - if(typeof mi==="number")cm=mi;if(typeof ri==="number")cr=ri;esi=(typeof si==="number")?si:-1; +// ===== EDIT (no regions) ===== +function oe(id,mi,si){ + if(typeof mi==="number")cm=mi;esi=(typeof si==="number")?si:-1; var e=null;for(var i=0;i"; - h+="

"+esc(e.t)+"

"; - h+="
Филиал"+br[e.b]+"
Срок"+e.due+" ("+daysLeft(e)+")
"; + var m=ms[cm],md=getMD(e.id,-1),cd=md[m]||{report:"",files:[]},cfs=cd.files||[]; + var h="×"; + h+="

"+e.id+". "+esc(e.t)+"

"; + h+="
Филиал"+br[e.b]+"
Срок"+e.due+"
Статус"+st[e.s]+"
Осталось"+daysLeft(e)+"
"; if(e.sub&&e.sub.length){ h+=""; e.sub.forEach(function(sb,i){var isA=esi===i; - h+="
"+sb.l+") "+esc(sb.t)+"
"; - if(isA){var sd=getMD(e.id,cr,i),scd=sd[m]||{report:"",files:[]},scfs=scd.files||[]; - h+="
"+sb.l+") "+esc(sb.t)+"

"+reg[cr]+" · "+M(cm)+"

"; + h+="
"+sb.l+") "+esc(sb.t)+"
"; + if(isA){var sd=getMD(e.id,i),scd=sd[m]||{report:"",files:[]},scfs=scd.files||[]; + h+="
"; + h+=""+sb.l+") "+esc(sb.t)+"

"+M(cm)+"

"; h+=""; h+=""; - scfs.forEach(function(f,fi){h+="
📄 "+esc(f.name)+""+(f.size/1024).toFixed(0)+" КБ · "+f.date+"
"}); - h+="

📤 Загрузить документы

"; + scfs.forEach(function(f,fi){h+="
📄 "+esc(f.name)+""+(f.size/1024).toFixed(0)+" КБ · "+(f.date||"")+"
"}); + h+="
"; } }); - h+="
";ms.forEach(function(_,i){h+=""+M(i)+""});h+="
"; - h+="
";reg.forEach(function(r,i){h+=""+r+""});h+="
"; + h+="
";ms.forEach(function(_,i){h+=""+M(i)+""});h+="
"; h+=""; }else{ - h+="
";ms.forEach(function(_,i){h+=""+M(i)+""});h+="
"; - h+="
";reg.forEach(function(r,i){h+=""+r+""});h+="
"; + h+="
";ms.forEach(function(_,i){h+=""+M(i)+""});h+="
"; h+=""; - h+=""; + h+=""; h+=""; - cfs.forEach(function(f,i){h+="
📄 "+esc(f.name)+""+(f.size/1024).toFixed(0)+" КБ · "+f.date+"
"}); - h+="

📤 Загрузить документы

"; + cfs.forEach(function(f,i){h+="
📄 "+esc(f.name)+""+(f.size/1024).toFixed(0)+" КБ · "+(f.date||"")+"
"}); + h+="

PDF, DOC, XLS, фото, презентации

"; } - h+="
🤖 ИИ: "+esc(e.ai)+"
"; + h+="
🤖 ИИ-анализ: "+esc(e.ai)+"
"; h+="
История изменений:";e.h.forEach(function(x){h+="
"+esc(x)+"
"});h+="
"; - h+="
"; + h+="
"; document.getElementById("mc").innerHTML=h;document.getElementById("mo").classList.add("on"); } -function sv(id,mk){mk=ms[mk];var e=null;for(var i=0;i=0?"_s"+si:"",fi=document.getElementById("fi2"+pfx);if(!fi||!fi.files.length)return;var btn=document.getElementById("ub2"+pfx);if(btn){btn.textContent="...";btn.disabled=true}var ad=getMD(eid,ri,si);if(!ad[mk])ad[mk]={report:"",files:[]};var arr=ad[mk].files,pr=0,sk=0;function fin(){try{setMD(eid,ad,ri,si)}catch(e){alert("Хранилище заполнено")}if(sk)alert(sk+" файлов >3 МБ");closeM();oe(eid,cm,ri,si>=0?si:undefined)}for(var i=0;i3072*1024){sk++;pr++;if(pr===fi.files.length)fin();return}var r=new FileReader();r.onload=function(evt){arr.push({name:f.name,size:f.size,type:f.type,date:new Date().toLocaleDateString(),user:cu?cu.n:"?",data:evt.target.result});pr++;if(pr===fi.files.length)fin()};r.onerror=function(){pr++;if(pr===fi.files.length)fin()};r.readAsDataURL(f)})(fi.files[i])}} -function dlF2(eid,mk,idx,ri,si){si=si||-1;mk=ms[mk];var ad=getMD(eid,ri,si),arr=ad[mk]?ad[mk].files:null;if(!arr||!arr[idx]||!arr[idx].data)return;var f=arr[idx],a=document.createElement("a");a.href=f.data;a.download=f.name;document.body.appendChild(a);a.click();document.body.removeChild(a)} -function rmF2(eid,mk,idx,ri,si){si=si||-1;mk=ms[mk];var ad=getMD(eid,ri,si);if(!ad[mk]||!ad[mk].files)return;ad[mk].files.splice(idx,1);setMD(eid,ad,ri,si);closeM();oe(eid,cm,ri,si>=0?si:undefined)} +function upF2(eid,mk,si){mk=ms[mk];var pfx=si>=0?"_s"+si:"",fi=document.getElementById("fi2"+pfx);if(!fi||!fi.files.length)return;var btn=document.getElementById("ub2"+pfx);if(btn){btn.textContent="...";btn.disabled=true}var ad=getMD(eid,si);if(!ad[mk])ad[mk]={report:"",files:[]};var arr=ad[mk].files,pr=0,sk=0;function fin(){try{setMD(eid,ad,si)}catch(e){alert("Хранилище заполнено")}if(sk)alert(sk+" файлов >3 МБ");closeM();oe(eid,cm,si>=0?si:undefined)}for(var i=0;i3072*1024){sk++;pr++;if(pr===fi.files.length)fin();return}var r=new FileReader();r.onload=function(evt){arr.push({name:f.name,size:f.size,type:f.type,date:new Date().toLocaleDateString(),user:cu?cu.n:"?",data:evt.target.result});pr++;if(pr===fi.files.length)fin()};r.onerror=function(){pr++;if(pr===fi.files.length)fin()};r.readAsDataURL(f)})(fi.files[i])}} +function dlF2(eid,mk,idx,si){si=si||-1;mk=ms[mk];var ad=getMD(eid,si),arr=ad[mk]?ad[mk].files:null;if(!arr||!arr[idx]||!arr[idx].data)return;var f=arr[idx],a=document.createElement("a");a.href=f.data;a.download=f.name;document.body.appendChild(a);a.click();document.body.removeChild(a)} +function rmF2(eid,mk,idx,si){si=si||-1;mk=ms[mk];var ad=getMD(eid,si);if(!ad[mk]||!ad[mk].files)return;ad[mk].files.splice(idx,1);setMD(eid,ad,si);closeM();oe(eid,cm,si>=0?si:undefined)} document.getElementById("mo").addEventListener("click",function(e){if(e.target===this)closeM()}); document.addEventListener("keydown",function(e){if(e.key==="Escape")closeM()});