@@ -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')}
+
+
+
+
С нарушениями
${withDanger}
+
+
Выполняют график
${onTrack}
+
Отстают от графика
${behind}
+
+
📂 Нарушения по категориям
| Категория | Кол-во нарушений |
${catStats.map(c=>`| ${c.name} | ${c.count} |
`).join('')}
+
🏢 По регионам
| Регион | Всего | Безопасно | С наруш. | % Безоп. |
${regRows}
+
🏭 По филиалам
+
👥 Выполнение графика по работникам
| ФИО | Должность | Филиал | Подразделение | Регион | Город | Прогресс | Период |
${workerRows}
+
🔝 Топ-15 нарушений
| Нарушение | Кол-во |
${topItems}
+
+`;
+ const w=window.open('','_blank','width=1000,height=800');w.document.write(html);w.document.close();
+}