474 lines
36 KiB
HTML
474 lines
36 KiB
HTML
<!doctype html>
|
||
<html lang="ru">
|
||
<head>
|
||
<meta charset="utf-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||
<title>Дашборд по устранению замечаний БиОТ</title>
|
||
<style>
|
||
* { margin: 0; padding: 0; box-sizing: border-box; }
|
||
body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; background: #f5f7fa; color: #1a1a1a; padding: 20px; }
|
||
.container { max-width: 1400px; margin: 0 auto; }
|
||
h1 { font-size: 28px; margin-bottom: 10px; color: #1e3a5f; }
|
||
.subtitle { color: #666; margin-bottom: 30px; }
|
||
|
||
.summary-cards { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 20px; margin-bottom: 30px; }
|
||
.card { background: white; border-radius: 12px; padding: 20px; box-shadow: 0 2px 8px rgba(0,0,0,0.08); }
|
||
.card-title { font-size: 14px; color: #666; margin-bottom: 8px; }
|
||
.card-value { font-size: 32px; font-weight: bold; color: #1e3a5f; }
|
||
.card-subtitle { font-size: 12px; color: #999; margin-top: 4px; }
|
||
.card.success .card-value { color: #10b981; }
|
||
.card.warning .card-value { color: #f59e0b; }
|
||
.card.danger .card-value { color: #ef4444; }
|
||
|
||
.region-selector { display: flex; gap: 10px; margin-bottom: 20px; }
|
||
.region-btn { padding: 10px 20px; border: 2px solid #e2e8f0; background: white; border-radius: 8px; cursor: pointer; font-size: 14px; font-weight: 500; transition: all 0.2s; }
|
||
.region-btn:hover { border-color: #1e3a5f; }
|
||
.region-btn.active { background: #1e3a5f; color: white; border-color: #1e3a5f; }
|
||
|
||
.dashboard { display: grid; grid-template-columns: 1fr 1fr; gap: 20px; margin-bottom: 30px; }
|
||
@media (max-width: 900px) { .dashboard { grid-template-columns: 1fr; } }
|
||
|
||
.chart-container { background: white; border-radius: 12px; padding: 20px; box-shadow: 0 2px 8px rgba(0,0,0,0.08); }
|
||
.chart-title { font-size: 18px; font-weight: 600; margin-bottom: 20px; color: #1e3a5f; }
|
||
|
||
.bar-chart { display: flex; flex-direction: column; gap: 12px; }
|
||
.bar-item { display: flex; align-items: center; gap: 10px; }
|
||
.bar-label { width: 180px; font-size: 13px; color: #333; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
||
.bar-wrapper { flex: 1; background: #e2e8f0; border-radius: 6px; height: 28px; overflow: hidden; }
|
||
.bar { height: 100%; border-radius: 6px; transition: width 0.5s ease; }
|
||
.bar.success { background: linear-gradient(90deg, #10b981, #34d399); }
|
||
.bar.warning { background: linear-gradient(90deg, #f59e0b, #fbbf24); }
|
||
.bar.danger { background: linear-gradient(90deg, #ef4444, #f87171); }
|
||
.bar-value { width: 60px; text-align: right; font-size: 13px; font-weight: 600; color: #333; }
|
||
|
||
.status-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 15px; margin-bottom: 20px; }
|
||
.status-box { padding: 15px; border-radius: 8px; text-align: center; }
|
||
.status-box.success { background: #d1fae5; }
|
||
.status-box.warning { background: #fef3c7; }
|
||
.status-box.danger { background: #fee2e2; }
|
||
.status-box .value { font-size: 24px; font-weight: bold; margin-bottom: 4px; }
|
||
.status-box .label { font-size: 12px; color: #666; }
|
||
.status-box.success .value { color: #059669; }
|
||
.status-box.warning .value { color: #d97706; }
|
||
.status-box.danger .value { color: #dc2626; }
|
||
|
||
.table-container { background: white; border-radius: 12px; padding: 20px; box-shadow: 0 2px 8px rgba(0,0,0,0.08); overflow-x: auto; }
|
||
.table-title { font-size: 18px; font-weight: 600; margin-bottom: 15px; color: #1e3a5f; }
|
||
|
||
table { width: 100%; border-collapse: collapse; }
|
||
th, td { padding: 12px; text-align: left; border-bottom: 1px solid #e2e8f0; }
|
||
th { background: #f8fafc; font-weight: 600; font-size: 13px; color: #333; position: sticky; top: 0; }
|
||
td { font-size: 13px; }
|
||
tr:hover { background: #f8fafc; }
|
||
.status-badge { padding: 4px 10px; border-radius: 12px; font-size: 12px; font-weight: 500; }
|
||
.status-badge.success { background: #d1fae5; color: #059669; }
|
||
.status-badge.warning { background: #fef3c7; color: #d97706; }
|
||
.status-badge.danger { background: #fee2e2; color: #dc2626; }
|
||
|
||
.filter-section { display: flex; gap: 15px; margin-bottom: 20px; flex-wrap: wrap; align-items: center; }
|
||
.filter-input { padding: 8px 12px; border: 1px solid #e2e8f0; border-radius: 6px; font-size: 14px; }
|
||
.filter-select { padding: 8px 12px; border: 1px solid #e2e8f0; border-radius: 6px; font-size: 14px; background: white; }
|
||
|
||
.progress-ring { width: 120px; height: 120px; margin: 0 auto 15px; }
|
||
.progress-ring circle { fill: none; stroke-width: 8; }
|
||
.progress-ring .bg { stroke: #e2e8f0; }
|
||
.progress-ring .progress { stroke: #1e3a5f; stroke-linecap: round; transform: rotate(-90deg); transform-origin: 50% 50%; transition: stroke-dashoffset 0.5s; }
|
||
.progress-text { font-size: 24px; font-weight: bold; fill: #1e3a5f; }
|
||
.progress-label { font-size: 12px; fill: #666; }
|
||
|
||
.charts-row { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 20px; margin-bottom: 30px; }
|
||
</style>
|
||
</head>
|
||
<body>
|
||
<div class="container">
|
||
<h1>📊 Дашборд по устранению замечаний БиОТ</h1>
|
||
<p class="subtitle">Северный регион • 2026 год</p>
|
||
|
||
<div class="summary-cards">
|
||
<div class="card">
|
||
<div class="card-title">Всего замечаний</div>
|
||
<div class="card-value" id="total">0</div>
|
||
<div class="card-subtitle">по Северному региону</div>
|
||
</div>
|
||
<div class="card success">
|
||
<div class="card-title">Исполнено</div>
|
||
<div class="card-value" id="completed">0</div>
|
||
<div class="card-subtitle" id="completedPct">0%</div>
|
||
</div>
|
||
<div class="card warning">
|
||
<div class="card-title">На контроле</div>
|
||
<div class="card-value" id="inControl">0</div>
|
||
<div class="card-subtitle" id="inControlPct">0%</div>
|
||
</div>
|
||
<div class="card danger">
|
||
<div class="card-title">Просрочено</div>
|
||
<div class="card-value" id="overdue">0</div>
|
||
<div class="card-subtitle" id="overduePct">0%</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="region-selector">
|
||
<button class="region-btn active" data-region="all">Все области</button>
|
||
<button class="region-btn" data-region="kostanay">Костанайская область</button>
|
||
<button class="region-btn" data-region="sko">Северо-Казахстанская область</button>
|
||
</div>
|
||
|
||
<div class="status-grid">
|
||
<div class="status-box success">
|
||
<div class="value" id="kostanayCompleted">0</div>
|
||
<div class="label">Костанай: Исполнено</div>
|
||
</div>
|
||
<div class="status-box success">
|
||
<div class="value" id="skoCompleted">0</div>
|
||
<div class="label">СКО: Исполнено</div>
|
||
</div>
|
||
<div class="status-box warning">
|
||
<div class="value" id="totalOnControl">0</div>
|
||
<div class="label">Всего на контроле</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="dashboard">
|
||
<div class="chart-container">
|
||
<div class="chart-title">📈 Статус исполнения по областям</div>
|
||
<div class="bar-chart" id="regionChart"></div>
|
||
</div>
|
||
<div class="chart-container">
|
||
<div class="chart-title">🎯 Общий процент исполнения</div>
|
||
<div style="display: flex; justify-content: space-around; align-items: center; height: 200px;">
|
||
<div>
|
||
<svg class="progress-ring" viewBox="0 0 120 120">
|
||
<circle class="bg" cx="60" cy="60" r="52"></circle>
|
||
<circle class="progress" cx="60" cy="60" r="52" stroke-dasharray="326.73" stroke-dashoffset="0"></circle>
|
||
<text class="progress-text" x="60" y="65" text-anchor="middle" id="progressPercent">0%</text>
|
||
<text class="progress-label" x="60" y="80" text-anchor="middle">Исполнение</text>
|
||
</svg>
|
||
</div>
|
||
<div style="flex: 1;">
|
||
<div class="bar-item" style="margin-bottom: 10px;">
|
||
<div class="bar-label">Исполнено</div>
|
||
<div class="bar-wrapper"><div class="bar success" id="completedBar" style="width: 0%"></div></div>
|
||
<div class="bar-value" id="completedVal">0</div>
|
||
</div>
|
||
<div class="bar-item" style="margin-bottom: 10px;">
|
||
<div class="bar-label">На контроле</div>
|
||
<div class="bar-wrapper"><div class="bar warning" id="controlBar" style="width: 0%"></div></div>
|
||
<div class="bar-value" id="controlVal">0</div>
|
||
</div>
|
||
<div class="bar-item">
|
||
<div class="bar-label">Просрочено</div>
|
||
<div class="bar-wrapper"><div class="bar danger" id="overdueBar" style="width: 0%"></div></div>
|
||
<div class="bar-value" id="overdueVal">0</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="charts-row">
|
||
<div class="chart-container">
|
||
<div class="chart-title">📍 По подразделениям (ОДС)</div>
|
||
<div class="bar-chart" id="odsChart"></div>
|
||
</div>
|
||
<div class="chart-container">
|
||
<div class="chart-title">📍 По подразделениям (СФ)</div>
|
||
<div class="bar-chart" id="sfChart"></div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="table-container">
|
||
<div class="table-title">📋 Детальная таблица по регионам</div>
|
||
<div class="filter-section">
|
||
<input type="text" class="filter-input" id="searchInput" placeholder="Поиск по населённому пункту..." style="min-width: 250px;">
|
||
<select class="filter-select" id="divisionFilter">
|
||
<option value="">Все подразделения</option>
|
||
<option value="ОДС">ОДС</option>
|
||
<option value="СФ">СФ</option>
|
||
<option value="ДРБ">ДРБ</option>
|
||
<option value="ДКБ">ДКБ</option>
|
||
<option value="ДЦБ">ДЦБ</option>
|
||
</select>
|
||
<select class="filter-select" id="statusFilter">
|
||
<option value="">Все статусы</option>
|
||
<option value="executed">Исполнено</option>
|
||
<option value="control">На контроле</option>
|
||
<option value="overdue">Просрочено</option>
|
||
</select>
|
||
</div>
|
||
<table>
|
||
<thead>
|
||
<tr>
|
||
<th>№</th>
|
||
<th>Подразделение</th>
|
||
<th>Населённый пункт</th>
|
||
<th>Область</th>
|
||
<th>Статус</th>
|
||
<th>Документ</th>
|
||
<th>Ответственный</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody id="dataTable"></tbody>
|
||
</table>
|
||
</div>
|
||
</div>
|
||
|
||
<script>
|
||
const DATA = [
|
||
{"id":38,"division":"УИТР","location":"г.Аркалык","region":"Костанай","status":"executed","doc":"№21 от 30.01.2026","responsible":"Адырбаев Ж.А."},
|
||
{"id":39,"division":"ТУСМ-8","location":"г.Аркалык","region":"Костанай","status":"executed","doc":"32 от 18.02.2026/№49","responsible":"Адырбаев Ж.А./Нурманов К.А."},
|
||
{"id":40,"division":"ЛТУ, ЦТПСР, ЦЭиК","location":"с.Амангельды","region":"Костанай","status":"executed","doc":"54 от 27.02.2026","responsible":"Нурманов К.А."},
|
||
{"id":41,"division":"УТО, ЦПХО","location":"с.Амангельды","region":"Костанай","status":"executed","doc":"55 от 27.02.2026","responsible":"Нурманов К.А."},
|
||
{"id":42,"division":"ГП ЦРК","location":"с.Амангельды","region":"Костанай","status":"executed","doc":"56 от 27.02.2026","responsible":"Нурманов К.А."},
|
||
{"id":43,"division":"ЛТУ, ЦТПСР, ЦЭиК","location":"с.Торгай","region":"Костанай","status":"executed","doc":"51от 25.02.2026","responsible":"Нурманов К.А."},
|
||
{"id":44,"division":"УТО, ЦПХО","location":"с.Торгай","region":"Костанай","status":"executed","doc":"52 от 25.02.2026","responsible":"Нурманов К.А."},
|
||
{"id":45,"division":"ГП ЦРК","location":"с.Торгай","region":"Костанай","status":"executed","doc":"53 от 25.02.2026","responsible":"Нурманов К.А."},
|
||
{"id":46,"division":"ЛТЦ, ЦТПСР, ЦЭиК","location":"с.Аулиеколь","region":"Костанай","status":"executed","doc":"№ 92 от 30.03.2026","responsible":"Книга А.В."},
|
||
{"id":47,"division":"УТО, ЦПХО","location":"с.Аулиеколь","region":"Костанай","status":"executed","doc":"№ 93 от 30.03.2026","responsible":"Книга А.В."},
|
||
{"id":48,"division":"ГП ЦРК","location":"с.Аулиеколь","region":"Костанай","status":"executed","doc":"№ 184 от 29.05.2026","responsible":"Книга А.В."},
|
||
{"id":49,"division":"ТУСМ-8","location":"п.Кушмурун","region":"Костанай","status":"executed","doc":"№ 212 от 14.04.2026","responsible":"Книга А.В."},
|
||
{"id":50,"division":"ЛТЦ, ЦТПСР, ЦЭиК","location":"п.Карасу","region":"Костанай","status":"executed","doc":"№ 6 от 22.01 2026","responsible":"Книга А.В."},
|
||
{"id":51,"division":"УТО, ЦПХО","location":"п.Карасу","region":"Костанай","status":"executed","doc":"№ 5 от 22.01 2026","responsible":"Книга А.В."},
|
||
{"id":52,"division":"ГП ЦРК","location":"п.Карасу","region":"Костанай","status":"executed","doc":"№ 7 от 23.01 2026","responsible":"Книга А.В."},
|
||
{"id":53,"division":"ЛУ, ЦТПСР, ЦЭиК","location":"c.Октябрьcкое","region":"Костанай","status":"executed","doc":"№ 90 от 29.03.2026","responsible":"Книга А.В."},
|
||
{"id":54,"division":"УТО, ЦПХО","location":"c.Октябрьcкое","region":"Костанай","status":"executed","doc":"№ 91 от 29.03.2026","responsible":"Книга А.В."},
|
||
{"id":55,"division":"ЛТУ, ЦТПСР, ЦЭиК","location":"с.Караменды","region":"Костанай","status":"executed","doc":"№ 98 от 30.03.2026","responsible":"Книга А.В."},
|
||
{"id":56,"division":"УТО, ЦПХО","location":"с.Караменды","region":"Костанай","status":"executed","doc":"№ 97 от 30.03.2026","responsible":"Книга А.В."},
|
||
{"id":57,"division":"ЛТЦ, ЦТПСР, ЦЭиК","location":"п.Сарыколь","region":"Костанай","status":"executed","doc":"№ 72 от 14.03.2026","responsible":"Книга А.В."},
|
||
{"id":58,"division":"УТО, ЦПХО","location":"п.Сарыколь","region":"Костанай","status":"executed","doc":"№ 73 от 14.03.2026","responsible":"Книга А.В."},
|
||
{"id":59,"division":"ГП ЦРК","location":"п.Сарыколь","region":"Костанай","status":"executed","doc":"№ 259 от28.07.26","responsible":"Книга А.В."},
|
||
{"id":60,"division":"ТУСМ-8","location":"п.Сарыколь","region":"Костанай","status":"executed","doc":"№ 81 от 17.03.2026","responsible":"Книга А.В."},
|
||
{"id":61,"division":"ЛТУ, ЦТПСР, ЦЭиК","location":"с.Узунколь","region":"Костанай","status":"executed","doc":"№ 86 от 23.03.2026","responsible":"Книга А.В."},
|
||
{"id":62,"division":"УТО, ЦПХО","location":"с.Узунколь","region":"Костанай","status":"executed","doc":"№ 87 от 23.03.2026","responsible":"Книга А.В."},
|
||
{"id":63,"division":"ГП ЦРК","location":"с.Узунколь","region":"Костанай","status":"executed","doc":"№ 271 от29.07.26","responsible":"Книга А.В."},
|
||
{"id":64,"division":"ЛТУ, ЦТПСР, ЦЭиК","location":"с.Силантьевка","region":"Костанай","status":"executed","doc":"№ 47 от 27.02.2026","responsible":"Книга А.В."},
|
||
{"id":65,"division":"УТО, ЦПХО","location":"с.Силантьевка","region":"Костанай","status":"executed","doc":"№ 48 от 27.02.2026","responsible":"Книга А.В."},
|
||
{"id":66,"division":"ЛТУ, ЦТПСР, ЦЭиК","location":"с.Боровское","region":"Костанай","status":"executed","doc":"№ 100 от 30.03.2026","responsible":"Книга А.В."},
|
||
{"id":67,"division":"УТО, ЦПХО","location":"с.Боровское","region":"Костанай","status":"executed","doc":"№ 99 от 30.03.2026","responsible":"Книга А.В."},
|
||
{"id":68,"division":"ГП ЦРК","location":"с.Боровское","region":"Костанай","status":"executed","doc":"№ 177 от 26.05.2026","responsible":"Книга А.В."},
|
||
{"id":69,"division":"ЛТЦ, ЦТПСР, ЦЭиК","location":"г.Житикара","region":"Костанай","status":"executed","doc":"№ 23 от 02-03.02.2026","responsible":"Ляшенко А.Л."},
|
||
{"id":70,"division":"ЦЛКС-82 ТУСМ-8","location":"г.Житикара","region":"Костанай","status":"executed","doc":"№ 45 от 26.02.2026","responsible":"Ляшенко А.Л."},
|
||
{"id":71,"division":"ГП ЦРК, ДИР","location":"г.Житикара","region":"Костанай","status":"executed","doc":"№ 22 от 02.02.2026","responsible":"Ляшенко А.Л."},
|
||
{"id":72,"division":"УТО, ЦПХО","location":"г.Житикара","region":"Костанай","status":"executed","doc":"№ 46 от 26.02.2026","responsible":"Ляшенко А.Л."},
|
||
{"id":73,"division":"ЛТУ, ЦТПСР, ЦЭиК","location":"с.Денисовка","region":"Костанай","status":"executed","doc":"№ 66 от 03.03.2026","responsible":"Ляшенко А.Л."},
|
||
{"id":74,"division":"ГП ЦРК","location":"с.Денисовка","region":"Костанай","status":"executed","doc":"№ 65 от 03.03.2026","responsible":"Ляшенко А.Л."},
|
||
{"id":75,"division":"УТО, ЦПХО","location":"с.Денисовка","region":"Костанай","status":"executed","doc":"№ 67 от 03.03.2026","responsible":"Ляшенко А.Л."},
|
||
{"id":76,"division":"ЛТУ, ЦТПСР, ЦЭиК","location":"с.Камысты","region":"Костанай","status":"executed","doc":"№ 107 от 27.03.2026","responsible":"Ляшенко А.Л."},
|
||
{"id":77,"division":"ГП ЦРК, ДИР","location":"с.Камысты","region":"Костанай","status":"executed","doc":"№ 108 от 27.03.2026","responsible":"Ляшенко А.Л."},
|
||
{"id":78,"division":"УТО, ЦПХО","location":"с.Камысты","region":"Костанай","status":"executed","doc":"№ 109 от 27.03.2026","responsible":"Ляшенко А.Л."},
|
||
{"id":79,"division":"ЛТУ, ЦТПСР, ЦЭиК","location":"г.Лисаковск","region":"Костанай","status":"executed","doc":"№ 78 от 03.03.2026","responsible":"Ляшенко А.Л."},
|
||
{"id":80,"division":"ГП ЦРК","location":"г.Лисаковск","region":"Костанай","status":"executed","doc":"№ 77 от 03.03.2026","responsible":"Ляшенко А.Л."},
|
||
{"id":81,"division":"УТО, ЦПХО","location":"г.Лисаковск","region":"Костанай","status":"executed","doc":"№ 79 от 03.03.2026","responsible":"Ляшенко А.Л."},
|
||
{"id":102,"division":"ЦТО МС ДЭСД","location":"г.Петропавловск","region":"СКО","status":"executed","doc":"№37 от 20.02.2026","responsible":"Шаймарданов А.С."},
|
||
{"id":103,"division":"ЦЭиК ДЭСД","location":"г.Петропавловск","region":"СКО","status":"executed","doc":"№14 от 28.01.2026","responsible":"Шаймарданов А.С."},
|
||
{"id":104,"division":"ЦТПСР ДЭСД","location":"г.Петропавловск","region":"СКО","status":"executed","doc":"№13от 28.01.2026","responsible":"Шаймарданов А.С."},
|
||
{"id":105,"division":"СТУиП ДЭСД","location":"г.Петропавловск","region":"СКО","status":"executed","doc":"№9 от 23.01.2026","responsible":"Шаймарданов А.С."},
|
||
{"id":106,"division":"ТУСМ-8","location":"г.Петропавловск","region":"СКО","status":"executed","doc":"№38 от 20.02.2026","responsible":"Ванин М.М."},
|
||
{"id":107,"division":"СЭРСТ ДЭСД","location":"г.Петропавловск","region":"СКО","status":"executed","doc":"№34 от 18.02.2026","responsible":"Шаймарданов А.С."},
|
||
{"id":108,"division":"УОД ДЭСД","location":"г.Петропавловск","region":"СКО","status":"executed","doc":"№268 от 30.07.2026","responsible":"Платонова Е.В."},
|
||
{"id":110,"division":"ДИТ","location":"г.Петропавловск","region":"СКО","status":"executed","doc":"№10 от 23.01.2026","responsible":"Шаймарданов А.С."},
|
||
{"id":109,"division":"ДУП","location":"г.Петропавловск","region":"СКО","status":"executed","doc":"№11 от 23.01.2026","responsible":"Шаймарданов А.С."},
|
||
{"id":111,"division":"ЦТО","location":"г.Петропавловск","region":"СКО","status":"executed","doc":"№25 от 04.02.2026","responsible":"Шаймарданов А.С."},
|
||
{"id":112,"division":"ЦПХО","location":"г.Петропавловск","region":"СКО","status":"executed","doc":"№33 от 18.02.2026","responsible":"Шаймарданов А.С."},
|
||
{"id":113,"division":"ЦРУ ДИР","location":"г.Петропавловск","region":"СКО","status":"executed","doc":"№29 от 16.02.2026","responsible":"Шаймарданов А.С."},
|
||
{"id":114,"division":"ПСС","location":"г.Петропавловск","region":"СКО","status":"executed","doc":"№71 от 16.03.2026","responsible":"Ванин М.М."},
|
||
{"id":115,"division":"ЦАП","location":"г.Петропавловск","region":"СКО","status":"executed","doc":"№70 от 16.03.2026","responsible":"Ванин М.М."},
|
||
{"id":116,"division":"ЦКП","location":"г.Петропавловск","region":"СКО","status":"executed","doc":"№69 от 13.03.2026","responsible":"Ванин М.М."},
|
||
{"id":117,"division":"СТПКР (165)","location":"г.Петропавловск","region":"СКО","status":"executed","doc":"№68 от 13.03.2026","responsible":"Ванин М.М."},
|
||
{"id":118,"division":"ЦРСТ","location":"г.Петропавловск","region":"СКО","status":"executed","doc":"№28 от 16.02.2026","responsible":"Шаймарданов А.С."},
|
||
{"id":119,"division":"Data Analytics&BI","location":"г.Петропавловск","region":"СКО","status":"executed","doc":"№170 от 29.05.2026","responsible":"Платонова Е.В."},
|
||
{"id":120,"division":"ОКиСК","location":"г.Петропавловск","region":"СКО","status":"control","doc":"СЗ № MMVN-DUHFC6","responsible":"Шаймарданов А.С."},
|
||
{"id":121,"division":"ГВБ/СС","location":"г.Петропавловск","region":"СКО","status":"control","doc":"№171,172 от 28.05.2026","responsible":"Платонова Е.В."},
|
||
{"id":122,"division":"ЛТЦ, ЦТПСР, ЦЭиК","location":"г.Булаево","region":"СКО","status":"executed","doc":"№125 от 16.04.2026","responsible":"Шаймарданов А.С."},
|
||
{"id":123,"division":"УТО, ЦПХО","location":"г.Булаево","region":"СКО","status":"executed","doc":"№127 от 16.04.2026","responsible":"Шаймарданов А.С."},
|
||
{"id":124,"division":"ГП ЦРК","location":"г.Булаево","region":"СКО","status":"executed","doc":"№126 от 16.04.2028","responsible":"Шаймарданов А.С."},
|
||
{"id":125,"division":"ЛТУ, ЦТПСР, ЦЭиК","location":"с.Пресновка","region":"СКО","status":"executed","doc":"№147 от 27.04.2026","responsible":"Ванин М.М."},
|
||
{"id":126,"division":"УТО, ЦПХО","location":"с.Пресновка","region":"СКО","status":"executed","doc":"№149 от 27.04.2026","responsible":"Ванин М.М."},
|
||
{"id":127,"division":"ГП ЦРК","location":"с.Пресновка","region":"СКО","status":"executed","doc":"№148 от 27.04.2026","responsible":"Ванин М.М."},
|
||
{"id":128,"division":"ЛТУ, ЦТПСР, ЦЭиК","location":"г.Мамлютка","region":"СКО","status":"executed","doc":"№131 от 06.04.2026","responsible":"Шаймарданов А.С."},
|
||
{"id":129,"division":"УТО, ЦПХО","location":"г.Мамлютка","region":"СКО","status":"executed","doc":"№132 от 06.04.2026","responsible":"Шаймарданов А.С."},
|
||
{"id":130,"division":"ГП ЦРК","location":"г.Мамлютка","region":"СКО","status":"executed","doc":"№133 от 06.04.2026","responsible":"Шаймарданов А.С."},
|
||
{"id":131,"division":"ЛТУ, ЦТПСР, ЦЭиК","location":"г.Сергеевка","region":"СКО","status":"executed","doc":"№44 от 25.02.2026","responsible":"Шаймарданов А.С."},
|
||
{"id":132,"division":"УТО, ЦПХО","location":"г.Сергеевка","region":"СКО","status":"executed","doc":"№43 от 25.02.2026","responsible":"Шаймарданов А.С."},
|
||
{"id":133,"division":"ГП ЦРК","location":"г.Сергеевка","region":"СКО","status":"executed","doc":"№50 от 25.02.2026","responsible":"Шаймарданов А.С."},
|
||
{"id":134,"division":"ЛТУ, ЦТПСР, ЦЭиК","location":"с.Тимирязево","region":"СКО","status":"executed","doc":"№42 от 24.02.2026","responsible":"Шаймарданов А.С."},
|
||
{"id":135,"division":"УТО, ЦПХО","location":"с.Тимирязево","region":"СКО","status":"executed","doc":"№41 от 24.02.2026","responsible":"Шаймарданов А.С."},
|
||
{"id":136,"division":"ГП ЦРК","location":"с.Тимирязево","region":"СКО","status":"executed","doc":"№40 от 24.02.2026","responsible":"Шаймарданов А.С."},
|
||
{"id":137,"division":"ЛТУ, ЦТПСР, ЦЭиК","location":"с.Явленка","region":"СКО","status":"executed","doc":"№62 от 13.03.2026","responsible":"Шаймарданов А.С."},
|
||
{"id":138,"division":"УТО, ЦПХО","location":"с.Явленка","region":"СКО","status":"executed","doc":"№63 от 13.03.2026","responsible":"Шаймарданов А.С."},
|
||
{"id":139,"division":"ГП ЦРК","location":"с.Явленка","region":"СКО","status":"executed","doc":"№64 от 13.03.2026","responsible":"Шаймарданов А.С."},
|
||
{"id":140,"division":"ЛТЦ, ЦТПСР, ЦЭиК","location":"с.Бесколь","region":"СКО","status":"executed","doc":"№102 от 31.03.2026","responsible":"Ванин М.М."},
|
||
{"id":141,"division":"УТО, ЦПХО","location":"с.Бесколь","region":"СКО","status":"executed","doc":"№103 от 31.03.2026","responsible":"Ванин М.М."},
|
||
{"id":142,"division":"ГП ЦРК","location":"с.Бесколь","region":"СКО","status":"executed","doc":"№104 от 31.03.2026","responsible":"Ванин М.М."}
|
||
];
|
||
|
||
let currentRegion = 'all';
|
||
|
||
function getStatusLabel(status) {
|
||
if (status === 'executed') return { text: 'Исполнено', class: 'success' };
|
||
if (status === 'control') return { text: 'На контроле', class: 'warning' };
|
||
if (status === 'overdue') return { text: 'Просрочено', class: 'danger' };
|
||
return { text: status, class: '' };
|
||
}
|
||
|
||
function updateDashboard() {
|
||
const filtered = currentRegion === 'all' ? DATA : DATA.filter(d => d.region === currentRegion);
|
||
|
||
const stats = { executed: 0, control: 0, overdue: 0 };
|
||
const kostanayStats = { executed: 0, control: 0, overdue: 0 };
|
||
const skoStats = { executed: 0, control: 0, overdue: 0 };
|
||
|
||
DATA.forEach(d => {
|
||
stats[d.status]++;
|
||
if (d.region === 'Костанай') kostanayStats[d.status]++;
|
||
else if (d.region === 'СКО') skoStats[d.status]++;
|
||
});
|
||
|
||
const total = filtered.length;
|
||
const completedPct = total > 0 ? Math.round((stats.executed / total) * 100) : 0;
|
||
const controlPct = total > 0 ? Math.round((stats.control / total) * 100) : 0;
|
||
const overduePct = total > 0 ? Math.round((stats.overdue / total) * 100) : 0;
|
||
|
||
document.getElementById('total').textContent = total;
|
||
document.getElementById('completed').textContent = stats.executed;
|
||
document.getElementById('inControl').textContent = stats.control;
|
||
document.getElementById('overdue').textContent = stats.overdue;
|
||
document.getElementById('completedPct').textContent = completedPct + '%';
|
||
document.getElementById('inControlPct').textContent = controlPct + '%';
|
||
document.getElementById('overduePct').textContent = overduePct + '%';
|
||
|
||
document.getElementById('kostanayCompleted').textContent = kostanayStats.executed;
|
||
document.getElementById('skoCompleted').textContent = skoStats.executed;
|
||
document.getElementById('totalOnControl').textContent = stats.control;
|
||
|
||
const progressCircle = document.querySelector('.progress-ring .progress');
|
||
const circumference = 2 * Math.PI * 52;
|
||
const offset = circumference - (completedPct / 100) * circumference;
|
||
progressCircle.style.strokeDashoffset = offset;
|
||
document.getElementById('progressPercent').textContent = completedPct + '%';
|
||
|
||
document.getElementById('completedBar').style.width = completedPct + '%';
|
||
document.getElementById('controlBar').style.width = controlPct + '%';
|
||
document.getElementById('overdueBar').style.width = overduePct + '%';
|
||
document.getElementById('completedVal').textContent = stats.executed;
|
||
document.getElementById('controlVal').textContent = stats.control;
|
||
document.getElementById('overdueVal').textContent = stats.overdue;
|
||
|
||
renderRegionChart(kostanayStats, skoStats);
|
||
renderDivisionCharts(filtered);
|
||
renderTable(filtered);
|
||
}
|
||
|
||
function renderRegionChart(kostanay, sko) {
|
||
const html = `
|
||
<div class="bar-item">
|
||
<div class="bar-label">Костанай: Исполнено</div>
|
||
<div class="bar-wrapper"><div class="bar success" style="width: ${Math.min(100, kostanay.executed * 2)}%"></div></div>
|
||
<div class="bar-value">${kostanay.executed}</div>
|
||
</div>
|
||
<div class="bar-item">
|
||
<div class="bar-label">Костанай: На контроле</div>
|
||
<div class="bar-wrapper"><div class="bar warning" style="width: ${Math.min(100, kostanay.control * 2)}%"></div></div>
|
||
<div class="bar-value">${kostanay.control}</div>
|
||
</div>
|
||
<div class="bar-item">
|
||
<div class="bar-label">СКО: Исполнено</div>
|
||
<div class="bar-wrapper"><div class="bar success" style="width: ${Math.min(100, sko.executed * 2)}%"></div></div>
|
||
<div class="bar-value">${sko.executed}</div>
|
||
</div>
|
||
<div class="bar-item">
|
||
<div class="bar-label">СКО: На контроле</div>
|
||
<div class="bar-wrapper"><div class="bar warning" style="width: ${Math.min(100, sko.control * 2)}%"></div></div>
|
||
<div class="bar-value">${sko.control}</div>
|
||
</div>
|
||
`;
|
||
document.getElementById('regionChart').innerHTML = html;
|
||
}
|
||
|
||
function renderDivisionCharts(data) {
|
||
function countByDivision(div, status) {
|
||
return data.filter(d => d.division.includes(div) && d.status === status).length;
|
||
}
|
||
|
||
const odsDivisions = ['ОДС', 'ЛТУ', 'ЛТЦ', 'ТУСМ', 'ЦТПСР', 'ЦЭиК'];
|
||
const sfDivisions = ['СФ', 'УТО', 'ЦПХО'];
|
||
|
||
const odsExecuted = data.filter(d => odsDivisions.some(div => d.division.includes(div)) && d.status === 'executed').length;
|
||
const odsControl = data.filter(d => odsDivisions.some(div => d.division.includes(div)) && d.status === 'control').length;
|
||
const sfExecuted = data.filter(d => sfDivisions.some(div => d.division.includes(div)) && d.status === 'executed').length;
|
||
const sfControl = data.filter(d => sfDivisions.some(div => d.division.includes(div)) && d.status === 'control').length;
|
||
|
||
document.getElementById('odsChart').innerHTML = `
|
||
<div class="bar-item">
|
||
<div class="bar-label">Исполнено</div>
|
||
<div class="bar-wrapper"><div class="bar success" style="width: ${Math.min(100, odsExecuted * 3)}%"></div></div>
|
||
<div class="bar-value">${odsExecuted}</div>
|
||
</div>
|
||
<div class="bar-item">
|
||
<div class="bar-label">На контроле</div>
|
||
<div class="bar-wrapper"><div class="bar warning" style="width: ${Math.min(100, odsControl * 3)}%"></div></div>
|
||
<div class="bar-value">${odsControl}</div>
|
||
</div>
|
||
`;
|
||
|
||
document.getElementById('sfChart').innerHTML = `
|
||
<div class="bar-item">
|
||
<div class="bar-label">Исполнено</div>
|
||
<div class="bar-wrapper"><div class="bar success" style="width: ${Math.min(100, sfExecuted * 3)}%"></div></div>
|
||
<div class="bar-value">${sfExecuted}</div>
|
||
</div>
|
||
<div class="bar-item">
|
||
<div class="bar-label">На контроле</div>
|
||
<div class="bar-wrapper"><div class="bar warning" style="width: ${Math.min(100, sfControl * 3)}%"></div></div>
|
||
<div class="bar-value">${sfControl}</div>
|
||
</div>
|
||
`;
|
||
}
|
||
|
||
function renderTable(data) {
|
||
const search = document.getElementById('searchInput').value.toLowerCase();
|
||
const divisionFilter = document.getElementById('divisionFilter').value;
|
||
const statusFilter = document.getElementById('statusFilter').value;
|
||
|
||
const filtered = data.filter(d => {
|
||
if (search && !d.location.toLowerCase().includes(search)) return false;
|
||
if (divisionFilter && !d.division.includes(divisionFilter)) return false;
|
||
if (statusFilter && d.status !== statusFilter) return false;
|
||
return true;
|
||
});
|
||
|
||
const html = filtered.slice(0, 100).map(d => {
|
||
const status = getStatusLabel(d.status);
|
||
return `
|
||
<tr>
|
||
<td>${d.id}</td>
|
||
<td>${d.division}</td>
|
||
<td>${d.location}</td>
|
||
<td>${d.region === 'СКО' ? 'Северо-Казахстанская' : 'Костанайская'}</td>
|
||
<td><span class="status-badge ${status.class}">${status.text}</span></td>
|
||
<td>${d.doc}</td>
|
||
<td>${d.responsible}</td>
|
||
</tr>
|
||
`;
|
||
}).join('');
|
||
|
||
document.getElementById('dataTable').innerHTML = html || '<tr><td colspan="7" style="text-align: center; padding: 40px;">Нет данных</td></tr>';
|
||
}
|
||
|
||
document.querySelectorAll('.region-btn').forEach(btn => {
|
||
btn.addEventListener('click', () => {
|
||
document.querySelectorAll('.region-btn').forEach(b => b.classList.remove('active'));
|
||
btn.classList.add('active');
|
||
currentRegion = btn.dataset.region;
|
||
updateDashboard();
|
||
});
|
||
});
|
||
|
||
document.getElementById('searchInput').addEventListener('input', () => updateDashboard());
|
||
document.getElementById('divisionFilter').addEventListener('change', () => updateDashboard());
|
||
document.getElementById('statusFilter').addEventListener('change', () => updateDashboard());
|
||
|
||
updateDashboard();
|
||
</script>
|
||
</body>
|
||
</html>
|