1587 lines
106 KiB
HTML
1587 lines
106 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="ru">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
<title>Управление ИТ — Обучающий курс</title>
|
||
<link href="https://fonts.googleapis.com/css2?family=Montserrat:wght@400;600;700;900&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet">
|
||
<style>
|
||
:root {
|
||
--bg: #0d1117;
|
||
--surface: #161b22;
|
||
--surface2: #21262d;
|
||
--accent: #00d4aa;
|
||
--accent2: #0095ff;
|
||
--warn: #ff6b6b;
|
||
--gold: #ffd700;
|
||
--text: #e6edf3;
|
||
--muted: #8b949e;
|
||
--border: #30363d;
|
||
--correct: #3fb950;
|
||
--wrong: #f85149;
|
||
}
|
||
* { box-sizing: border-box; margin: 0; padding: 0; }
|
||
body {
|
||
background: var(--bg);
|
||
color: var(--text);
|
||
font-family: 'Montserrat', sans-serif;
|
||
min-height: 100vh;
|
||
overflow-x: hidden;
|
||
}
|
||
body::before {
|
||
content: '';
|
||
position: fixed; inset: 0;
|
||
background-image:
|
||
linear-gradient(var(--border) 1px, transparent 1px),
|
||
linear-gradient(90deg, var(--border) 1px, transparent 1px);
|
||
background-size: 40px 40px;
|
||
opacity: 0.3;
|
||
pointer-events: none;
|
||
z-index: 0;
|
||
}
|
||
.app { position: relative; z-index: 1; max-width: 920px; margin: 0 auto; padding: 20px; }
|
||
|
||
.header {
|
||
text-align: center;
|
||
padding: 48px 0 32px;
|
||
animation: fadeDown 0.7s ease both;
|
||
}
|
||
.header .badge {
|
||
display: inline-block;
|
||
background: linear-gradient(135deg, var(--accent2), var(--accent));
|
||
color: #000;
|
||
font-size: 11px;
|
||
font-weight: 700;
|
||
letter-spacing: 2px;
|
||
text-transform: uppercase;
|
||
padding: 4px 14px;
|
||
border-radius: 20px;
|
||
margin-bottom: 16px;
|
||
}
|
||
.header h1 {
|
||
font-size: clamp(28px, 5vw, 48px);
|
||
font-weight: 900;
|
||
line-height: 1.1;
|
||
background: linear-gradient(135deg, #fff 30%, var(--accent));
|
||
-webkit-background-clip: text;
|
||
-webkit-text-fill-color: transparent;
|
||
background-clip: text;
|
||
margin-bottom: 10px;
|
||
}
|
||
.header p { color: var(--muted); font-size: 15px; }
|
||
|
||
.progress-bar-wrap {
|
||
background: var(--surface2);
|
||
border: 1px solid var(--border);
|
||
border-radius: 12px;
|
||
padding: 16px 24px;
|
||
margin-bottom: 24px;
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 16px;
|
||
animation: fadeUp 0.5s ease 0.2s both;
|
||
}
|
||
.progress-label { font-size: 13px; color: var(--muted); white-space: nowrap; }
|
||
.progress-track {
|
||
flex: 1;
|
||
height: 8px;
|
||
background: var(--bg);
|
||
border-radius: 4px;
|
||
overflow: hidden;
|
||
border: 1px solid var(--border);
|
||
}
|
||
.progress-fill {
|
||
height: 100%;
|
||
background: linear-gradient(90deg, var(--accent2), var(--accent));
|
||
border-radius: 4px;
|
||
transition: width 0.5s ease;
|
||
}
|
||
.progress-count { font-family: 'JetBrains Mono', monospace; font-size: 13px; color: var(--accent); }
|
||
|
||
.screen { display: none; animation: fadeUp 0.5s ease both; }
|
||
.screen.active { display: block; }
|
||
|
||
.modules-grid { display: grid; gap: 16px; }
|
||
.module-card {
|
||
background: var(--surface);
|
||
border: 1px solid var(--border);
|
||
border-radius: 16px;
|
||
padding: 24px;
|
||
cursor: pointer;
|
||
transition: all 0.25s ease;
|
||
position: relative;
|
||
overflow: hidden;
|
||
}
|
||
.module-card::before {
|
||
content: '';
|
||
position: absolute;
|
||
top: 0; left: 0; right: 0;
|
||
height: 3px;
|
||
background: linear-gradient(90deg, var(--accent2), var(--accent));
|
||
transform: scaleX(0);
|
||
transform-origin: left;
|
||
transition: transform 0.3s ease;
|
||
}
|
||
.module-card:hover { border-color: var(--accent); transform: translateY(-2px); box-shadow: 0 8px 30px rgba(0,212,170,0.1); }
|
||
.module-card:hover::before { transform: scaleX(1); }
|
||
.module-card.done { border-color: var(--correct); opacity: 0.85; }
|
||
.module-card.done::before { transform: scaleX(1); background: var(--correct); }
|
||
.module-header { display: flex; align-items: center; gap: 14px; margin-bottom: 10px; }
|
||
.module-icon {
|
||
width: 44px; height: 44px;
|
||
background: linear-gradient(135deg, rgba(0,149,255,0.2), rgba(0,212,170,0.2));
|
||
border: 1px solid var(--border);
|
||
border-radius: 10px;
|
||
display: flex; align-items: center; justify-content: center;
|
||
font-size: 20px;
|
||
flex-shrink: 0;
|
||
}
|
||
.module-title { font-size: 16px; font-weight: 700; }
|
||
.module-sub { font-size: 12px; color: var(--muted); margin-top: 2px; }
|
||
.module-desc { font-size: 13px; color: var(--muted); line-height: 1.6; }
|
||
.module-footer { display: flex; align-items: center; justify-content: space-between; margin-top: 14px; }
|
||
.module-topics { display: flex; gap: 6px; flex-wrap: wrap; }
|
||
.topic-tag {
|
||
background: rgba(0,149,255,0.1);
|
||
border: 1px solid rgba(0,149,255,0.3);
|
||
color: var(--accent2);
|
||
font-size: 10px;
|
||
font-weight: 600;
|
||
letter-spacing: 0.5px;
|
||
padding: 2px 8px;
|
||
border-radius: 4px;
|
||
font-family: 'JetBrains Mono', monospace;
|
||
}
|
||
.module-status { font-size: 12px; color: var(--muted); }
|
||
.module-card.done .module-status { color: var(--correct); }
|
||
|
||
.lesson-nav {
|
||
display: flex; align-items: center; gap: 12px;
|
||
margin-bottom: 24px;
|
||
}
|
||
.btn-back {
|
||
background: var(--surface2);
|
||
border: 1px solid var(--border);
|
||
color: var(--text);
|
||
padding: 8px 16px;
|
||
border-radius: 8px;
|
||
cursor: pointer;
|
||
font-family: 'Montserrat', sans-serif;
|
||
font-size: 13px;
|
||
font-weight: 600;
|
||
transition: all 0.2s;
|
||
}
|
||
.btn-back:hover { border-color: var(--accent2); color: var(--accent2); }
|
||
.lesson-title-bar { flex: 1; }
|
||
.lesson-title-bar h2 { font-size: 18px; font-weight: 700; }
|
||
.lesson-title-bar .lesson-sub { font-size: 12px; color: var(--muted); margin-top: 2px; }
|
||
|
||
.slide-container {
|
||
background: var(--surface);
|
||
border: 1px solid var(--border);
|
||
border-radius: 16px;
|
||
min-height: 420px;
|
||
position: relative;
|
||
}
|
||
.slide { display: none; padding: 32px; animation: fadeUp 0.4s ease both; }
|
||
.slide.active { display: block; }
|
||
.slide-num {
|
||
font-family: 'JetBrains Mono', monospace;
|
||
font-size: 11px;
|
||
color: var(--muted);
|
||
text-transform: uppercase;
|
||
letter-spacing: 1px;
|
||
margin-bottom: 20px;
|
||
display: flex; align-items: center; gap: 8px;
|
||
}
|
||
.slide-num::after { content: ''; flex: 1; height: 1px; background: var(--border); }
|
||
.slide h3 { font-size: 22px; font-weight: 800; margin-bottom: 20px; line-height: 1.3; }
|
||
.slide h3 span { color: var(--accent); }
|
||
.slide h4 { font-size: 15px; font-weight: 700; margin: 20px 0 10px; color: var(--accent2); }
|
||
.slide p { font-size: 14px; color: #c9d1d9; line-height: 1.8; margin-bottom: 14px; }
|
||
.slide ul { list-style: none; margin: 10px 0; }
|
||
.slide ul li {
|
||
font-size: 14px;
|
||
color: #c9d1d9;
|
||
padding: 7px 0 7px 20px;
|
||
position: relative;
|
||
border-bottom: 1px solid rgba(255,255,255,0.04);
|
||
line-height: 1.6;
|
||
}
|
||
.slide ul li::before { content: '▸'; position: absolute; left: 0; color: var(--accent); }
|
||
.slide ul li strong { color: var(--text); }
|
||
.slide ul.compact li { padding: 4px 0 4px 18px; border: none; font-size: 13px; }
|
||
|
||
.info-box {
|
||
background: rgba(0,149,255,0.07);
|
||
border: 1px solid rgba(0,149,255,0.25);
|
||
border-left: 3px solid var(--accent2);
|
||
border-radius: 8px;
|
||
padding: 14px 16px;
|
||
margin: 16px 0;
|
||
font-size: 13px;
|
||
line-height: 1.7;
|
||
color: #c9d1d9;
|
||
}
|
||
.warn-box {
|
||
background: rgba(255,107,107,0.07);
|
||
border: 1px solid rgba(255,107,107,0.25);
|
||
border-left: 3px solid var(--warn);
|
||
border-radius: 8px;
|
||
padding: 14px 16px;
|
||
margin: 16px 0;
|
||
font-size: 13px;
|
||
line-height: 1.7;
|
||
color: #c9d1d9;
|
||
}
|
||
.tip-box {
|
||
background: rgba(0,212,170,0.07);
|
||
border: 1px solid rgba(0,212,170,0.25);
|
||
border-left: 3px solid var(--accent);
|
||
border-radius: 8px;
|
||
padding: 14px 16px;
|
||
margin: 16px 0;
|
||
font-size: 13px;
|
||
line-height: 1.7;
|
||
color: #c9d1d9;
|
||
}
|
||
|
||
.sla-table { width: 100%; border-collapse: collapse; margin: 14px 0; font-size: 13px; }
|
||
.sla-table th {
|
||
background: var(--surface2);
|
||
color: var(--accent2);
|
||
font-weight: 700;
|
||
text-align: left;
|
||
padding: 9px 12px;
|
||
border: 1px solid var(--border);
|
||
font-size: 11px;
|
||
letter-spacing: 0.5px;
|
||
text-transform: uppercase;
|
||
}
|
||
.sla-table td { padding: 8px 12px; border: 1px solid var(--border); color: #c9d1d9; vertical-align: top; line-height: 1.5; }
|
||
.sla-table tr:nth-child(even) td { background: rgba(255,255,255,0.02); }
|
||
.sla-table .highlight { color: var(--accent); font-weight: 700; font-family: 'JetBrains Mono', monospace; }
|
||
.sla-table .critical { color: var(--warn); font-weight: 700; }
|
||
.sla-table .gold { color: var(--gold); font-weight: 700; }
|
||
|
||
.lp-card {
|
||
background: var(--surface2);
|
||
border: 1px solid var(--border);
|
||
border-radius: 10px;
|
||
padding: 14px 16px;
|
||
margin: 8px 0;
|
||
display: flex; gap: 12px; align-items: flex-start;
|
||
}
|
||
.lp-badge {
|
||
background: linear-gradient(135deg, var(--accent2), var(--accent));
|
||
color: #000;
|
||
font-weight: 900;
|
||
font-size: 13px;
|
||
width: 32px; height: 32px;
|
||
border-radius: 8px;
|
||
display: flex; align-items: center; justify-content: center;
|
||
flex-shrink: 0;
|
||
font-family: 'JetBrains Mono', monospace;
|
||
}
|
||
.lp-content h4 { font-size: 13px; font-weight: 700; margin-bottom: 4px; color: var(--text); }
|
||
.lp-content p { font-size: 12px; color: var(--muted); margin: 0; line-height: 1.5; }
|
||
|
||
.rfo-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; margin: 12px 0; }
|
||
.rfo-item {
|
||
background: var(--surface2);
|
||
border: 1px solid var(--border);
|
||
border-radius: 8px;
|
||
padding: 10px 12px;
|
||
font-size: 12px;
|
||
}
|
||
.rfo-item .rfo-area { color: var(--accent2); font-weight: 700; font-size: 11px; margin-bottom: 3px; text-transform: uppercase; }
|
||
.rfo-item .rfo-name { color: var(--text); font-size: 12px; font-weight: 600; }
|
||
.rfo-item .rfo-div { color: var(--muted); font-size: 11px; margin-top: 2px; }
|
||
|
||
.is-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 6px; margin: 12px 0; }
|
||
.is-item {
|
||
background: var(--surface2);
|
||
border: 1px solid var(--border);
|
||
border-radius: 6px;
|
||
padding: 8px 10px;
|
||
display: flex; justify-content: space-between; align-items: center; gap: 8px;
|
||
}
|
||
.is-name { color: var(--accent); font-family: 'JetBrains Mono', monospace; font-size: 12px; font-weight: 700; }
|
||
.is-owner { color: var(--muted); font-size: 11px; text-align: right; }
|
||
|
||
.flow-steps { margin: 16px 0; }
|
||
.flow-step {
|
||
display: flex; gap: 12px; align-items: flex-start;
|
||
padding: 10px 0;
|
||
border-bottom: 1px solid rgba(255,255,255,0.04);
|
||
}
|
||
.flow-num {
|
||
width: 26px; height: 26px;
|
||
border-radius: 50%;
|
||
background: linear-gradient(135deg, var(--accent2), var(--accent));
|
||
color: #000;
|
||
font-weight: 900;
|
||
font-size: 12px;
|
||
display: flex; align-items: center; justify-content: center;
|
||
flex-shrink: 0;
|
||
font-family: 'JetBrains Mono', monospace;
|
||
}
|
||
.flow-content { flex: 1; }
|
||
.flow-content strong { font-size: 13px; display: block; margin-bottom: 3px; }
|
||
.flow-content span { font-size: 12px; color: var(--muted); line-height: 1.5; }
|
||
|
||
.slide-controls {
|
||
display: flex; justify-content: space-between; align-items: center;
|
||
padding: 16px 32px;
|
||
border-top: 1px solid var(--border);
|
||
background: var(--surface2);
|
||
border-radius: 0 0 16px 16px;
|
||
}
|
||
.slide-dots { display: flex; gap: 6px; align-items: center; }
|
||
.slide-dot {
|
||
width: 6px; height: 6px;
|
||
border-radius: 50%;
|
||
background: var(--border);
|
||
transition: all 0.2s;
|
||
cursor: pointer;
|
||
}
|
||
.slide-dot.active { background: var(--accent); width: 18px; border-radius: 3px; }
|
||
.btn-slide {
|
||
background: var(--surface);
|
||
border: 1px solid var(--border);
|
||
color: var(--text);
|
||
padding: 8px 20px;
|
||
border-radius: 8px;
|
||
cursor: pointer;
|
||
font-family: 'Montserrat', sans-serif;
|
||
font-size: 13px;
|
||
font-weight: 600;
|
||
transition: all 0.2s;
|
||
display: flex; align-items: center; gap: 6px;
|
||
}
|
||
.btn-slide:hover { border-color: var(--accent); color: var(--accent); }
|
||
.btn-slide.primary { background: linear-gradient(135deg, var(--accent2), var(--accent)); border: none; color: #000; }
|
||
.btn-slide.primary:hover { opacity: 0.9; transform: translateY(-1px); }
|
||
.btn-slide:disabled { opacity: 0.3; cursor: not-allowed; pointer-events: none; }
|
||
|
||
.quiz-header {
|
||
background: var(--surface);
|
||
border: 1px solid var(--border);
|
||
border-radius: 16px;
|
||
padding: 24px;
|
||
margin-bottom: 20px;
|
||
display: flex; align-items: center; gap: 16px;
|
||
}
|
||
.quiz-icon { font-size: 36px; }
|
||
.quiz-header-text h2 { font-size: 20px; font-weight: 800; }
|
||
.quiz-header-text p { font-size: 13px; color: var(--muted); margin-top: 4px; }
|
||
.quiz-stats { margin-left: auto; text-align: right; }
|
||
.quiz-stats .score-num { font-family: 'JetBrains Mono', monospace; font-size: 28px; font-weight: 700; color: var(--accent); }
|
||
.quiz-stats .score-label { font-size: 11px; color: var(--muted); }
|
||
|
||
.question-card {
|
||
background: var(--surface);
|
||
border: 1px solid var(--border);
|
||
border-radius: 16px;
|
||
padding: 28px;
|
||
margin-bottom: 16px;
|
||
animation: fadeUp 0.4s ease both;
|
||
}
|
||
.q-meta { display: flex; align-items: center; gap: 10px; margin-bottom: 16px; }
|
||
.q-num {
|
||
font-family: 'JetBrains Mono', monospace;
|
||
font-size: 11px;
|
||
color: var(--muted);
|
||
background: var(--surface2);
|
||
padding: 2px 8px;
|
||
border-radius: 4px;
|
||
border: 1px solid var(--border);
|
||
}
|
||
.q-category {
|
||
font-size: 11px;
|
||
font-weight: 700;
|
||
letter-spacing: 0.5px;
|
||
text-transform: uppercase;
|
||
color: var(--accent2);
|
||
background: rgba(0,149,255,0.1);
|
||
padding: 2px 8px;
|
||
border-radius: 4px;
|
||
}
|
||
.q-text { font-size: 15px; font-weight: 600; line-height: 1.6; margin-bottom: 20px; }
|
||
.options { display: grid; gap: 10px; }
|
||
.option-btn {
|
||
background: var(--surface2);
|
||
border: 2px solid var(--border);
|
||
border-radius: 10px;
|
||
padding: 12px 16px;
|
||
cursor: pointer;
|
||
font-family: 'Montserrat', sans-serif;
|
||
font-size: 13px;
|
||
color: var(--text);
|
||
text-align: left;
|
||
transition: all 0.2s;
|
||
display: flex; align-items: center; gap: 12px;
|
||
font-weight: 500;
|
||
line-height: 1.5;
|
||
}
|
||
.option-btn:hover:not(:disabled) { border-color: var(--accent2); background: rgba(0,149,255,0.08); }
|
||
.option-letter {
|
||
width: 28px; height: 28px;
|
||
border-radius: 6px;
|
||
background: var(--border);
|
||
display: flex; align-items: center; justify-content: center;
|
||
font-size: 11px;
|
||
font-weight: 700;
|
||
flex-shrink: 0;
|
||
font-family: 'JetBrains Mono', monospace;
|
||
}
|
||
.option-btn.correct { border-color: var(--correct); background: rgba(63,185,80,0.1); }
|
||
.option-btn.correct .option-letter { background: var(--correct); color: #000; }
|
||
.option-btn.wrong { border-color: var(--wrong); background: rgba(248,81,73,0.1); }
|
||
.option-btn.wrong .option-letter { background: var(--wrong); color: #fff; }
|
||
.option-btn:disabled { cursor: not-allowed; }
|
||
|
||
.explanation { margin-top: 16px; padding: 12px 16px; border-radius: 8px; font-size: 13px; line-height: 1.7; display: none; }
|
||
.explanation.show { display: block; animation: fadeUp 0.3s ease both; }
|
||
.explanation.correct-exp { background: rgba(63,185,80,0.08); border: 1px solid rgba(63,185,80,0.3); }
|
||
.explanation.wrong-exp { background: rgba(248,81,73,0.08); border: 1px solid rgba(248,81,73,0.3); }
|
||
|
||
.quiz-nav { display: flex; justify-content: flex-end; margin-top: 8px; }
|
||
.btn-next {
|
||
background: linear-gradient(135deg, var(--accent2), var(--accent));
|
||
border: none; color: #000;
|
||
padding: 12px 28px; border-radius: 10px;
|
||
cursor: pointer;
|
||
font-family: 'Montserrat', sans-serif;
|
||
font-size: 14px; font-weight: 700;
|
||
transition: all 0.2s;
|
||
display: none;
|
||
}
|
||
.btn-next.show { display: flex; align-items: center; gap: 8px; animation: fadeUp 0.3s ease both; }
|
||
.btn-next:hover { opacity: 0.9; transform: translateY(-2px); box-shadow: 0 6px 20px rgba(0,212,170,0.3); }
|
||
|
||
.results-card {
|
||
background: var(--surface);
|
||
border: 1px solid var(--border);
|
||
border-radius: 20px;
|
||
padding: 48px 40px;
|
||
text-align: center;
|
||
animation: fadeUp 0.6s ease both;
|
||
}
|
||
.trophy { font-size: 72px; margin-bottom: 20px; display: block; }
|
||
.results-card h2 { font-size: 28px; font-weight: 900; margin-bottom: 8px; }
|
||
.score-big {
|
||
font-family: 'JetBrains Mono', monospace;
|
||
font-size: 64px; font-weight: 700; line-height: 1;
|
||
margin: 24px 0;
|
||
background: linear-gradient(135deg, var(--accent2), var(--accent));
|
||
-webkit-background-clip: text;
|
||
-webkit-text-fill-color: transparent;
|
||
background-clip: text;
|
||
}
|
||
.results-desc { font-size: 15px; color: var(--muted); max-width: 500px; margin: 0 auto 32px; line-height: 1.7; }
|
||
.results-breakdown { display: grid; grid-template-columns: repeat(3, 1fr); gap: 16px; margin: 32px 0; text-align: left; }
|
||
.rb-card { background: var(--surface2); border: 1px solid var(--border); border-radius: 12px; padding: 16px; }
|
||
.rb-card .rb-val { font-family: 'JetBrains Mono', monospace; font-size: 24px; font-weight: 700; color: var(--accent); }
|
||
.rb-card .rb-label { font-size: 11px; color: var(--muted); margin-top: 4px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.5px; }
|
||
.btn-restart {
|
||
background: linear-gradient(135deg, var(--accent2), var(--accent));
|
||
border: none; color: #000;
|
||
padding: 14px 36px; border-radius: 10px;
|
||
cursor: pointer; font-family: 'Montserrat', sans-serif;
|
||
font-size: 15px; font-weight: 700;
|
||
transition: all 0.2s; margin: 8px;
|
||
}
|
||
.btn-restart:hover { transform: translateY(-2px); box-shadow: 0 8px 24px rgba(0,212,170,0.35); }
|
||
.btn-outline {
|
||
background: transparent; border: 2px solid var(--border); color: var(--text);
|
||
padding: 12px 36px; border-radius: 10px;
|
||
cursor: pointer; font-family: 'Montserrat', sans-serif;
|
||
font-size: 15px; font-weight: 700;
|
||
transition: all 0.2s; margin: 8px;
|
||
}
|
||
.btn-outline:hover { border-color: var(--accent2); color: var(--accent2); }
|
||
.cert-card {
|
||
background: linear-gradient(135deg, #0d2137 0%, #0d1117 50%, #0a1f0d 100%);
|
||
border: 2px solid; border-image: linear-gradient(135deg, var(--accent2), var(--accent)) 1;
|
||
border-radius: 20px; padding: 48px; text-align: center; margin: 24px 0;
|
||
position: relative; overflow: hidden;
|
||
}
|
||
.cert-card::before { content: '🏆'; position: absolute; font-size: 200px; opacity: 0.04; top: 50%; left: 50%; transform: translate(-50%, -50%); }
|
||
.cert-card h3 { font-size: 11px; letter-spacing: 3px; text-transform: uppercase; color: var(--accent); margin-bottom: 20px; }
|
||
.cert-card h2 { font-size: 26px; font-weight: 900; margin-bottom: 8px; }
|
||
.cert-card .cert-name { font-size: 20px; color: var(--accent2); font-weight: 700; margin: 16px 0; }
|
||
.cert-card .cert-date { font-size: 12px; color: var(--muted); font-family: 'JetBrains Mono', monospace; }
|
||
.cert-stars { font-size: 24px; margin: 12px 0; letter-spacing: 4px; }
|
||
|
||
@keyframes fadeUp { from { opacity: 0; transform: translateY(20px); } to { opacity: 1; transform: translateY(0); } }
|
||
@keyframes fadeDown { from { opacity: 0; transform: translateY(-20px); } to { opacity: 1; transform: translateY(0); } }
|
||
.welcome-card {
|
||
background: var(--surface);
|
||
border: 1px solid var(--border);
|
||
border-radius: 20px;
|
||
padding: 48px 40px;
|
||
max-width: 480px;
|
||
margin: 0 auto;
|
||
animation: fadeUp 0.6s ease both;
|
||
}
|
||
.welcome-card h2 { font-size: 22px; font-weight: 800; margin-bottom: 12px; }
|
||
.welcome-card p { color: var(--muted); font-size: 14px; margin-bottom: 24px; line-height: 1.6; }
|
||
.welcome-card label { display: block; font-size: 13px; font-weight: 600; margin-bottom: 8px; color: var(--text); }
|
||
.welcome-card input[type="text"] {
|
||
width: 100%;
|
||
background: var(--surface2);
|
||
border: 2px solid var(--border);
|
||
border-radius: 10px;
|
||
padding: 14px 16px;
|
||
font-family: 'Montserrat', sans-serif;
|
||
font-size: 15px;
|
||
color: var(--text);
|
||
margin-bottom: 24px;
|
||
box-sizing: border-box;
|
||
}
|
||
.welcome-card input[type="text"]:focus {
|
||
outline: none;
|
||
border-color: var(--accent2);
|
||
}
|
||
.welcome-card input[type="text"]::placeholder { color: var(--muted); }
|
||
.welcome-card .welcome-error { color: var(--warn); font-size: 13px; margin-bottom: 12px; display: none; }
|
||
.welcome-card .welcome-error.show { display: block; }
|
||
.welcome-card .btn-start {
|
||
background: linear-gradient(135deg, var(--accent2), var(--accent));
|
||
border: none; color: #000;
|
||
padding: 14px 32px; border-radius: 10px;
|
||
cursor: pointer; font-family: 'Montserrat', sans-serif;
|
||
font-size: 15px; font-weight: 700;
|
||
transition: all 0.2s;
|
||
width: 100%;
|
||
}
|
||
.welcome-card .btn-start:hover { opacity: 0.95; transform: translateY(-2px); }
|
||
.welcome-card .btn-start:disabled { opacity: 0.6; cursor: not-allowed; transform: none; }
|
||
.user-bar {
|
||
font-size: 12px; color: var(--muted);
|
||
margin-bottom: 16px;
|
||
display: flex; align-items: center; justify-content: flex-end; gap: 8px;
|
||
}
|
||
.user-bar span { color: var(--accent); font-weight: 600; }
|
||
|
||
@media (max-width: 600px) {
|
||
.results-breakdown { grid-template-columns: 1fr 1fr; }
|
||
.rfo-grid, .is-grid { grid-template-columns: 1fr; }
|
||
.slide { padding: 18px; }
|
||
.cert-card { padding: 24px 16px; }
|
||
.welcome-card { padding: 28px 20px; }
|
||
}
|
||
</style>
|
||
</head>
|
||
<body>
|
||
<div class="app">
|
||
<div class="header">
|
||
<div class="badge">ИТ-специалист · Обучение v2</div>
|
||
<h1>Управление ИТ</h1>
|
||
<p>Интерактивный курс по руководству ИТ-сервисами компании · Редакция 03.03.2026</p>
|
||
<div class="user-bar" id="user-bar" style="display:none;">Вы вошли как: <span id="user-fio"></span></div>
|
||
</div>
|
||
|
||
<div id="screen-welcome" class="screen active">
|
||
<div class="welcome-card">
|
||
<h2>Вход в курс</h2>
|
||
<p>Укажите ваши фамилию, имя и отчество для регистрации прохождения обучения и фиксации результата тестирования.</p>
|
||
<form id="welcome-form" onsubmit="return submitWelcome(event)">
|
||
<label for="input-fio">ФИО</label>
|
||
<input type="text" id="input-fio" placeholder="Иванов Иван Иванович" autocomplete="name" required maxlength="500">
|
||
<div class="welcome-error" id="welcome-error"></div>
|
||
<button type="submit" class="btn-start" id="btn-welcome-start">Начать обучение</button>
|
||
</form>
|
||
</div>
|
||
</div>
|
||
|
||
<div id="screen-menu" class="screen">
|
||
<div class="progress-bar-wrap">
|
||
<span class="progress-label">Прогресс курса</span>
|
||
<div class="progress-track"><div class="progress-fill" id="main-progress" style="width:0%"></div></div>
|
||
<span class="progress-count" id="progress-text">0 / 4</span>
|
||
</div>
|
||
<div class="modules-grid" id="modules-grid"></div>
|
||
</div>
|
||
|
||
<div id="screen-lesson" class="screen">
|
||
<div class="lesson-nav">
|
||
<button class="btn-back" onclick="goMenu()">← Назад</button>
|
||
<div class="lesson-title-bar">
|
||
<h2 id="lesson-title"></h2>
|
||
<div class="lesson-sub" id="lesson-sub"></div>
|
||
</div>
|
||
</div>
|
||
<div class="slide-container">
|
||
<div id="slides-host"></div>
|
||
<div class="slide-controls">
|
||
<div class="slide-dots" id="slide-dots"></div>
|
||
<div style="display:flex;gap:10px">
|
||
<button class="btn-slide" id="btn-prev" onclick="changeSlide(-1)">← Назад</button>
|
||
<button class="btn-slide primary" id="btn-next-slide" onclick="changeSlide(1)">Далее →</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div id="screen-quiz" class="screen">
|
||
<div class="quiz-header">
|
||
<div class="quiz-icon">📝</div>
|
||
<div class="quiz-header-text">
|
||
<h2>Итоговое тестирование</h2>
|
||
<p>Подтверждение прохождения курса «Управление ИТ»</p>
|
||
</div>
|
||
<div class="quiz-stats">
|
||
<div class="score-num" id="quiz-score">0</div>
|
||
<div class="score-label">правильных</div>
|
||
</div>
|
||
</div>
|
||
<div class="progress-bar-wrap">
|
||
<span class="progress-label">Вопрос</span>
|
||
<div class="progress-track"><div class="progress-fill" id="quiz-progress" style="width:0%"></div></div>
|
||
<span class="progress-count" id="quiz-q-count">1 / 25</span>
|
||
</div>
|
||
<div id="question-host"></div>
|
||
<div class="quiz-nav">
|
||
<button class="btn-next" id="btn-next-q" onclick="nextQuestion()">Следующий вопрос →</button>
|
||
</div>
|
||
</div>
|
||
|
||
<div id="screen-results" class="screen">
|
||
<div class="results-card">
|
||
<span class="trophy" id="result-trophy">🏆</span>
|
||
<h2 id="result-title"></h2>
|
||
<div class="score-big" id="result-score"></div>
|
||
<p class="results-desc" id="result-desc"></p>
|
||
<div class="results-breakdown">
|
||
<div class="rb-card"><div class="rb-val" id="rb-correct"></div><div class="rb-label">Правильно</div></div>
|
||
<div class="rb-card"><div class="rb-val" id="rb-wrong"></div><div class="rb-label">Ошибок</div></div>
|
||
<div class="rb-card"><div class="rb-val" id="rb-percent"></div><div class="rb-label">Результат</div></div>
|
||
</div>
|
||
<div id="cert-host"></div>
|
||
<div>
|
||
<button class="btn-restart" onclick="restartQuiz()">↺ Пройти тест снова</button>
|
||
<button class="btn-outline" onclick="goMenu()">← В меню курса</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<script>
|
||
const modules = [
|
||
{
|
||
id: 0, icon: '📋', title: 'Работа с запросами', sub: 'Раздел 1.1–1.2',
|
||
desc: 'Типы запросов, порядок подачи через ЕЗС, уведомления и эскалации, жизненный цикл инцидента, 4 линии поддержки, порядок маршрутизации и роль Менеджера инцидентов.',
|
||
tags: ['Запросы', 'Инциденты', 'ЛП', 'Эскалации'],
|
||
slides: [
|
||
{
|
||
title: 'Типы ИТ-запросов', num: 'Раздел 1 · Подраздел 1.1',
|
||
html: `
|
||
<div class="slide-num">Раздел 1 · Подраздел 1.1</div>
|
||
<h3>Три типа <span>ИТ-запросов</span></h3>
|
||
<p>Все обращения в Службу ИТ делятся на три категории. Правильная классификация запроса — обязательное условие его своевременного исполнения.</p>
|
||
<ul>
|
||
<li><strong>Обслуживание</strong> — обращение для получения ИТ-сервисов: доступы, оборудование, консультации, администрирование</li>
|
||
<li><strong>Инцидент</strong> — уведомление о неисправности информационной системы или ИТ-оборудования</li>
|
||
<li><strong>Изменение</strong> — разработка нового или изменение текущего функционала информационной системы</li>
|
||
</ul>
|
||
<div class="warn-box">⚠️ <strong>Важно:</strong> если инцидент содержит запрос на изменение ИС — он не может быть выполнен в рамках управления инцидентами. Инициатору будет отказано с рекомендацией оформить отдельный запрос на изменение согласно Подразделу 1.3.</div>
|
||
<div class="tip-box">✅ Все сотрудники компании обязаны знать правила работы с ИТ-сервисами, изложенные в Руководстве по ИТ.</div>
|
||
`
|
||
},
|
||
{
|
||
title: 'Способы подачи запросов', num: 'Раздел 1 · Подраздел 1.1',
|
||
html: `
|
||
<div class="slide-num">Раздел 1 · Подраздел 1.1</div>
|
||
<h3>Каналы подачи <span>запросов</span></h3>
|
||
<h4>Запрос на обслуживание</h4>
|
||
<ul>
|
||
<li><strong>Новые сотрудники</strong> — указывается в Заявке на трудоустройство (согласно регламенту КДП)</li>
|
||
<li><strong>Действующие сотрудники</strong> — в ЕЗС: кнопка «Добавить запрос» → «ИТ Сервис» → выбрать нужный вид сервиса с типом «Обслуживание»</li>
|
||
</ul>
|
||
<h4>Инцидент — для всех пользователей</h4>
|
||
<ul>
|
||
<li>В ЕЗС: выбрать сервис с типом «Инцидент»</li>
|
||
<li>📧 Электронная почта: <strong>it@omc.ru</strong></li>
|
||
<li>📞 Телефон единой поддержки: <strong>8-800-700-37-18</strong></li>
|
||
<li>Виджет на корпоративном портале или чат-бот в Telegram: <strong>@HelpOMCbot</strong></li>
|
||
</ul>
|
||
<h4>Изменение ИС</h4>
|
||
<ul>
|
||
<li>В ЕЗС: меню «Зарегистрировать Изменение ИС» → «Изменение/Доработка»</li>
|
||
</ul>
|
||
`
|
||
},
|
||
{
|
||
title: 'Уведомления и эскалации', num: 'Раздел 1 · Подраздел 1.1',
|
||
html: `
|
||
<div class="slide-num">Раздел 1 · Подраздел 1.1 + Приложение 1</div>
|
||
<h3>Система <span>оповещений</span></h3>
|
||
<p>Служба ИТ уведомляет инициатора через ЕЗС и по e-mail о статусе запроса и необходимости выполнения действий.</p>
|
||
<h4>Ключевые оповещения по инцидентам</h4>
|
||
<ul>
|
||
<li>При <strong>регистрации</strong> инцидента — инициатор получает номер, тип, SLA, описание, время регистрации</li>
|
||
<li>При переводе в статус <strong>«Решён»</strong> — инициатор получает ссылки для оценки удовлетворённости и возврата в работу</li>
|
||
<li>При <strong>эскалации на 80%</strong> срока — уведомляются исполнитель, старший группы поддержки, начальник отдела</li>
|
||
<li>При <strong>эскалации на 100%</strong> — добавляется контроль; нарушение фиксируется в системе</li>
|
||
</ul>
|
||
<div class="info-box">💡 Если превышено время регистрации или нарушен крайний срок исполнения — Система автоматически направляет оповещения и эскалации согласно Приложению 1 «Эскалации и оповещения».</div>
|
||
<div class="tip-box">✅ По завершении ИТ-сервиса инициатору направляется запрос на подтверждение завершения работ и оценку качества. Оценки влияют на KPI сотрудников ИТ.</div>
|
||
`
|
||
},
|
||
{
|
||
title: 'Жизненный цикл инцидента', num: 'Раздел 1 · Подраздел 1.2',
|
||
html: `
|
||
<div class="slide-num">Раздел 1 · Подраздел 1.2</div>
|
||
<h3>Статусы <span>инцидента</span></h3>
|
||
<div class="flow-steps">
|
||
<div class="flow-step">
|
||
<div class="flow-num">1</div>
|
||
<div class="flow-content">
|
||
<strong>Зарегистрирован</strong>
|
||
<span>Присваивается автоматически при поступлении запроса. При регистрации через телефон/email — Диспетчерская служба назначает на группу поддержки.</span>
|
||
</div>
|
||
</div>
|
||
<div class="flow-step">
|
||
<div class="flow-num">2</div>
|
||
<div class="flow-content">
|
||
<strong>Выполняется</strong>
|
||
<span>Инцидент назначен на линию поддержки. При регистрации через ЕЗС — система автоматически назначает группу по сервису и географии инициатора.</span>
|
||
</div>
|
||
</div>
|
||
<div class="flow-step">
|
||
<div class="flow-num">3</div>
|
||
<div class="flow-content">
|
||
<strong>Передан внешнему контрагенту</strong>
|
||
<span>Изменяется исполнителем при формировании задания внешней стороне. Исполнитель инцидента остаётся прежним до завершения задания.</span>
|
||
</div>
|
||
</div>
|
||
<div class="flow-step">
|
||
<div class="flow-num">4</div>
|
||
<div class="flow-content">
|
||
<strong>Решён</strong>
|
||
<span>Переводится исполнителем, если работы выполнены полностью. Ожидается подтверждение от инициатора.</span>
|
||
</div>
|
||
</div>
|
||
<div class="flow-step">
|
||
<div class="flow-num">5</div>
|
||
<div class="flow-content">
|
||
<strong>Закрыт</strong>
|
||
<span>Система закрывает автоматически: при получении подтверждения инициатором / аннулировании им / по истечении 3 дней ожидания с момента статуса «Решён».</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="info-box">💡 Повторяющиеся инциденты (одни условия, тот же результат, те же причины) — решаются по известному решению, а Служба ИТ регистрирует корневую <strong>Проблему</strong> для устранения в рамках управления проблемами.</div>
|
||
`
|
||
},
|
||
{
|
||
title: 'Линии поддержки', num: 'Раздел 1 · Подраздел 1.2',
|
||
html: `
|
||
<div class="slide-num">Раздел 1 · Подраздел 1.2</div>
|
||
<h3>4 линии <span>поддержки</span></h3>
|
||
<div class="lp-card">
|
||
<div class="lp-badge">0</div>
|
||
<div class="lp-content">
|
||
<h4>Диспетчерская служба</h4>
|
||
<p>Приём, регистрация, обработка и решение типовых инцидентов. Направление: все инциденты.</p>
|
||
</div>
|
||
</div>
|
||
<div class="lp-card">
|
||
<div class="lp-badge">1</div>
|
||
<div class="lp-content">
|
||
<h4>Отдел технической поддержки</h4>
|
||
<p>Решение инцидентов, консультирование пользователей, эскалация на более высокоуровневые ЛП. Направление: ПО на рабочих местах сотрудников.</p>
|
||
</div>
|
||
</div>
|
||
<div class="lp-card">
|
||
<div class="lp-badge">2</div>
|
||
<div class="lp-content">
|
||
<h4>Отделы компетенций (инфраструктура, ИС, разработка)</h4>
|
||
<p>Консультирование, решение инцидентов, эскалация. Направления: инфраструктурные сервисы, телефония и каналы связи, закупки (ИТ), информационные системы.</p>
|
||
</div>
|
||
</div>
|
||
<div class="lp-card">
|
||
<div class="lp-badge">3</div>
|
||
<div class="lp-content">
|
||
<h4>Внешние подрядные организации</h4>
|
||
<p>Консультирование и решение инцидентов. Порядок работы регулируется договорами с подрядчиками.</p>
|
||
</div>
|
||
</div>
|
||
`
|
||
},
|
||
{
|
||
title: 'Маршрутизация и роли', num: 'Раздел 1 · Подраздел 1.2',
|
||
html: `
|
||
<div class="slide-num">Раздел 1 · Подраздел 1.2</div>
|
||
<h3>Маршрутизация инцидентов <span>и задач</span></h3>
|
||
<p>При невозможности самостоятельно решить инцидент исполнитель может:</p>
|
||
<ul>
|
||
<li>Создать <strong>Задачу</strong> и назначить её на другую группу поддержки (в рамках инцидента)</li>
|
||
<li><strong>Переназначить</strong> инцидент на другую группу специалистов</li>
|
||
<li>Если исполнитель не определён или есть административные препятствия — <strong>назначить на Менеджера инцидентов</strong></li>
|
||
</ul>
|
||
<h4>Правила назначения по линиям</h4>
|
||
<table class="sla-table">
|
||
<tr><th>Специалист</th><th>Может назначить на</th></tr>
|
||
<tr><td>1-я ЛП</td><td>Группу 2-й ЛП; Менеджеру инцидентов</td></tr>
|
||
<tr><td>2-я ЛП</td><td>Группе 1-й, 2-й или 3-й ЛП; Менеджеру инцидентов</td></tr>
|
||
<tr><td>3-я ЛП</td><td>Группе 2-й ЛП; Менеджеру инцидентов</td></tr>
|
||
<tr><td>Менеджер инцидентов</td><td>Любой группе 1-й, 2-й, 3-й ЛП; конкретному специалисту</td></tr>
|
||
</table>
|
||
<div class="warn-box">⚠️ До исполнения задания исполнитель инцидента не может быть изменён. Менеджер инцидентов при маршрутизации обязан указать в комментариях требуемые для решения действия.</div>
|
||
`
|
||
}
|
||
]
|
||
},
|
||
{
|
||
id: 1, icon: '🔄', title: 'Управление изменениями', sub: 'Раздел 1.3',
|
||
desc: 'Полный жизненный цикл запроса на изменение ИС: инициирование, цепочка согласований (РФО, Служба ИТ, Владелец ИС, ГД), реестр, разработка, тестирование, передача в поддержку.',
|
||
tags: ['Изменения', 'Согласование', 'КИ', 'РФО', 'ВИС'],
|
||
slides: [
|
||
{
|
||
title: 'Инициирование запроса', num: 'Раздел 1 · Подраздел 1.3',
|
||
html: `
|
||
<div class="slide-num">Раздел 1 · Подраздел 1.3</div>
|
||
<h3>Запрос на <span>изменение ИС</span></h3>
|
||
<p>Запрос создаётся инициатором в ЕЗС: «Зарегистрировать Изменение ИС» → «Изменение/Доработка». Форма запроса описана в Приложении 5.</p>
|
||
<p><strong>Обязательный состав запроса:</strong></p>
|
||
<ul>
|
||
<li>Описание изменений в бизнес-функциональности ИС</li>
|
||
<li>Цели, результаты, которые предполагается достичь</li>
|
||
<li>Перечень отчётных форм (если предусмотрены в рамках ЗНИ)</li>
|
||
<li>Описание преимуществ и выгод для Компании</li>
|
||
<li>Критичность, срочность и масштаб влияния на бизнес</li>
|
||
<li>При изменении законодательства — ссылки на регулирующие документы и подтверждение от ГД (если финансирование уже утверждено)</li>
|
||
</ul>
|
||
<div class="tip-box">✅ Ответственность за заполнение — на инициаторе. Проверка соответствия целей и метрик — на Руководителе Функциональной Области (РФО).</div>
|
||
`
|
||
},
|
||
{
|
||
title: 'Согласование РФО', num: 'Раздел 1 · Подраздел 1.3',
|
||
html: `
|
||
<div class="slide-num">Раздел 1 · Подраздел 1.3</div>
|
||
<h3>Первый этап: согласование <span>РФО</span></h3>
|
||
<p>Запрос направляется на согласование Руководителю Функциональной Области (РФО) согласно Приложению 2 «РФО и Владельцы систем».</p>
|
||
<h4>Правила маршрутизации к РФО</h4>
|
||
<ul>
|
||
<li><strong>Уровень КЦ</strong> → согласует РФО уровня ТОП-0,1</li>
|
||
<li><strong>Уровень ДЦ</strong> → сначала РФО ТОП-2 ДЦ, затем РФО ТОП-0,1 КЦ (при наличии). РФО ДЦ согласовывает вне ЕЗС и прикладывает письмо</li>
|
||
<li><strong>Междивизиональная услуга</strong> → согласуют все РФО дивизионов, где присутствует услуга</li>
|
||
</ul>
|
||
<h4>Точки контроля РФО</h4>
|
||
<ul>
|
||
<li>Отсутствие противоречий с корпоративными Стандартами</li>
|
||
<li>Применимость доработки для всей Компании (если функционал есть во всех Дивизионах)</li>
|
||
</ul>
|
||
<h4>Решения РФО</h4>
|
||
<ul class="compact">
|
||
<li>Согласовать → переход к параллельному согласованию Службой ИТ и Владельцем ИС</li>
|
||
<li>Вернуть на доработку → инициатор дорабатывает и повторно согласовывает</li>
|
||
<li>Аргументированно отклонить → запрос закрывается</li>
|
||
</ul>
|
||
<div class="info-box">💡 Срок согласования РФО — <strong>1 рабочий день</strong>. Срок на доработку запроса инициатором — <strong>1 рабочий день</strong>.</div>
|
||
`
|
||
},
|
||
{
|
||
title: 'Согласование Службой ИТ и Владельцем ИС', num: 'Раздел 1 · Подраздел 1.3',
|
||
html: `
|
||
<div class="slide-num">Раздел 1 · Подраздел 1.3</div>
|
||
<h3>Параллельное согласование: <span>ИТ и Владелец</span></h3>
|
||
<h4>Критерии Службы ИТ (1 раб. день)</h4>
|
||
<ul>
|
||
<li><strong>Новизна</strong> — изменение не было реализовано ранее и не реализуется сейчас</li>
|
||
<li><strong>Архитектура</strong> — не противоречит архитектуре ИС Компании</li>
|
||
<li><strong>Реализуемость</strong> — возможна доработка существующих ИС без внедрения новых</li>
|
||
<li><strong>Уникальность</strong> — отсутствие дублирующих запросов</li>
|
||
</ul>
|
||
<p>Если запрос требует внедрения новых ИС — Служба ИТ отклоняет его и информирует инициатора о переходе к проектной деятельности.</p>
|
||
<h4>Критерии Владельца ИС (1 раб. день)</h4>
|
||
<ul>
|
||
<li>Отсутствие противоречий со Стандартами Компании</li>
|
||
<li>Отсутствие противоречий с логикой настройки системы</li>
|
||
</ul>
|
||
<div class="info-box">💡 При отклонении Владельцем ИС — инициатор вправе созвать рабочее совещание с участием Владельца ИС, Руководителя Службы ИТ и РФО. По итогам принимается совместное решение.</div>
|
||
<div class="warn-box">⚠️ Если изменение классифицировано как <strong>Комплексное (КИ)</strong> — требуется согласование Руководителя КИ (срок: 3 раб. дня). Запросу присваивается признак КИ, формируется рабочая группа.</div>
|
||
`
|
||
},
|
||
{
|
||
title: 'Реестр и согласование с ГД', num: 'Раздел 1 · Подраздел 1.3',
|
||
html: `
|
||
<div class="slide-num">Раздел 1 · Подраздел 1.3</div>
|
||
<h3>Реестр изменений <span>и ГД</span></h3>
|
||
<p>По итогам согласований запросы делятся на 5 групп:</p>
|
||
<table class="sla-table">
|
||
<tr><th>Группа</th><th>Следующий шаг</th></tr>
|
||
<tr><td>Отклонённые запросы</td><td>Запрос закрывается</td></tr>
|
||
<tr><td>Изменения законодательства / ВНД (финансирование есть)</td><td>Сразу к разработке</td></tr>
|
||
<tr><td>Комплексные изменения (КИ)</td><td>В реестр, доп. рассмотрение</td></tr>
|
||
<tr><td>Требующие доп. финансирования</td><td>В реестр, доп. рассмотрение</td></tr>
|
||
<tr><td>Внутренние ресурсы, без доп. финансирования</td><td>В реестр, очередь на реализацию</td></tr>
|
||
</table>
|
||
<h4>Регламент реестра</h4>
|
||
<ul>
|
||
<li>Реестр формируется ежемесячно по всем поступившим и согласованным в ЕЗС запросам</li>
|
||
<li>Рассмотрение — 1 раз в месяц, <strong>не позже 7 рабочих дней</strong> с начала нового месяца</li>
|
||
<li>Ответственный за формирование — <strong>Директор по ИТ</strong></li>
|
||
<li>Совещание с ГД: обязательно участие ГД, Финансового директора КЦ, Директора по ИТ</li>
|
||
</ul>
|
||
<div class="info-box">💡 Срочный запрос, не терпящий отлагательств — Директор по ИТ инициирует <strong>внеплановое заочное рассмотрение</strong>: информация о запросе, стоимости и сроках направляется ГД и ФД КЦ по email.</div>
|
||
`
|
||
},
|
||
{
|
||
title: 'Разработка, тестирование и внедрение', num: 'Раздел 1 · Подраздел 1.3',
|
||
html: `
|
||
<div class="slide-num">Раздел 1 · Подраздел 1.3</div>
|
||
<h3>Разработка и <span>внедрение</span></h3>
|
||
<div class="flow-steps">
|
||
<div class="flow-step">
|
||
<div class="flow-num">1</div>
|
||
<div class="flow-content">
|
||
<strong>Оценка стоимости и сроков</strong>
|
||
<span>Служба ИТ оценивает стоимость и сроки реализации в течение <strong>7 раб. дней</strong> после согласования. Если запрос затрагивает несколько ИС — оценивается каждая система.</span>
|
||
</div>
|
||
</div>
|
||
<div class="flow-step">
|
||
<div class="flow-num">2</div>
|
||
<div class="flow-content">
|
||
<strong>Формирование ФТ</strong>
|
||
<span>Если требуется новая функциональность — Служба ИТ разрабатывает Функциональные Требования (<strong>10 раб. дней</strong>). ФТ согласовываются с РФО.</span>
|
||
</div>
|
||
</div>
|
||
<div class="flow-step">
|
||
<div class="flow-num">3</div>
|
||
<div class="flow-content">
|
||
<strong>Разработка</strong>
|
||
<span>Ведётся в согласованные сроки. При необходимости формируется «Программа и методика испытаний» (согласуется с РФО).</span>
|
||
</div>
|
||
</div>
|
||
<div class="flow-step">
|
||
<div class="flow-num">4</div>
|
||
<div class="flow-content">
|
||
<strong>Тестирование</strong>
|
||
<span>Проводят инициатор и РФО в согласованные сроки. Замечания, противоречащие исходным требованиям, оформляются как <strong>новый запрос на изменение</strong>.</span>
|
||
</div>
|
||
</div>
|
||
<div class="flow-step">
|
||
<div class="flow-num">5</div>
|
||
<div class="flow-content">
|
||
<strong>Внедрение и оценка</strong>
|
||
<span>После успешного тестирования — внедрение в продуктивную среду, запрос закрывается. Инициатор получает запрос на оценку сроков и качества.</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="warn-box">⚠️ При внедрении новой ИС или существенном улучшении — Отдел развития ИС обязан передать систему в поддержку с документом «Передача ИС в поддержку» (Приложение 7). Документ утверждается Директором по ИТ.</div>
|
||
`
|
||
},
|
||
{
|
||
title: 'Руководители функциональных областей', num: 'Приложение 2',
|
||
html: `
|
||
<div class="slide-num">Приложение 2 · РФО и Владельцы систем</div>
|
||
<h3>Руководители <span>функциональных областей (РФО)</span></h3>
|
||
<p>РФО — руководитель функциональной области уровня ТОП-0,1, ММ для КЦ; ТОП-0,1,2 для ДЦ. Именно к ним направляется запрос на изменение ИС на первичное согласование.</p>
|
||
<p><strong>Примеры РФО по функциональным областям (КЦ):</strong></p>
|
||
<div class="rfo-grid">
|
||
<div class="rfo-item"><div class="rfo-area">HR / Управление персоналом</div><div class="rfo-name">Директор по управлению персоналом КЦ</div></div>
|
||
<div class="rfo-item"><div class="rfo-area">Экономика и финансы</div><div class="rfo-name">Финансовый директор КЦ</div></div>
|
||
<div class="rfo-item"><div class="rfo-area">Маркетинг</div><div class="rfo-name">Директор по маркетингу</div></div>
|
||
<div class="rfo-item"><div class="rfo-area">Качество (SQI)</div><div class="rfo-name">Директор по качеству и инновациям</div></div>
|
||
<div class="rfo-item"><div class="rfo-area">Управление проектами</div><div class="rfo-name">Директор по проектам</div></div>
|
||
<div class="rfo-item"><div class="rfo-area">Договорной / внутренний документооборот</div><div class="rfo-name">Руководитель отдела стандартов</div></div>
|
||
</div>
|
||
<p style="margin-top:14px;"><strong>Примеры РФО по направлениям (ДFFM, ДRS):</strong></p>
|
||
<div class="rfo-grid">
|
||
<div class="rfo-item"><div class="rfo-area">Услуги питания (ДFFM / ДRS)</div><div class="rfo-name">Директор по кейтерингу</div></div>
|
||
<div class="rfo-item"><div class="rfo-area">Услуга охрана / клининг (ДFFM)</div><div class="rfo-name">Директор по клинингу / услуге Охрана</div></div>
|
||
<div class="rfo-item"><div class="rfo-area">Техническая эксплуатация (ДFFM)</div><div class="rfo-name">Директор по технической эксплуатации</div></div>
|
||
<div class="rfo-item"><div class="rfo-area">Финансы (ДFFM, ДRS)</div><div class="rfo-name">Зам. фин. директора по направлению</div></div>
|
||
</div>
|
||
<div class="tip-box">✅ Полный актуальный перечень РФО по всем функциональным областям, дивизионам и филиалам закреплён в <strong>Приложении 2 «РФО и Владельцы систем»</strong>.</div>
|
||
`
|
||
},
|
||
{
|
||
title: 'Владельцы информационных систем', num: 'Приложение 2',
|
||
html: `
|
||
<div class="slide-num">Приложение 2 · РФО и Владельцы систем</div>
|
||
<h3>Владельцы <span>информационных систем</span></h3>
|
||
<p><strong>Владелец ИС</strong> — сотрудник Компании, ответственный за эксплуатацию ИС и предоставление прав доступа к ней. Именно Владелец ИС параллельно с Службой ИТ согласовывает запрос на изменение.</p>
|
||
<div class="is-grid">
|
||
<div class="is-item"><span class="is-name">ЕЗС</span><span class="is-owner">Директор по ИТ</span></div>
|
||
<div class="is-item"><span class="is-name">CRM</span><span class="is-owner">Директор по работе с Клиентами КЦ</span></div>
|
||
<div class="is-item"><span class="is-name">СЭД</span><span class="is-owner">Рук. отдела стандартов</span></div>
|
||
<div class="is-item"><span class="is-name">1С УХ</span><span class="is-owner">Финансовый директор КЦ</span></div>
|
||
<div class="is-item"><span class="is-name">1С БУХ</span><span class="is-owner">Главный бухгалтер</span></div>
|
||
<div class="is-item"><span class="is-name">ЗУП КОРП</span><span class="is-owner">Директор по управл. персоналом КЦ</span></div>
|
||
<div class="is-item"><span class="is-name">УПП ОМС / RS</span><span class="is-owner">Директор по проектам</span></div>
|
||
<div class="is-item"><span class="is-name">МДМ / BI</span><span class="is-owner">Рук. отдела компетенций по ИС</span></div>
|
||
<div class="is-item"><span class="is-name">СКК</span><span class="is-owner">Директор по качеству и инновациям</span></div>
|
||
<div class="is-item"><span class="is-name">Корп. Портал</span><span class="is-owner">Директор по управл. персоналом КЦ</span></div>
|
||
<div class="is-item"><span class="is-name">R-Keeper</span><span class="is-owner">Рук. отдела компетенций по ИС</span></div>
|
||
<div class="is-item"><span class="is-name">ЭДО / КЭДО</span><span class="is-owner">Рук. отдела компетенций по ИС</span></div>
|
||
<div class="is-item"><span class="is-name">TalentForce</span><span class="is-owner">Директор по управл. персоналом КЦ</span></div>
|
||
<div class="is-item"><span class="is-name">Сайты omc.ru</span><span class="is-owner">Директор по маркетингу</span></div>
|
||
<div class="is-item"><span class="is-name">Меню-онлайн</span><span class="is-owner">Рук. отдела разработки ИС</span></div>
|
||
<div class="is-item"><span class="is-name">ЛК Заказчика</span><span class="is-owner">Директор по ИТ</span></div>
|
||
</div>
|
||
<div class="tip-box">✅ Полный актуальный список — в <strong>Приложении 2 «РФО и Владельцы систем»</strong>. Проверяйте перед подачей запроса на изменение.</div>
|
||
`
|
||
}
|
||
]
|
||
},
|
||
{
|
||
id: 2, icon: '💻', title: 'Оборудование и ПО', sub: 'Раздел 2',
|
||
desc: 'Общие принципы обеспечения сотрудников АРМ, стандартное ПО, корпоративная мобильная связь и печатное оборудование: правила предоставления и использования.',
|
||
tags: ['АРМ', 'ПО', 'Мобильная связь', 'Печать'],
|
||
slides: [
|
||
{
|
||
title: 'АРМ: принципы обеспечения', num: 'Раздел 2 · Подраздел 2.1',
|
||
html: `
|
||
<div class="slide-num">Раздел 2 · Подраздел 2.1</div>
|
||
<h3>Автоматизированное <span>рабочее место</span></h3>
|
||
<p><strong>АРМ</strong> — комплекс средств вычислительной техники и ПО, расположенный на рабочем месте сотрудника для автоматизации его работы в рамках должности.</p>
|
||
<h4>Критерии определения перечня оборудования</h4>
|
||
<ul>
|
||
<li><strong>Характеристика рабочего места:</strong> стационарное или нестационарное</li>
|
||
<li><strong>Правила установки:</strong> обязательное (по умолчанию для всех сотрудников со стационарным РМ) или по запросу (ТОП-0,1 при наличии бюджета)</li>
|
||
<li>Технические ограничения и специфика функционала сотрудника</li>
|
||
</ul>
|
||
<h4>Правила использования</h4>
|
||
<ul>
|
||
<li>Пользователи несут <strong>материальную ответственность</strong> за эксплуатируемое ими оборудование</li>
|
||
<li>Оборудование и ПО — только для выполнения <strong>должностных обязанностей</strong></li>
|
||
<li>Использование в личных целях (веб-сайты, личные документы) — <strong>запрещено</strong></li>
|
||
<li>Служба ИТ не осуществляет поддержку личного оборудования и ПО</li>
|
||
</ul>
|
||
<div class="warn-box">⚠️ При выявлении нарушений использования оборудования Служба ИТ временно приостанавливает доступ пользователя, уведомив его руководителя.</div>
|
||
`
|
||
},
|
||
{
|
||
title: 'Стандартное ПО', num: 'Раздел 2 · Подраздел 2.1',
|
||
html: `
|
||
<div class="slide-num">Раздел 2 · Подраздел 2.1</div>
|
||
<h3>Стандартное <span>программное обеспечение</span></h3>
|
||
<p>На ноутбуки и системные блоки по умолчанию устанавливается следующий набор ПО:</p>
|
||
<table class="sla-table">
|
||
<tr><th>ПО</th><th>Назначение</th></tr>
|
||
<tr><td><strong>MS Windows 10/11</strong></td><td>Операционная система</td></tr>
|
||
<tr><td><strong>MS Office 2016–2019</strong></td><td>Офисный пакет (Excel, Word, PowerPoint)</td></tr>
|
||
<tr><td><strong>Adobe Reader</strong></td><td>Просмотр и работа с файлами PDF</td></tr>
|
||
<tr><td><strong>PRO32 Connect</strong></td><td>Удалённое подключение к ПК</td></tr>
|
||
<tr><td><strong>7-Zip</strong></td><td>Файловый архиватор</td></tr>
|
||
<tr><td><strong>Autodesk DWG TrueView</strong></td><td>Просмотр и печать чертежей DWG</td></tr>
|
||
<tr><td><strong>Zoom</strong></td><td>Видеосвязь, сообщения, файлы</td></tr>
|
||
</table>
|
||
<div class="info-box">💡 Для новых сотрудников требуемое оборудование и ПО указывается в Заявке на трудоустройство. Закупка осуществляется через заявку в ЕЗС при наличии бюджета.</div>
|
||
`
|
||
},
|
||
{
|
||
title: 'Корпоративная мобильная связь', num: 'Раздел 2 · Подраздел 2.2',
|
||
html: `
|
||
<div class="slide-num">Раздел 2 · Подраздел 2.2</div>
|
||
<h3>Корпоративная <span>мобильная связь</span></h3>
|
||
<p>Сотрудник может получить корпоративную SIM-карту или подключить личную к корпоративному договору. Служба ИТ принимает заявку и связывается с сотрудником в течение <strong>3 рабочих дней</strong>.</p>
|
||
<h4>Сервисы по умолчанию</h4>
|
||
<ul class="compact">
|
||
<li>GPRS, исходящая связь (домашний регион, МГ, МН)</li>
|
||
<li>SMS и MMS (домашний регион, МГ, МН)</li>
|
||
<li>Запрет SMS-контента (короткие номера)</li>
|
||
</ul>
|
||
<h4>По запросу</h4>
|
||
<ul class="compact">
|
||
<li>Роуминг (международный, национальный), оптимизирующие тарифы</li>
|
||
<li>Блокировки, переадресация, смена тарифа, переоформление номера</li>
|
||
</ul>
|
||
<h4>Финансовая ответственность</h4>
|
||
<ul>
|
||
<li>При превышении лимита — сумма вычитается из зарплаты месяца перерасхода</li>
|
||
<li>Компенсация возможна только при согласовании с ТОП 0-1 (КЦ) / ТОП 0-2 (ДЦ)</li>
|
||
<li>Счёт от провайдера — в Службу финансов не позже <strong>10 дней</strong> с момента получения</li>
|
||
</ul>
|
||
<div class="warn-box">⚠️ При увольнении сотрудника блокировка SIM-карты происходит <strong>в день обращения</strong>. Все запросы по мобильной связи оформляются через Службу ИТ.</div>
|
||
`
|
||
},
|
||
{
|
||
title: 'Печатное оборудование', num: 'Раздел 2 · Подраздел 2.3',
|
||
html: `
|
||
<div class="slide-num">Раздел 2 · Подраздел 2.3</div>
|
||
<h3>Принципы печатной <span>инфраструктуры</span></h3>
|
||
<p>Вся офисная печать переведена на устройства общего доступа. Это повышает эффективность использования оборудования и снижает TCO.</p>
|
||
<h4>Ключевые принципы размещения</h4>
|
||
<ul>
|
||
<li>Соотношение пользователи/устройство: <strong>30:1</strong></li>
|
||
<li>Максимальное расстояние до монохромного принтера А4: <strong>15 метров</strong></li>
|
||
<li>До устройства копирования / сканирования А4: <strong>30 метров</strong></li>
|
||
<li>Цветной принтер А4: <strong>одно устройство на этаж</strong></li>
|
||
<li>Доступ к принтеру — без необходимости подниматься/спускаться или проходить через охраняемые зоны</li>
|
||
</ul>
|
||
<h4>Ограничения</h4>
|
||
<ul>
|
||
<li>Персональные принтеры — не допускаются (только по утверждённым исключениям)</li>
|
||
<li>Струйные принтеры — не допускаются (только по исключениям)</li>
|
||
<li>Принтер по умолчанию для пользователей не может быть цветным</li>
|
||
<li>Все устройства должны быть подключены к сети</li>
|
||
</ul>
|
||
<div class="info-box">💡 Базовые бренды — <strong>HP и Xerox</strong>. Не более двух производителей в парке. Исключения для специальных задач утверждаются Директором Дивизиона (КЦ — Топ 1).</div>
|
||
`
|
||
}
|
||
]
|
||
},
|
||
{
|
||
id: 3, icon: '📊', title: 'SLA и KPI', sub: 'Раздел 3',
|
||
desc: 'Уровни сервиса для разных групп пользователей, критичность инцидентов, конкретные сроки по всем типам запросов и KPI ИТ-службы с целевыми значениями.',
|
||
tags: ['SLA', 'KPI', 'Сроки', 'VIP'],
|
||
slides: [
|
||
{
|
||
title: 'SLA — Запросы на обслуживание', num: 'Раздел 3 · Подраздел 3.1',
|
||
html: `
|
||
<div class="slide-num">Раздел 3 · Подраздел 3.1</div>
|
||
<h3>Уровни сервиса: <span>обслуживание</span></h3>
|
||
<p>Сроки зависят от группы пользователя:</p>
|
||
<table class="sla-table">
|
||
<tr><th>Группа</th><th>Режим</th><th>Срок согласования</th><th>Срок решения</th></tr>
|
||
<tr><td><strong>VIP</strong> (ТОП 0–1)</td><td class="highlight">24×7</td><td>Без согласования</td><td class="highlight">8 часов</td></tr>
|
||
<tr><td>Сотрудники офисов</td><td>9×5</td><td>8 часов на согласование; по истечении — отклонение</td><td>По таблице сервисов</td></tr>
|
||
</table>
|
||
<h4>Сроки ключевых сервисов (для офисных сотрудников)</h4>
|
||
<table class="sla-table">
|
||
<tr><th>Сервис</th><th>Срок</th></tr>
|
||
<tr><td>Предоставление / изменение доступа к ИС</td><td class="highlight">24 ч</td></tr>
|
||
<tr><td>Администрирование учётных записей AD</td><td class="highlight">24 ч</td></tr>
|
||
<tr><td>Администрирование справочников НСИ</td><td class="highlight">24 ч</td></tr>
|
||
<tr><td>Комплексная печать (КЦ)</td><td class="highlight">24 ч</td></tr>
|
||
<tr><td>Администрирование ПО кассовой системы (POS)</td><td class="highlight">8 ч</td></tr>
|
||
<tr><td>Консультирование, организация РМ, восстановление данных, закупка, мобильная связь и прочее</td><td>32 ч</td></tr>
|
||
</table>
|
||
`
|
||
},
|
||
{
|
||
title: 'SLA — Инциденты', num: 'Раздел 3 · Подраздел 3.2',
|
||
html: `
|
||
<div class="slide-num">Раздел 3 · Подраздел 3.2</div>
|
||
<h3>Параметры SLA: <span>инциденты</span></h3>
|
||
<table class="sla-table">
|
||
<tr><th>Критичность</th><th>Режим</th><th>Реакция оператора</th><th>Регистрация</th><th>Реакция исп.</th><th>Срок устранения</th></tr>
|
||
<tr><td class="critical">Критичный (VIP или ИС)</td><td class="highlight">24×7</td><td>30 сек</td><td>15 мин</td><td>0,5 ч</td><td class="highlight">4 часа</td></tr>
|
||
<tr><td style="color:var(--gold)">Высокий</td><td>9×5</td><td>30 сек</td><td>15 мин</td><td>4 ч</td><td class="highlight">8 часов</td></tr>
|
||
<tr><td>Стандартный</td><td>9×5</td><td>30 сек</td><td>15 мин</td><td>8 ч</td><td class="highlight">32 часа</td></tr>
|
||
</table>
|
||
<h4>Определения критичности</h4>
|
||
<ul>
|
||
<li><strong class="critical">Критичный</strong> — останавливает работу системы / аппаратного комплекса, влечёт серьёзные финансовые или репутационные риски</li>
|
||
<li><strong style="color:var(--gold)">Высокий</strong> — частично затрагивает работу системы, существует риск остановки бизнес-процесса</li>
|
||
<li><strong>Стандартный</strong> — ошибка, не останавливающая работу и бизнес-процесс, не влекущая репутационных или финансовых потерь</li>
|
||
</ul>
|
||
<div class="warn-box">⚠️ Любой инцидент от VIP-пользователя (или его ассистента) считается критичным и обрабатывается в режиме 24×7, срок — 4 часа.</div>
|
||
`
|
||
},
|
||
{
|
||
title: 'SLA — Изменения', num: 'Раздел 3 · Подраздел 3.3',
|
||
html: `
|
||
<div class="slide-num">Раздел 3 · Подраздел 3.3</div>
|
||
<h3>Регламентные сроки <span>по изменениям</span></h3>
|
||
<table class="sla-table">
|
||
<tr><th>#</th><th>Этап</th><th>Ответственный</th><th>Срок (р.д.)</th></tr>
|
||
<tr><td>1</td><td>Согласование РФО</td><td>РФО</td><td class="highlight">1</td></tr>
|
||
<tr><td>2</td><td>Доработка запроса</td><td>Инициатор</td><td class="highlight">1</td></tr>
|
||
<tr><td>3</td><td>Согласование Службой ИТ</td><td>Служба ИТ</td><td class="highlight">1</td></tr>
|
||
<tr><td>4</td><td>Согласование Владельцем ИС</td><td>Владелец ИС</td><td class="highlight">1</td></tr>
|
||
<tr><td>5</td><td>Согласование Руководителем КИ</td><td>Руководитель КИ</td><td class="highlight">3</td></tr>
|
||
<tr><td>7</td><td>Оценка стоимости и сроков</td><td>Служба ИТ</td><td class="highlight">7</td></tr>
|
||
<tr><td>10</td><td>Формирование ФТ</td><td>Служба ИТ</td><td class="highlight">10</td></tr>
|
||
<tr><td>14</td><td>Устранение замечаний тестирования</td><td>Служба ИТ</td><td class="highlight">2</td></tr>
|
||
</table>
|
||
<div class="warn-box">⚠️ Нарушение сроков по задачам может повлечь дисциплинарную ответственность. Перенос срока допустим только по договорённости с инициатором запроса.</div>
|
||
`
|
||
},
|
||
{
|
||
title: 'KPI ИТ-службы', num: 'Раздел 3 · Подраздел 3.4',
|
||
html: `
|
||
<div class="slide-num">Раздел 3 · Подраздел 3.4</div>
|
||
<h3>Ключевые показатели <span>эффективности</span></h3>
|
||
<table class="sla-table">
|
||
<tr><th>KPI</th><th>Целевое</th><th>Пороговое</th></tr>
|
||
<tr><td>Выполнение инцидентов в срок</td><td class="highlight">≥ 98%</td><td>≥ 97%</td></tr>
|
||
<tr><td>Возвращённые заявки (инциденты)</td><td class="highlight">≤ 0,5%</td><td>≤ 1%</td></tr>
|
||
<tr><td>Удовлетворённость пользователей (инциденты)</td><td class="highlight">≥ 98%</td><td>≥ 97%</td></tr>
|
||
<tr><td>Доступность ИС</td><td class="highlight">≥ 99,5%</td><td>≥ 99%</td></tr>
|
||
<tr><td>Удовлетворённость заказчика (изменения)</td><td class="highlight">≥ 95%</td><td>≥ 90%</td></tr>
|
||
<tr><td>Реализация изменений в срок</td><td class="highlight">≥ 95%</td><td>≥ 90%</td></tr>
|
||
</table>
|
||
<div class="tip-box">✅ Доступность ИС = (Д − П) / Д × 100%, где Д — обещанное время доступности, П — время простоя. Запланированные простои из расчёта исключаются.</div>
|
||
<div class="info-box">💡 Оценки качества, проставленные сотрудниками после закрытия инцидентов и запросов на изменение, напрямую влияют на расчёт KPI конкретных специалистов ИТ.</div>
|
||
`
|
||
}
|
||
]
|
||
}
|
||
];
|
||
|
||
// ===================== QUESTIONS (25 шт) =====================
|
||
const questions = [
|
||
// --- ЗАПРОСЫ (7) ---
|
||
{ cat: 'Запросы', q: 'Какой тип запроса нужно создать, если система работает некорректно и мешает выполнению бизнес-процесса?', opts: ['Запрос на обслуживание', 'Инцидент', 'Запрос на изменение', 'Обращение к руководителю'], ans: 1, exp: 'Инцидент — это обращение в Службу ИТ для уведомления о неисправности информационной системы или ИТ-оборудования. Именно этот тип запроса используется при сбоях в работе системы.' },
|
||
{ cat: 'Запросы', q: 'Сотрудник хочет получить доступ к новой информационной системе. Какой тип запроса он должен создать?', opts: ['Инцидент', 'Изменение ИС', 'Запрос на обслуживание', 'Устное обращение к ИТ'], ans: 2, exp: 'Предоставление прав и доступов к ИС — это Запрос на обслуживание. Он подаётся в ЕЗС через кнопку «Добавить запрос» → «ИТ Сервис» → выбрать нужный вид сервиса с типом «Обслуживание».' },
|
||
{ cat: 'Запросы', q: 'Инцидент зарегистрирован в ЕЗС. Кто / что назначает его на группу поддержки?', opts: ['Диспетчерская служба вручную', 'Менеджер инцидентов', 'Система автоматически по сервису и географии', 'Инициатор выбирает группу'], ans: 2, exp: 'При регистрации через ЕЗС система автоматически назначает инцидент на Группу поддержки в соответствии с выбранным сервисом и географическим расположением инициатора. При регистрации по телефону/email — назначает Диспетчерская служба.' },
|
||
{ cat: 'Запросы', q: 'Через сколько дней инцидент в статусе «Решён» автоматически переводится в «Закрыт», если инициатор не реагирует?', opts: ['1 день', '2 дня', '3 дня', '5 дней'], ans: 2, exp: 'По регламенту инцидент автоматически переводится в статус «Закрыт» по истечении 3 дней с момента перевода в статус «Решён», если инициатор не подтвердил выполнение работ и не аннулировал запрос.' },
|
||
{ cat: 'Запросы', q: 'Что происходит, если инцидент содержит в описании запрос на добавление нового функционала в ИС?', opts: ['Инцидент выполняется полностью, включая изменение', 'Инциденту отказывают, рекомендуя оформить запрос на изменение', 'Инцидент передаётся на 3-ю линию поддержки', 'Инициатору предлагают переоформить как запрос на обслуживание'], ans: 1, exp: 'Инцидент, содержащий запрос на изменение ИС, не может быть выполнен в рамках управления инцидентами. Инициатору будет отказано с рекомендацией оформить запрос согласно Подразделу «Управление изменениями».' },
|
||
{ cat: 'Запросы', q: 'При нарушении срока исполнения инцидента — на какой процент времени срабатывает эскалация с оповещением начальника отдела?', opts: ['50%', '80%', '100%', 'Только после закрытия'], ans: 1, exp: 'По Приложению 1 «Эскалации и оповещения»: при достижении 80% регламентного времени уведомляются исполнитель, старший группы поддержки и начальник отдела. При 100% — добавляется контроль.' },
|
||
{ cat: 'Запросы', q: 'Какое действие специалист 1-й линии НЕ может выполнить самостоятельно?', opts: ['Решить стандартный инцидент по ПО', 'Назначить задачу на 2-ю ЛП', 'Назначить инцидент на Менеджера инцидентов', 'Назначить инцидент напрямую на 3-ю ЛП'], ans: 3, exp: 'Специалист 1-й ЛП может назначить инцидент или задачу только на группу специалистов 2-й ЛП или на Менеджера инцидентов. Прямое назначение на 3-ю ЛП — недопустимо, это прерогатива 2-й ЛП.' },
|
||
|
||
// --- ИЗМЕНЕНИЯ (9) ---
|
||
{ cat: 'Изменения', q: 'Кто несёт ответственность за корректное заполнение запроса на изменение ИС?', opts: ['Служба ИТ', 'Владелец ИС', 'Инициатор изменения', 'РФО'], ans: 2, exp: 'Ответственность за заполнение запроса лежит на инициаторе изменения. Проверка соответствия заявленных целей и метрик — на Руководителе Функциональной Области (РФО).' },
|
||
{ cat: 'Изменения', q: 'Запрос на изменение инициирован сотрудником Дивизиона (ДЦ). В каком порядке он согласовывается с РФО?', opts: ['Только с РФО КЦ уровня ТОП-0,1', 'Сначала с РФО ТОП-2 ДЦ, затем с РФО ТОП-0,1 КЦ (при наличии)', 'Только с РФО ДЦ, без КЦ', 'Одновременно с РФО ДЦ и КЦ через ЕЗС'], ans: 1, exp: 'Если запрос инициирован на уровне ДЦ, в согласующие последовательно включаются РФО уровня ТОП-2 ДЦ и РФО уровня ТОП-0,1 КЦ (при наличии в КЦ данной функциональной области). РФО ДЦ согласовывает вне ЕЗС и прикладывает письмо.' },
|
||
{ cat: 'Изменения', q: 'Что является критерием для классификации изменения ИС как Комплексного (КИ)?', opts: ['Стоимость изменения превышает бюджет', 'Изменение затрагивает более одной функциональной области и/или несколько ИС', 'Изменение инициировано на уровне ГД', 'Срок реализации превышает 3 месяца'], ans: 1, exp: 'Комплексное изменение (КИ) — разработка нового или изменение текущего функционала ИС, затрагивающая более одной функциональной области и/или несколько информационных систем, касающаяся нескольких Дивизионов/Служб и требующая выработки совместных решений.' },
|
||
{ cat: 'Изменения', q: 'Какой срок отводится Службе ИТ на оценку стоимости и сроков реализации изменений?', opts: ['3 рабочих дня', '5 рабочих дней', '7 рабочих дней', '10 рабочих дней'], ans: 2, exp: 'На оценку стоимости и сроков реализации изменений ИС Службе ИТ отводится 7 рабочих дней после согласования запроса.' },
|
||
{ cat: 'Изменения', q: 'В ходе тестирования выявлено замечание, которое противоречит первоначальным требованиям. Как оно обрабатывается?', opts: ['Устраняется Службой ИТ в рамках текущего запроса', 'Регистрируется как новый запрос на изменение ИС', 'Инициатор закрывает текущий запрос и создаёт новый', 'Выносится на совещание с ГД'], ans: 1, exp: 'Если выявленные замечания противоречат изначально заявленным требованиям, они регистрируются инициатором как новый Запрос на изменение ИС. При этом тестирование признаётся завершённым.' },
|
||
{ cat: 'Изменения', q: 'Кто является обязательным участником совещания по согласованию реестра изменений с ГД?', opts: ['Инициатор + РФО + Директор ИТ', 'ГД + Финансовый директор КЦ + Директор по ИТ', 'Владелец ИС + Директор ИТ + ГД', 'Только Директор по ИТ и ГД'], ans: 1, exp: 'Обязательные участники совещания: Генеральный Директор, Финансовый Директор КЦ и Директор по ИТ. При необходимости могут быть приглашены эксперты для дополнительных пояснений.' },
|
||
{ cat: 'Изменения', q: 'Кто является владельцем информационной системы ЕЗС?', opts: ['Руководитель отдела компетенций по ИС', 'Руководитель отдела разработки ИС', 'Директор по ИТ', 'Заместитель директора по поддержке ИС'], ans: 2, exp: 'Согласно Приложению 2 «РФО и Владельцы систем», владельцем ЕЗС является Директор по ИТ. Он же является владельцем ЛК Заказчика.' },
|
||
{ cat: 'Изменения', q: 'Кто является владельцем информационных систем CRM и 1С БУХ?', opts: ['CRM — Директор по ИТ; 1С БУХ — Финансовый директор КЦ', 'CRM — Директор по работе с Клиентами КЦ; 1С БУХ — Главный бухгалтер', 'Оба — Руководитель отдела компетенций по ИС', 'CRM — Директор по маркетингу; 1С БУХ — Директор по проектам'], ans: 1, exp: 'Согласно Приложению 2: владелец CRM — Директор по работе с Клиентами КЦ, владелец 1С БУХ — Главный бухгалтер. Это важно знать при подаче запроса на изменение этих систем.' },
|
||
{ cat: 'Изменения', q: 'РФО какой функциональной области согласовывает запрос на изменение в сфере Управления персоналом (КЦ)?', opts: ['Финансовый директор КЦ', 'Руководитель отдела стандартов', 'Директор по управлению персоналом КЦ', 'Директор по качеству и инновациям'], ans: 2, exp: 'Согласно Приложению 2 «РФО и Владельцы систем», РФО по функциональной области «Управление персоналом» на уровне КЦ — Директор по управлению персоналом КЦ.' },
|
||
|
||
// --- SLA (5) ---
|
||
{ cat: 'SLA', q: 'Каков режим обслуживания для VIP-пользователей (ТОП 0–1)?', opts: ['9×5 (рабочие часы)', '16×7', '24×5', '24×7 (круглосуточно)'], ans: 3, exp: 'VIP-пользователи (руководители ТОП 0–1) обслуживаются в режиме 24×7 — круглосуточно, без выходных. Любой инцидент от VIP считается критичным с SLA 4 часа.' },
|
||
{ cat: 'SLA', q: 'Инцидент частично затрагивает работу ИС, существует риск остановки бизнес-процесса. Какой SLA (срок устранения)?', opts: ['4 часа', '8 часов', '16 часов', '32 часа'], ans: 1, exp: 'Это инцидент с критичностью «Высокий». Срок устранения — 8 часов. Критичный (полная остановка) — 4 часа. Стандартный (ошибка без остановки) — 32 часа.' },
|
||
{ cat: 'SLA', q: 'Какой срок решения установлен для запроса на предоставление доступа к ИС для офисных сотрудников?', opts: ['8 часов', '16 часов', '24 часа', '32 часа'], ans: 2, exp: 'Согласно SLA (Подраздел 3.1), срок на предоставление/изменение доступа к информационным системам для офисных сотрудников составляет 24 часа.' },
|
||
{ cat: 'SLA', q: 'Сколько времени отводится на регистрацию инцидента с момента его поступления?', opts: ['5 минут', '10 минут', '15 минут', '30 минут'], ans: 2, exp: 'Время регистрации обращения — 15 минут с момента поступления запроса до момента присвоения ему уникального номера в единой заявочной системе.' },
|
||
{ cat: 'SLA', q: 'Какой срок согласования отводится на этап согласования РФО в процессе изменений?', opts: ['Немедленно', '1 рабочий день', '3 рабочих дня', '7 рабочих дней'], ans: 1, exp: 'По регламенту (Подраздел 3.3), срок согласования РФО — 1 рабочий день. Такой же срок установлен для Службы ИТ и Владельца ИС на первичное согласование.' },
|
||
|
||
// --- KPI (4) ---
|
||
{ cat: 'KPI', q: 'Каков целевой показатель доступности ИС согласно KPI?', opts: ['≥ 95%', '≥ 97%', '≥ 99%', '≥ 99,5%'], ans: 3, exp: 'Целевое значение KPI «Высокая доступность ИС» — ≥ 99,5%. Пороговое (минимально допустимое) — ≥ 99%. Доступность считается по формуле: (Д − П) / Д × 100%.' },
|
||
{ cat: 'KPI', q: 'Что является пороговым значением KPI «Процент возвращённых заявок в работу» (инциденты)?', opts: ['≤ 0,3%', '≤ 0,5%', '≤ 1%', '≤ 2%'], ans: 2, exp: 'Целевое значение для этого KPI — ≤ 0,5%, пороговое — ≤ 1%. Это доля возвращённых инцидентов от общего числа решённых. Показатель влияет на оценку качества работы специалиста.' },
|
||
{ cat: 'KPI', q: 'Каков целевой показатель удовлетворённости заказчика по запросам на изменение ИС?', opts: ['≥ 90%', '≥ 95%', '≥ 97%', '≥ 98%'], ans: 1, exp: 'Целевое значение KPI «Уровень удовлетворённости заказчика (Запросы на изменение)» — ≥ 95%, пороговое — ≥ 90%. Это отличается от показателя по инцидентам, где целевое значение выше — ≥ 98%.' },
|
||
{ cat: 'KPI', q: 'Как используются оценки, выставленные сотрудниками после закрытия инцидентов?', opts: ['Только для статистики по отделу', 'Для расчёта KPI конкретных специалистов ИТ', 'Для определения стоимости следующего обслуживания', 'Публикуются в общем рейтинге ИТ-службы'], ans: 1, exp: 'Оценки, проставленные сотрудниками после подтверждения завершения работ, используются для оценки работы конкретных специалистов ИТ и участвуют в расчёте KPI ИТ-службы.' }
|
||
];
|
||
|
||
// ===================== STATE =====================
|
||
let completedModules = new Set();
|
||
let currentModule = null;
|
||
let currentSlide = 0;
|
||
let currentQuestion = 0;
|
||
let score = 0;
|
||
let answered = [];
|
||
|
||
// ===================== RENDER =====================
|
||
function renderMenu() {
|
||
const grid = document.getElementById('modules-grid');
|
||
grid.innerHTML = modules.map(m => `
|
||
<div class="module-card ${completedModules.has(m.id) ? 'done' : ''}" onclick="openModule(${m.id})">
|
||
<div class="module-header">
|
||
<div class="module-icon">${m.icon}</div>
|
||
<div>
|
||
<div class="module-title">${m.title}</div>
|
||
<div class="module-sub">${m.sub} · ${m.slides.length} слайдов</div>
|
||
</div>
|
||
</div>
|
||
<div class="module-desc">${m.desc}</div>
|
||
<div class="module-footer">
|
||
<div class="module-topics">${m.tags.map(t => `<span class="topic-tag">${t}</span>`).join('')}</div>
|
||
<div class="module-status">${completedModules.has(m.id) ? '✓ Изучено' : 'Открыть →'}</div>
|
||
</div>
|
||
</div>
|
||
`).join('') + `
|
||
<div class="module-card" onclick="startQuiz()" style="background:linear-gradient(135deg,rgba(0,149,255,0.08),rgba(0,212,170,0.08));border-color:rgba(0,212,170,0.3);">
|
||
<div class="module-header">
|
||
<div class="module-icon">🎯</div>
|
||
<div>
|
||
<div class="module-title">Итоговое тестирование</div>
|
||
<div class="module-sub">${questions.length} вопросов · Все разделы курса</div>
|
||
</div>
|
||
</div>
|
||
<div class="module-desc">Подтвердите знания прохождением теста по всем разделам курса. При результате ≥ 75% выдаётся сертификат.</div>
|
||
<div class="module-footer">
|
||
<div class="module-topics"><span class="topic-tag" style="color:var(--accent);border-color:rgba(0,212,170,0.4);background:rgba(0,212,170,0.1)">ТЕСТ</span></div>
|
||
<div class="module-status" style="color:var(--accent)">Пройти →</div>
|
||
</div>
|
||
</div>
|
||
`;
|
||
updateProgress();
|
||
}
|
||
|
||
function updateProgress() {
|
||
const pct = (completedModules.size / modules.length) * 100;
|
||
document.getElementById('main-progress').style.width = pct + '%';
|
||
document.getElementById('progress-text').textContent = `${completedModules.size} / ${modules.length}`;
|
||
}
|
||
|
||
function openModule(id) {
|
||
currentModule = modules[id];
|
||
currentSlide = 0;
|
||
document.getElementById('lesson-title').textContent = currentModule.title;
|
||
document.getElementById('lesson-sub').textContent = currentModule.sub;
|
||
renderSlides();
|
||
showScreen('screen-lesson');
|
||
}
|
||
|
||
function renderSlides() {
|
||
const host = document.getElementById('slides-host');
|
||
host.innerHTML = currentModule.slides.map((s, i) => `
|
||
<div class="slide ${i === 0 ? 'active' : ''}" id="slide-${i}">${s.html}</div>
|
||
`).join('');
|
||
const dots = document.getElementById('slide-dots');
|
||
dots.innerHTML = currentModule.slides.map((_, i) =>
|
||
`<div class="slide-dot ${i === 0 ? 'active' : ''}" onclick="jumpSlide(${i})"></div>`
|
||
).join('');
|
||
updateSlideControls();
|
||
}
|
||
|
||
function jumpSlide(idx) {
|
||
document.getElementById('slide-' + currentSlide).classList.remove('active');
|
||
document.querySelectorAll('.slide-dot')[currentSlide].classList.remove('active');
|
||
currentSlide = idx;
|
||
document.getElementById('slide-' + currentSlide).classList.add('active');
|
||
document.querySelectorAll('.slide-dot')[currentSlide].classList.add('active');
|
||
updateSlideControls();
|
||
}
|
||
|
||
function changeSlide(dir) {
|
||
const slides = currentModule.slides;
|
||
const prev = currentSlide;
|
||
currentSlide = Math.max(0, Math.min(slides.length - 1, currentSlide + dir));
|
||
if (prev !== currentSlide) {
|
||
document.getElementById('slide-' + prev).classList.remove('active');
|
||
document.querySelectorAll('.slide-dot')[prev].classList.remove('active');
|
||
document.getElementById('slide-' + currentSlide).classList.add('active');
|
||
document.querySelectorAll('.slide-dot')[currentSlide].classList.add('active');
|
||
}
|
||
updateSlideControls();
|
||
if (currentSlide === slides.length - 1) {
|
||
completedModules.add(currentModule.id);
|
||
renderMenu();
|
||
}
|
||
}
|
||
|
||
function updateSlideControls() {
|
||
const slides = currentModule.slides;
|
||
document.getElementById('btn-prev').disabled = currentSlide === 0;
|
||
const btn = document.getElementById('btn-next-slide');
|
||
if (currentSlide === slides.length - 1) {
|
||
btn.textContent = '✓ Завершить раздел';
|
||
btn.onclick = () => goMenu();
|
||
} else {
|
||
btn.textContent = 'Далее →';
|
||
btn.onclick = () => changeSlide(1);
|
||
}
|
||
}
|
||
|
||
// ===================== QUIZ =====================
|
||
function startQuiz() {
|
||
currentQuestion = 0;
|
||
score = 0;
|
||
answered = Array(questions.length).fill(null);
|
||
document.getElementById('quiz-score').textContent = '0';
|
||
document.getElementById('quiz-q-count').textContent = `1 / ${questions.length}`;
|
||
updateQuizProgress();
|
||
renderQuestion();
|
||
showScreen('screen-quiz');
|
||
}
|
||
|
||
function renderQuestion() {
|
||
const q = questions[currentQuestion];
|
||
const letters = ['A', 'B', 'C', 'D'];
|
||
document.getElementById('question-host').innerHTML = `
|
||
<div class="question-card">
|
||
<div class="q-meta">
|
||
<span class="q-num">Вопрос ${currentQuestion + 1} / ${questions.length}</span>
|
||
<span class="q-category">${q.cat}</span>
|
||
</div>
|
||
<div class="q-text">${q.q}</div>
|
||
<div class="options">
|
||
${q.opts.map((o, i) => `
|
||
<button class="option-btn" id="opt-${i}" onclick="selectAnswer(${i})">
|
||
<span class="option-letter">${letters[i]}</span>${o}
|
||
</button>
|
||
`).join('')}
|
||
</div>
|
||
<div class="explanation" id="explanation"></div>
|
||
</div>
|
||
`;
|
||
document.getElementById('btn-next-q').classList.remove('show');
|
||
}
|
||
|
||
function selectAnswer(idx) {
|
||
if (answered[currentQuestion] !== null) return;
|
||
answered[currentQuestion] = idx;
|
||
const q = questions[currentQuestion];
|
||
for (let i = 0; i < q.opts.length; i++) {
|
||
const btn = document.getElementById('opt-' + i);
|
||
btn.disabled = true;
|
||
if (i === q.ans) btn.classList.add('correct');
|
||
else if (i === idx && idx !== q.ans) btn.classList.add('wrong');
|
||
}
|
||
const exp = document.getElementById('explanation');
|
||
if (idx === q.ans) {
|
||
score++;
|
||
document.getElementById('quiz-score').textContent = score;
|
||
exp.className = 'explanation correct-exp show';
|
||
exp.innerHTML = '✅ ' + q.exp;
|
||
} else {
|
||
exp.className = 'explanation wrong-exp show';
|
||
exp.innerHTML = '❌ ' + q.exp;
|
||
}
|
||
const btn = document.getElementById('btn-next-q');
|
||
btn.classList.add('show');
|
||
btn.textContent = currentQuestion < questions.length - 1 ? 'Следующий вопрос →' : '📊 Посмотреть результаты';
|
||
}
|
||
|
||
function nextQuestion() {
|
||
if (currentQuestion < questions.length - 1) {
|
||
currentQuestion++;
|
||
updateQuizProgress();
|
||
renderQuestion();
|
||
} else {
|
||
showResults();
|
||
}
|
||
}
|
||
|
||
function updateQuizProgress() {
|
||
const pct = ((currentQuestion + 1) / questions.length) * 100;
|
||
document.getElementById('quiz-progress').style.width = pct + '%';
|
||
document.getElementById('quiz-q-count').textContent = `${currentQuestion + 1} / ${questions.length}`;
|
||
}
|
||
|
||
function showResults() {
|
||
const pct = Math.round((score / questions.length) * 100);
|
||
const wrong = questions.length - score;
|
||
document.getElementById('result-score').textContent = `${pct}%`;
|
||
document.getElementById('rb-correct').textContent = score;
|
||
document.getElementById('rb-wrong').textContent = wrong;
|
||
document.getElementById('rb-percent').textContent = pct + '%';
|
||
let trophy, title, desc;
|
||
if (pct >= 90) { trophy = '🏆'; title = 'Отличный результат!'; desc = 'Вы продемонстрировали отличное знание регламентов управления ИТ. Сертификат о прохождении курса сформирован.'; }
|
||
else if (pct >= 75) { trophy = '🎖'; title = 'Хороший результат!'; desc = 'Вы хорошо усвоили материал курса. Рекомендуем повторить темы с ошибками для закрепления знаний.'; }
|
||
else if (pct >= 60) { trophy = '📚'; title = 'Курс пройден'; desc = 'Базовые знания получены. Рекомендуем ещё раз изучить разделы курса перед повторным тестированием.'; }
|
||
else { trophy = '🔄'; title = 'Нужно повторить'; desc = 'Рекомендуем ещё раз пройти все обучающие материалы и затем повторить тестирование.'; }
|
||
document.getElementById('result-trophy').textContent = trophy;
|
||
document.getElementById('result-title').textContent = title;
|
||
document.getElementById('result-desc').textContent = desc;
|
||
const certHost = document.getElementById('cert-host');
|
||
if (pct >= 75) {
|
||
const today = new Date().toLocaleDateString('ru-RU', { day: '2-digit', month: 'long', year: 'numeric' });
|
||
const stars = pct >= 90 ? '★★★★★' : pct >= 80 ? '★★★★☆' : '★★★☆☆';
|
||
certHost.innerHTML = `
|
||
<div class="cert-card">
|
||
<h3>Сертификат о прохождении</h3>
|
||
<h2>Управление ИТ</h2>
|
||
<div class="cert-name">ИТ-специалист</div>
|
||
<div class="cert-stars">${stars}</div>
|
||
<div>Результат: <strong style="color:var(--accent)">${pct}%</strong> (${score} из ${questions.length})</div>
|
||
<div class="cert-date" style="margin-top:12px">${today}</div>
|
||
</div>
|
||
`;
|
||
} else { certHost.innerHTML = ''; }
|
||
sendResults(score, questions.length, pct, pct >= 75);
|
||
showScreen('screen-results');
|
||
}
|
||
|
||
function restartQuiz() { startQuiz(); }
|
||
|
||
function goMenu() {
|
||
renderMenu();
|
||
showScreen('screen-menu');
|
||
}
|
||
|
||
function showScreen(id) {
|
||
document.querySelectorAll('.screen').forEach(s => s.classList.remove('active'));
|
||
document.getElementById(id).classList.add('active');
|
||
window.scrollTo({ top: 0, behavior: 'smooth' });
|
||
}
|
||
|
||
// ——— Связка с сервером: ФИО и результаты ———
|
||
const STORAGE_KEY_ID = 'lms_participant_id';
|
||
const STORAGE_KEY_FIO = 'lms_fio';
|
||
|
||
function getApiBase() {
|
||
const origin = window.location.origin;
|
||
const path = window.location.pathname;
|
||
const base = path.includes('/content/') ? path.replace(/\/content\/[^/]*$/, '') : '';
|
||
return origin + base;
|
||
}
|
||
|
||
function submitWelcome(e) {
|
||
e.preventDefault();
|
||
const input = document.getElementById('input-fio');
|
||
const errEl = document.getElementById('welcome-error');
|
||
const btn = document.getElementById('btn-welcome-start');
|
||
const fio = (input.value || '').trim();
|
||
if (!fio) {
|
||
errEl.textContent = 'Введите ФИО';
|
||
errEl.classList.add('show');
|
||
return false;
|
||
}
|
||
errEl.classList.remove('show');
|
||
btn.disabled = true;
|
||
btn.textContent = 'Загрузка…';
|
||
fetch(getApiBase() + '/api/start', {
|
||
method: 'POST',
|
||
headers: { 'Content-Type': 'application/json' },
|
||
body: JSON.stringify({ fio: fio })
|
||
})
|
||
.then(r => r.json().then(data => ({ ok: r.ok, data })))
|
||
.then(({ ok, data }) => {
|
||
if (ok && data.participant_id) {
|
||
try {
|
||
sessionStorage.setItem(STORAGE_KEY_ID, data.participant_id);
|
||
sessionStorage.setItem(STORAGE_KEY_FIO, data.fio || fio);
|
||
} catch (e) {}
|
||
document.getElementById('user-fio').textContent = data.fio || fio;
|
||
document.getElementById('user-bar').style.display = 'flex';
|
||
showScreen('screen-menu');
|
||
renderMenu();
|
||
} else {
|
||
errEl.textContent = data.detail || 'Ошибка регистрации. Проверьте подключение.';
|
||
errEl.classList.add('show');
|
||
btn.disabled = false;
|
||
btn.textContent = 'Начать обучение';
|
||
}
|
||
})
|
||
.catch(() => {
|
||
errEl.textContent = 'Сервер недоступен. Проверьте подключение и обновите страницу.';
|
||
errEl.classList.add('show');
|
||
btn.disabled = false;
|
||
btn.textContent = 'Начать обучение';
|
||
});
|
||
return false;
|
||
}
|
||
|
||
function sendResults(score, totalQuestions, percent, passed) {
|
||
let participantId = null;
|
||
try {
|
||
participantId = sessionStorage.getItem(STORAGE_KEY_ID);
|
||
} catch (e) {}
|
||
if (!participantId) return;
|
||
fetch(getApiBase() + '/api/complete', {
|
||
method: 'POST',
|
||
headers: { 'Content-Type': 'application/json' },
|
||
body: JSON.stringify({
|
||
participant_id: participantId,
|
||
score: score,
|
||
total_questions: totalQuestions,
|
||
percent: percent,
|
||
passed: passed
|
||
})
|
||
}).catch(() => {});
|
||
}
|
||
|
||
// Инициализация: показать меню или экран ввода ФИО
|
||
function initScreens() {
|
||
let participantId = null;
|
||
let fio = null;
|
||
try {
|
||
participantId = sessionStorage.getItem(STORAGE_KEY_ID);
|
||
fio = sessionStorage.getItem(STORAGE_KEY_FIO);
|
||
} catch (e) {}
|
||
if (participantId && fio) {
|
||
document.getElementById('user-fio').textContent = fio;
|
||
document.getElementById('user-bar').style.display = 'flex';
|
||
showScreen('screen-menu');
|
||
renderMenu();
|
||
} else {
|
||
showScreen('screen-welcome');
|
||
}
|
||
}
|
||
|
||
renderMenu();
|
||
initScreens();
|
||
</script>
|
||
</body>
|
||
</html>
|