kazakhtelecom-ai-agent/index.html

247 lines
18 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!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></script></script></script></script>
</body>
</html>