246 lines
18 KiB
HTML
246 lines
18 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="ru">
|
||
<head>
|
||
<meta charset="utf-8">
|
||
<meta name="viewport" content="width=device-width,initial-scale=1">
|
||
<title>QAZAQtelecom HSE — План ПБ 2026</title>
|
||
<style>
|
||
|
||
*{box-sizing:border-box;margin:0;padding:0}
|
||
body{font:14px/1.4 Arial,sans-serif;background:#F4F6F9;color:#1A1A2E;min-height:100vh}
|
||
input,select,textarea,button{font:inherit;outline:none}
|
||
.btn{background:#005BAA;color:#fff;padding:12px 24px;border-radius:8px;font-weight:600;font-size:14px;border:none;cursor:pointer;display:inline-block;text-align:center;transition:all 0.2s}.btn:hover{background:#004B8C;box-shadow:0 2px 8px rgba(0,91,170,0.3)}
|
||
.btn-sm{padding:7px 16px;font-size:12px}.btn-r{background:#E53935;color:#fff}.btn-g{background:#2E7D32;color:#fff}.btn-o{background:#F57C00;color:#fff}
|
||
#login{display:flex;align-items:center;justify-content:center;min-height:100vh;background:linear-gradient(135deg,#003D73,#005BAA,#0077CC)}
|
||
#login>div{background:#fff;border-radius:16px;padding:40px;width:400px;max-width:90vw;text-align:center;box-shadow:0 8px 32px rgba(0,0,0,0.15)}
|
||
#login h1{font-size:22px;font-weight:800;margin-bottom:4px}#login h1 span{color:#005BAA}
|
||
#login>div>p{color:#64748B;font-size:13px;margin-bottom:24px}
|
||
#login input{display:block;width:100%;padding:12px;border:2px solid #E2E8F0;border-radius:10px;font-size:14px;margin-bottom:12px;transition:border 0.2s}
|
||
#login input:focus{border-color:#005BAA}
|
||
#app{display:none;min-height:100vh}
|
||
#sidebar{position:fixed;left:0;top:0;bottom:0;width:220px;background:#0A1628;color:#fff;z-index:100;overflow-y:auto;box-shadow:2px 0 12px rgba(0,0,0,0.1)}
|
||
#sidebar .logo{padding:20px 16px 12px;font-size:16px;font-weight:800;border-bottom:1px solid rgba(255,255,255,.1);display:flex;align-items:center;gap:8px}
|
||
#sidebar .logo span{color:#005BAA}
|
||
#sidebar .user{font-size:11px;color:#94A3B8;padding:10px 16px;border-bottom:1px solid rgba(255,255,255,.05)}
|
||
#sidebar a{display:block;padding:12px 16px;color:#CBD5E1;text-decoration:none;font-size:13px;cursor:pointer;border-left:3px solid transparent;transition:all 0.15s}
|
||
#sidebar a:hover{background:rgba(0,91,170,.1);color:#fff}
|
||
#sidebar a.active{background:rgba(0,91,170,.2);color:#005BAA;border-left-color:#005BAA;font-weight:600}
|
||
#sidebar .logout{position:absolute;bottom:16px;left:16px;right:16px}
|
||
#main{margin-left:220px;padding:24px;min-height:100vh}
|
||
.top{display:flex;justify-content:space-between;align-items:center;padding:0 0 16px;border-bottom:2px solid #E2E8F0;margin-bottom:20px}
|
||
.top h2{font-size:20px;font-weight:700}
|
||
.card{background:#fff;border-radius:12px;padding:20px;margin-bottom:16px;border:1px solid #E8ECF1;overflow-x:auto;box-shadow:0 1px 4px rgba(0,0,0,0.04)}
|
||
.card h3{font-size:16px;font-weight:700;margin-bottom:12px}
|
||
table{width:100%;border-collapse:collapse}
|
||
th,td{padding:8px 10px;font-size:13px;text-align:left;border-bottom:1px solid #E2E8F0;vertical-align:top}
|
||
th{background:#F1F5F9;font-weight:600;font-size:11px;text-transform:uppercase;color:#64748B;white-space:nowrap}
|
||
tr:hover{background:#FAFBFC}
|
||
.badge{display:inline-block;padding:3px 8px;border-radius:100px;font-size:11px;font-weight:600;white-space:nowrap}
|
||
.badge.g{background:#E8F5E9;color:#2E7D32}.badge.a{background:#FFF3E0;color:#E65100}.badge.r{background:#FFEBEE;color:#C62828}.badge.b{background:#E3F2FD;color:#1565C0}.badge.w{background:#F5F5F5;color:#757575}
|
||
.fr{display:flex;gap:8px;margin-bottom:14px;flex-wrap:wrap;align-items:center}
|
||
.fr input,.fr select{padding:8px 12px;border:1px solid #E2E8F0;border-radius:8px;font-size:13px;background:#fff}.fr input{min-width:200px}
|
||
.tr-red{background:#FFF5F5}.tr-red td{border-bottom-color:#FECACA;color:#991B1B}
|
||
.tr-amber{background:#FFFBEB}.tr-amber td{border-bottom-color:#FDE68A;color:#92400E}
|
||
.tr-green{background:#F0FDF4}.tr-green td{border-bottom-color:#BBF7D0;color:#065F46}
|
||
.sec-h{background:#005BAA;color:#fff;padding:6px 12px;border-radius:6px;font-size:12px;font-weight:700;display:inline-block;margin:16px 0 8px}
|
||
.stat-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(160px,1fr));gap:12px;margin-bottom:20px}
|
||
.stat-card{background:#fff;border-radius:12px;padding:16px;border:1px solid #E2E8F0;text-align:center}
|
||
.stat-card .num{font-size:28px;font-weight:800;margin:4px 0}.stat-card .lb{font-size:12px;color:#64748B}
|
||
.stat-card.sg .num{color:#10B981}.stat-card.sr .num{color:#EF4444}.stat-card.sb .num{color:#00B4D8}.stat-card.sa .num{color:#F59E0B}
|
||
.chat-box{height:280px;overflow-y:auto;border:1px solid #E2E8F0;border-radius:10px;padding:12px;margin-bottom:12px;background:#FAFBFC}
|
||
.msg{padding:8px 12px;border-radius:10px;margin-bottom:8px;max-width:85%;font-size:13px;line-height:1.4}
|
||
.msg.u{margin-left:auto;background:#005BAA;color:#fff}.msg.b{background:#F1F5F9;color:#0B1A2E}
|
||
.msg .nm{font-size:10px;color:#94A3B8;margin-bottom:2px}
|
||
.chat-inp{display:flex;gap:8px}.chat-inp input{flex:1;padding:10px 14px;border:1px solid #E2E8F0;border-radius:8px;font-size:13px}
|
||
.chat-q{display:flex;flex-wrap:wrap;gap:6px;margin-bottom:12px}
|
||
.chat-q button{padding:6px 12px;border:1px solid #E2E8F0;border-radius:100px;font-size:11px;background:#fff;cursor:pointer;color:#0B1A2E}
|
||
.chat-q button:hover{background:#00B4D8;color:#fff;border-color:#00B4D8}
|
||
.rank-bar{height:8px;border-radius:4px;background:#E2E8F0;overflow:hidden;margin-top:4px}
|
||
.rank-bar>div{height:100%;border-radius:4px;transition:width .3s}
|
||
.sub-row{font-size:12px;color:#64748B;cursor:pointer;user-select:none}
|
||
.sub-row:hover{color:#00B4D8}.sub-row .arr{display:inline-block;width:16px;text-align:center}
|
||
.sub-items{padding-left:24px}.sub-item{font-size:12px;padding:4px 0;border-bottom:1px solid #F1F5F9}.sub-item:last-child{border:none}
|
||
.mod-overlay{position:fixed;top:0;left:0;right:0;bottom:0;background:rgba(0,0,0,.5);z-index:1000;display:none;align-items:center;justify-content:center}
|
||
.mod-box{background:#fff;border-radius:16px;padding:28px;max-width:750px;width:90vw;max-height:85vh;overflow-y:auto;position:relative}
|
||
.file-item{display:flex;align-items:center;gap:8px;padding:6px 8px;background:#F8FAFC;border-radius:6px;margin:4px 0;border:1px solid #E2E8F0;flex-wrap:wrap}
|
||
.file-item .fn{font-size:12px;flex:1;min-width:80px}.file-item .fs{font-size:10px;color:#64748B}.file-item a{font-size:11px;color:#00B4D8;cursor:pointer;text-decoration:underline}
|
||
.stor-bar{font-size:11px;color:#64748B;padding:4px 0}
|
||
@media(max-width:768px){#sidebar{width:56px}#sidebar .logo span,#sidebar a span,#sidebar .user{display:none}#main{margin-left:56px}.stat-grid{grid-template-columns:repeat(2,1fr)}}
|
||
</style>
|
||
</head>
|
||
<body onload="init()" style="margin:0">
|
||
<div id="login"><div>
|
||
<h1><span>QAZAQtelecom</span> HSE</h1>
|
||
<p>План производственной безопасности 2026</p>
|
||
<input id="lem" placeholder="curator@telecom.kz">
|
||
<input id="lpw" type="password" placeholder="Пароль">
|
||
<p id="lerr" style="color:#EF4444;font-size:12px;display:none">Неверная почта</p>
|
||
<button class="btn" style="width:100%" onclick="doLogin()">Войти</button>
|
||
</div></div>
|
||
<div id="app">
|
||
<div id="sidebar">
|
||
<div class="logo">QAZAQtelecom <span>HSE</span></div>
|
||
<div class="user" id="su_name"></div>
|
||
<a class=" active" id="snav_events" onclick="switchTab('events')"><span>Мероприятия</span></a>
|
||
<a class="" id="snav_analytics" onclick="switchTab('analytics')"><span>Аналитика</span></a>
|
||
<a class="" id="snav_reports" onclick="switchTab('reports')"><span>Отчётность</span></a>
|
||
<a class="" id="snav_ai" onclick="switchTab('ai')"><span>Джарвис</span></a>
|
||
<a class="" id="snav_hse" onclick="switchTab('hse')"><span>HSE.sk.kz</span></a>
|
||
<a class="" id="snav_users" onclick="switchTab('users')"><span>Учётные записи</span></a>
|
||
<div class="logout"><button class="btn btn-sm btn-r" style="width:100%" onclick="doLogout()">Выйти</button></div>
|
||
</div>
|
||
<div id="main">
|
||
<div class="top"><h2 id="page_title">Мероприятия</h2>
|
||
<div style="display:flex;gap:8px;align-items:center">
|
||
<span id="stor_ind" class="stor-bar"></span>
|
||
<button class="btn btn-sm btn-o" onclick="saveBackup()">Резерв</button>
|
||
<button class="btn btn-sm btn-g" onclick="document.getElementById('fu').click()">Восст.</button>
|
||
<input type="file" id="fu" accept=".json" style="display:none" onchange="loadBackup(this)">
|
||
</div></div>
|
||
<div id="tab_events">
|
||
<div class="fr">
|
||
<input id="sea" placeholder="Поиск..." oninput="renderEv()">
|
||
<select id="fs" onchange="renderEv()"><option value="">Все статусы</option><option value="warn">В процессе</option><option value="done">Исполнено</option><option value="late">Просрочено</option></select>
|
||
<select id="fb" onchange="renderEv()"><option value="">Все филиалы</option></select>
|
||
<span id="sc" style="font-size:12px;color:#64748B;margin-left:auto"></span>
|
||
</div>
|
||
<div class="card" id="ev_content"></div>
|
||
</div>
|
||
<div id="tab_analytics" style="display:none">
|
||
<div class="stat-grid" id="an_stats"></div>
|
||
<div class="card"><h3>TOP-10 проблемных мероприятий</h3><div id="an_top"></div></div>
|
||
<div class="card"><h3>Выполнение по разделам</h3><div id="an_sections"></div></div>
|
||
<div style="display:flex;gap:8px;margin-bottom:16px">
|
||
<button class="btn btn-sm btn-o" onclick="dlAnalyticsPPT()">Скачать PPT</button>
|
||
<button class="btn btn-sm btn-r" onclick="dlAnalyticsPDF()">Скачать PDF</button>
|
||
<button class="btn btn-sm" onclick="dlAnalyticsWord()">Скачать Word</button>
|
||
</div>
|
||
<div class="card" id="ltif_card"><h3>LTIF — Коэффициент частоты травм</h3>
|
||
<p style="font-size:12px;color:#64748B;margin-bottom:8px">LTIF = (A × 1 000 000) / Человеко-часы, где A — число пострадавших</p>
|
||
<div style="display:flex;gap:8px;flex-wrap:wrap;align-items:end;margin-bottom:10px">
|
||
<div><span style="font-size:11px;color:#64748B">Месяц</span>
|
||
<select id="ltif_month" style="padding:6px 10px;border:1px solid #E2E8F0;border-radius:6px;font-size:12px">
|
||
<option value="0">Январь</option><option value="1">Февраль</option><option value="2">Март</option>
|
||
<option value="3">Апрель</option><option value="4">Май</option><option value="5">Июнь</option>
|
||
<option value="6">Июль</option><option value="7">Август</option><option value="8">Сентябрь</option>
|
||
<option value="9">Октябрь</option><option value="10">Ноябрь</option><option value="11">Декабрь</option>
|
||
</select></div>
|
||
<div><span style="font-size:11px;color:#64748B">Человеко-часы</span>
|
||
<input id="ltif_hours" type="number" placeholder="0" style="width:130px;padding:6px;border:1px solid #E2E8F0;border-radius:6px;font-size:12px"></div>
|
||
<div><span style="font-size:11px;color:#64748B">Пострадавших (A)</span>
|
||
<input id="ltif_inj" type="number" placeholder="0" style="width:80px;padding:6px;border:1px solid #E2E8F0;border-radius:6px;font-size:12px"></div>
|
||
<button class="btn btn-sm btn-g" onclick="saveLTIF()">Сохранить</button>
|
||
<button class="btn btn-sm" onclick="loadLTIF()">Загрузить</button>
|
||
</div>
|
||
<div id="ltif_result" style="font-size:14px;padding:8px 0"></div>
|
||
<div id="ltif_table"></div>
|
||
<div id="ltif_corr_div"></div>
|
||
</div>
|
||
</div>
|
||
<div id="tab_reports" style="display:none">
|
||
<div class="card"><h3>Выгрузка сводного отчёта</h3>
|
||
<p style="font-size:13px;color:#64748B;margin-bottom:12px">Выберите период и формат для скачивания отчёта.</p>
|
||
<div class="fr">
|
||
<span style="font-size:13px;color:#64748B">Период:</span>
|
||
<select id="rp_period" style="padding:6px 10px;border:1px solid #E2E8F0;border-radius:6px" onchange="rpPeriodChange()">
|
||
<option value="year">Год</option>
|
||
<option value="month">Месяц</option>
|
||
<option value="q1">Январь-Март (Q1)</option>
|
||
<option value="q2">Апрель-Июнь (Q2)</option>
|
||
<option value="q3">Июль-Сентябрь (Q3)</option>
|
||
<option value="q4">Октябрь-Декабрь (Q4)</option>
|
||
<option value="h1">1-е полугодие</option>
|
||
<option value="h2">2-е полугодие</option>
|
||
</select>
|
||
<select id="rp_month" onchange="renderReports()" style="padding:6px 10px;border:1px solid #E2E8F0;border-radius:6px;display:none">
|
||
<option value="0">Январь</option><option value="1">Февраль</option><option value="2">Март</option>
|
||
<option value="3">Апрель</option><option value="4">Май</option><option value="5">Июнь</option>
|
||
<option value="6">Июль</option><option value="7">Август</option><option value="8">Сентябрь</option>
|
||
<option value="9">Октябрь</option><option value="10">Ноябрь</option><option value="11" selected>Декабрь</option>
|
||
</select>
|
||
<select id="rp_year" style="padding:6px 10px;border:1px solid #E2E8F0;border-radius:6px">
|
||
<option>2026</option><option>2027</option>
|
||
</select>
|
||
<select id="rp_status" style="padding:6px 10px;border:1px solid #E2E8F0;border-radius:6px">
|
||
<option value="">Все статусы</option>
|
||
<option value="warn">В процессе</option>
|
||
<option value="done">Исполнено</option>
|
||
<option value="late">Просрочено</option>
|
||
</select>
|
||
</div>
|
||
<div style="display:flex;gap:8px;flex-wrap:wrap">
|
||
<button class="btn btn-sm btn-g" onclick="dlCSV()">CSV</button>
|
||
<button class="btn btn-sm" onclick="dlHTML()">HTML</button>
|
||
<button class="btn btn-sm btn-o" onclick="dlWord()">Word</button>
|
||
<button class="btn btn-sm btn-r" onclick="dlPdf()">PDF</button>
|
||
</div>
|
||
<p id="rp_count" style="font-size:12px;color:#64748B;margin-top:8px"></p>
|
||
</div>
|
||
<div class="card" id="rp_preview"></div>
|
||
</div>
|
||
<div id="tab_users" style="display:none">
|
||
<div class="card"><h3>Учётные записи</h3>
|
||
<p style="font-size:13px;color:#64748B;margin-bottom:8px">Управление ответственными лицами по филиалам</p>
|
||
<button class="btn btn-sm btn-g" onclick="showRegModal()">+ Зарегистрировать</button>
|
||
<div id="users_list" style="margin-top:14px"></div>
|
||
</div></div>
|
||
<div id="tab_hse" style="display:none">
|
||
<div class="card"><h3>Интеграция с HSE.sk.kz</h3>
|
||
<p style="font-size:13px;color:#64748B;margin-bottom:16px">Направление подписанного сводного отчёта по месяцам в систему hse.sk.kz</p>
|
||
<div style="margin-bottom:12px"><strong>Месяц:</strong>
|
||
<input type="month" id="hse_month" style="padding:6px 10px;border:1px solid #E2E8F0;border-radius:6px;margin-left:8px">
|
||
</div>
|
||
<div style="margin-bottom:12px"><strong>Формат:</strong>
|
||
<select id="hse_fmt" style="padding:6px 10px;border:1px solid #E2E8F0;border-radius:6px;margin-left:8px">
|
||
<option value="word">Word (.docx)</option>
|
||
<option value="pdf">PDF</option>
|
||
</select>
|
||
</div>
|
||
<div style="margin-bottom:12px"><strong>API Ключ:</strong>
|
||
<input id="hse_key" type="password" placeholder="Ключ API HSE.sk.kz" style="padding:6px 10px;border:1px solid #E2E8F0;border-radius:6px;margin-left:8px;width:300px">
|
||
</div>
|
||
<button class="btn btn-sm btn-g" onclick="hseSend()" id="hse_btn">Отправить отчёт в HSE.sk.kz</button>
|
||
<div id="hse_result" style="margin-top:12px;font-size:13px"></div>
|
||
</div></div>
|
||
<div id="tab_ai" style="display:none">
|
||
<div class="card">
|
||
<div class="chat-q">
|
||
<button onclick="aiAsk('сводка')">Сводка</button>
|
||
<button onclick="aiAsk('просроченные')">Просроченные</button>
|
||
<button onclick="aiAsk('риски')">Риски</button>
|
||
<button onclick="aiAsk('рейтинг')">Рейтинг</button>
|
||
<button onclick="aiAsk('прогноз')">Прогноз</button>
|
||
<button onclick="aiAsk('статус')">Статус</button>
|
||
<button onclick="aiAsk('план')">План действий</button>
|
||
</div>
|
||
<div class="chat-box" id="ai_chat"></div>
|
||
<div class="chat-inp"><input id="ai_inp" placeholder="Спроси про план ПБ..." onkeydown="if(event.key=='Enter')aiSend()">
|
||
<button class="btn btn-sm" onclick="aiSend()">Отправить</button></div>
|
||
</div></div>
|
||
</div></div>
|
||
<div id="modal" class="mod-overlay" onclick="if(event.target===this)closeModal()">
|
||
<div class="mod-box" id="modal_body"></div>
|
||
</div>
|
||
<div id="regModal" class="mod-overlay" onclick="if(event.target===this)closeRegModal()">
|
||
<div class="mod-box" style="max-width:500px">
|
||
<h3 style="margin-bottom:14px">Регистрация пользователя</h3>
|
||
<div style="margin-bottom:8px"><label style="font-size:12px;color:#64748B">Email (логин)</label>
|
||
<input id="reg_email" placeholder="ivanov@telecom.kz" style="width:100%;padding:8px;border:1px solid #E2E8F0;border-radius:6px;font-size:13px"></div>
|
||
<div style="margin-bottom:8px"><label style="font-size:12px;color:#64748B">ФИО</label>
|
||
<input id="reg_name" placeholder="Иванов И.И." style="width:100%;padding:8px;border:1px solid #E2E8F0;border-radius:6px;font-size:13px"></div>
|
||
<div style="margin-bottom:8px"><label style="font-size:12px;color:#64748B">Телефон</label>
|
||
<input id="reg_phone" placeholder="+77001234567" style="width:100%;padding:8px;border:1px solid #E2E8F0;border-radius:6px;font-size:13px"></div>
|
||
<div style="margin-bottom:8px"><label style="font-size:12px;color:#64748B">Роль</label>
|
||
<select id="reg_role" style="width:100%;padding:8px;border:1px solid #E2E8F0;border-radius:6px;font-size:13px"></select></div>
|
||
<div style="margin-bottom:8px"><label style="font-size:12px;color:#64748B">Филиал</label>
|
||
<select id="reg_branch" style="width:100%;padding:8px;border:1px solid #E2E8F0;border-radius:6px;font-size:13px"></select></div>
|
||
<div style="margin-bottom:14px"><label style="font-size:12px;color:#64748B">Пароль</label>
|
||
<input id="reg_pass" type="password" placeholder="****" style="width:100%;padding:8px;border:1px solid #E2E8F0;border-radius:6px;font-size:13px"></div>
|
||
<div style="display:flex;gap:8px;justify-content:flex-end">
|
||
<button class="btn btn-sm" style="background:#E2E8F0;color:#0B1A2E" onclick="closeRegModal()">Отмена</button>
|
||
<button class="btn btn-sm btn-g" onclick="addUser()">Зарегистрировать</button>
|
||
<p style="font-size:11px;color:#64748B;margin-top:8px">На корпоративную почту придёт уведомление о регистрации и напоминания о необходимости представления отчёта</p>
|
||
</div></div></div>
|
||
<script src="script.js"></script>
|
||
</body>
|
||
</html> |