274 lines
14 KiB
HTML
274 lines
14 KiB
HTML
<!doctype html>
|
||
<html lang="ru">
|
||
<head>
|
||
<meta charset="UTF-8" />
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||
<title>KonturCC Супервизор</title>
|
||
<link rel="icon" href="/operator/assets/favicon.svg" type="image/svg+xml" />
|
||
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
||
<link href="https://fonts.googleapis.com/css2?family=Manrope:wght@500;600;700;800&family=IBM+Plex+Sans:wght@400;500;600&display=swap" rel="stylesheet" />
|
||
<link rel="stylesheet" href="/operator/assets/styles.css" />
|
||
</head>
|
||
<body>
|
||
<div class="app-shell">
|
||
<aside class="sidebar">
|
||
<div class="brand">
|
||
<div class="brand-mark">K</div>
|
||
<div>
|
||
<div class="brand-title">KonturCC</div>
|
||
<div class="brand-sub">Операционный контроль</div>
|
||
</div>
|
||
</div>
|
||
|
||
<nav class="nav-menu">
|
||
<div class="nav-group">
|
||
<div class="nav-label">Рабочие зоны</div>
|
||
<a class="nav-link" data-shell="operator" data-roles="admin,supervisor,operator,analyst" href="/operator"><span class="nav-bullet"></span>Оператор</a>
|
||
<a class="nav-link active" data-shell="supervisor" data-roles="admin,supervisor" href="/supervisor"><span class="nav-bullet"></span>Супервизор</a>
|
||
<a class="nav-link" data-shell="analyst" data-roles="admin,supervisor,analyst" href="/analyst"><span class="nav-bullet"></span>Аналитика</a>
|
||
<a class="nav-link" data-shell="sales" data-roles="admin,supervisor,operator,analyst" href="/sales"><span class="nav-bullet"></span>Продажи</a>
|
||
<a class="nav-link" data-shell="admin" data-roles="admin" href="/admin"><span class="nav-bullet"></span>Администрирование</a>
|
||
</div>
|
||
<div class="nav-group">
|
||
<div class="nav-label">Блоки</div>
|
||
<a class="nav-link" href="#realtime"><span class="nav-bullet"></span>Оперативный срез</a>
|
||
<a class="nav-link" href="#liveCalls"><span class="nav-bullet"></span>Живые звонки</a>
|
||
<a class="nav-link" href="#agents"><span class="nav-bullet"></span>Агенты</a>
|
||
<a class="nav-link" href="#queues"><span class="nav-bullet"></span>Очереди</a>
|
||
<a class="nav-link" href="#knowledge"><span class="nav-bullet"></span>База знаний</a>
|
||
</div>
|
||
<div class="nav-group">
|
||
<div class="nav-label">Записи</div>
|
||
<a class="nav-link" href="#recordings"><span class="nav-bullet"></span>Записи</a>
|
||
</div>
|
||
</nav>
|
||
|
||
<div class="sidebar-footer">
|
||
<strong>Экран супервизора</strong>
|
||
<p>Сводка по агентам, очередям и KPI без захода в операторский экран.</p>
|
||
<button id="logoutBtn" class="btn ghost" type="button">Выйти</button>
|
||
</div>
|
||
</aside>
|
||
|
||
<section class="workspace">
|
||
<header class="workspace-topbar reveal">
|
||
<div class="search-box">
|
||
<input class="app-search" placeholder="Найти агента, очередь или KPI..." />
|
||
</div>
|
||
<div class="topbar-actions">
|
||
<div class="status-pill" id="gatewayStatus">Шлюз: проверка...</div>
|
||
<button class="icon-button" type="button" aria-label="Уведомления">•</button>
|
||
<div class="profile-chip">
|
||
<div class="avatar-badge">SV</div>
|
||
<div class="profile-meta">
|
||
<div class="profile-name" id="profileName">Экран супервизора</div>
|
||
<div class="profile-role" id="profileRole">Операционный контроль</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</header>
|
||
|
||
<main class="layout">
|
||
<section class="page-hero reveal">
|
||
<p class="eyebrow">Операционный контур</p>
|
||
<h1>Пульт супервизора</h1>
|
||
<p class="hint">Операционный обзор: состояние команды, очередей и ключевых KPI.</p>
|
||
</section>
|
||
|
||
<section class="panel auth reveal" id="authPanel">
|
||
<h2>Сессия</h2>
|
||
<div class="row">
|
||
<label>Пользователь</label>
|
||
<input id="sessionUser" value="supervisor" />
|
||
</div>
|
||
<div class="row">
|
||
<label>Роль</label>
|
||
<select id="sessionRole">
|
||
<option value="supervisor" selected>Супервизор</option>
|
||
<option value="admin">Администратор</option>
|
||
<option value="operator">Оператор</option>
|
||
<option value="analyst">Аналитик</option>
|
||
</select>
|
||
</div>
|
||
<div class="row">
|
||
<label>Пароль</label>
|
||
<input id="sessionPassword" type="password" value="sup12345" />
|
||
</div>
|
||
<div class="actions">
|
||
<button id="loginBtn" class="btn">Войти</button>
|
||
<button id="corporateLoginBtn" class="btn ghost" type="button">Корпоративный вход</button>
|
||
<button id="refreshBtn" class="btn ghost">Обновить все</button>
|
||
</div>
|
||
<p class="hint" id="sessionInfo">Токен: отсутствует</p>
|
||
</section>
|
||
|
||
<section class="grid">
|
||
<article class="panel reveal" id="realtime">
|
||
<h2>Оперативный срез</h2>
|
||
<div class="actions compact-actions">
|
||
<button id="loadRealtimeBtn" class="btn ghost">Обновить срез</button>
|
||
<button id="loadKpiBtn" class="btn ghost">Обновить KPI</button>
|
||
</div>
|
||
<p class="hint">Этот блок нужен для оперативной проверки и технической диагностики на экране супервизора.</p>
|
||
<div id="realtimeSummary" class="summary-grid"></div>
|
||
<details class="details-block">
|
||
<summary>Технический ответ оперативного среза</summary>
|
||
<pre id="realtimeOutput" class="output"></pre>
|
||
</details>
|
||
<div id="kpiSummary" class="summary-grid"></div>
|
||
<details class="details-block">
|
||
<summary>Технический ответ KPI</summary>
|
||
<pre id="kpiOutput" class="output"></pre>
|
||
</details>
|
||
</article>
|
||
|
||
<article class="panel reveal" id="liveCalls">
|
||
<h2>Живые звонки Asterisk</h2>
|
||
<div class="actions compact-actions">
|
||
<button id="loadLiveCallsBtn" class="btn ghost">Обновить звонки</button>
|
||
</div>
|
||
<p class="hint">Показываются последние звонки, пришедшие от Asterisk.</p>
|
||
<ul id="liveCallsList" class="list"></ul>
|
||
</article>
|
||
|
||
<article class="panel reveal" id="agents">
|
||
<h2>Агенты</h2>
|
||
<div class="inline-form split-two">
|
||
<input id="agentId" placeholder="ID агента" value="supervisor_demo_agent" />
|
||
<select id="agentState">
|
||
<option value="READY">Готовы</option>
|
||
<option value="BUSY">Заняты</option>
|
||
<option value="BREAK">BREAK</option>
|
||
<option value="OFFLINE">OFFLINE</option>
|
||
</select>
|
||
</div>
|
||
<div class="inline-form compact">
|
||
<input id="agentQueueId" placeholder="Очередь" value="line2" />
|
||
<button id="setAgentBtn" class="btn">Обновить статус</button>
|
||
</div>
|
||
<div class="inline-form compact">
|
||
<button id="loadAgentsBtn" class="btn ghost">Показать агентов</button>
|
||
</div>
|
||
<ul id="agentsList" class="list"></ul>
|
||
</article>
|
||
|
||
<article class="panel reveal" id="queues">
|
||
<h2>Очередь</h2>
|
||
<div class="inline-form split-two">
|
||
<input id="queueMetricId" placeholder="ID очереди" value="line2" />
|
||
<input id="queueInQueue" placeholder="В очереди" type="number" value="2" />
|
||
</div>
|
||
<div class="inline-form compact">
|
||
<input id="queueAvgWait" placeholder="Среднее ожидание (сек)" type="number" value="18" />
|
||
<button id="saveQueueMetricsBtn" class="btn">Обновить очередь</button>
|
||
</div>
|
||
<p class="hint">Используйте это как быстрый операционный контроль для демонстрационного среза.</p>
|
||
<pre id="queueMetricsOutput" class="output"></pre>
|
||
</article>
|
||
|
||
<article class="panel reveal panel-span-full" id="knowledge">
|
||
<h2>База знаний</h2>
|
||
<p class="hint">Супервизор может вручную создать категорию, добавить статью и сразу обновить базу знаний для Voice AI.</p>
|
||
<div id="kbSummary" class="summary-grid"></div>
|
||
|
||
<div class="inline-form split-two">
|
||
<input id="kbCategoryName" placeholder="Новая категория" />
|
||
<input id="kbCategoryDescription" placeholder="Описание категории" />
|
||
</div>
|
||
<div class="inline-form compact">
|
||
<button id="createKbCategoryBtn" class="btn">Добавить категорию</button>
|
||
<button id="loadKbBtn" class="btn ghost" type="button">Обновить базу знаний</button>
|
||
</div>
|
||
|
||
<div class="inline-form split-two">
|
||
<select id="kbArticleCategory"></select>
|
||
<select id="kbArticleLanguage">
|
||
<option value="ru">RU</option>
|
||
<option value="kz">KZ</option>
|
||
</select>
|
||
</div>
|
||
<div class="inline-form compact">
|
||
<input id="kbArticleGroupId" placeholder="ID группы статей (связка RU/KZ)" />
|
||
</div>
|
||
<div class="inline-form split-two">
|
||
<input id="kbArticleTitle" placeholder="Заголовок статьи" />
|
||
</div>
|
||
<div class="inline-form compact">
|
||
<input id="kbArticleTags" placeholder="Теги через запятую" />
|
||
</div>
|
||
<div class="row">
|
||
<label for="kbArticleBody">Текст статьи</label>
|
||
<textarea id="kbArticleBody" rows="6" placeholder="Например: график работы, адреса, частые вопросы, правила маршрутизации..."></textarea>
|
||
</div>
|
||
<div class="actions compact-actions">
|
||
<button id="saveKbArticleBtn" class="btn">Сохранить статью</button>
|
||
<button id="resetKbArticleBtn" class="btn ghost" type="button">Новая статья</button>
|
||
</div>
|
||
<p class="hint" id="kbFormHint">Создайте новую статью или выберите существующую для редактирования.</p>
|
||
|
||
<div class="inline-form split-two">
|
||
<input id="kbSearchQuery" placeholder="Поиск по базе знаний" />
|
||
<button id="searchKbBtn" class="btn ghost" type="button">Искать</button>
|
||
</div>
|
||
|
||
<div class="inline-form split-two">
|
||
<div>
|
||
<h3>Категории</h3>
|
||
<ul id="kbCategoriesList" class="list"></ul>
|
||
</div>
|
||
<div>
|
||
<h3>Статьи</h3>
|
||
<ul id="kbArticlesList" class="list"></ul>
|
||
</div>
|
||
</div>
|
||
<details class="details-block">
|
||
<summary>Предпросмотр выбранной статьи</summary>
|
||
<pre id="kbArticlePreview" class="output"></pre>
|
||
</details>
|
||
</article>
|
||
|
||
<article class="panel reveal">
|
||
<h2>Лог действий</h2>
|
||
<p class="hint">Сверху всегда последнее действие супервизора.</p>
|
||
<pre id="eventLog" class="output tall"></pre>
|
||
</article>
|
||
|
||
<article class="panel reveal" id="recordings">
|
||
<h2>Записи</h2>
|
||
<div class="inline-form compact">
|
||
<input id="recordingEventId" placeholder="ID voice_event / обращения / звонка" />
|
||
<button id="importRecordingBtn" class="btn">Импорт / поиск</button>
|
||
</div>
|
||
<div class="inline-form split-two">
|
||
<input id="recordingCallId" placeholder="Фильтр по ID звонка" />
|
||
<input id="recordingInteractionId" placeholder="Фильтр по ID обращения" />
|
||
</div>
|
||
<div class="inline-form compact">
|
||
<select id="recordingStatus">
|
||
<option value="">Все</option>
|
||
<option value="ready">Готова</option>
|
||
<option value="archived">В архиве</option>
|
||
<option value="missing">Отсутствует</option>
|
||
</select>
|
||
<button id="loadRecordingsBtn" class="btn ghost">Показать записи</button>
|
||
<button id="archiveRecordingBtn" class="btn ghost" type="button">Архивировать</button>
|
||
</div>
|
||
<p class="hint">Для Asterisk запись обычно импортируется автоматически после завершения звонка.</p>
|
||
<ul id="recordingsList" class="list"></ul>
|
||
<div class="recording-detail">
|
||
<div class="hint" id="recordingSelectionHint">Выберите запись для предпросмотра.</div>
|
||
<pre id="recordingMetaOutput" class="output"></pre>
|
||
<audio id="recordingPlayer" controls preload="none"></audio>
|
||
<button id="downloadRecordingBtn" class="btn ghost" type="button">Скачать</button>
|
||
</div>
|
||
</article>
|
||
</section>
|
||
</main>
|
||
</section>
|
||
</div>
|
||
|
||
<script src="/supervisor/assets/app.js?v=track34-supervisor-ru-polish"></script>
|
||
</body>
|
||
</html>
|