mirror of
https://github.com/wasrusgen/wasrusgen1-crm.git
synced 2026-06-03 16:24:47 +00:00
- 15 HTML mockups (admin, assembler, manager, owner и др.) - CLAUDE.md с политикой работы с файлами - .claude/launch.json Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
619 lines
38 KiB
HTML
619 lines
38 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="ru">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
<title>Архитектура платформы @wasrusgen1 CRM</title>
|
||
<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=Inter:wght@400;500;600;700;800;900&family=JetBrains+Mono:wght@400;500;700&display=swap" rel="stylesheet">
|
||
<style>
|
||
:root{
|
||
--bg:#0F0F1A;
|
||
--accent:#3B82F6;
|
||
--accent2:#60A5FA;
|
||
--success:#10B981;
|
||
--warn:#F59E0B;
|
||
--text:#F8FAFC;
|
||
--card:#1A1A2E;
|
||
--muted:#94A3B8;
|
||
--border:rgba(148,163,184,.16);
|
||
--mono:'JetBrains Mono',ui-monospace,SFMono-Regular,Menlo,monospace;
|
||
}
|
||
*{margin:0;padding:0;box-sizing:border-box}
|
||
html,body{height:100%}
|
||
body{
|
||
font-family:'Inter',system-ui,sans-serif;
|
||
background:var(--bg);
|
||
color:var(--text);
|
||
overflow:hidden;
|
||
}
|
||
/* ===== DECK ===== */
|
||
.deck{position:fixed;inset:0}
|
||
.slide{
|
||
position:absolute;inset:0;
|
||
display:flex;flex-direction:column;
|
||
padding:64px 88px 90px;
|
||
opacity:0;visibility:hidden;
|
||
transform:translateY(14px);
|
||
transition:opacity .5s ease,transform .5s ease,visibility .5s;
|
||
overflow:hidden;
|
||
}
|
||
.slide.active{opacity:1;visibility:visible;transform:none;z-index:2}
|
||
/* aspect frame to keep 16:9 readable on any screen */
|
||
.stage{
|
||
position:relative;width:100%;height:100%;
|
||
max-width:1920px;max-height:1080px;margin:auto;
|
||
}
|
||
|
||
/* background glows */
|
||
.slide::before{
|
||
content:"";position:absolute;width:760px;height:760px;border-radius:50%;
|
||
background:radial-gradient(circle,rgba(59,130,246,.16),transparent 62%);
|
||
top:-300px;right:-200px;pointer-events:none;
|
||
}
|
||
.slide::after{
|
||
content:"";position:absolute;width:620px;height:620px;border-radius:50%;
|
||
background:radial-gradient(circle,rgba(16,185,129,.08),transparent 65%);
|
||
bottom:-280px;left:-160px;pointer-events:none;
|
||
}
|
||
|
||
/* ===== TYPO ===== */
|
||
.kicker{
|
||
font-family:var(--mono);font-size:14px;letter-spacing:.28em;text-transform:uppercase;
|
||
color:var(--accent2);margin-bottom:18px;display:flex;align-items:center;gap:12px;
|
||
}
|
||
.kicker::before{content:"";width:30px;height:2px;background:var(--accent);display:inline-block}
|
||
h1{font-size:64px;font-weight:900;line-height:1.04;letter-spacing:-.02em}
|
||
h2{font-size:44px;font-weight:800;line-height:1.08;letter-spacing:-.015em;margin-bottom:10px}
|
||
.sub{color:var(--muted);font-size:20px;font-weight:400;line-height:1.5;max-width:980px}
|
||
.slide-body{flex:1;min-height:0;margin-top:34px;display:flex;flex-direction:column}
|
||
|
||
/* ===== TITLE SLIDE ===== */
|
||
.title-slide{justify-content:center}
|
||
.title-slide h1{font-size:84px;max-width:1300px}
|
||
.title-slide .lede{font-size:30px;color:var(--accent2);font-weight:600;margin-top:26px}
|
||
.brandtag{
|
||
display:inline-flex;align-items:center;gap:14px;
|
||
font-family:var(--mono);font-size:16px;color:var(--muted);
|
||
border:1px solid var(--border);border-radius:100px;padding:12px 22px;margin-bottom:40px;
|
||
background:rgba(26,26,46,.6);width:max-content;
|
||
}
|
||
.dot{width:10px;height:10px;border-radius:50%;background:var(--success);box-shadow:0 0 14px var(--success)}
|
||
.title-meta{
|
||
margin-top:64px;display:flex;gap:64px;flex-wrap:wrap;
|
||
}
|
||
.title-meta div span{display:block;font-family:var(--mono);font-size:13px;color:var(--muted);letter-spacing:.1em;text-transform:uppercase;margin-bottom:6px}
|
||
.title-meta div strong{font-size:24px;font-weight:700}
|
||
|
||
/* ===== CARDS / GRID ===== */
|
||
.grid{display:grid;gap:22px}
|
||
.g2{grid-template-columns:repeat(2,1fr)}
|
||
.g3{grid-template-columns:repeat(3,1fr)}
|
||
.g4{grid-template-columns:repeat(4,1fr)}
|
||
.card{
|
||
background:linear-gradient(160deg,var(--card),rgba(26,26,46,.55));
|
||
border:1px solid var(--border);border-radius:18px;padding:28px 26px;
|
||
position:relative;overflow:hidden;
|
||
}
|
||
.card .ic{
|
||
width:46px;height:46px;border-radius:12px;display:flex;align-items:center;justify-content:center;
|
||
font-size:22px;margin-bottom:16px;background:rgba(59,130,246,.14);border:1px solid rgba(59,130,246,.3);
|
||
}
|
||
.card h3{font-size:21px;font-weight:700;margin-bottom:8px}
|
||
.card p{color:var(--muted);font-size:16px;line-height:1.55}
|
||
.card.accent{border-color:rgba(59,130,246,.45)}
|
||
.card.success .ic{background:rgba(16,185,129,.14);border-color:rgba(16,185,129,.35)}
|
||
.card.warn .ic{background:rgba(245,158,11,.14);border-color:rgba(245,158,11,.35)}
|
||
.tag{font-family:var(--mono);font-size:12px;letter-spacing:.08em;text-transform:uppercase;color:var(--accent2);font-weight:600}
|
||
.pill{display:inline-block;font-family:var(--mono);font-size:13px;padding:4px 12px;border-radius:100px;border:1px solid var(--border);color:var(--muted)}
|
||
.pill.rec{color:var(--success);border-color:rgba(16,185,129,.4);background:rgba(16,185,129,.08)}
|
||
|
||
/* ===== CODE / DIAGRAM BLOCK ===== */
|
||
.codeblock{
|
||
font-family:var(--mono);background:#0A0A12;border:1px solid var(--border);
|
||
border-radius:16px;padding:30px 34px;font-size:18px;line-height:1.85;color:#CBD5E1;
|
||
box-shadow:inset 0 0 0 1px rgba(59,130,246,.05);position:relative;
|
||
}
|
||
.codeblock .winbar{position:absolute;top:14px;left:18px;display:flex;gap:7px}
|
||
.codeblock .winbar i{width:11px;height:11px;border-radius:50%;display:inline-block}
|
||
.codeblock pre{margin-top:14px;white-space:pre;overflow:auto}
|
||
.c-key{color:var(--accent2)} .c-ok{color:var(--success)} .c-warn{color:var(--warn)}
|
||
.c-mut{color:var(--muted)} .c-acc{color:var(--accent);font-weight:700}
|
||
|
||
/* ===== ARCH MAP ===== */
|
||
.archmap{display:flex;flex-direction:column;align-items:center;gap:0;font-family:var(--mono)}
|
||
.node{
|
||
border:1px solid var(--border);border-radius:14px;padding:16px 28px;background:var(--card);
|
||
text-align:center;min-width:300px;
|
||
}
|
||
.node strong{display:block;font-size:20px;font-family:'Inter';font-weight:700}
|
||
.node span{font-size:13px;color:var(--muted)}
|
||
.node.master{border-color:var(--accent);box-shadow:0 0 32px rgba(59,130,246,.25);background:rgba(59,130,246,.08)}
|
||
.node.git{border-color:rgba(96,165,250,.4)}
|
||
.node.vps{border-color:rgba(16,185,129,.4);background:rgba(16,185,129,.05)}
|
||
.arrow{color:var(--accent2);font-size:22px;padding:8px 0;font-family:var(--mono)}
|
||
.arrow small{display:block;font-size:11px;color:var(--muted);letter-spacing:.1em}
|
||
.tenants{display:flex;gap:18px;margin-top:6px}
|
||
.tenant{
|
||
border:1px dashed rgba(16,185,129,.4);border-radius:12px;padding:14px 20px;
|
||
font-family:var(--mono);font-size:14px;text-align:center;background:rgba(16,185,129,.04);
|
||
}
|
||
.tenant b{color:var(--success)} .tenant span{display:block;color:var(--muted);font-size:12px;margin-top:4px}
|
||
|
||
/* ===== TABLE ===== */
|
||
table{width:100%;border-collapse:collapse;font-size:18px}
|
||
th,td{text-align:left;padding:18px 22px;border-bottom:1px solid var(--border)}
|
||
th{font-family:var(--mono);font-size:13px;letter-spacing:.1em;text-transform:uppercase;color:var(--muted);font-weight:600}
|
||
td{color:#E2E8F0}
|
||
tr:last-child td{border-bottom:none}
|
||
td .mono{font-family:var(--mono)}
|
||
.num{font-family:var(--mono);font-weight:700;color:var(--accent2);text-align:right}
|
||
.num.ok{color:var(--success)}
|
||
tbody tr:hover{background:rgba(59,130,246,.05)}
|
||
|
||
/* ===== CHECKLIST ===== */
|
||
.checklist{display:grid;grid-template-columns:1fr 1fr;gap:16px 38px;align-self:stretch}
|
||
.check{
|
||
display:flex;align-items:center;gap:18px;cursor:pointer;user-select:none;
|
||
background:var(--card);border:1px solid var(--border);border-radius:14px;padding:20px 24px;
|
||
transition:.25s;
|
||
}
|
||
.check:hover{border-color:rgba(59,130,246,.4);transform:translateX(3px)}
|
||
.box{
|
||
width:30px;height:30px;border-radius:8px;border:2px solid var(--muted);flex:0 0 auto;
|
||
display:flex;align-items:center;justify-content:center;transition:.2s;font-weight:900;color:transparent;
|
||
}
|
||
.check.done .box{background:var(--success);border-color:var(--success);color:#06281c}
|
||
.check.done .box::after{content:"✓"}
|
||
.check .label{font-size:19px;font-weight:500;transition:.2s}
|
||
.check.done .label{color:var(--muted);text-decoration:line-through}
|
||
.check .mono{font-family:var(--mono);color:var(--accent2);font-size:16px}
|
||
|
||
/* ===== TIMELINE / ROADMAP ===== */
|
||
.timeline{display:flex;align-items:stretch;gap:0;margin-top:30px}
|
||
.phase{flex:1;position:relative;padding:0 14px}
|
||
.phase .ring{
|
||
width:26px;height:26px;border-radius:50%;border:3px solid var(--accent);
|
||
background:var(--bg);margin:0 auto 22px;position:relative;z-index:2;
|
||
}
|
||
.phase.now .ring{background:var(--accent);box-shadow:0 0 22px var(--accent)}
|
||
.phase::before{
|
||
content:"";position:absolute;top:11px;left:-50%;width:100%;height:3px;
|
||
background:var(--border);z-index:1;
|
||
}
|
||
.phase:first-child::before{display:none}
|
||
.phase.now::before,.phase.now ~ .phase::before{background:var(--border)}
|
||
.phase-card{
|
||
background:var(--card);border:1px solid var(--border);border-radius:16px;padding:24px 22px;text-align:center;height:100%;
|
||
}
|
||
.phase.now .phase-card{border-color:var(--accent);background:rgba(59,130,246,.08)}
|
||
.phase .ph-tag{font-family:var(--mono);font-size:12px;letter-spacing:.12em;text-transform:uppercase;color:var(--accent2);margin-bottom:8px}
|
||
.phase h3{font-size:22px;font-weight:700;margin-bottom:10px}
|
||
.phase p{font-size:15px;color:var(--muted);line-height:1.5}
|
||
|
||
/* ===== ER DIAGRAM ===== */
|
||
.er .codeblock{font-size:16px;line-height:1.75}
|
||
|
||
/* generic list */
|
||
.blist{list-style:none;display:flex;flex-direction:column;gap:14px}
|
||
.blist li{display:flex;gap:14px;font-size:19px;line-height:1.5;align-items:flex-start}
|
||
.blist li::before{content:"▸";color:var(--accent);font-weight:900;margin-top:2px}
|
||
.blist li b{color:var(--text)}
|
||
.blist li span{color:var(--muted)}
|
||
|
||
/* steps for lifecycle */
|
||
.steps{display:flex;flex-direction:column;gap:14px}
|
||
.step{display:flex;gap:22px;align-items:center;background:var(--card);border:1px solid var(--border);border-radius:14px;padding:20px 26px}
|
||
.step .no{font-family:var(--mono);font-size:26px;font-weight:700;color:var(--accent);width:46px;flex:0 0 auto}
|
||
.step .txt{flex:1}
|
||
.step .txt b{font-size:20px;font-weight:700;display:block}
|
||
.step .txt span{color:var(--muted);font-size:16px}
|
||
.step .time{font-family:var(--mono);font-size:15px;color:var(--success);background:rgba(16,185,129,.1);border:1px solid rgba(16,185,129,.3);border-radius:100px;padding:7px 16px;white-space:nowrap}
|
||
|
||
/* P&L econ */
|
||
.pl{display:grid;grid-template-columns:1fr 1fr;gap:26px}
|
||
.pl .block{background:var(--card);border:1px solid var(--border);border-radius:16px;padding:30px}
|
||
.pl .block.rev{border-color:rgba(16,185,129,.35)}
|
||
.pl .block.cost{border-color:rgba(245,158,11,.35)}
|
||
.pl .row{display:flex;justify-content:space-between;padding:12px 0;border-bottom:1px dashed var(--border);font-size:18px}
|
||
.pl .row:last-child{border:none}
|
||
.pl .row b{font-family:var(--mono)}
|
||
.be{margin-top:24px;display:flex;gap:24px}
|
||
.be .stat{flex:1;background:linear-gradient(160deg,rgba(59,130,246,.12),rgba(26,26,46,.6));border:1px solid rgba(59,130,246,.35);border-radius:16px;padding:24px 28px}
|
||
.be .stat span{font-family:var(--mono);font-size:13px;letter-spacing:.1em;text-transform:uppercase;color:var(--muted)}
|
||
.be .stat strong{display:block;font-size:38px;font-weight:800;color:var(--accent2);margin-top:6px}
|
||
|
||
/* ===== NAV ===== */
|
||
.nav{position:fixed;bottom:26px;left:50%;transform:translateX(-50%);display:flex;align-items:center;gap:18px;z-index:50}
|
||
.nav button{
|
||
width:46px;height:46px;border-radius:12px;border:1px solid var(--border);background:rgba(26,26,46,.85);
|
||
color:var(--text);font-size:20px;cursor:pointer;transition:.2s;backdrop-filter:blur(8px);
|
||
}
|
||
.nav button:hover{border-color:var(--accent);color:var(--accent2)}
|
||
.nav .counter{font-family:var(--mono);font-size:15px;color:var(--muted);min-width:64px;text-align:center}
|
||
.nav .counter b{color:var(--text)}
|
||
.progress{position:fixed;top:0;left:0;height:3px;background:linear-gradient(90deg,var(--accent),var(--success));z-index:60;transition:width .5s ease;box-shadow:0 0 10px var(--accent)}
|
||
.brandmark{position:fixed;bottom:30px;left:40px;font-family:var(--mono);font-size:13px;color:var(--muted);z-index:50;letter-spacing:.1em}
|
||
.pagenum{position:fixed;bottom:30px;right:40px;font-family:var(--mono);font-size:13px;color:var(--muted);z-index:50}
|
||
|
||
.twocol{display:grid;grid-template-columns:1fr 1fr;gap:48px;align-items:center;height:100%}
|
||
.footnote{margin-top:auto;padding-top:22px;color:var(--muted);font-size:15px;font-family:var(--mono)}
|
||
|
||
@media(max-width:1100px){
|
||
.slide{padding:40px 44px 90px}
|
||
h1{font-size:48px}.title-slide h1{font-size:56px}h2{font-size:34px}
|
||
.g4{grid-template-columns:repeat(2,1fr)}.g3{grid-template-columns:repeat(2,1fr)}
|
||
.checklist{grid-template-columns:1fr}.timeline{flex-direction:column;gap:14px}
|
||
.phase::before{display:none}.twocol{grid-template-columns:1fr;gap:24px}
|
||
}
|
||
</style>
|
||
</head>
|
||
<body>
|
||
<div class="progress" id="progress"></div>
|
||
<div class="deck" id="deck">
|
||
|
||
<!-- 1 TITLE -->
|
||
<section class="slide title-slide active">
|
||
<div class="stage" style="display:flex;flex-direction:column;justify-content:center">
|
||
<div class="brandtag"><span class="dot"></span> @wasrusgen1 CRM · PLATFORM ARCHITECTURE</div>
|
||
<h1>Архитектура платформы<br><span style="color:var(--accent2)">@wasrusgen1 CRM</span></h1>
|
||
<p class="lede">Один продукт — много клиентов. Полный контроль.</p>
|
||
<div class="title-meta">
|
||
<div><span>Документ для</span><strong>Собственника системы</strong></div>
|
||
<div><span>Тема</span><strong>Ввод проекта в работу</strong></div>
|
||
<div><span>Дата</span><strong>2026</strong></div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- 2 SYSTEM MAP -->
|
||
<section class="slide">
|
||
<div class="stage">
|
||
<div class="kicker">Слайд 02 · Big picture</div>
|
||
<h2>Карта системы</h2>
|
||
<p class="sub">Единый код в GitHub разворачивается на VPS. Каждый клиент — отдельный поддомен и отдельная база.</p>
|
||
<div class="slide-body" style="justify-content:center">
|
||
<div class="archmap">
|
||
<div class="node master"><strong>Руслан · Мастер-панель</strong><span>управление всеми проектами</span></div>
|
||
<div class="arrow">↓</div>
|
||
<div class="node git"><strong>GitHub</strong><span>единый исходный код</span></div>
|
||
<div class="arrow">↓ <small>авто-деплой CI/CD</small></div>
|
||
<div class="node vps"><strong>VPS сервер · Nginx + Docker</strong><span>роутинг по поддоменам</span></div>
|
||
<div class="arrow">↓</div>
|
||
<div class="tenants">
|
||
<div class="tenant"><b>salon1.crm.ru</b><span>→ PostgreSQL DB_1</span></div>
|
||
<div class="tenant"><b>salon2.crm.ru</b><span>→ PostgreSQL DB_2</span></div>
|
||
<div class="tenant"><b>salonN.crm.ru</b><span>→ PostgreSQL DB_N</span></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- 3 THREE MODELS -->
|
||
<section class="slide">
|
||
<div class="stage">
|
||
<div class="kicker">Слайд 03 · Стратегия</div>
|
||
<h2>Три модели управления</h2>
|
||
<p class="sub">Как обслуживать множество клиентов на одной кодовой базе.</p>
|
||
<div class="slide-body">
|
||
<div class="grid g3" style="flex:1;align-content:center">
|
||
<div class="card">
|
||
<div class="ic">A</div>
|
||
<h3>Мультитенант</h3>
|
||
<p>Один деплой, одна БД, разделение по <span class="mono" style="color:var(--accent2)">tenant_id</span>. Дёшево в масштабе, но слабая изоляция и риск общего сбоя.</p>
|
||
<div style="margin-top:14px"><span class="pill">сложно стартовать</span></div>
|
||
</div>
|
||
<div class="card success">
|
||
<div class="ic">B</div>
|
||
<h3>Мультидеплой</h3>
|
||
<p>Отдельный контейнер + отдельная БД на клиента. Полная изоляция, простой старт, легко считать расходы по клиенту.</p>
|
||
<div style="margin-top:14px"><span class="pill rec">★ старт здесь</span></div>
|
||
</div>
|
||
<div class="card accent">
|
||
<div class="ic">C</div>
|
||
<h3>Гибрид</h3>
|
||
<p>Общий код и инфра-слой, изолированные БД, общий мониторинг и единое обновление. Баланс цены и изоляции на росте.</p>
|
||
<div style="margin-top:14px"><span class="pill rec">★ цель</span></div>
|
||
</div>
|
||
</div>
|
||
<div class="footnote">Рекомендация: начать с модели <b style="color:var(--success)">B (мультидеплой)</b> → перейти на <b style="color:var(--accent2)">C (гибрид)</b> при 5+ клиентах.</div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- 4 LIFECYCLE -->
|
||
<section class="slide">
|
||
<div class="stage">
|
||
<div class="kicker">Слайд 04 · Процесс</div>
|
||
<h2>Жизненный цикл нового проекта</h2>
|
||
<p class="sub">От подписи договора до запуска — около 3 рабочих дней.</p>
|
||
<div class="slide-body">
|
||
<div class="steps" style="margin:auto 0">
|
||
<div class="step"><div class="no">01</div><div class="txt"><b>Договор с клиентом</b><span>согласование условий, тариф, доступы</span></div><div class="time">1 день</div></div>
|
||
<div class="step"><div class="no">02</div><div class="txt"><b>Настройка инстанса</b><span>создание БД, конфиг, поддомен, деплой</span></div><div class="time">2–4 ч</div></div>
|
||
<div class="step"><div class="no">03</div><div class="txt"><b>Загрузка данных</b><span>салоны, пользователи, справочники</span></div><div class="time">1–2 ч</div></div>
|
||
<div class="step"><div class="no">04</div><div class="txt"><b>Обучение команды</b><span>КД, администраторы, мастера</span></div><div class="time">1–2 дня</div></div>
|
||
<div class="step"><div class="no">05</div><div class="txt"><b>Старт → техподдержка</b><span>пилот, мониторинг, SLA</span></div><div class="time">запуск</div></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- 5 STACK -->
|
||
<section class="slide">
|
||
<div class="stage">
|
||
<div class="kicker">Слайд 05 · Технологии</div>
|
||
<h2>Стек технологий</h2>
|
||
<p class="sub">Проверенные инструменты, без экзотики — быстрый найм и поддержка.</p>
|
||
<div class="slide-body">
|
||
<div class="grid g4" style="flex:1;align-content:center">
|
||
<div class="card"><div class="ic">🖥️</div><h3>Frontend</h3><p>HTML/JS (текущий прототип) → <b style="color:var(--accent2)">React</b> в v2</p></div>
|
||
<div class="card"><div class="ic">⚙️</div><h3>Backend</h3><p>Node.js + Express — REST API, авторизация</p></div>
|
||
<div class="card success"><div class="ic">🗄️</div><h3>База данных</h3><p>PostgreSQL — <b style="color:var(--success)">одна БД на клиента</b></p></div>
|
||
<div class="card"><div class="ic">⚡</div><h3>Кеш / сессии</h3><p>Redis — сессии, очереди, кеш</p></div>
|
||
<div class="card"><div class="ic">📦</div><h3>Файлы</h3><p>S3 / MinIO — фото, документы, экспорты</p></div>
|
||
<div class="card accent"><div class="ic">🚀</div><h3>Деплой</h3><p>Docker Compose + GitHub Actions CI/CD</p></div>
|
||
<div class="card"><div class="ic">☁️</div><h3>Хостинг</h3><p>VPS: Hetzner / Timeweb / Selectel</p></div>
|
||
<div class="card"><div class="ic">🔒</div><h3>Сеть</h3><p>Nginx reverse-proxy + Let's Encrypt HTTPS</p></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- 6 ER DIAGRAM -->
|
||
<section class="slide er">
|
||
<div class="stage">
|
||
<div class="kicker">Слайд 06 · Данные</div>
|
||
<h2>Схема базы данных</h2>
|
||
<p class="sub">8 ключевых сущностей. Каждый клиент получает изолированную копию этой схемы.</p>
|
||
<div class="slide-body" style="justify-content:center">
|
||
<div class="codeblock">
|
||
<div class="winbar"><i style="background:#ff5f57"></i><i style="background:#febc2e"></i><i style="background:#28c840"></i></div>
|
||
<pre><span class="c-mut"># SCHEMA.md — ER-диаграмма (одна БД на клиента)</span>
|
||
|
||
<span class="c-acc">┌────────────┐</span <span class="c-acc">┌────────────┐</span <span class="c-acc">┌────────────┐</span
|
||
<span class="c-acc">│ salons │</span<span class="c-key">──1:N──</span<span class="c-acc">│ users │</span<span class="c-key">──1:N──</span<span class="c-acc">│shiftRequest│</span
|
||
<span class="c-acc">└─────┬──────┘</span <span class="c-acc">└─────┬──────┘</span <span class="c-acc">└────────────┘</span
|
||
<span class="c-key">│ 1:N</span <span class="c-key">│ 1:N</span
|
||
<span class="c-acc">┌─────┴──────┐</span <span class="c-acc">┌─────┴──────┐</span <span class="c-acc">┌────────────┐</span
|
||
<span class="c-acc">│ clients │</span<span class="c-key">──1:N──</span<span class="c-acc">│ orders │</span<span class="c-key">──1:N──</span<span class="c-acc">│ ratings │</span
|
||
<span class="c-acc">└─────┬──────┘</span <span class="c-acc">└─────┬──────┘</span <span class="c-acc">└────────────┘</span
|
||
<span class="c-key">│ 1:N</span <span class="c-key">│ 1:N</span
|
||
<span class="c-acc">┌─────┴──────┐</span <span class="c-acc">┌─────┴──────┐</span
|
||
<span class="c-acc">│appointments│</span<span class="c-key">───────│</span <span class="c-acc">│ requests │</span
|
||
<span class="c-acc">└────────────┘</span <span class="c-acc">└────────────┘</span
|
||
|
||
<span class="c-ok">salons</span> → сеть салонов клиента
|
||
<span class="c-ok">users</span> → сотрудники (КД / админ / мастер)
|
||
<span class="c-ok">clients</span> → клиентская база салона
|
||
<span class="c-ok">orders</span> → сделки / заказы
|
||
<span class="c-ok">appointments</span>→ записи на услуги
|
||
<span class="c-ok">requests</span> → заявки / лиды
|
||
<span class="c-ok">shiftRequests</span>→ заявки на смены сотрудников
|
||
<span class="c-ok">ratings</span> → оценки и обратная связь</pre>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- 7 MASTER PANEL -->
|
||
<section class="slide">
|
||
<div class="stage">
|
||
<div class="kicker">Слайд 07 · Инструмент владельца</div>
|
||
<h2>Мастер-панель Руслана</h2>
|
||
<p class="sub">Что нужно разработать для управления всем парком проектов из одного места.</p>
|
||
<div class="slide-body">
|
||
<div class="grid g2" style="flex:1;align-content:center">
|
||
<div class="card accent"><div class="ic">📋</div><h3>Список проектов</h3><p>Все клиентские инстансы: статус, last activity, число пользователей, тариф.</p></div>
|
||
<div class="card success"><div class="ic">➕</div><h3>Создать новый проект</h3><p>Кнопка «Новый проект» → деплой инстанса в 1 клик (или скриптом).</p></div>
|
||
<div class="card"><div class="ic">📡</div><h3>Мониторинг</h3><p>Uptime, ошибки, нагрузка CPU/RAM, статус БД по каждому клиенту.</p></div>
|
||
<div class="card"><div class="ic">🔄</div><h3>Массовое обновление</h3><p>Выкатить новую версию на все проекты одновременно одной командой.</p></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- 8 CHECKLIST -->
|
||
<section class="slide">
|
||
<div class="stage">
|
||
<div class="kicker">Слайд 08 · Onboarding</div>
|
||
<h2>Как подключить нового клиента</h2>
|
||
<p class="sub">Интерактивный чеклист — кликните по пунктам. <span style="color:var(--accent2)">Прогресс сохраняется в сессии.</span></p>
|
||
<div class="slide-body" style="justify-content:center">
|
||
<div class="checklist" id="checklist">
|
||
<div class="check"><div class="box"></div><div class="label">Подписан договор</div></div>
|
||
<div class="check"><div class="box"></div><div class="label">Получены данные: сеть, салоны, сотрудники</div></div>
|
||
<div class="check"><div class="box"></div><div class="label">Создан поддомен <span class="mono">client-name.wasrusgen1.ru</span></div></div>
|
||
<div class="check"><div class="box"></div><div class="label">Развёрнута БД и заполнены справочники</div></div>
|
||
<div class="check"><div class="box"></div><div class="label">Созданы учётные записи (КД, Администраторы)</div></div>
|
||
<div class="check"><div class="box"></div><div class="label">Проведено обучение команды</div></div>
|
||
<div class="check"><div class="box"></div><div class="label">Запущен пилот</div></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- 9 INFRA COST -->
|
||
<section class="slide">
|
||
<div class="stage">
|
||
<div class="kicker">Слайд 09 · Инфраструктура</div>
|
||
<h2>Инфраструктура и стоимость</h2>
|
||
<p class="sub">Расходы растут вместе с числом клиентов — на старте почти нулевые.</p>
|
||
<div class="slide-body" style="justify-content:center">
|
||
<div class="card" style="padding:8px 16px">
|
||
<table>
|
||
<thead><tr><th>Этап</th><th>Конфигурация</th><th style="text-align:right">$/мес</th></tr></thead>
|
||
<tbody>
|
||
<tr><td><b>Прототип</b> <span style="color:var(--muted)">(сейчас)</span></td><td class="mono">GitHub Pages</td><td class="num ok">$0</td></tr>
|
||
<tr><td><b>Пилот</b> <span style="color:var(--muted)">(1–3 клиента)</span></td><td class="mono">VPS 2CPU / 4GB + Postgres</td><td class="num">~$25–35</td></tr>
|
||
<tr><td><b>Рост</b> <span style="color:var(--muted)">(4–10 клиентов)</span></td><td class="mono">VPS 4CPU / 8GB + backup</td><td class="num">~$50–80</td></tr>
|
||
<tr><td><b>Масштаб</b> <span style="color:var(--muted)">(10+ клиентов)</span></td><td class="mono">2 VPS + балансировщик</td><td class="num">~$120–200</td></tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<div class="footnote">При 8 000 ₽/мес с клиента стоимость инфраструктуры — менее <b style="color:var(--success)">3 %</b> от выручки даже на масштабе.</div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- 10 ECONOMICS -->
|
||
<section class="slide">
|
||
<div class="stage">
|
||
<div class="kicker">Слайд 10 · Экономика</div>
|
||
<h2>Экономика продукта · P&L</h2>
|
||
<p class="sub">Точка безубыточности — первый же клиент. Маржа растёт с каждым следующим.</p>
|
||
<div class="slide-body" style="justify-content:center">
|
||
<div class="pl">
|
||
<div class="block cost">
|
||
<div class="tag" style="color:var(--warn)">— РАСХОДЫ / мес</div>
|
||
<div class="row"><span>Сервер (VPS + Postgres)</span><b>~$35</b></div>
|
||
<div class="row"><span>Поддержка (N часов)</span><b>переменные</b></div>
|
||
<div class="row"><span>Прочее (домены, бэкап)</span><b>~$5</b></div>
|
||
<div class="row" style="color:var(--warn)"><span><b>Итого база</b></span><b>~$40</b></div>
|
||
</div>
|
||
<div class="block rev">
|
||
<div class="tag" style="color:var(--success)">+ ДОХОДЫ / мес</div>
|
||
<div class="row"><span>Тариф на клиента</span><b>8 000 ₽</b></div>
|
||
<div class="row"><span>5 клиентов</span><b>40 000 ₽</b></div>
|
||
<div class="row"><span>10 клиентов</span><b>80 000 ₽</b></div>
|
||
<div class="row" style="color:var(--success)"><span><b>Модель X × 8 000 ₽</b></span><b>растёт линейно</b></div>
|
||
</div>
|
||
</div>
|
||
<div class="be">
|
||
<div class="stat"><span>Break-even</span><strong>1 клиент</strong></div>
|
||
<div class="stat"><span>Целевая маржа</span><strong>85 %+</strong></div>
|
||
<div class="stat"><span>При</span><strong>5+ клиентах</strong></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- 11 ROADMAP -->
|
||
<section class="slide">
|
||
<div class="stage">
|
||
<div class="kicker">Слайд 11 · Roadmap</div>
|
||
<h2>Roadmap продукта</h2>
|
||
<p class="sub">Четыре фазы — от прототипа до AI-функций.</p>
|
||
<div class="slide-body" style="justify-content:center">
|
||
<div class="timeline">
|
||
<div class="phase now">
|
||
<div class="ring"></div>
|
||
<div class="phase-card"><div class="ph-tag">Фаза 1 · сейчас</div><h3>Прототип</h3><p>Готовый интерфейс → первый пилотный клиент.</p></div>
|
||
</div>
|
||
<div class="phase">
|
||
<div class="ring"></div>
|
||
<div class="phase-card"><div class="ph-tag">Фаза 2</div><h3>Бэкенд</h3><p>Node.js + PostgreSQL + авторизация (JWT).</p></div>
|
||
</div>
|
||
<div class="phase">
|
||
<div class="ring"></div>
|
||
<div class="phase-card"><div class="ph-tag">Фаза 3</div><h3>Мобильное (PWA)</h3><p>Установка на телефон, офлайн, push-уведомления.</p></div>
|
||
</div>
|
||
<div class="phase">
|
||
<div class="ring"></div>
|
||
<div class="phase-card"><div class="ph-tag">Фаза 4</div><h3>AI-функции</h3><p>Прогноз сделок, автоматизация рутины, аналитика.</p></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- 12 SECURITY -->
|
||
<section class="slide">
|
||
<div class="stage">
|
||
<div class="kicker">Слайд 12 · Безопасность</div>
|
||
<h2>Безопасность и изоляция данных</h2>
|
||
<p class="sub">Данные каждого клиента физически отделены — утечка одного не затрагивает других.</p>
|
||
<div class="slide-body">
|
||
<div class="grid g3" style="flex:1;align-content:center">
|
||
<div class="card success"><div class="ic">🧱</div><h3>Физическая изоляция</h3><p>Каждый клиент — отдельная БД. Данные не пересекаются на уровне хранилища.</p></div>
|
||
<div class="card"><div class="ic">🔑</div><h3>JWT авторизация</h3><p>Токены доступа, роли и права на уровне API.</p></div>
|
||
<div class="card"><div class="ic">🔐</div><h3>HTTPS везде</h3><p>Let's Encrypt, авто-обновление сертификатов на всех поддоменах.</p></div>
|
||
<div class="card"><div class="ic">💾</div><h3>Бэкапы ежедневно</h3><p>Автоматический бэкап каждой БД, хранение и восстановление.</p></div>
|
||
<div class="card accent"><div class="ic">📤</div><h3>Экспорт данных</h3><p>Клиент может запросить выгрузку своих данных в любой момент.</p></div>
|
||
<div class="card"><div class="ic">📜</div><h3>Соответствие ПДн</h3><p>Хранение в РФ, разграничение доступа, журналирование.</p></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- 13 SLA -->
|
||
<section class="slide">
|
||
<div class="stage">
|
||
<div class="kicker">Слайд 13 · Обязательства</div>
|
||
<h2>SLA и поддержка</h2>
|
||
<p class="sub">Понятные обязательства перед клиентом — основа доверия и удержания.</p>
|
||
<div class="slide-body">
|
||
<div class="grid g4" style="flex:1;align-content:center">
|
||
<div class="card success"><div class="ic">⏱️</div><h3>Uptime</h3><p style="font-size:34px;font-weight:800;color:var(--success);font-family:var(--mono)">99.5 %</p></div>
|
||
<div class="card"><div class="ic">📞</div><h3>Реакция</h3><p style="font-size:34px;font-weight:800;color:var(--accent2);font-family:var(--mono)">4 ч</p><p>в рабочее время</p></div>
|
||
<div class="card"><div class="ic">🔁</div><h3>Обновления</h3><p style="font-size:34px;font-weight:800;color:var(--accent2);font-family:var(--mono)">2 нед</p><p>регулярный цикл</p></div>
|
||
<div class="card accent"><div class="ic">🚀</div><h3>Onboarding</h3><p style="font-size:34px;font-weight:800;color:var(--accent);font-family:var(--mono)">3 дня</p><p>до запуска</p></div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- 14 NEXT STEPS -->
|
||
<section class="slide">
|
||
<div class="stage">
|
||
<div class="kicker">Слайд 14 · План действий</div>
|
||
<h2>Следующие шаги</h2>
|
||
<p class="sub">Конкретный план на 4 недели — от выбора клиента до запуска пилота.</p>
|
||
<div class="slide-body">
|
||
<div class="steps" style="margin:auto 0">
|
||
<div class="step"><div class="no">W1</div><div class="txt"><b>Выбрать первого пилотного клиента</b><span>сеть салонов, готовая дать данные и команду</span></div><div class="time">Неделя 1</div></div>
|
||
<div class="step"><div class="no">W2</div><div class="txt"><b>Развернуть бэкенд на VPS</b><span>Node.js + PostgreSQL + Docker + CI/CD</span></div><div class="time">Неделя 2</div></div>
|
||
<div class="step"><div class="no">W3</div><div class="txt"><b>Перевести прототип на реальные данные</b><span>подключить API, загрузить салоны и пользователей</span></div><div class="time">Неделя 3</div></div>
|
||
<div class="step"><div class="no">W4</div><div class="txt"><b>Запуск пилота с командой клиента</b><span>обучение, мониторинг, сбор обратной связи</span></div><div class="time">Неделя 4</div></div>
|
||
</div>
|
||
<div class="footnote">Готов начать с недели 1 — нужен выбор пилотного клиента.</div>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
</div>
|
||
|
||
<div class="brandmark">@wasrusgen1 · CRM PLATFORM</div>
|
||
<div class="pagenum" id="pagenum">01 / 14</div>
|
||
|
||
<nav class="nav">
|
||
<button id="prev" aria-label="Назад">‹</button>
|
||
<div class="counter"><b id="cur">1</b> / 14</div>
|
||
<button id="next" aria-label="Вперёд">›</button>
|
||
</nav>
|
||
|
||
<script>
|
||
(function(){
|
||
const slides=[...document.querySelectorAll('.slide')];
|
||
let i=0;const total=slides.length;
|
||
const progress=document.getElementById('progress');
|
||
const cur=document.getElementById('cur');
|
||
const pagenum=document.getElementById('pagenum');
|
||
function pad(n){return String(n).padStart(2,'0');}
|
||
function show(n){
|
||
i=Math.max(0,Math.min(total-1,n));
|
||
slides.forEach((s,k)=>s.classList.toggle('active',k===i));
|
||
progress.style.width=((i+1)/total*100)+'%';
|
||
cur.textContent=i+1;
|
||
pagenum.textContent=pad(i+1)+' / '+pad(total);
|
||
}
|
||
document.getElementById('next').onclick=()=>show(i+1);
|
||
document.getElementById('prev').onclick=()=>show(i-1);
|
||
document.addEventListener('keydown',e=>{
|
||
if(['ArrowRight','PageDown',' '].includes(e.key)){e.preventDefault();show(i+1);}
|
||
else if(['ArrowLeft','PageUp'].includes(e.key)){e.preventDefault();show(i-1);}
|
||
else if(e.key==='Home')show(0);
|
||
else if(e.key==='End')show(total-1);
|
||
});
|
||
// interactive checklist
|
||
document.querySelectorAll('#checklist .check').forEach(c=>{
|
||
c.addEventListener('click',()=>c.classList.toggle('done'));
|
||
});
|
||
show(0);
|
||
})();
|
||
</script>
|
||
</body>
|
||
</html>
|