From c9ac12a3a471319e1a1376591e1d8ccd1714988f Mon Sep 17 00:00:00 2001 From: Dauren777 Date: Wed, 3 Jun 2026 12:22:48 +0000 Subject: [PATCH] =?UTF-8?q?=D0=90=D0=B4=D0=BC=D0=B8=D0=BD:=20=D1=81=D0=BA?= =?UTF-8?q?=D0=B0=D1=87=D0=B8=D0=B2=D0=B0=D0=BD=D0=B8=D0=B5=20=D0=BF=D0=BE?= =?UTF-8?q?=D0=BB=D0=BD=D0=BE=D0=B3=D0=BE=20CSV,=20=D0=BE=D1=82=D1=87?= =?UTF-8?q?=D1=91=D1=82=D0=B0=20=D0=BF=D0=BE=20=D1=80=D0=B0=D0=B1=D0=BE?= =?UTF-8?q?=D1=82=D0=BD=D0=B8=D0=BA=D0=B0=D0=BC,=20=D1=81=D0=B2=D0=BE?= =?UTF-8?q?=D0=B4=D0=BD=D0=BE=D0=B3=D0=BE=20HTML-=D0=BE=D1=82=D1=87=D1=91?= =?UTF-8?q?=D1=82=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- index.html | 98 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 98 insertions(+) diff --git a/index.html b/index.html index 17e11cf..07f36ce 100644 --- a/index.html +++ b/index.html @@ -319,6 +319,13 @@ body{font:15px/1.5 -apple-system,BlinkMacSystemFont,"Segoe UI",Inter,system-ui,s
+
+ +
@@ -698,6 +705,7 @@ function switchPanel(name,el){ // ========== DASHBOARD ========== function renderDashboard(){ + document.getElementById('adminBar').style.display=isAdmin()?'flex':'none'; const allUsers=getAllUsers(); const userList=Object.entries(allUsers).map(([login,data])=>({login,...data})); @@ -846,6 +854,96 @@ function exportCSV(){ const rows=audits.map(a=>{const u=all[a.createdBy]||{};return `${a.number||''};${a.date};${a.timeStart||''}-${a.timeEnd||''};"${a.location}";"${a.workType||''}";"${a.observer}";"${a.observerRole||''}";"${u.branch||''}";"${u.region||''}";"${u.oblast||''}";"${u.city||''}";${a.overallSafe?'Безопасно':'Нарушения'};${a.totalViolations||0}`}); const csv='\uFEFF'+header+'\n'+rows.join('\n');const blob=new Blob([csv],{type:'text/csv;charset=utf-8'});const url=URL.createObjectURL(blob);const a=document.createElement('a');a.href=url;a.download='pab-audit.csv';a.click();URL.revokeObjectURL(url); } + +// ========== ADMIN DOWNLOADS ========== +function downloadFullCSV(){ + const audits=getAudits();if(audits.length===0){alert('Нет данных');return} + const all=getAllUsers(); + const header='Бланк №;Дата;Время;Место;Тип работы;Наблюдатель;Должность;Руководитель;Филиал;Подразделение;Регион;Область;Город;Статус;Нарушений;Категории с нарушениями'; + const rows=audits.map(a=>{ + const u=all[a.createdBy]||{}; + const catsWithVio=CATEGORIES.filter(cat=>{const c=a.categories&&a.categories[cat.id];return c&&c.items.length>0}).map(c=>c.title.split('. ')[1]).join(' | '); + return `${a.number||''};${a.date};${a.timeStart||''}-${a.timeEnd||''};"${a.location}";"${a.workType||''}";"${a.observer}";"${a.observerRole||''}";"${a.supervisor||''}";"${u.branch||''}";"${u.dept||''}";"${u.region||''}";"${u.oblast||''}";"${u.city||''}";${a.overallSafe?'Безопасно':'Нарушения'};${a.totalViolations||0};"${catsWithVio}"`; + }); + const csv='\uFEFF'+header+'\n'+rows.join('\n');const blob=new Blob([csv],{type:'text/csv;charset=utf-8'});const url=URL.createObjectURL(blob);const a=document.createElement('a');a.href=url;a.download='pab-full-report.csv';a.click();URL.revokeObjectURL(url); +} + +function downloadWorkerReport(){ + const all=getAllUsers();const audits=getAudits();const userList=Object.entries(all).filter(([l])=>l!=='admin'); + if(userList.length===0){alert('Нет зарегистрированных работников');return} + const header='Логин;ФИО;Должность;Филиал;Подразделение;Регион;Область;Город;Email;График;Период;Выполнено;Нужно;Статус'; + const rows=userList.map(([login,u])=>{ + const q=getQuota(u.role); + if(!q.period)return `${login};"${u.name}";"${u.role}";"${u.branch||''}";"${u.dept||''}";"${u.region||''}";"${u.oblast||''}";"${u.city||''}";"${u.email||''}";Без графика;;;0;—`; + const p=getCurrentPeriod(q.period);const done=audits.filter(a=>a.createdBy===login&&new Date(a.date)>=p.start).length; + const status=done>=q.count?'Выполнен':'Отстаёт ('+(q.count-done)+')'; + return `${login};"${u.name}";"${u.role}";"${u.branch||''}";"${u.dept||''}";"${u.region||''}";"${u.oblast||''}";"${u.city||''}";"${u.email||''}";"${q.label}";"${p.label}";${done};${q.count};"${status}"`; + }); + const csv='\uFEFF'+header+'\n'+rows.join('\n');const blob=new Blob([csv],{type:'text/csv;charset=utf-8'});const url=URL.createObjectURL(blob);const a=document.createElement('a');a.href=url;a.download='pab-worker-report.csv';a.click();URL.revokeObjectURL(url); +} + +function downloadSummaryHTML(){ + const audits=getAudits();const all=getAllUsers();const userList=Object.entries(all).filter(([l])=>l!=='admin'); + const total=audits.length;const allSafe=audits.filter(a=>a.overallSafe).length; + const withDanger=audits.filter(a=>!a.overallSafe).length;const totalVio=audits.reduce((s,a)=>s+(a.totalViolations||0),0); + + // Schedule stats + let onTrack=0,behind=0,noQuota=0; + userList.forEach(([login,u])=>{const q=getQuota(u.role);if(!q.period){noQuota++;return}const p=getCurrentPeriod(q.period);const done=audits.filter(a=>a.createdBy===login&&new Date(a.date)>=p.start).length;if(done>=q.count)onTrack++;else behind++}); + + // Category stats + const catStats=CATEGORIES.map(cat=>({name:cat.title,count:audits.reduce((s,a)=>{const c=a.categories&&a.categories[cat.id];return s+(c?c.items.length:0)},0)})).sort((a,b)=>b.count-a.count); + + // Region stats + const regStats={};audits.forEach(a=>{const u=all[a.createdBy];const r=u?u.region||'Не указан':'Не указан';if(!regStats[r])regStats[r]={total:0,safe:0,danger:0};regStats[r].total++;if(a.overallSafe)regStats[r].safe++;else regStats[r].danger++}); + const regRows=Object.entries(regStats).sort((a,b)=>b[1].total-a[1].total).map(([r,s])=>`${r}${s.total}${s.safe}${s.danger}${Math.round(s.safe/s.total*100)}%`).join(''); + + // Branch stats + const brStats={};audits.forEach(a=>{const u=all[a.createdBy];const b=u?u.branch||'Не указан':'Не указан';brStats[b]=(brStats[b]||0)+1}); + const brRows=Object.entries(brStats).sort((a,b)=>b[1]-a[1]).map(([b,c])=>`${b}${c}`).join(''); + + // Top violations + const itemCounts={};audits.forEach(a=>{if(a.categories){Object.values(a.categories).forEach(cat=>{if(cat.items){cat.items.forEach(it=>{itemCounts[it.item]=(itemCounts[it.item]||0)+1})})}}); + const topItems=Object.entries(itemCounts).sort((a,b)=>b[1]-a[1]).slice(0,15).map(([i,c])=>`${i}${c}`).join(''); + + // Worker schedule + const workerRows=userList.map(([login,u])=>{ + const q=getQuota(u.role);if(!q.period)return`${u.name}${u.role}${u.branch||'—'}${u.dept||'—'}${u.region||'—'}${u.city||'—'}Без графика—`; + const p=getCurrentPeriod(q.period);const done=audits.filter(a=>a.createdBy===login&&new Date(a.date)>=p.start).length; + const cls=done>=q.count?'green':'red';return`${u.name}${u.role}${u.branch||'—'}${u.dept||'—'}${u.region||'—'}${u.city||'—'}${done}/${q.count} (${q.label})${p.label}`; + }).join(''); + + const html=`Сводный отчёт ПАБ + + +

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

Сформирован: ${new Date().toLocaleString('ru')}

+
+
Всего аудитов
${total}
+
Безопасно
${allSafe}
+
С нарушениями
${withDanger}
+
Нарушений
${totalVio}
+
Выполняют график
${onTrack}
+
Отстают от графика
${behind}
+
+

📂 Нарушения по категориям

${catStats.map(c=>``).join('')}
КатегорияКол-во нарушений
${c.name}${c.count}
+

🏢 По регионам

${regRows}
РегионВсегоБезопасноС наруш.% Безоп.
+

🏭 По филиалам

${brRows}
ФилиалАудитов
+

👥 Выполнение графика по работникам

${workerRows}
ФИОДолжностьФилиалПодразделениеРегионГородПрогрессПериод
+

🔝 Топ-15 нарушений

${topItems}
НарушениеКол-во
+ +`; + const w=window.open('','_blank','width=1000,height=800');w.document.write(html);w.document.close(); +}