862e6b7b25
Co-authored-by: Cursor <cursoragent@cursor.com>
406 lines
25 KiB
HTML
406 lines
25 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>
|
||
<style>
|
||
:root {
|
||
--bg: #f4f4f5; --card: #fff; --border: #d4d4d8; --text: #18181b; --muted: #71717a;
|
||
--primary: #1d4ed8; --note-bg: #f8fafc;
|
||
}
|
||
* { box-sizing: border-box; }
|
||
body { margin: 0; font-family: "Segoe UI", system-ui, sans-serif; background: var(--bg); color: var(--text); }
|
||
header { background: var(--card); border-bottom: 1px solid var(--border); padding: 14px 20px; position: sticky; top: 0; z-index: 20; }
|
||
header h1 { margin: 0 0 4px; font-size: 1.15rem; }
|
||
header p { margin: 0; color: var(--muted); font-size: 0.85rem; }
|
||
nav { display: flex; flex-wrap: wrap; gap: 6px; padding: 10px 20px; background: var(--card); border-bottom: 1px solid var(--border); position: sticky; top: 54px; z-index: 19; }
|
||
nav button { padding: 7px 12px; border: 1px solid var(--border); border-radius: 5px; background: #fafafa; cursor: pointer; font-size: 0.8rem; }
|
||
nav button.active { background: var(--primary); color: #fff; border-color: var(--primary); }
|
||
main { padding: 16px 20px 40px; }
|
||
section { display: none; }
|
||
section.visible { display: block; }
|
||
.panel { background: var(--card); border: 1px solid var(--border); border-radius: 8px; padding: 16px 18px; margin-bottom: 16px; }
|
||
.panel h2 { margin: 0 0 4px; font-size: 1.05rem; }
|
||
.panel .hint { margin: 0 0 10px; color: var(--muted); font-size: 0.82rem; }
|
||
.legend { display: flex; flex-wrap: wrap; gap: 14px; margin-bottom: 12px; font-size: 0.76rem; color: var(--muted); }
|
||
.legend i { display: inline-block; width: 28px; height: 0; vertical-align: middle; margin-right: 4px; border-top: 2px solid #18181b; }
|
||
.legend .ret i { border-top: 2px dashed #52525b; }
|
||
.legend .fb i { border-top: 2px solid #ea580c; }
|
||
.svg-scroll { overflow-x: auto; border: 1px solid var(--border); border-radius: 6px; background: #fff; }
|
||
svg { display: block; }
|
||
</style>
|
||
</head>
|
||
<body>
|
||
<header>
|
||
<h1>ВКУС — схемы понятным языком</h1>
|
||
<p>Та же логика, что diagrams_viewer.html · без технических терминов на стрелках</p>
|
||
</header>
|
||
<nav>
|
||
<button class="active" data-tab="target">Цель: клиентский путь</button>
|
||
<button data-tab="prototype">Прототип сейчас</button>
|
||
<button data-tab="ai">Как подключается ИИ</button>
|
||
<button data-tab="c4-1">Кто с кем связан</button>
|
||
</nav>
|
||
<main>
|
||
<section id="target" class="visible">
|
||
<div class="panel">
|
||
<h2>Целевой путь: от вопроса до заявки</h2>
|
||
<p class="hint">Как должно работать по клиентскому пути (CJM) · время сверху вниз</p>
|
||
<div class="legend">
|
||
<span><i></i> действие</span>
|
||
<span class="ret"><i></i> ответ (пунктир)</span>
|
||
<span class="fb"><i></i> запасной путь</span>
|
||
</div>
|
||
<div class="svg-scroll" id="seq-target"></div>
|
||
</div>
|
||
</section>
|
||
<section id="prototype">
|
||
<div class="panel">
|
||
<h2>Прототип: как обрабатывается запрос сейчас</h2>
|
||
<p class="hint">Текущая реализация · оранжевые ветки — обход или запасной вариант</p>
|
||
<div class="legend">
|
||
<span><i></i> действие</span>
|
||
<span class="ret"><i></i> ответ (пунктир)</span>
|
||
<span class="fb"><i></i> запасной путь</span>
|
||
</div>
|
||
<div class="svg-scroll" id="seq-prototype"></div>
|
||
</div>
|
||
</section>
|
||
<section id="ai">
|
||
<div class="panel">
|
||
<h2>Интеграции ИИ: поиск и генерация ответа</h2>
|
||
<p class="hint">Как ВКУС обращается к корпоративной платформе ИИ</p>
|
||
<div class="legend">
|
||
<span><i></i> действие</span>
|
||
<span class="ret"><i></i> ответ (пунктир)</span>
|
||
<span class="fb"><i></i> запасной путь</span>
|
||
</div>
|
||
<div class="svg-scroll" id="seq-ai"></div>
|
||
</div>
|
||
</section>
|
||
<section id="c4-1">
|
||
<div class="panel">
|
||
<h2>Общая картина: кто с кем взаимодействует</h2>
|
||
<p class="hint">Контекстная диаграмма (C4 Level 1) · роли систем простым языком</p>
|
||
<div class="svg-scroll" id="c4-context"></div>
|
||
</div>
|
||
</section>
|
||
</main>
|
||
|
||
<script>
|
||
(function () {
|
||
"use strict";
|
||
|
||
var STYLES = {
|
||
actor: { fill: "#fef9c3", stroke: "#ca8a04" },
|
||
core: { fill: "#eff6ff", stroke: "#3b82f6" },
|
||
integ: { fill: "#f0fdf4", stroke: "#16a34a" },
|
||
ext: { fill: "#fef3c7", stroke: "#d97706" },
|
||
fragAlt:{ fill: "rgba(255,247,237,0.92)", stroke: "#ea580c" },
|
||
fragOpt:{ fill: "rgba(248,250,252,0.92)", stroke: "#64748b" },
|
||
};
|
||
|
||
function esc(s) {
|
||
return String(s).replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
||
}
|
||
|
||
function fragRect(f, msgs, xs, y0, rowH) {
|
||
var minP = 999, maxP = -1;
|
||
var extra = f.participants || [];
|
||
extra.forEach(function (p) { minP = Math.min(minP, p); maxP = Math.max(maxP, p); });
|
||
for (var i = f.start; i <= f.end; i++) {
|
||
if (!msgs[i]) continue;
|
||
minP = Math.min(minP, msgs[i].from, msgs[i].to);
|
||
maxP = Math.max(maxP, msgs[i].from, msgs[i].to);
|
||
}
|
||
if (minP > maxP) return null;
|
||
var margin = 62;
|
||
return {
|
||
x: xs[minP] - margin,
|
||
y: y0 + f.start * rowH - 16,
|
||
w: xs[maxP] - xs[minP] + margin * 2,
|
||
h: (f.end - f.start + 1) * rowH + 8,
|
||
};
|
||
}
|
||
|
||
function renderSequence(el, cfg) {
|
||
var uid = cfg.id || "s";
|
||
var parts = cfg.participants;
|
||
var msgs = cfg.messages;
|
||
var colW = cfg.colW || 124;
|
||
var left = 28;
|
||
var top = 62;
|
||
var rowH = cfg.rowH || 40;
|
||
var headH = 52;
|
||
var w = left + 30 + colW * parts.length + 40;
|
||
var h = top + headH + msgs.length * rowH + 50;
|
||
|
||
var xs = parts.map(function (_, i) { return left + 50 + i * colW; });
|
||
var y0 = top + headH;
|
||
|
||
var svg = '<svg xmlns="http://www.w3.org/2000/svg" width="' + w + '" height="' + h + '" viewBox="0 0 ' + w + ' ' + h + '">';
|
||
svg += '<defs>';
|
||
svg += '<marker id="' + uid + '-ar" markerWidth="8" markerHeight="8" refX="7" refY="3" orient="auto"><path d="M0,0 L8,3 L0,6 Z" fill="#18181b"/></marker>';
|
||
svg += '<marker id="' + uid + '-fb" markerWidth="8" markerHeight="8" refX="7" refY="3" orient="auto"><path d="M0,0 L8,3 L0,6 Z" fill="#ea580c"/></marker>';
|
||
svg += '<marker id="' + uid + '-ret" markerWidth="8" markerHeight="8" refX="7" refY="3" orient="auto"><path d="M0,0 L8,3 L0,6 Z" fill="#52525b"/></marker>';
|
||
svg += '</defs>';
|
||
|
||
parts.forEach(function (p, i) {
|
||
var st = STYLES[p.kind] || STYLES.core;
|
||
var x = xs[i];
|
||
var bw = Math.min(colW - 6, p.kind === "actor" ? 80 : 108);
|
||
svg += '<rect x="' + (x - bw / 2) + '" y="10" width="' + bw + '" height="' + headH + '" rx="4" fill="' + st.fill + '" stroke="' + st.stroke + '" stroke-width="1.2"/>';
|
||
(p.label || "").split("\n").forEach(function (ln, li) {
|
||
svg += '<text x="' + x + '" y="' + (28 + li * 13) + '" text-anchor="middle" font-size="10.5" font-weight="600">' + esc(ln) + '</text>';
|
||
});
|
||
if (p.sub) {
|
||
svg += '<text x="' + x + '" y="' + (headH + 2) + '" text-anchor="middle" font-size="8.5" fill="#71717a">' + esc(p.sub) + '</text>';
|
||
}
|
||
svg += '<line x1="' + x + '" y1="' + (10 + headH) + '" x2="' + x + '" y2="' + (h - 16) + '" stroke="#d4d4d8" stroke-width="1" stroke-dasharray="5 4"/>';
|
||
});
|
||
|
||
if (cfg.fragments) {
|
||
cfg.fragments.forEach(function (f) {
|
||
var r = fragRect(f, msgs, xs, y0, rowH);
|
||
if (!r) return;
|
||
var st = f.kind === "opt" ? STYLES.fragOpt : STYLES.fragAlt;
|
||
svg += '<rect x="' + r.x + '" y="' + r.y + '" width="' + r.w + '" height="' + r.h + '" fill="' + st.fill + '" stroke="' + st.stroke + '" stroke-width="1.2" rx="5"/>';
|
||
svg += '<text x="' + (r.x + 8) + '" y="' + (r.y + 15) + '" font-size="9.5" font-weight="700" fill="' + st.stroke + '">' + esc(f.label) + '</text>';
|
||
});
|
||
}
|
||
|
||
msgs.forEach(function (m, idx) {
|
||
var y = y0 + idx * rowH + rowH / 2;
|
||
var fi = m.from, ti = m.to;
|
||
var xFrom = xs[fi], xTo = xs[ti];
|
||
var isRet = m.type === "return";
|
||
var isSelf = fi === ti;
|
||
var isFb = m.fallback;
|
||
var col = isFb ? "#ea580c" : (isRet ? "#52525b" : "#18181b");
|
||
var mk = uid + (isFb ? "-fb" : (isRet ? "-ret" : "-ar"));
|
||
var dash = isRet ? ' stroke-dasharray="7 5"' : "";
|
||
var lines = (m.label || "").split("\n");
|
||
|
||
if (isSelf) {
|
||
var sx = xFrom + 10;
|
||
svg += '<path d="M' + sx + ' ' + y + ' h34 v18 h-34" fill="none" stroke="' + col + '" stroke-width="1.4" marker-end="url(#' + mk + ')"/>';
|
||
lines.forEach(function (ln, li) {
|
||
svg += '<text x="' + (sx + 42) + '" y="' + (y - 4 + li * 12) + '" font-size="9.5" fill="#3f3f46">' + esc(ln) + '</text>';
|
||
});
|
||
} else {
|
||
svg += '<line x1="' + xFrom + '" y1="' + y + '" x2="' + xTo + '" y2="' + y + '" stroke="' + col + '" stroke-width="1.4"' + dash + ' marker-end="url(#' + mk + ')"/>';
|
||
var lx = (xFrom + xTo) / 2;
|
||
var anchor = "middle";
|
||
if (Math.abs(xTo - xFrom) < 90) { lx = Math.max(xFrom, xTo) + 6; anchor = "start"; }
|
||
lines.forEach(function (ln, li) {
|
||
svg += '<text x="' + lx + '" y="' + (y - 8 + li * 12) + '" text-anchor="' + anchor + '" font-size="9.5" fill="#3f3f46">' + esc(ln) + '</text>';
|
||
});
|
||
}
|
||
|
||
if (m.num) {
|
||
svg += '<circle cx="' + (left + 4) + '" cy="' + y + '" r="10" fill="#1d4ed8"/>';
|
||
svg += '<text x="' + (left + 4) + '" y="' + (y + 4) + '" text-anchor="middle" font-size="9" fill="#fff" font-weight="700">' + m.num + '</text>';
|
||
}
|
||
});
|
||
|
||
svg += '</svg>';
|
||
el.innerHTML = svg;
|
||
}
|
||
|
||
// ——— ЦЕЛЕВОЙ CJM ———
|
||
renderSequence(document.getElementById("seq-target"), {
|
||
id: "tgt",
|
||
colW: 118,
|
||
rowH: 42,
|
||
participants: [
|
||
{ label: "Сотрудник", kind: "actor" },
|
||
{ label: "Экран\nВКУС", sub: "витрина", kind: "core" },
|
||
{ label: "Ядро\nсистемы", sub: "оркестратор", kind: "core" },
|
||
{ label: "Понимание\nзапроса", sub: "намерения", kind: "core" },
|
||
{ label: "База\nзнаний", sub: "инструкции", kind: "core" },
|
||
{ label: "Шлюз\nк ИИ", sub: "корп. API", kind: "integ" },
|
||
{ label: "Поиск в\nдокументах", sub: "RAG", kind: "integ" },
|
||
{ label: "Генерация\nтекста", sub: "LLM", kind: "integ" },
|
||
{ label: "Заявки", sub: "Creatio", kind: "ext" },
|
||
],
|
||
fragments: [
|
||
{ label: "не вопрос — ответ без поиска", start: 4, end: 6 },
|
||
{ label: "система не в базе — уточнить", start: 7, end: 9 },
|
||
{ label: "корпоративный поиск по документам", start: 12, end: 15, kind: "opt" },
|
||
{ label: "запасной: только своя база", start: 15, end: 15 },
|
||
{ label: "улучшить ответ с помощью ИИ", start: 16, end: 19, kind: "opt" },
|
||
{ label: "запасной: шаблон без ИИ", start: 20, end: 20 },
|
||
{ label: "помогло — вопрос закрыт", start: 24, end: 26 },
|
||
{ label: "не помогло — заявка в поддержку", start: 27, end: 28 },
|
||
],
|
||
messages: [
|
||
{ num: 1, from: 0, to: 1, label: "Описывает\nзадачу" },
|
||
{ num: 2, from: 1, to: 2, label: "Передаёт\nвопрос" },
|
||
{ num: 3, from: 2, to: 3, label: "Что имел\nв виду?" },
|
||
{ num: 4, from: 2, to: 2, label: "Запоминаем\nсессию" },
|
||
{ num: 5, from: 3, to: 2, label: "Без поиска\n— короткий ответ", type: "return", fallback: true },
|
||
{ num: 6, from: 2, to: 1, label: "Ответ без\nбазы знаний", type: "return" },
|
||
{ num: 7, from: 1, to: 0, label: "Показ\nв чате", type: "return" },
|
||
{ num: 8, from: 2, to: 3, label: "По какой\nИТ-системе?" },
|
||
{ num: 9, from: 3, to: 2, label: "Уточните\nсистему", type: "return", fallback: true },
|
||
{ num: 10, from: 2, to: 1, label: "Сообщение\nсотруднику", type: "return" },
|
||
{ num: 11, from: 2, to: 4, label: "Поиск инструкций\nи истории" },
|
||
{ num: 12, from: 4, to: 4, label: "Сначала\nсвоя база" },
|
||
{ num: 13, from: 4, to: 5, label: "Запрос в\nплатформу ИИ" },
|
||
{ num: 14, from: 5, to: 6, label: "Поиск по смыслу\nв документах" },
|
||
{ num: 15, from: 6, to: 5, label: "Подходящие\nфрагменты", type: "return" },
|
||
{ num: 16, from: 4, to: 4, label: "Запасной:\nтолько своя база", fallback: true },
|
||
{ num: 17, from: 4, to: 5, label: "Собрать\nответ ИИ" },
|
||
{ num: 18, from: 5, to: 7, label: "Формирование\nтекста" },
|
||
{ num: 19, from: 7, to: 5, label: "Текст и\nуверенность", type: "return" },
|
||
{ num: 20, from: 4, to: 2, label: "Запасной:\nшаблон", type: "return", fallback: true },
|
||
{ num: 21, from: 4, to: 2, label: "Найденное +\nчерновик заявки", type: "return" },
|
||
{ num: 22, from: 2, to: 1, label: "Ответ, шаги,\nисточники", type: "return" },
|
||
{ num: 23, from: 1, to: 0, label: "«Помогло» /\n«Не помогло»" },
|
||
{ num: 24, from: 0, to: 1, label: "Помогло" },
|
||
{ num: 25, from: 1, to: 2, label: "Оценка\nрезультата" },
|
||
{ num: 26, from: 2, to: 1, label: "Вопрос закрыт\nбез заявки", type: "return" },
|
||
{ num: 27, from: 2, to: 8, label: "Создание\nзаявки" },
|
||
{ num: 28, from: 8, to: 2, label: "Номер\nи срок", type: "return" },
|
||
{ num: 29, from: 2, to: 1, label: "Номер заявки\nсотруднику", type: "return" },
|
||
],
|
||
});
|
||
|
||
// ——— ПРОТОТИП ———
|
||
renderSequence(document.getElementById("seq-prototype"), {
|
||
id: "proto",
|
||
colW: 128,
|
||
rowH: 42,
|
||
participants: [
|
||
{ label: "Сотрудник", kind: "actor" },
|
||
{ label: "Экран\nчата", sub: "витрина", kind: "core" },
|
||
{ label: "Обработка\nзапроса", sub: "ядро", kind: "core" },
|
||
{ label: "Тип\nреплики", sub: "диалог", kind: "core" },
|
||
{ label: "Проверка\nсистемы", sub: "фильтр", kind: "core" },
|
||
{ label: "Поиск\nинструкций", sub: "база знаний", kind: "core" },
|
||
{ label: "Внешняя\nбаза", sub: "если есть", kind: "integ" },
|
||
{ label: "Прошлые\nобращения", sub: "опыт", kind: "core" },
|
||
{ label: "Ответ\nс ИИ", sub: "улучшение", kind: "integ" },
|
||
],
|
||
fragments: [
|
||
{ label: "не вопрос — ответ без поиска", start: 3, end: 4 },
|
||
{ label: "система не в нашей базе", start: 5, end: 7 },
|
||
{ label: "сначала по смыслу, иначе по словам", start: 9, end: 10 },
|
||
{ label: "доп. поиск снаружи", start: 11, end: 13, kind: "opt" },
|
||
{ label: "похожие случаи коллег", start: 14, end: 15, kind: "opt" },
|
||
{ label: "ИИ или готовый шаблон", start: 17, end: 20 },
|
||
],
|
||
messages: [
|
||
{ num: 1, from: 0, to: 1, label: "Пишет\nвопрос" },
|
||
{ num: 2, from: 1, to: 2, label: "Передаёт\nв систему" },
|
||
{ num: 3, from: 2, to: 3, label: "Что это:\nвопрос или реплика?" },
|
||
{ num: 4, from: 3, to: 2, label: "Без поиска\n(спасибо, смена темы)", type: "return", fallback: true },
|
||
{ num: 5, from: 2, to: 1, label: "Короткий\nответ", type: "return" },
|
||
{ num: 6, from: 2, to: 4, label: "По какой\nИТ-системе?" },
|
||
{ num: 7, from: 4, to: 2, label: "Не поддерживаем\n— уточнить", type: "return", fallback: true },
|
||
{ num: 8, from: 2, to: 1, label: "Просьба назвать\nсистему", type: "return" },
|
||
{ num: 9, from: 2, to: 5, label: "Ищем в\nофициальных материалах" },
|
||
{ num: 10, from: 5, to: 5, label: "Сравниваем\nсмысл текста" },
|
||
{ num: 11, from: 5, to: 5, label: "Запасной путь:\nпо ключевым словам", fallback: true },
|
||
{ num: 12, from: 2, to: 6, label: "Доп. поиск\nво внешней базе" },
|
||
{ num: 13, from: 6, to: 2, label: "Найденные\nфрагменты", type: "return" },
|
||
{ num: 14, from: 2, to: 2, label: "Остаёмся\nна своей базе", fallback: true },
|
||
{ num: 15, from: 2, to: 7, label: "Ищем похожие\nслучаи" },
|
||
{ num: 16, from: 7, to: 2, label: "Опыт коллег\nили пусто", type: "return" },
|
||
{ num: 17, from: 2, to: 2, label: "Решаем:\nответить или заявка" },
|
||
{ num: 18, from: 2, to: 8, label: "Собрать ответ\nс помощью ИИ" },
|
||
{ num: 19, from: 8, to: 2, label: "Готовый\nтекст", type: "return" },
|
||
{ num: 20, from: 8, to: 2, label: "Текст\n(запасной канал)", type: "return", fallback: true },
|
||
{ num: 21, from: 2, to: 2, label: "Ответ\nпо шаблону", fallback: true },
|
||
{ num: 22, from: 2, to: 2, label: "Блок «что помогало»\n+ черновик заявки" },
|
||
{ num: 23, from: 2, to: 1, label: "Ответ\nдля экрана", type: "return" },
|
||
{ num: 24, from: 1, to: 0, label: "Рекомендация\nи похожие случаи", type: "return" },
|
||
],
|
||
});
|
||
|
||
// ——— ИИ ———
|
||
renderSequence(document.getElementById("seq-ai"), {
|
||
id: "ai",
|
||
colW: 148,
|
||
rowH: 44,
|
||
participants: [
|
||
{ label: "Слой знаний\nВКУС", sub: "обработка", kind: "core" },
|
||
{ label: "Корпоративный\nAPI ИИ", sub: "единая точка", kind: "integ" },
|
||
{ label: "Поиск по\nдокументам", sub: "RAG", kind: "integ" },
|
||
{ label: "Языковая\nмодель", sub: "LLM", kind: "integ" },
|
||
{ label: "Заявки\nCreatio", sub: "поддержка", kind: "ext" },
|
||
],
|
||
fragments: [
|
||
{ label: "поиск в документах или запасной путь", start: 1, end: 4 },
|
||
{ label: "генерация ИИ или шаблон", start: 6, end: 9 },
|
||
{ label: "мало уверенности — заявка в поддержку", start: 10, end: 10 },
|
||
],
|
||
messages: [
|
||
{ num: 1, from: 0, to: 1, label: "Найти фрагменты\nпо вопросу" },
|
||
{ num: 2, from: 1, to: 2, label: "Поиск по смыслу\nв базе документов" },
|
||
{ num: 3, from: 2, to: 1, label: "Лучшие\nфрагменты", type: "return" },
|
||
{ num: 4, from: 1, to: 0, label: "Список\nисточников", type: "return" },
|
||
{ num: 5, from: 0, to: 0, label: "Запасной:\nпоиск по словам", fallback: true },
|
||
{ num: 6, from: 0, to: 1, label: "Сформировать\nответ" },
|
||
{ num: 7, from: 1, to: 3, label: "Вопрос +\nнайденные тексты" },
|
||
{ num: 8, from: 3, to: 1, label: "Ответ и\nуверенность", type: "return" },
|
||
{ num: 9, from: 1, to: 0, label: "Готовая\nрекомендация", type: "return" },
|
||
{ num: 10, from: 0, to: 0, label: "Запасной:\nшаблон без ИИ", fallback: true },
|
||
{ num: 11, from: 0, to: 4, label: "Создать заявку\nв поддержку", fallback: true },
|
||
],
|
||
});
|
||
|
||
// ——— C4 Level 1 ———
|
||
document.getElementById("c4-context").innerHTML =
|
||
'<svg xmlns="http://www.w3.org/2000/svg" width="860" height="340" viewBox="0 0 860 340">' +
|
||
'<defs><marker id="c4a" markerWidth="8" markerHeight="8" refX="7" refY="3" orient="auto"><path d="M0,0 L8,3 L0,6 Z" fill="#52525b"/></marker>' +
|
||
'<marker id="c4o" markerWidth="8" markerHeight="8" refX="7" refY="3" orient="auto"><path d="M0,0 L8,3 L0,6 Z" fill="#ea580c"/></marker></defs>' +
|
||
'<rect x="350" y="10" width="160" height="44" rx="4" fill="#fef9c3" stroke="#ca8a04"/>' +
|
||
'<text x="430" y="30" text-anchor="middle" font-size="12" font-weight="600">Пользователи</text>' +
|
||
'<text x="430" y="46" text-anchor="middle" font-size="9" fill="#71717a">сотрудники компании</text>' +
|
||
'<rect x="300" y="72" width="240" height="78" fill="none" stroke="#71717a" stroke-dasharray="5 3"/>' +
|
||
'<text x="312" y="88" font-size="10" fill="#71717a">Портал ВКУС — единая точка входа</text>' +
|
||
'<rect x="315" y="100" width="95" height="42" rx="3" fill="#eff6ff" stroke="#3b82f6"/>' +
|
||
'<text x="362" y="120" text-anchor="middle" font-size="11" font-weight="600">Экран</text>' +
|
||
'<text x="362" y="134" text-anchor="middle" font-size="9" fill="#71717a">чат и формы</text>' +
|
||
'<rect x="430" y="100" width="95" height="42" rx="3" fill="#eff6ff" stroke="#3b82f6"/>' +
|
||
'<text x="477" y="120" text-anchor="middle" font-size="11" font-weight="600">Ядро</text>' +
|
||
'<text x="477" y="134" text-anchor="middle" font-size="9" fill="#71717a">логика ответа</text>' +
|
||
'<line x1="410" y1="121" x2="430" y2="121" stroke="#52525b" marker-end="url(#c4a)"/>' +
|
||
'<text x="420" y="115" text-anchor="middle" font-size="8" fill="#71717a">запрос</text>' +
|
||
'<line x1="430" y1="32" x2="362" y2="100" stroke="#52525b" marker-end="url(#c4a)"/>' +
|
||
'<text x="380" y="72" font-size="8" fill="#71717a">задаёт вопрос</text>' +
|
||
'<rect x="30" y="175" width="390" height="125" fill="none" stroke="#16a34a" stroke-dasharray="5 3"/>' +
|
||
'<text x="42" y="192" font-size="10" fill="#16a34a">Корпоративная платформа ИИ — внешний сервис</text>' +
|
||
'<rect x="48" y="208" width="108" height="44" rx="3" fill="#f0fdf4" stroke="#16a34a"/>' +
|
||
'<text x="102" y="228" text-anchor="middle" font-size="10" font-weight="600">Шлюз ИИ</text>' +
|
||
'<text x="102" y="242" text-anchor="middle" font-size="8.5" fill="#71717a">доступ и безопасность</text>' +
|
||
'<rect x="172" y="208" width="108" height="44" rx="3" fill="#f0fdf4" stroke="#16a34a"/>' +
|
||
'<text x="226" y="228" text-anchor="middle" font-size="10" font-weight="600">Поиск в базе</text>' +
|
||
'<text x="226" y="242" text-anchor="middle" font-size="8.5" fill="#71717a">инструкции, документы</text>' +
|
||
'<rect x="296" y="208" width="108" height="44" rx="3" fill="#f0fdf4" stroke="#16a34a"/>' +
|
||
'<text x="350" y="228" text-anchor="middle" font-size="10" font-weight="600">Генерация</text>' +
|
||
'<text x="350" y="242" text-anchor="middle" font-size="8.5" fill="#71717a">текст ответа</text>' +
|
||
'<line x1="477" y1="142" x2="102" y2="208" stroke="#52525b" marker-end="url(#c4a)"/>' +
|
||
'<text x="280" y="168" font-size="8.5" fill="#71717a">поиск и генерация через платформу</text>' +
|
||
'<rect x="560" y="208" width="120" height="44" rx="3" fill="#fef3c7" stroke="#d97706"/>' +
|
||
'<text x="620" y="228" text-anchor="middle" font-size="10" font-weight="600">Creatio</text>' +
|
||
'<text x="620" y="242" text-anchor="middle" font-size="8.5" fill="#71717a">заявки в поддержку</text>' +
|
||
'<line x1="500" y1="130" x2="560" y2="208" stroke="#ea580c" marker-end="url(#c4o)"/>' +
|
||
'<text x="545" y="168" font-size="8.5" fill="#ea580c">если не помогло — заявка</text>' +
|
||
'</svg>';
|
||
|
||
document.querySelectorAll("nav button").forEach(function (btn) {
|
||
btn.addEventListener("click", function () {
|
||
document.querySelectorAll("nav button").forEach(function (b) { b.classList.remove("active"); });
|
||
document.querySelectorAll("main section").forEach(function (s) { s.classList.remove("visible"); });
|
||
btn.classList.add("active");
|
||
document.getElementById(btn.dataset.tab).classList.add("visible");
|
||
});
|
||
});
|
||
})();
|
||
</script>
|
||
</body>
|
||
</html>
|