763 lines
46 KiB
HTML
763 lines
46 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?v=track25-messenger-polish1" />
|
||
</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="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="admin" data-roles="admin" href="/admin"><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>
|
||
</div>
|
||
<div class="nav-group">
|
||
<div class="nav-label">Страницы</div>
|
||
<a class="nav-link active" data-operator-view-link="workspace" href="#workspace"><span class="nav-bullet"></span>Рабочий стол</a>
|
||
<a class="nav-link" data-operator-view-link="messages" href="#messages"><span class="nav-bullet"></span>Сообщения</a>
|
||
<a class="nav-link" data-operator-view-link="customers" href="#customers-page"><span class="nav-bullet"></span>Клиенты</a>
|
||
<a class="nav-link" data-debug-channel="telegram" href="#telegram-page" hidden><span class="nav-bullet"></span>Telegram</a>
|
||
<a class="nav-link" data-debug-channel="whatsapp" href="#whatsapp-page" hidden><span class="nav-bullet"></span>WhatsApp</a>
|
||
<a class="nav-link" data-operator-view-link="calls" data-roles="admin,operator" href="#calls"><span class="nav-bullet"></span>Звонки</a>
|
||
</div>
|
||
</nav>
|
||
|
||
<div class="sidebar-footer">
|
||
<strong>Операторский экран</strong>
|
||
<p>Показывает единый контур: клиент, обращение, каналы, база знаний и voice lifecycle.</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="Найти клиента, обращение или канал..." />
|
||
</div>
|
||
<div class="topbar-actions">
|
||
<div class="status-pill" id="gatewayStatus">Шлюз: проверка...</div>
|
||
<div class="phone-entrypoint">
|
||
<button id="browserPhoneStatusBtn" class="phone-chip" type="button" aria-label="Состояние браузерного телефона" aria-expanded="false" data-state="offline">
|
||
<span class="phone-chip-dot" id="browserPhoneStatusDot"></span>
|
||
<span class="phone-chip-copy">
|
||
<span class="phone-chip-title">Телефон</span>
|
||
<span class="phone-chip-status" id="browserPhoneStatusLabel">Не подключен</span>
|
||
</span>
|
||
</button>
|
||
<div id="browserPhoneSettingsPanel" class="phone-settings hidden">
|
||
<div class="softphone-summary compact">
|
||
<div class="softphone-status-block">
|
||
<div class="softphone-status-label">Регистрация</div>
|
||
<div class="softphone-status-value" id="browserPhoneRegistrationState">Не настроен</div>
|
||
</div>
|
||
<div class="softphone-status-block">
|
||
<div class="softphone-status-label">Внутренний номер оператора</div>
|
||
<div class="softphone-status-value" id="browserPhoneOperatorExtension">—</div>
|
||
</div>
|
||
<div class="softphone-status-block">
|
||
<div class="softphone-status-label">WSS</div>
|
||
<div class="softphone-status-value" id="browserPhoneWsUrl">—</div>
|
||
</div>
|
||
</div>
|
||
<div class="inline-form compact phone-settings-actions">
|
||
<button id="browserPhoneConnectBtn" class="btn" type="button">Подключить телефон</button>
|
||
<button id="browserPhoneDisconnectBtn" class="btn ghost" type="button">Отключить</button>
|
||
</div>
|
||
<div class="inline-form split-two">
|
||
<div class="row stacked">
|
||
<label for="browserPhoneMicSelect">Микрофон</label>
|
||
<select id="browserPhoneMicSelect"></select>
|
||
</div>
|
||
<div class="row stacked">
|
||
<label for="browserPhoneSpeakerSelect">Динамик</label>
|
||
<select id="browserPhoneSpeakerSelect"></select>
|
||
</div>
|
||
</div>
|
||
<p class="hint" id="browserPhoneHint">Браузерный телефон выключен или не настроен.</p>
|
||
</div>
|
||
</div>
|
||
<button class="icon-button" type="button" aria-label="Уведомления">•</button>
|
||
<div class="profile-chip">
|
||
<div class="avatar-badge">OP</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 id="workspaceView" class="operator-view" data-operator-view="workspace">
|
||
<section class="page-hero reveal">
|
||
<h1>Операторский пульт v2</h1>
|
||
</section>
|
||
|
||
<section class="panel auth reveal" id="authPanel">
|
||
<h2>Сессия</h2>
|
||
<div class="row">
|
||
<label>Пользователь</label>
|
||
<input id="sessionUser" value="admin" />
|
||
</div>
|
||
<div class="row">
|
||
<label>Роль</label>
|
||
<select id="sessionRole">
|
||
<option value="admin" selected>Администратор</option>
|
||
<option value="supervisor">Супервизор</option>
|
||
<option value="operator">Оператор</option>
|
||
<option value="analyst">Аналитик</option>
|
||
</select>
|
||
</div>
|
||
<div class="row">
|
||
<label>Пароль</label>
|
||
<input id="sessionPassword" type="password" value="admin123" />
|
||
</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 panel-span-full unified-inbox-panel" id="unifiedInbox">
|
||
<div class="unified-inbox-head">
|
||
<div>
|
||
<h2>Единая очередь</h2>
|
||
<p class="hint">Новые задачи, мои диалоги, AI handoff, эскалации и живые звонки в одном месте.</p>
|
||
</div>
|
||
<button id="refreshUnifiedInboxBtn" class="btn ghost" type="button">Обновить очередь</button>
|
||
</div>
|
||
<div id="unifiedInboxSummary" class="summary-grid"></div>
|
||
<div id="unifiedInboxBoard" class="unified-inbox-scroll"></div>
|
||
</article>
|
||
|
||
<article class="panel reveal panel-span-full" id="interactions">
|
||
<h2>Обращения</h2>
|
||
<div class="inline-form">
|
||
<select id="interactionChannel">
|
||
<option value="voice">Голос</option>
|
||
<option value="telegram">Telegram</option>
|
||
<option value="whatsapp" data-feature-option="whatsapp" hidden disabled>WhatsApp</option>
|
||
<option value="webchat">Веб-чат</option>
|
||
<option value="email">Электронная почта</option>
|
||
</select>
|
||
<input id="interactionSubject" placeholder="Тема обращения" />
|
||
<input id="interactionCustomerId" placeholder="ID клиента" />
|
||
<button id="createInteractionBtn" class="btn">Создать</button>
|
||
</div>
|
||
<div class="inline-form split-two">
|
||
<input id="defaultAssignee" value="operator_a" placeholder="Исполнитель по умолчанию" />
|
||
<input id="defaultEscalationQueue" value="line2" placeholder="Очередь 2 линии" />
|
||
</div>
|
||
<div class="inline-form compact">
|
||
<button id="loadInteractionsBtn" class="btn ghost">Загрузить список</button>
|
||
</div>
|
||
<div id="interactionTable" class="table"></div>
|
||
</article>
|
||
|
||
</section>
|
||
</section>
|
||
|
||
<section id="messagesView" class="operator-view hidden" data-operator-view="messages">
|
||
<article class="panel reveal panel-span-full messenger-panel" id="messengerWorkspace">
|
||
<div class="messenger-layout">
|
||
<aside class="messenger-list-pane">
|
||
<div class="messenger-pane-head">
|
||
<div>
|
||
<p class="eyebrow">Unified messenger</p>
|
||
<h2>Сообщения</h2>
|
||
<p class="hint">Единое окно для Telegram сейчас и WhatsApp позже.</p>
|
||
</div>
|
||
<button id="messengerRefreshBtn" class="btn ghost" type="button">Повторить</button>
|
||
</div>
|
||
<div class="messenger-filters" aria-label="Фильтры сообщений">
|
||
<button class="messenger-filter active" data-messenger-filter="all" type="button">Все</button>
|
||
<button class="messenger-filter" data-messenger-filter="new" type="button">Новые</button>
|
||
<button class="messenger-filter" data-messenger-filter="mine" type="button">Мои</button>
|
||
<button class="messenger-filter" data-messenger-filter="ai" type="button">AI handoff</button>
|
||
</div>
|
||
<div id="messengerConversationList" class="messenger-conversation-list"></div>
|
||
</aside>
|
||
|
||
<section class="messenger-chat-pane">
|
||
<header class="messenger-chat-header">
|
||
<div class="messenger-chat-identity">
|
||
<div id="messengerConversationAvatar" class="telegram-thread-avatar">TG</div>
|
||
<div class="messenger-chat-copy">
|
||
<div id="messengerConversationTitle" class="messenger-chat-title">Выберите диалог</div>
|
||
<div id="messengerConversationMeta" class="messenger-chat-meta">Выберите диалог слева.</div>
|
||
</div>
|
||
</div>
|
||
<div class="messenger-chat-actions">
|
||
<span id="messengerChannelBadge" class="messenger-channel-badge">Telegram</span>
|
||
<button id="messengerClaimBtn" class="btn ghost" type="button">Взять в работу</button>
|
||
<button id="messengerCloseBtn" class="btn ghost" type="button">Закрыть</button>
|
||
</div>
|
||
</header>
|
||
|
||
<section id="messengerAiSummaryCard" class="telegram-ai-summary messenger-ai-summary hidden">
|
||
<div class="telegram-ai-summary-head">
|
||
<div>
|
||
<div class="telegram-ai-summary-title">AI summary</div>
|
||
<div class="telegram-ai-summary-caption">Короткий контекст перед ручным ответом.</div>
|
||
</div>
|
||
<div class="telegram-ai-summary-side">
|
||
<div id="messengerAiSummaryStatus"></div>
|
||
<div id="messengerAiSummaryMeta" class="telegram-ai-summary-meta"></div>
|
||
</div>
|
||
</div>
|
||
<div id="messengerAiSummaryContent" class="telegram-ai-summary-grid"></div>
|
||
</section>
|
||
|
||
<div id="messengerBackendError" class="messenger-error hidden">
|
||
<span>Backend сообщений недоступен.</span>
|
||
<button id="messengerRetryBtn" class="btn ghost" type="button">Повторить</button>
|
||
</div>
|
||
|
||
<div class="messenger-chat-surface">
|
||
<div id="messengerMessagesTimeline" class="telegram-message-timeline messenger-message-timeline"></div>
|
||
</div>
|
||
|
||
<footer class="messenger-composer-wrap">
|
||
<div class="telegram-composer-shell messenger-composer-shell">
|
||
<textarea id="messengerReplyText" placeholder="Написать ответ клиенту..."></textarea>
|
||
<button id="messengerSendReplyBtn" class="telegram-send-btn" type="button" aria-label="Отправить">
|
||
<svg viewBox="0 0 24 24" aria-hidden="true">
|
||
<path d="M21 3 3.9 10.09a1 1 0 0 0 .06 1.87l6.5 2.27 2.27 6.5a1 1 0 0 0 1.87.06L21 3Z" />
|
||
<path d="M10.5 14.5 21 3" />
|
||
</svg>
|
||
</button>
|
||
</div>
|
||
<div id="messengerComposerHint" class="telegram-composer-hint">Ответ доступен после выбора и принятия диалога в работу.</div>
|
||
</footer>
|
||
</section>
|
||
|
||
<aside class="messenger-context-pane">
|
||
<div class="messenger-context-card">
|
||
<p class="eyebrow">Клиент</p>
|
||
<h3 id="messengerContextName">Диалог не выбран</h3>
|
||
<dl class="messenger-context-list">
|
||
<div>
|
||
<dt>Канал</dt>
|
||
<dd id="messengerContextChannel">Telegram</dd>
|
||
</div>
|
||
<div>
|
||
<dt>Статус</dt>
|
||
<dd id="messengerContextStatus">—</dd>
|
||
</div>
|
||
<div>
|
||
<dt>Клиент</dt>
|
||
<dd id="messengerContextCustomer">—</dd>
|
||
</div>
|
||
<div>
|
||
<dt>Обращение</dt>
|
||
<dd id="messengerContextInteraction">—</dd>
|
||
</div>
|
||
</dl>
|
||
<button id="messengerOpenProfileBtn" class="btn" type="button">Открыть профиль</button>
|
||
</div>
|
||
<div class="messenger-context-card compact">
|
||
<p class="eyebrow">Последнее сообщение</p>
|
||
<p id="messengerContextPreview" class="messenger-context-preview">Выберите диалог слева.</p>
|
||
</div>
|
||
<div class="messenger-context-card compact">
|
||
<p class="eyebrow">AI summary</p>
|
||
<p id="messengerContextAiSummary" class="messenger-context-preview">Сводка появится после AI handoff.</p>
|
||
</div>
|
||
<div class="messenger-context-card compact">
|
||
<p class="eyebrow">Быстрые действия</p>
|
||
<button id="messengerContextOpenProfileBtn" class="btn ghost" type="button">Профиль клиента</button>
|
||
</div>
|
||
</aside>
|
||
</div>
|
||
</article>
|
||
</section>
|
||
|
||
<section id="customersView" class="operator-view hidden" data-operator-view="customers">
|
||
<section class="page-hero reveal customers-page-hero">
|
||
<h1>Список лидов</h1>
|
||
<p class="hint">База всех входящих и активных лидов.</p>
|
||
</section>
|
||
|
||
<article class="panel reveal panel-span-full customers-panel" id="customers">
|
||
<div class="customers-toolbar">
|
||
<div class="customers-toolbar-left">
|
||
<div class="customers-search">
|
||
<span class="customers-search-icon">⌕</span>
|
||
<input id="customerQuery" placeholder="Поиск по имени или телефону..." />
|
||
</div>
|
||
</div>
|
||
<div class="customers-toolbar-right">
|
||
<button id="exportCustomersBtn" class="btn ghost" type="button">⇩ Экспорт CSV</button>
|
||
<button id="toggleCustomerLeadFormBtn" class="btn" type="button">+ Добавить лид</button>
|
||
</div>
|
||
</div>
|
||
|
||
<div id="customerLeadForm" class="customer-lead-form hidden">
|
||
<div class="inline-form">
|
||
<input id="customerName" placeholder="Имя контакта" />
|
||
<input id="customerPhone" placeholder="Телефон" />
|
||
<button id="createCustomerBtn" class="btn" type="button">Сохранить лид</button>
|
||
<button id="customerCancelBtn" class="btn ghost" type="button">Отмена</button>
|
||
</div>
|
||
</div>
|
||
|
||
<div id="customerList" class="lead-table-shell"></div>
|
||
|
||
<div class="customers-footer">
|
||
<div id="customerPageSummary" class="customers-summary">Пока нет лидов.</div>
|
||
<div class="customers-pager">
|
||
<button id="customerPrevPageBtn" class="icon-button" type="button" aria-label="Предыдущая страница">‹</button>
|
||
<button id="customerNextPageBtn" class="icon-button" type="button" aria-label="Следующая страница">›</button>
|
||
</div>
|
||
</div>
|
||
</article>
|
||
</section>
|
||
|
||
<section id="customerProfileView" class="operator-view hidden" data-operator-view="customer-profile">
|
||
<section class="page-hero reveal customers-page-hero customer-profile-page-hero">
|
||
<div class="page-hero-actions">
|
||
<button id="customerProfileBackBtn" class="btn ghost" type="button">← К списку клиентов</button>
|
||
</div>
|
||
<h1 id="customerProfileTitle">Профиль клиента</h1>
|
||
<p id="customerProfileHint" class="hint">Единый профиль клиента и вся история его контактов в одном месте.</p>
|
||
</section>
|
||
|
||
<article class="panel reveal panel-span-full customer-profile-page-panel">
|
||
<section id="customerProfileContent" class="customer-spotlight-shell customer-spotlight-page">
|
||
<div class="customer-spotlight-empty">
|
||
<strong>Выберите клиента</strong>
|
||
<p>Откройте карточку из списка клиентов, чтобы увидеть профиль и историю.</p>
|
||
</div>
|
||
</section>
|
||
</article>
|
||
</section>
|
||
|
||
<section id="telegramView" class="operator-view hidden" data-operator-view="telegram">
|
||
<article class="panel reveal panel-span-full telegram-panel" id="telegramWorkspace">
|
||
<div class="telegram-layout">
|
||
<aside class="telegram-threads-pane">
|
||
<div class="telegram-pane-head">
|
||
<button class="telegram-pane-icon-btn" type="button" aria-label="Меню" disabled>
|
||
<svg viewBox="0 0 24 24" aria-hidden="true">
|
||
<path d="M4 7.25h16M4 12h16M4 16.75h16" />
|
||
</svg>
|
||
</button>
|
||
<div class="telegram-thread-search">
|
||
<span class="telegram-thread-search-icon" aria-hidden="true">
|
||
<svg viewBox="0 0 24 24">
|
||
<circle cx="11" cy="11" r="6.5" />
|
||
<path d="m16 16 4.5 4.5" />
|
||
</svg>
|
||
</span>
|
||
<input id="telegramThreadSearch" placeholder="Поиск" />
|
||
</div>
|
||
<button id="loadTelegramThreadsBtn" class="telegram-pane-icon-btn" type="button" aria-label="Обновить">
|
||
<svg viewBox="0 0 24 24" aria-hidden="true">
|
||
<path d="M20 12a8 8 0 1 1-2.34-5.66M20 4v6h-6" />
|
||
</svg>
|
||
</button>
|
||
</div>
|
||
<div id="telegramThreadsList" class="telegram-thread-list"></div>
|
||
</aside>
|
||
|
||
<section class="telegram-chat-pane">
|
||
<header class="telegram-chat-header">
|
||
<div class="telegram-thread-identity">
|
||
<div id="telegramThreadAvatar" class="telegram-thread-avatar">TG</div>
|
||
<div class="telegram-thread-copy">
|
||
<div id="telegramThreadDisplayName" class="telegram-thread-title">Выберите диалог</div>
|
||
<div class="telegram-thread-meta-row">
|
||
<div id="telegramThreadMeta" class="telegram-thread-meta">Выберите диалог слева.</div>
|
||
<span id="telegramThreadAiChip" class="telegram-thread-ai-chip hidden">AI активен</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div class="telegram-chat-actions">
|
||
<button id="telegramHeaderSearchBtn" class="telegram-chat-icon-btn" type="button" aria-label="Поиск">
|
||
<svg viewBox="0 0 24 24" aria-hidden="true">
|
||
<circle cx="11" cy="11" r="6.5" />
|
||
<path d="m16 16 4.5 4.5" />
|
||
</svg>
|
||
</button>
|
||
<button id="telegramHeaderCallBtn" class="telegram-chat-icon-btn" type="button" aria-label="Звонок">
|
||
<svg viewBox="0 0 24 24" aria-hidden="true">
|
||
<path d="M5.5 4.5h3l1.4 3.6-1.7 1.7a15.4 15.4 0 0 0 6 6l1.7-1.7 3.6 1.4v3a1.5 1.5 0 0 1-1.5 1.5A15.5 15.5 0 0 1 4 6A1.5 1.5 0 0 1 5.5 4.5Z" />
|
||
</svg>
|
||
</button>
|
||
<button id="telegramHeaderMenuBtn" class="telegram-chat-icon-btn" type="button" aria-label="Действия">
|
||
<svg viewBox="0 0 24 24" aria-hidden="true">
|
||
<circle cx="12" cy="5" r="1.5" />
|
||
<circle cx="12" cy="12" r="1.5" />
|
||
<circle cx="12" cy="19" r="1.5" />
|
||
</svg>
|
||
</button>
|
||
</div>
|
||
</header>
|
||
|
||
<div id="telegramMessageSearchBar" class="telegram-message-search hidden">
|
||
<div class="telegram-message-search-field">
|
||
<span class="telegram-thread-search-icon" aria-hidden="true">
|
||
<svg viewBox="0 0 24 24">
|
||
<circle cx="11" cy="11" r="6.5" />
|
||
<path d="m16 16 4.5 4.5" />
|
||
</svg>
|
||
</span>
|
||
<input id="telegramMessageSearch" placeholder="Поиск по чату" />
|
||
</div>
|
||
<div id="telegramMessageSearchMeta" class="telegram-message-search-meta">Поиск по текущему чату</div>
|
||
<button id="telegramMessageSearchClearBtn" class="telegram-message-search-clear" type="button">Закрыть</button>
|
||
</div>
|
||
|
||
<div id="telegramOperatorTray" class="telegram-operator-tray hidden">
|
||
<div class="telegram-operator-meta">
|
||
<span id="telegramThreadPresenceChip" class="telegram-operator-chip free">свободен</span>
|
||
<span id="telegramThreadOwnerChip" class="telegram-operator-chip subtle">владелец —</span>
|
||
</div>
|
||
<div class="telegram-operator-controls">
|
||
<button id="telegramClaimThreadBtn" class="telegram-operator-action" type="button">В работу</button>
|
||
<button id="telegramReturnToAiBtn" class="telegram-operator-action subtle" type="button">Вернуть AI</button>
|
||
<button id="telegramCloseThreadBtn" class="telegram-operator-action subtle" type="button">Закрыть</button>
|
||
<input id="telegramEscalationQueue" class="telegram-operator-input" placeholder="line2" />
|
||
<button id="telegramEscalateThreadBtn" class="telegram-operator-action subtle" type="button">Эскалация</button>
|
||
</div>
|
||
</div>
|
||
|
||
<section id="telegramAiSummaryCard" class="telegram-ai-summary hidden">
|
||
<div class="telegram-ai-summary-head">
|
||
<div>
|
||
<div class="telegram-ai-summary-title">Сводка AI</div>
|
||
<div class="telegram-ai-summary-caption">Краткая сводка для оператора перед ручным ответом.</div>
|
||
</div>
|
||
<div class="telegram-ai-summary-side">
|
||
<div id="telegramAiSummaryStatus"></div>
|
||
<div id="telegramAiSummaryMeta" class="telegram-ai-summary-meta"></div>
|
||
</div>
|
||
</div>
|
||
<div id="telegramAiSummaryContent" class="telegram-ai-summary-grid"></div>
|
||
</section>
|
||
|
||
<div class="telegram-chat-surface">
|
||
<div id="telegramMessagesTimeline" class="telegram-message-timeline"></div>
|
||
</div>
|
||
|
||
<footer class="telegram-composer-wrap">
|
||
<div class="telegram-composer-shell">
|
||
<button class="telegram-composer-icon-btn" type="button" aria-label="Вложение" disabled>
|
||
<svg viewBox="0 0 24 24" aria-hidden="true">
|
||
<path d="m9.5 12.5 5.94-5.94a3 3 0 1 1 4.24 4.24l-8.48 8.48a5 5 0 0 1-7.07-7.07l8.13-8.13" />
|
||
</svg>
|
||
</button>
|
||
<textarea id="telegramReplyText" placeholder="Написать сообщение..."></textarea>
|
||
<button class="telegram-composer-icon-btn" type="button" aria-label="Эмодзи">
|
||
<svg viewBox="0 0 24 24" aria-hidden="true">
|
||
<circle cx="12" cy="12" r="9" />
|
||
<path d="M8.5 14.5c.8 1.2 2 2 3.5 2s2.7-.8 3.5-2" />
|
||
<circle cx="9" cy="10" r="1" />
|
||
<circle cx="15" cy="10" r="1" />
|
||
</svg>
|
||
</button>
|
||
<button id="telegramSendReplyBtn" class="telegram-send-btn" type="button" aria-label="Отправить">
|
||
<svg viewBox="0 0 24 24" aria-hidden="true">
|
||
<path d="M21 3 3.9 10.09a1 1 0 0 0 .06 1.87l6.5 2.27 2.27 6.5a1 1 0 0 0 1.87.06L21 3Z" />
|
||
<path d="M10.5 14.5 21 3" />
|
||
</svg>
|
||
</button>
|
||
</div>
|
||
<div id="telegramComposerHint" class="telegram-composer-hint">Ответ доступен после принятия в работу или для admin/supervisor.</div>
|
||
</footer>
|
||
</section>
|
||
</div>
|
||
</article>
|
||
</section>
|
||
|
||
<section id="whatsappView" class="operator-view hidden" data-operator-view="whatsapp" data-feature="whatsapp" hidden>
|
||
<article class="panel reveal panel-span-full whatsapp-panel" id="whatsappWorkspace">
|
||
<div class="whatsapp-shell">
|
||
<aside class="whatsapp-nav-rail" aria-label="WhatsApp navigation">
|
||
<div class="whatsapp-rail-group">
|
||
<button class="whatsapp-rail-btn active" type="button" aria-label="Чаты" data-whatsapp-ui-action="chats">
|
||
<svg viewBox="0 0 24 24" aria-hidden="true">
|
||
<path d="M5.5 6.5h13a2 2 0 0 1 2 2v7a2 2 0 0 1-2 2H10l-4.5 3v-3H5.5a2 2 0 0 1-2-2v-7a2 2 0 0 1 2-2Z" />
|
||
</svg>
|
||
</button>
|
||
<button class="whatsapp-rail-btn" type="button" aria-label="Статус" data-whatsapp-ui-action="status">
|
||
<svg viewBox="0 0 24 24" aria-hidden="true">
|
||
<circle cx="12" cy="12" r="8.25" />
|
||
<path d="M12 7.75v4.5l3 1.75" />
|
||
</svg>
|
||
</button>
|
||
<button class="whatsapp-rail-btn" type="button" aria-label="Channels" data-whatsapp-ui-action="channels">
|
||
<svg viewBox="0 0 24 24" aria-hidden="true">
|
||
<path d="M4.5 8.5a7.5 7.5 0 0 1 15 0" />
|
||
<path d="M7 12a5 5 0 0 1 10 0" />
|
||
<path d="M9.5 15.5a2.5 2.5 0 0 1 5 0" />
|
||
</svg>
|
||
</button>
|
||
</div>
|
||
<div class="whatsapp-rail-footer">
|
||
<button class="whatsapp-rail-btn" type="button" aria-label="Настройки" data-whatsapp-ui-action="settings">
|
||
<svg viewBox="0 0 24 24" aria-hidden="true">
|
||
<path d="M12 8.5a3.5 3.5 0 1 1 0 7 3.5 3.5 0 0 1 0-7Z" />
|
||
<path d="M19.4 13.5a1 1 0 0 0 .2 1.1l.1.1a1 1 0 0 1 0 1.4l-1 1a1 1 0 0 1-1.4 0l-.1-.1a1 1 0 0 0-1.1-.2 1 1 0 0 0-.6.9V19a1 1 0 0 1-1 1h-1.4a1 1 0 0 1-1-1v-.1a1 1 0 0 0-.7-.9 1 1 0 0 0-1 .2l-.1.1a1 1 0 0 1-1.4 0l-1-1a1 1 0 0 1 0-1.4l.1-.1a1 1 0 0 0 .2-1.1 1 1 0 0 0-.9-.6H5a1 1 0 0 1-1-1v-1.4a1 1 0 0 1 1-1h.1a1 1 0 0 0 .9-.7 1 1 0 0 0-.2-1l-.1-.1a1 1 0 0 1 0-1.4l1-1a1 1 0 0 1 1.4 0l.1.1a1 1 0 0 0 1 .2 1 1 0 0 0 .6-.9V5a1 1 0 0 1 1-1h1.4a1 1 0 0 1 1 1v.1a1 1 0 0 0 .7.9 1 1 0 0 0 1.1-.2l.1-.1a1 1 0 0 1 1.4 0l1 1a1 1 0 0 1 0 1.4l-.1.1a1 1 0 0 0-.2 1 1 1 0 0 0 .9.6H19a1 1 0 0 1 1 1v1.4a1 1 0 0 1-1 1h-.1a1 1 0 0 0-.9.7Z" />
|
||
</svg>
|
||
</button>
|
||
<div class="whatsapp-rail-avatar" aria-hidden="true">OP</div>
|
||
</div>
|
||
</aside>
|
||
|
||
<aside class="whatsapp-list-pane">
|
||
<header class="whatsapp-list-head">
|
||
<div class="whatsapp-pane-title-wrap">
|
||
<div class="whatsapp-pane-title">WhatsApp</div>
|
||
<div id="whatsappPaneCaption" class="whatsapp-pane-caption">Держите телефон подключённым</div>
|
||
</div>
|
||
<div class="whatsapp-list-actions">
|
||
<button class="whatsapp-icon-btn" type="button" aria-label="Новый чат" data-whatsapp-ui-action="new-chat">
|
||
<svg viewBox="0 0 24 24" aria-hidden="true">
|
||
<path d="M12 5v14M5 12h14" />
|
||
</svg>
|
||
</button>
|
||
<button class="whatsapp-icon-btn" type="button" aria-label="Меню" data-whatsapp-ui-action="menu">
|
||
<svg viewBox="0 0 24 24" aria-hidden="true">
|
||
<circle cx="12" cy="5" r="1.5" />
|
||
<circle cx="12" cy="12" r="1.5" />
|
||
<circle cx="12" cy="19" r="1.5" />
|
||
</svg>
|
||
</button>
|
||
</div>
|
||
</header>
|
||
|
||
<div class="whatsapp-search-wrap">
|
||
<div class="whatsapp-search-field">
|
||
<span class="whatsapp-search-icon" aria-hidden="true">
|
||
<svg viewBox="0 0 24 24">
|
||
<circle cx="11" cy="11" r="6.5" />
|
||
<path d="m16 16 4.5 4.5" />
|
||
</svg>
|
||
</span>
|
||
<input id="whatsappSearchInput" type="search" placeholder="Поиск или новый чат" />
|
||
</div>
|
||
<div id="whatsappFilterBar" class="whatsapp-filter-bar" role="tablist" aria-label="Фильтры чатов">
|
||
<button class="whatsapp-filter-chip active" type="button" data-whatsapp-filter="all">Все</button>
|
||
<button class="whatsapp-filter-chip" type="button" data-whatsapp-filter="unread">Непрочитанные</button>
|
||
<button class="whatsapp-filter-chip" type="button" data-whatsapp-filter="groups">Группы</button>
|
||
</div>
|
||
</div>
|
||
|
||
<div id="whatsappChatList" class="whatsapp-chat-list"></div>
|
||
</aside>
|
||
|
||
<section class="whatsapp-chat-pane">
|
||
<header class="whatsapp-chat-head">
|
||
<div class="whatsapp-chat-identity">
|
||
<div id="whatsappChatAvatar" class="whatsapp-chat-avatar">WA</div>
|
||
<div class="whatsapp-chat-copy">
|
||
<div id="whatsappChatTitle" class="whatsapp-chat-title">WhatsApp</div>
|
||
<div id="whatsappChatMeta" class="whatsapp-chat-meta">Выберите чат для начала переписки.</div>
|
||
</div>
|
||
</div>
|
||
<div class="whatsapp-chat-actions">
|
||
<button class="whatsapp-icon-btn" type="button" aria-label="Голосовой звонок" data-whatsapp-ui-action="voice-call">
|
||
<svg viewBox="0 0 24 24" aria-hidden="true">
|
||
<path d="M5.5 4.5h3l1.4 3.6-1.7 1.7a15.4 15.4 0 0 0 6 6l1.7-1.7 3.6 1.4v3a1.5 1.5 0 0 1-1.5 1.5A15.5 15.5 0 0 1 4 6 1.5 1.5 0 0 1 5.5 4.5Z" />
|
||
</svg>
|
||
</button>
|
||
<button class="whatsapp-icon-btn" type="button" aria-label="Видеозвонок" data-whatsapp-ui-action="video-call">
|
||
<svg viewBox="0 0 24 24" aria-hidden="true">
|
||
<rect x="3.75" y="6.5" width="10.5" height="11" rx="2.5" />
|
||
<path d="m14.75 10.5 5.5-3v9l-5.5-3" />
|
||
</svg>
|
||
</button>
|
||
<button class="whatsapp-icon-btn" type="button" aria-label="Поиск по чату" data-whatsapp-ui-action="search-chat">
|
||
<svg viewBox="0 0 24 24" aria-hidden="true">
|
||
<circle cx="11" cy="11" r="6.5" />
|
||
<path d="m16 16 4.5 4.5" />
|
||
</svg>
|
||
</button>
|
||
<button class="whatsapp-icon-btn" type="button" aria-label="Меню чата" data-whatsapp-ui-action="chat-menu">
|
||
<svg viewBox="0 0 24 24" aria-hidden="true">
|
||
<circle cx="12" cy="5" r="1.5" />
|
||
<circle cx="12" cy="12" r="1.5" />
|
||
<circle cx="12" cy="19" r="1.5" />
|
||
</svg>
|
||
</button>
|
||
</div>
|
||
</header>
|
||
|
||
<section id="whatsappContextPanel" class="whatsapp-context-panel hidden" aria-live="polite">
|
||
<div class="whatsapp-context-bar">
|
||
<div class="whatsapp-context-pills">
|
||
<span id="whatsappAiStateChip" class="whatsapp-state-chip hidden"></span>
|
||
<span id="whatsappOwnerChip" class="whatsapp-state-chip subtle hidden"></span>
|
||
</div>
|
||
<div class="whatsapp-context-actions">
|
||
<button id="whatsappClaimBtn" class="whatsapp-context-btn" type="button">Взять в работу</button>
|
||
<button id="whatsappReturnToAiBtn" class="whatsapp-context-btn secondary" type="button">Вернуть AI</button>
|
||
</div>
|
||
</div>
|
||
<article id="whatsappAiSummaryCard" class="whatsapp-ai-summary hidden">
|
||
<div class="whatsapp-ai-summary-head">
|
||
<div>
|
||
<div class="whatsapp-ai-summary-kicker">Передача от AI</div>
|
||
<h3>Контекст для оператора</h3>
|
||
</div>
|
||
<div class="whatsapp-ai-summary-side">
|
||
<div id="whatsappAiSummaryStatus"></div>
|
||
<div id="whatsappAiSummaryMeta" class="whatsapp-ai-summary-meta"></div>
|
||
</div>
|
||
</div>
|
||
<div id="whatsappAiSummaryContent" class="whatsapp-ai-summary-grid"></div>
|
||
</article>
|
||
</section>
|
||
|
||
<div class="whatsapp-chat-surface">
|
||
<div id="whatsappMessageTimeline" class="whatsapp-message-timeline"></div>
|
||
</div>
|
||
|
||
<footer class="whatsapp-composer-wrap">
|
||
<div class="whatsapp-composer-shell">
|
||
<button class="whatsapp-composer-btn" type="button" aria-label="Вложение" data-whatsapp-ui-action="attach">
|
||
<svg viewBox="0 0 24 24" aria-hidden="true">
|
||
<path d="m9.5 12.5 5.94-5.94a3 3 0 1 1 4.24 4.24l-8.48 8.48a5 5 0 0 1-7.07-7.07l8.13-8.13" />
|
||
</svg>
|
||
</button>
|
||
<textarea id="whatsappComposerInput" placeholder="Написать сообщение"></textarea>
|
||
<button class="whatsapp-composer-btn" type="button" aria-label="Эмодзи" data-whatsapp-ui-action="emoji">
|
||
<svg viewBox="0 0 24 24" aria-hidden="true">
|
||
<circle cx="12" cy="12" r="9" />
|
||
<path d="M8.5 14.5c.8 1.2 2 2 3.5 2s2.7-.8 3.5-2" />
|
||
<circle cx="9" cy="10" r="1" />
|
||
<circle cx="15" cy="10" r="1" />
|
||
</svg>
|
||
</button>
|
||
<button id="whatsappSendBtn" class="whatsapp-send-btn" type="button" aria-label="Отправить">
|
||
<svg viewBox="0 0 24 24" aria-hidden="true">
|
||
<path d="M21 3 3.9 10.09a1 1 0 0 0 .06 1.87l6.5 2.27 2.27 6.5a1 1 0 0 0 1.87.06L21 3Z" />
|
||
<path d="M10.5 14.5 21 3" />
|
||
</svg>
|
||
</button>
|
||
</div>
|
||
</footer>
|
||
</section>
|
||
</div>
|
||
</article>
|
||
</section>
|
||
|
||
<section id="callsView" class="operator-view hidden" data-operator-view="calls">
|
||
<section class="page-hero reveal customers-page-hero">
|
||
<h1>Звонки</h1>
|
||
<p class="hint">Живые и недавние звонки, AI-handoff и журнал действий в одном месте. Основной take over остаётся во всплывающем окне браузерного телефона.</p>
|
||
</section>
|
||
|
||
<article class="panel reveal panel-span-full technical-panel" id="liveCalls">
|
||
<h2>Мониторинг звонков</h2>
|
||
<p class="hint">Здесь видны текущий статус, недавние вызовы и трассировка действий. Ответ, перевод и завершение звонка остаются во всплывающем окне.</p>
|
||
<div class="inline-form compact">
|
||
<button id="loadLiveCallsBtn" class="btn ghost">Обновить звонки</button>
|
||
<button id="loadLiveCallActionsBtn" class="btn ghost">Действия по звонку</button>
|
||
</div>
|
||
<div class="inline-form compact live-call-inspector">
|
||
<select id="liveCallIdSelect"></select>
|
||
</div>
|
||
<div id="liveCallNameEditor" class="live-call-name-editor hidden">
|
||
<div class="live-call-name-editor-head">
|
||
<div class="live-call-name-editor-title">Исправить имя клиента</div>
|
||
<p id="liveCallNameEditorMeta" class="hint">Выберите звонок, связанный с клиентом, чтобы исправить имя.</p>
|
||
</div>
|
||
<div class="live-call-name-editor-form">
|
||
<input id="liveCallNameInput" type="text" placeholder="Введите имя клиента" />
|
||
<button id="liveCallNameSaveBtn" class="btn" type="button">Сохранить имя</button>
|
||
<button id="liveCallNameCancelBtn" class="btn ghost" type="button">Отмена</button>
|
||
</div>
|
||
<p id="liveCallNameStatus" class="hint"></p>
|
||
</div>
|
||
<p class="hint">Здесь остаются живые и недавние звонки, а оперативные действия по ним вынесены во всплывающее окно.</p>
|
||
<p class="hint" id="liveCallStatusHint">Пока нет активных звонков.</p>
|
||
<div id="liveCallsTable" class="table"></div>
|
||
<details class="details-block">
|
||
<summary>Лог действий по звонку</summary>
|
||
<pre id="liveCallActionsOutput" class="output"></pre>
|
||
</details>
|
||
</article>
|
||
</section>
|
||
</main>
|
||
</section>
|
||
</div>
|
||
|
||
<div id="browserPhoneCallOverlay" class="call-window-overlay hidden" aria-live="polite">
|
||
<div class="call-window">
|
||
<div class="call-window-head">
|
||
<div>
|
||
<div id="browserPhoneCallState" class="call-window-status">Входящий звонок</div>
|
||
<h2 id="browserPhoneCallTitle" class="call-window-title">Неизвестный абонент</h2>
|
||
<p id="browserPhoneIncomingText" class="call-window-meta">SIP-приглашение ещё не поступало.</p>
|
||
<p id="browserPhoneCallMeta" class="call-window-meta subtle">Ждём входящий звонок в браузере.</p>
|
||
</div>
|
||
<button id="browserPhoneCallSettingsBtn" class="icon-button" type="button" aria-label="Настройки телефона">⋯</button>
|
||
</div>
|
||
<div class="call-window-body">
|
||
<div class="call-window-avatar">☎</div>
|
||
<div id="browserPhoneCallTimer" class="call-window-timer">00:00</div>
|
||
<p id="browserPhoneCallWarning" class="call-window-warning hidden"></p>
|
||
</div>
|
||
<div id="browserPhoneAiSummary" class="call-window-ai-summary hidden"></div>
|
||
<div id="browserPhoneNameEditor" class="call-window-name-editor hidden">
|
||
<div class="call-window-name-head">
|
||
<div class="voice-summary-label">Исправить имя клиента</div>
|
||
<p id="browserPhoneNameHint" class="call-window-meta subtle">Имя сохранится в профиле клиента и voice-контуре.</p>
|
||
</div>
|
||
<div class="call-window-name-form">
|
||
<input id="browserPhoneNameInput" type="text" placeholder="Введите имя клиента" />
|
||
<button id="browserPhoneNameSaveBtn" class="btn" type="button">Сохранить имя</button>
|
||
<button id="browserPhoneNameCancelBtn" class="btn ghost" type="button">Отмена</button>
|
||
</div>
|
||
<p id="browserPhoneNameStatus" class="call-window-meta subtle hidden"></p>
|
||
</div>
|
||
<div class="call-window-transfer">
|
||
<select id="browserPhoneTransferTargetType">
|
||
<option value="extension">внутренний номер</option>
|
||
<option value="queue_code">код очереди</option>
|
||
</select>
|
||
<input id="browserPhoneTransferTargetValue" placeholder="2002 или voice_lab" />
|
||
</div>
|
||
<div class="call-window-actions">
|
||
<button id="browserPhoneAnswerBtn" class="btn" type="button">Ответить</button>
|
||
<button id="browserPhoneRejectBtn" class="btn ghost" type="button">Отклонить</button>
|
||
<button id="browserPhoneCallClaimBtn" class="btn ghost" type="button">Принять в работу</button>
|
||
<button id="browserPhoneEditNameBtn" class="btn ghost" type="button">Исправить имя</button>
|
||
<button id="browserPhoneMuteBtn" class="btn ghost" type="button">Выключить микрофон</button>
|
||
<button id="browserPhoneCallTransferBtn" class="btn ghost" type="button">Передать</button>
|
||
<button id="browserPhoneCallHangupBtn" class="btn danger" type="button">Завершить</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<audio id="browserPhoneRemoteAudio" autoplay playsinline></audio>
|
||
|
||
<script src="/operator/assets/access-guards.js?v=track16-voice-transcript1"></script>
|
||
<script src="/operator/assets/sip-0.21.2.min.js?v=track16-voice-transcript1"></script>
|
||
<script src="/operator/assets/app.js?v=track44-messenger-polish1"></script>
|
||
</body>
|
||
</html>
|