mirror of
https://github.com/wasrusgen/wasrusgen1-crm.git
synced 2026-06-03 18:04:45 +00:00
brand(cabinet): пиктограммы по брендбуку (Lucide stroke 1.75) вместо эмодзи
This commit is contained in:
parent
cf98ff1a7e
commit
c003faf931
@ -55,7 +55,7 @@ body{font-family:'Inter',sans-serif;background:var(--bg);color:var(--text);displ
|
||||
.sv{display:none;flex:1;flex-direction:column;overflow:hidden}
|
||||
.sv.active{display:flex}
|
||||
.hero{background:var(--white);border-bottom:1px solid var(--border);padding:18px 26px;display:flex;align-items:center;gap:16px;flex-shrink:0}
|
||||
.hero-ic{width:46px;height:46px;border-radius:12px;background:linear-gradient(135deg,var(--dark),var(--primary));display:flex;align-items:center;justify-content:center;font-size:21px;flex-shrink:0}
|
||||
.hero-ic{width:46px;height:46px;border-radius:12px;background:linear-gradient(135deg,var(--dark),var(--primary));display:flex;align-items:center;justify-content:center;font-size:21px;flex-shrink:0;color:#fff}
|
||||
.hero-tag{font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.05em;color:var(--primary);margin-bottom:3px}
|
||||
.hero-h{font-size:18px;font-weight:700;color:var(--text)}
|
||||
.hero-d{font-size:13px;color:var(--muted);margin-top:2px}
|
||||
@ -229,16 +229,16 @@ body{font-family:'Inter',sans-serif;background:var(--bg);color:var(--text);displ
|
||||
<div class="hdr-client" id="hdrClient"></div>
|
||||
<div class="hdr-r"><div class="elena-chip"><div class="elena-av">Е</div><div class="elena-nm">Елена</div><div class="elena-dot"></div></div></div>
|
||||
</header>
|
||||
<div class="pay-banner" id="payBanner"><span>💳 К оплате: <b id="payAmount"></b></span><button class="pay-btn" onclick="showPayModal()">Оплатить →</button></div>
|
||||
<div class="pay-banner" id="payBanner"><span style="display:inline-flex;align-items:center;gap:7px"><svg width="17" height="17" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.9" stroke-linecap="round" stroke-linejoin="round"><rect x="1" y="4" width="22" height="16" rx="2" ry="2"/><line x1="1" y1="10" x2="23" y2="10"/></svg>К оплате: <b id="payAmount"></b></span><button class="pay-btn" onclick="showPayModal()">Оплатить →</button></div>
|
||||
<div class="modal-bg" id="signModal">
|
||||
<div class="modal" style="max-width:520px">
|
||||
<div class="modal-h">Подписание договора</div>
|
||||
<div class="modal-sub">Для продолжения подпишите документы простой электронной подписью</div>
|
||||
<div style="background:var(--subtle);border:1.5px solid var(--border);border-radius:11px;padding:14px;margin-bottom:16px;font-size:13px;line-height:1.6">
|
||||
Ознакомьтесь с документами:<br>
|
||||
📄 <a href="#" onclick="viewDoc('offer');return false" style="color:var(--primary);font-weight:600">Договор-оферта на консультационные услуги</a><br>
|
||||
📄 <a href="#" onclick="viewDoc('pep');return false" style="color:var(--primary);font-weight:600">Соглашение об использовании ПЭП</a><br>
|
||||
📄 <a href="#" onclick="viewDoc('pdn');return false" style="color:var(--primary);font-weight:600">Политика обработки персональных данных</a>
|
||||
<svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="#047857" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" style="vertical-align:-2px;margin-right:4px"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><polyline points="14 2 14 8 20 8"/></svg><a href="#" onclick="viewDoc('offer');return false" style="color:var(--primary);font-weight:600">Договор-оферта на консультационные услуги</a><br>
|
||||
<svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="#047857" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" style="vertical-align:-2px;margin-right:4px"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><polyline points="14 2 14 8 20 8"/></svg><a href="#" onclick="viewDoc('pep');return false" style="color:var(--primary);font-weight:600">Соглашение об использовании ПЭП</a><br>
|
||||
<svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="#047857" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" style="vertical-align:-2px;margin-right:4px"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><polyline points="14 2 14 8 20 8"/></svg><a href="#" onclick="viewDoc('pdn');return false" style="color:var(--primary);font-weight:600">Политика обработки персональных данных</a>
|
||||
</div>
|
||||
<label style="display:flex;align-items:flex-start;gap:10px;margin-bottom:16px;cursor:pointer">
|
||||
<input type="checkbox" id="signAgree" style="width:18px;height:18px;margin-top:2px;flex-shrink:0">
|
||||
@ -251,7 +251,7 @@ body{font-family:'Inter',sans-serif;background:var(--bg);color:var(--text);displ
|
||||
<div id="signStep2" style="display:none">
|
||||
<div id="signCodeHint" style="font-size:12px;color:var(--primary);background:var(--light);border-radius:8px;padding:8px 12px;margin-bottom:12px"></div>
|
||||
<input id="signCode" placeholder="Код из SMS/email" maxlength="4" style="width:100%;border:1.5px solid var(--border);border-radius:10px;padding:11px 14px;font-size:18px;font-family:Inter;outline:none;margin-bottom:12px;text-align:center;letter-spacing:8px">
|
||||
<button class="btn btn-p" style="width:100%;justify-content:center" onclick="signConfirm()">✓ Подписать договор</button>
|
||||
<button class="btn btn-p" style="width:100%;justify-content:center;gap:7px" onclick="signConfirm()"><svg width="17" height="17" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="20 6 9 17 4 12"/></svg>Подписать договор</button>
|
||||
</div>
|
||||
<button class="modal-close" onclick="document.getElementById('signModal').classList.remove('show')">Отмена</button>
|
||||
</div>
|
||||
@ -267,9 +267,9 @@ body{font-family:'Inter',sans-serif;background:var(--bg);color:var(--text);displ
|
||||
<div class="modal">
|
||||
<div class="modal-h">Оплата консалтинга</div>
|
||||
<div class="modal-sub">Сумма: <b id="modalAmount"></b> · выберите способ</div>
|
||||
<div class="pay-opt" onclick="payVia('card')"><div class="pay-opt-ic">💳</div><div><div class="pay-opt-t">Банковская карта</div><div class="pay-opt-d">Visa, Mastercard, Мир · мгновенно</div></div></div>
|
||||
<div class="pay-opt" onclick="payVia('sbp')"><div class="pay-opt-ic">📱</div><div><div class="pay-opt-t">СБП — по QR-коду</div><div class="pay-opt-d">Перевод через приложение банка</div></div></div>
|
||||
<div class="pay-opt" onclick="payVia('cash')"><div class="pay-opt-ic">💵</div><div><div class="pay-opt-t">Наличными</div><div class="pay-opt-d">При встрече с консультантом</div></div></div>
|
||||
<div class="pay-opt" onclick="payVia('card')"><div class="pay-opt-ic" style="color:#047857"><svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"><rect x="1" y="4" width="22" height="16" rx="2" ry="2"/><line x1="1" y1="10" x2="23" y2="10"/></svg></div><div><div class="pay-opt-t">Банковская карта</div><div class="pay-opt-d">Visa, Mastercard, Мир · мгновенно</div></div></div>
|
||||
<div class="pay-opt" onclick="payVia('sbp')"><div class="pay-opt-ic" style="color:#047857"><svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"><rect x="5" y="2" width="14" height="20" rx="2" ry="2"/><line x1="12" y1="18" x2="12.01" y2="18"/></svg></div><div><div class="pay-opt-t">СБП — по QR-коду</div><div class="pay-opt-d">Перевод через приложение банка</div></div></div>
|
||||
<div class="pay-opt" onclick="payVia('cash')"><div class="pay-opt-ic" style="color:#047857"><svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"><rect x="2" y="6" width="20" height="12" rx="2"/><circle cx="12" cy="12" r="2"/><path d="M6 12h.01M18 12h.01"/></svg></div><div><div class="pay-opt-t">Наличными</div><div class="pay-opt-d">При встрече с консультантом</div></div></div>
|
||||
<button class="modal-close" onclick="document.getElementById('payModal').classList.remove('show')">Отмена</button>
|
||||
</div>
|
||||
</div>
|
||||
@ -277,7 +277,7 @@ body{font-family:'Inter',sans-serif;background:var(--bg);color:var(--text);displ
|
||||
<div class="sb-backdrop" id="sbBackdrop" onclick="toggleSb()"></div>
|
||||
<aside class="sb" id="sbNav">
|
||||
<div class="sb-nav">
|
||||
<div class="si" id="si0" onclick="go(0)" style="margin-bottom:4px"><div class="si-num" style="background:rgba(255,255,255,.1);color:rgba(255,255,255,.7)">👤</div><div class="si-body"><div class="si-name">Профиль компании</div><div class="si-sub">О вашей деятельности</div></div></div>
|
||||
<div class="si" id="si0" onclick="go(0)" style="margin-bottom:4px"><div class="si-num" style="background:rgba(255,255,255,.1);color:rgba(255,255,255,.7)"><svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"><path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"/><circle cx="12" cy="7" r="4"/></svg></div><div class="si-body"><div class="si-name">Профиль компании</div><div class="si-sub">О вашей деятельности</div></div></div>
|
||||
<div style="height:1px;background:rgba(255,255,255,.06);margin:4px 18px 8px"></div>
|
||||
<div class="sb-cap">Путь к результату</div>
|
||||
<div class="si active" id="si1" onclick="go(1)"><div class="si-num">1</div><div class="si-body"><div class="si-lbl">Этап 1</div><div class="si-name">Разговор с Еленой</div><div class="si-sub">Знакомство и диагностика</div></div></div>
|
||||
@ -285,7 +285,7 @@ body{font-family:'Inter',sans-serif;background:var(--bg);color:var(--text);displ
|
||||
<div class="si" id="si4" onclick="go(4)"><div class="si-num">3</div><div class="si-body"><div class="si-lbl">Этап 3</div><div class="si-name">Анализ</div><div class="si-sub">Модель бизнеса</div></div></div>
|
||||
<div class="si" id="si5" onclick="go(5)"><div class="si-num">4</div><div class="si-body"><div class="si-lbl">Этап 4</div><div class="si-name">План</div><div class="si-sub">ТЗ на программу</div></div></div>
|
||||
<div style="height:1px;background:rgba(255,255,255,.06);margin:8px 18px"></div>
|
||||
<div class="si" id="si6" onclick="go(6)"><div class="si-num" style="background:rgba(4,120,87,.25);color:#10B981">💬</div><div class="si-body"><div class="si-name">Консультант</div><div class="si-sub">Связаться с Русланом</div></div></div>
|
||||
<div class="si" id="si6" onclick="go(6)"><div class="si-num" style="background:rgba(4,120,87,.25);color:#10B981"><svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"><path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"/></svg></div><div class="si-body"><div class="si-name">Консультант</div><div class="si-sub">Связаться с Русланом</div></div></div>
|
||||
</div>
|
||||
<div class="sb-foot"><div class="pb-box"><div class="pb-row"><span class="pb-l">Прогресс</span><span class="pb-p" id="pbPct">20%</span></div><div class="pb-track"><div class="pb-fill" id="pbFill" style="width:20%"></div></div></div></div>
|
||||
</aside>
|
||||
@ -293,7 +293,7 @@ body{font-family:'Inter',sans-serif;background:var(--bg);color:var(--text);displ
|
||||
|
||||
<!-- Профиль компании -->
|
||||
<div class="sv" id="sv0">
|
||||
<div class="hero"><div class="hero-ic">👤</div><div><div class="hero-tag">Профиль компании</div><div class="hero-h">Расскажите о вашей деятельности</div><div class="hero-d">Базовая информация — Елена начнёт разговор уже зная контекст</div></div></div>
|
||||
<div class="hero"><div class="hero-ic"><svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"><path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"/><circle cx="12" cy="7" r="4"/></svg></div><div><div class="hero-tag">Профиль компании</div><div class="hero-h">Расскажите о вашей деятельности</div><div class="hero-d">Базовая информация — Елена начнёт разговор уже зная контекст</div></div></div>
|
||||
<div class="scroll"><div class="pad">
|
||||
<div style="max-width:600px">
|
||||
<div style="margin-bottom:18px"><label class="pf-l">Ваше имя или название компании</label><input class="pf-i" id="pfName" placeholder="Например: Игорь / ООО «Автодом»"></div>
|
||||
@ -306,7 +306,7 @@ body{font-family:'Inter',sans-serif;background:var(--bg);color:var(--text);displ
|
||||
|
||||
<!-- Этап 1 — Разговор с Еленой (знакомство + диагностика) -->
|
||||
<div class="sv active" id="sv1">
|
||||
<div class="hero"><div class="hero-ic">💬</div><div><div class="hero-tag">Этап 1 из 4 · В процессе</div><div class="hero-h">Разговор с Еленой</div><div class="hero-d">Расскажите о бизнесе — Елена знакомится и сразу углубляется в детали. Текстом или голосом.</div></div></div>
|
||||
<div class="hero"><div class="hero-ic"><svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"><path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"/></svg></div><div><div class="hero-tag">Этап 1 из 4 · В процессе</div><div class="hero-h">Разговор с Еленой</div><div class="hero-d">Расскажите о бизнесе — Елена знакомится и сразу углубляется в детали. Текстом или голосом.</div></div></div>
|
||||
<div class="scroll"><div class="chat" id="chat"></div></div>
|
||||
<div class="inbar">
|
||||
<textarea class="inp" id="inp" rows="1" placeholder="Напишите или скажите Елене..." onkeydown="if(event.key==='Enter'&&!event.shiftKey){event.preventDefault();sendMsg()}"></textarea>
|
||||
@ -317,10 +317,10 @@ body{font-family:'Inter',sans-serif;background:var(--bg);color:var(--text);displ
|
||||
|
||||
<!-- Этап 3 — Документы -->
|
||||
<div class="sv" id="sv3">
|
||||
<div class="hero"><div class="hero-ic">📁</div><div><div class="hero-tag">Этап 2 из 4</div><div class="hero-h">Документы</div><div class="hero-d">Загрузите материалы — Елена учтёт их в анализе</div></div></div>
|
||||
<div class="hero"><div class="hero-ic"><svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"><path d="M22 19a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5l2 3h9a2 2 0 0 1 2 2z"/></svg></div><div><div class="hero-tag">Этап 2 из 4</div><div class="hero-h">Документы</div><div class="hero-d">Загрузите материалы — Елена учтёт их в анализе</div></div></div>
|
||||
<div class="scroll"><div class="pad">
|
||||
<div class="drop" id="dropZone" onclick="document.getElementById('fileInp').click()">
|
||||
<div class="drop-ic">📎</div>
|
||||
<div class="drop-ic" style="color:#94A3B8"><svg width="28" height="28" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"><path d="M21.44 11.05l-9.19 9.19a6 6 0 0 1-8.49-8.49l9.19-9.19a4 4 0 0 1 5.66 5.66l-9.2 9.19a2 2 0 0 1-2.83-2.83l8.49-8.48"/></svg></div>
|
||||
<div style="font-size:14px;font-weight:600;margin-bottom:4px">Нажмите или перетащите документы</div>
|
||||
<div style="font-size:12px;color:#9ca3af">PDF, Word, Excel, txt · прайс, оргструктура, отчёты</div>
|
||||
<input type="file" id="fileInp" multiple style="display:none" onchange="handleFiles(this.files)">
|
||||
@ -331,19 +331,19 @@ body{font-family:'Inter',sans-serif;background:var(--bg);color:var(--text);displ
|
||||
|
||||
<!-- Этап 4 — Анализ -->
|
||||
<div class="sv" id="sv4">
|
||||
<div class="hero"><div class="hero-ic">🧠</div><div><div class="hero-tag">Этап 3 из 4</div><div class="hero-h">Анализ бизнеса</div><div class="hero-d">Елена строит модель вашего бизнеса</div></div></div>
|
||||
<div class="hero"><div class="hero-ic"><svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"><line x1="18" y1="20" x2="18" y2="10"/><line x1="12" y1="20" x2="12" y2="4"/><line x1="6" y1="20" x2="6" y2="14"/></svg></div><div><div class="hero-tag">Этап 3 из 4</div><div class="hero-h">Анализ бизнеса</div><div class="hero-d">Елена строит модель вашего бизнеса</div></div></div>
|
||||
<div class="scroll"><div class="pad" id="anPad"></div></div>
|
||||
</div>
|
||||
|
||||
<!-- Этап 5 — План -->
|
||||
<div class="sv" id="sv5">
|
||||
<div class="hero"><div class="hero-ic">🚀</div><div><div class="hero-tag">Этап 4 из 4</div><div class="hero-h">План — ТЗ на программу</div><div class="hero-d">Проект системы для вашего бизнеса</div></div></div>
|
||||
<div class="hero"><div class="hero-ic"><svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"><path d="M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2"/><rect x="8" y="2" width="8" height="4" rx="1" ry="1"/></svg></div><div><div class="hero-tag">Этап 4 из 4</div><div class="hero-h">План — ТЗ на программу</div><div class="hero-d">Проект системы для вашего бизнеса</div></div></div>
|
||||
<div class="scroll"><div class="pad" id="specPad"></div></div>
|
||||
</div>
|
||||
|
||||
<!-- Канал «Консультант» (живой) -->
|
||||
<div class="sv" id="sv6">
|
||||
<div class="hero"><div class="hero-ic">💬</div><div style="flex:1"><div class="hero-tag">Личный консультант</div><div class="hero-h">Связаться с Русланом</div><div class="hero-d">Вопросы по проекту, срокам, оплате — напишите напрямую</div></div><button onclick="openIdeas()" style="align-self:center;background:#ECFDF5;color:#047857;border:1.5px solid rgba(4,120,87,.25);border-radius:10px;padding:9px 14px;font-size:13px;font-weight:700;font-family:Inter;cursor:pointer;white-space:nowrap">💡 Мои идеи</button></div>
|
||||
<div class="hero"><div class="hero-ic"><svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"><path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"/></svg></div><div style="flex:1"><div class="hero-tag">Личный консультант</div><div class="hero-h">Связаться с Русланом</div><div class="hero-d">Вопросы по проекту, срокам, оплате — напишите напрямую</div></div><button onclick="openIdeas()" style="align-self:center;background:#ECFDF5;color:#047857;border:1.5px solid rgba(4,120,87,.25);border-radius:10px;padding:9px 14px;font-size:13px;font-weight:700;font-family:Inter;cursor:pointer;white-space:nowrap;display:inline-flex;align-items:center;gap:6px"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round"><path d="M9 18h6"/><path d="M10 22h4"/><path d="M15.09 14c.18-.98.65-1.74 1.41-2.5A4.65 4.65 0 0 0 18 8 6 6 0 0 0 6 8c0 1 .23 2.23 1.5 3.5A4.61 4.61 0 0 1 8.91 14"/></svg> Мои идеи</button></div>
|
||||
<div class="scroll"><div class="chat" id="opChat"></div></div>
|
||||
<div class="inbar">
|
||||
<textarea class="inp" id="opInp" rows="1" placeholder="Напишите консультанту…" onkeydown="if(event.key==='Enter'&&!event.shiftKey){event.preventDefault();opSend()}"></textarea>
|
||||
@ -354,7 +354,7 @@ body{font-family:'Inter',sans-serif;background:var(--bg);color:var(--text);displ
|
||||
|
||||
<!-- Спросить Елену — док на этапах 3-5 -->
|
||||
<div class="askdock" id="askDock">
|
||||
<div class="askdock-head" onclick="toggleAsk()">💬 Спросить Елену <span class="ad-sub" id="adSub">об этом этапе</span><svg class="ad-chev" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round"><polyline points="18 15 12 9 6 15"/></svg></div>
|
||||
<div class="askdock-head" onclick="toggleAsk()"><svg width="17" height="17" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.9" stroke-linecap="round" stroke-linejoin="round" style="margin-right:6px;vertical-align:-3px"><path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"/></svg>Спросить Елену <span class="ad-sub" id="adSub">об этом этапе</span><svg class="ad-chev" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round"><polyline points="18 15 12 9 6 15"/></svg></div>
|
||||
<div class="askdock-body">
|
||||
<div class="askdock-thread" id="askThread"></div>
|
||||
<div class="askdock-inbar">
|
||||
@ -380,6 +380,35 @@ const chat=document.getElementById("chat"), inp=document.getElementById("inp");
|
||||
const PCTS={1:25,3:50,4:75,5:100}; // 4 шага для клиента (Этап 1 объединён)
|
||||
function esc(s){return (s||"").replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">")}
|
||||
function fmt(s){return esc(s).replace(/\*\*(.+?)\*\*/g,"<strong>$1</strong>")}
|
||||
/* ── Иконки по брендбуку: Lucide, stroke 1.75, fill none, round ── */
|
||||
const ICONS={
|
||||
user:'<path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"/><circle cx="12" cy="7" r="4"/>',
|
||||
message:'<path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"/>',
|
||||
folder:'<path d="M22 19a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5l2 3h9a2 2 0 0 1 2 2z"/>',
|
||||
file:'<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><polyline points="14 2 14 8 20 8"/><line x1="16" y1="13" x2="8" y2="13"/><line x1="16" y1="17" x2="8" y2="17"/>',
|
||||
chart:'<line x1="18" y1="20" x2="18" y2="10"/><line x1="12" y1="20" x2="12" y2="4"/><line x1="6" y1="20" x2="6" y2="14"/>',
|
||||
activity:'<polyline points="22 12 18 12 15 21 9 3 6 12 2 12"/>',
|
||||
process:'<circle cx="12" cy="12" r="3"/><path d="M19.07 4.93a10 10 0 0 1 0 14.14M4.93 19.07a10 10 0 0 1 0-14.14"/>',
|
||||
team:'<path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2"/><circle cx="9" cy="7" r="4"/><path d="M23 21v-2a4 4 0 0 0-3-3.87"/><path d="M16 3.13a4 4 0 0 1 0 7.75"/>',
|
||||
clipboard:'<path d="M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2"/><rect x="8" y="2" width="8" height="4" rx="1" ry="1"/>',
|
||||
idea:'<path d="M9 18h6"/><path d="M10 22h4"/><path d="M15.09 14c.18-.98.65-1.74 1.41-2.5A4.65 4.65 0 0 0 18 8 6 6 0 0 0 6 8c0 1 .23 2.23 1.5 3.5A4.61 4.61 0 0 1 8.91 14"/>',
|
||||
paperclip:'<path d="M21.44 11.05l-9.19 9.19a6 6 0 0 1-8.49-8.49l9.19-9.19a4 4 0 0 1 5.66 5.66l-9.2 9.19a2 2 0 0 1-2.83-2.83l8.49-8.48"/>',
|
||||
card:'<rect x="1" y="4" width="22" height="16" rx="2" ry="2"/><line x1="1" y1="10" x2="23" y2="10"/>',
|
||||
phone:'<rect x="5" y="2" width="14" height="20" rx="2" ry="2"/><line x1="12" y1="18" x2="12.01" y2="18"/>',
|
||||
cash:'<rect x="2" y="6" width="20" height="12" rx="2"/><circle cx="12" cy="12" r="2"/><path d="M6 12h.01M18 12h.01"/>',
|
||||
printer:'<polyline points="6 9 6 2 18 2 18 9"/><path d="M6 18H4a2 2 0 0 1-2-2v-5a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2v5a2 2 0 0 1-2 2h-2"/><rect x="6" y="14" width="12" height="8"/>',
|
||||
download:'<path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="7 10 12 15 17 10"/><line x1="12" y1="15" x2="12" y2="3"/>',
|
||||
lock:'<rect x="3" y="11" width="18" height="11" rx="2" ry="2"/><path d="M7 11V7a5 5 0 0 1 10 0v4"/>',
|
||||
calendar:'<rect x="3" y="4" width="18" height="18" rx="2" ry="2"/><line x1="16" y1="2" x2="16" y2="6"/><line x1="8" y1="2" x2="8" y2="6"/><line x1="3" y1="10" x2="21" y2="10"/>',
|
||||
check:'<polyline points="20 6 9 17 4 12"/>',
|
||||
alert:'<path d="M10.29 3.86L1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z"/><line x1="12" y1="9" x2="12" y2="13"/><line x1="12" y1="17" x2="12.01" y2="17"/>',
|
||||
mic:'<path d="M12 1a3 3 0 0 0-3 3v8a3 3 0 0 0 6 0V4a3 3 0 0 0-3-3z"/><path d="M19 10v2a7 7 0 0 1-14 0v-2"/><line x1="12" y1="19" x2="12" y2="23"/><line x1="8" y1="23" x2="16" y2="23"/>',
|
||||
receipt:'<path d="M4 2v20l2-1 2 1 2-1 2 1 2-1 2 1 2-1 2 1V2l-2 1-2-1-2 1-2-1-2 1-2-1-2 1-2-1z"/><path d="M16 8H8M16 12H8M13 16H8"/>',
|
||||
search:'<circle cx="11" cy="11" r="8"/><line x1="21" y1="21" x2="16.65" y2="16.65"/>',
|
||||
target:'<circle cx="12" cy="12" r="10"/><circle cx="12" cy="12" r="6"/><circle cx="12" cy="12" r="2"/>',
|
||||
send:'<line x1="22" y1="2" x2="11" y2="13"/><polygon points="22 2 15 22 11 13 2 9 22 2"/>'
|
||||
};
|
||||
function ic(n,s,sw){s=s||20;return '<svg style="display:inline-block;vertical-align:middle" width="'+s+'" height="'+s+'" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="'+(sw||1.75)+'" stroke-linecap="round" stroke-linejoin="round">'+(ICONS[n]||'')+'</svg>';}
|
||||
|
||||
function toggleSb(){
|
||||
const sb=document.getElementById('sbNav'), bd=document.getElementById('sbBackdrop');
|
||||
@ -471,7 +500,7 @@ function openIdeas(){
|
||||
const list=sgs.length?sgs.map(s=>{const st=SUG_ST[s.status]||SUG_ST.new;return `<div style="border:1px solid var(--border);border-radius:10px;padding:10px 12px;margin-bottom:8px"><div style="font-size:13px">${esc(s.text)}</div><div style="margin-top:6px;display:flex;align-items:center;gap:8px;flex-wrap:wrap"><span style="font-size:11px;font-weight:700;color:${st[2]};background:${st[1]};padding:2px 8px;border-radius:6px">${st[0]}</span>${s.decision?`<span style="font-size:11px;color:#6B7280">— ${esc(s.decision)}</span>`:''}</div></div>`}).join(''):'<div style="font-size:13px;color:#9ca3af;text-align:center;padding:10px">Пока нет. Предложите первую идею — мы рассмотрим её.</div>';
|
||||
const m=document.createElement('div');m.id='ideaModal';m.style.cssText='position:fixed;inset:0;background:rgba(15,15,26,.5);z-index:260;display:flex;align-items:center;justify-content:center;padding:18px';m.onclick=()=>m.remove();
|
||||
m.innerHTML=`<div onclick="event.stopPropagation()" style="background:#fff;border-radius:16px;padding:22px;width:100%;max-width:420px;max-height:84vh;display:flex;flex-direction:column">
|
||||
<div style="font-size:18px;font-weight:800;font-family:Montserrat,Inter;margin-bottom:4px">💡 Мои предложения</div>
|
||||
<div style="font-size:18px;font-weight:800;font-family:Montserrat,Inter;margin-bottom:4px;display:flex;align-items:center;gap:8px">${ic('idea',20)} Мои предложения</div>
|
||||
<div style="font-size:12px;color:#6B7280;margin-bottom:12px">Ваши идеи по проекту. Консультант рассмотрит каждую и ответит решением.</div>
|
||||
<div style="overflow-y:auto;flex:1;margin-bottom:12px">${list}</div>
|
||||
<textarea id="ideaInp" rows="2" placeholder="Опишите идею или улучшение…" style="width:100%;border:1.5px solid var(--border);border-radius:10px;padding:10px 12px;font-size:13px;font-family:Inter;resize:vertical;outline:none;box-sizing:border-box"></textarea>
|
||||
@ -557,7 +586,7 @@ function fillProfile(){
|
||||
function renderDocs(){
|
||||
const dl=document.getElementById("docList");if(!dl)return;
|
||||
const docs=state.documents||[];
|
||||
dl.innerHTML=docs.length?docs.map(d=>{const u=`${API}/api/doc?token=${encodeURIComponent(token)}&name=${encodeURIComponent(d.filename)}`;return `<div style="display:flex;align-items:center;gap:10px;background:var(--white);border:1px solid var(--border);border-radius:10px;padding:11px 14px;margin-bottom:8px"><span style="font-size:18px">📄</span><div style="flex:1;min-width:0"><a href="${u}" target="_blank" rel="noopener" style="font-size:13px;font-weight:600;color:var(--primary);text-decoration:none">${esc(d.filename)}</a><div style="font-size:11px;color:#9ca3af">${(d.size/1024).toFixed(0)} КБ · учтён в анализе</div></div><a href="${u}&dl=1" title="Скачать" style="color:#9ca3af;text-decoration:none;font-size:16px">⬇</a></div>`}).join(""):'<div style="text-align:center;color:#cbd5e1;font-size:13px;padding:10px">Документов пока нет</div>';
|
||||
dl.innerHTML=docs.length?docs.map(d=>{const u=`${API}/api/doc?token=${encodeURIComponent(token)}&name=${encodeURIComponent(d.filename)}`;return `<div style="display:flex;align-items:center;gap:10px;background:var(--white);border:1px solid var(--border);border-radius:10px;padding:11px 14px;margin-bottom:8px"><span style="color:#047857;display:inline-flex">${ic('file',18)}</span><div style="flex:1;min-width:0"><a href="${u}" target="_blank" rel="noopener" style="font-size:13px;font-weight:600;color:var(--primary);text-decoration:none">${esc(d.filename)}</a><div style="font-size:11px;color:#9ca3af">${(d.size/1024).toFixed(0)} КБ · учтён в анализе</div></div><a href="${u}&dl=1" title="Скачать" style="color:#9ca3af;text-decoration:none;display:inline-flex">${ic('download',16)}</a></div>`}).join(""):'<div style="text-align:center;color:#cbd5e1;font-size:13px;padding:10px">Документов пока нет</div>';
|
||||
}
|
||||
async function handleFiles(files){
|
||||
const dl=document.getElementById("docList");
|
||||
@ -665,29 +694,29 @@ async function sendMsg(){
|
||||
let anTab="canvas";
|
||||
function renderAnalysis(){
|
||||
const pad=document.getElementById("anPad");
|
||||
pad.innerHTML=`<div class="an-tabs"><div class="an-tab ${anTab==='canvas'?'active':''}" onclick="setAnTab('canvas')">📊 Стратегия</div><div class="an-tab ${anTab==='idef0'?'active':''}" onclick="setAnTab('idef0')">🔧 Функции</div><div class="an-tab ${anTab==='org'?'active':''}" onclick="setAnTab('org')">🏢 Организация</div></div><div id="anContent"></div>`;
|
||||
pad.innerHTML=`<div class="an-tabs"><div class="an-tab ${anTab==='canvas'?'active':''}" onclick="setAnTab('canvas')">${ic('chart',16)} Стратегия</div><div class="an-tab ${anTab==='idef0'?'active':''}" onclick="setAnTab('idef0')">${ic('process',16)} Функции</div><div class="an-tab ${anTab==='org'?'active':''}" onclick="setAnTab('org')">${ic('team',16)} Организация</div></div><div id="anContent"></div>`;
|
||||
renderAnContent();
|
||||
}
|
||||
function setAnTab(t){anTab=t;renderAnalysis()}
|
||||
function renderAnContent(){
|
||||
const c=document.getElementById("anContent");
|
||||
if(anTab==='canvas'){
|
||||
if(!state.canvas){c.innerHTML=runCard("canvas","📊","Стратегическая модель","Елена построит Business Model Canvas — как устроен ваш бизнес и как он зарабатывает.","Построить стратегию →");return}
|
||||
if(!state.canvas){c.innerHTML=runCard("canvas",ic('chart',30),"Стратегическая модель","Елена построит Business Model Canvas — как устроен ваш бизнес и как он зарабатывает.","Построить стратегию →");return}
|
||||
c.innerHTML=renderCanvas(state.canvas);
|
||||
}else if(anTab==='idef0'){
|
||||
if(!state.model){c.innerHTML=runCard("model","🔧","Функциональная модель","Елена разложит бизнес на функции (IDEF0): входы, выходы, нормы, ресурсы и разрывы.","Построить модель →");return}
|
||||
if(!state.model){c.innerHTML=runCard("model",ic('process',30),"Функциональная модель","Елена разложит бизнес на функции (IDEF0): входы, выходы, нормы, ресурсы и разрывы.","Построить модель →");return}
|
||||
c.innerHTML=renderIdef(state.model);
|
||||
}else{
|
||||
c.innerHTML=renderOrg();
|
||||
}
|
||||
}
|
||||
function renderOrg(){
|
||||
if(!state.model)return runCard(null,"⚠️","Сначала функции","Оргструктура строится из функциональной модели. Постройте модель на вкладке «Функции».","→ К функциям",()=>setAnTab('idef0'));
|
||||
if(!state.model)return runCard(null,ic('alert',30),"Сначала функции","Оргструктура строится из функциональной модели. Постройте модель на вкладке «Функции».","→ К функциям",()=>setAnTab('idef0'));
|
||||
let h='';
|
||||
if(!state.orgchart)h+=runCard("orgchart","🏢","Целевая оргструктура","Елена построит оргструктуру из модели: кто за что отвечает, подчинённость, штат, узкие места.","Построить оргструктуру →");
|
||||
if(!state.orgchart)h+=runCard("orgchart",ic('team',30),"Целевая оргструктура","Елена построит оргструктуру из модели: кто за что отвечает, подчинённость, штат, узкие места.","Построить оргструктуру →");
|
||||
else h+=renderOrgChart(state.orgchart);
|
||||
if(state.orgchart){
|
||||
if(!state.jobs)h+=`<div style="height:14px"></div>`+runCard("jobs","📋","Должностные инструкции","По ролям: зоны ответственности, KPI, полномочия. С учётом ваших пожеланий (отклонений).","Собрать инструкции →");
|
||||
if(!state.jobs)h+=`<div style="height:14px"></div>`+runCard("jobs",ic('clipboard',30),"Должностные инструкции","По ролям: зоны ответственности, KPI, полномочия. С учётом ваших пожеланий (отклонений).","Собрать инструкции →");
|
||||
else h+=`<div style="height:14px"></div>`+renderJobs(state.jobs);
|
||||
}
|
||||
return h;
|
||||
@ -708,7 +737,7 @@ function renderOrgChart(o){
|
||||
}
|
||||
function renderJobs(j){
|
||||
const roles=j.roles||[];
|
||||
return `<div style="font-size:13px;font-weight:800;margin-bottom:10px">📋 Должностные инструкции</div>`+roles.map(r=>`<div style="background:var(--white);border:1px solid var(--border);border-radius:11px;padding:14px 16px;margin-bottom:10px">
|
||||
return `<div style="font-size:13px;font-weight:800;margin-bottom:10px;display:flex;align-items:center;gap:7px">${ic('clipboard',17)} Должностные инструкции</div>`+roles.map(r=>`<div style="background:var(--white);border:1px solid var(--border);border-radius:11px;padding:14px 16px;margin-bottom:10px">
|
||||
<div style="font-size:14px;font-weight:800">${esc(r.role||'')}</div>
|
||||
<div style="font-size:12px;color:#6b7280;margin:3px 0 9px">${esc(r.purpose||'')}${r.reports_to?` · ↑ ${esc(r.reports_to)}`:''}</div>
|
||||
${(r.responsibilities&&r.responsibilities.length)?`<div style="font-size:11px;font-weight:700;color:#374151;margin-bottom:3px">Зоны ответственности</div><ul style="margin:0 0 9px;padding-left:18px;font-size:12px;color:#4B5563">${r.responsibilities.map(x=>`<li>${esc(x)}</li>`).join('')}</ul>`:''}
|
||||
@ -720,17 +749,17 @@ function renderJobs(j){
|
||||
function renderSpecPane(){
|
||||
const pad=document.getElementById("specPad");
|
||||
if(!state.spec){
|
||||
if(!state.model){pad.innerHTML=runCard(null,"⚠️","Сначала Анализ","ТЗ собирается из функциональной модели. Перейдите на Этап 4 и постройте модель.","← К анализу",()=>go(4));return}
|
||||
pad.innerHTML=runCard("spec","📋","Техническое задание","Из модели бизнеса Елена спроектирует программу: роли, модули, экраны, данные.","Собрать ТЗ →");return}
|
||||
if(!state.model){pad.innerHTML=runCard(null,ic('alert',30),"Сначала Анализ","ТЗ собирается из функциональной модели. Перейдите на Этап 4 и постройте модель.","← К анализу",()=>go(4));return}
|
||||
pad.innerHTML=runCard("spec",ic('clipboard',30),"Техническое задание","Из модели бизнеса Елена спроектирует программу: роли, модули, экраны, данные.","Собрать ТЗ →");return}
|
||||
pad.innerHTML=renderSpec(state.spec)+renderExportBar();
|
||||
}
|
||||
const EST_STAGES=[
|
||||
{key:"interview", name:"Интервью", icon:"💬", desc:"Диагностика «как есть» — карта проблем"},
|
||||
{key:"methods", name:"Методологии", icon:"🎯", desc:"Подбор фреймворков под вашу задачу"},
|
||||
{key:"canvas", name:"Стратегия", icon:"📊", desc:"Целевая модель процессов (TO-BE)"},
|
||||
{key:"idef0", name:"Функции IDEF0", icon:"🔧", desc:"Декомпозиция функций + регламенты"},
|
||||
{key:"org", name:"Организация", icon:"🏢", desc:"Оргструктура + должностные инструкции"},
|
||||
{key:"spec", name:"Выдача ТЗ", icon:"📋", desc:"Готовое ТЗ к внедрению"},
|
||||
{key:"interview", name:"Интервью", icon:ic('message',15), desc:"Диагностика «как есть» — карта проблем"},
|
||||
{key:"methods", name:"Методологии", icon:ic('target',15), desc:"Подбор фреймворков под вашу задачу"},
|
||||
{key:"canvas", name:"Стратегия", icon:ic('chart',15), desc:"Целевая модель процессов (TO-BE)"},
|
||||
{key:"idef0", name:"Функции IDEF0", icon:ic('process',15), desc:"Декомпозиция функций + регламенты"},
|
||||
{key:"org", name:"Организация", icon:ic('team',15), desc:"Оргструктура + должностные инструкции"},
|
||||
{key:"spec", name:"Выдача ТЗ", icon:ic('clipboard',15), desc:"Готовое ТЗ к внедрению"},
|
||||
];
|
||||
function estStageDone(k){
|
||||
if(k==="interview")return (state.messages||[]).length>0;
|
||||
@ -751,7 +780,7 @@ function renderEstimateCard(){
|
||||
const total=Object.values(sp).reduce((a,b)=>a+(+b||0),0);
|
||||
const paid=Object.values(pays).reduce((s,p)=>s+(p.amount||0),0);
|
||||
return `<div class="exp-bar" style="margin-bottom:14px">
|
||||
<div class="exp-h">🧾 Смета проекта</div>
|
||||
<div class="exp-h" style="display:flex;align-items:center;gap:7px">${ic('receipt',18)} Смета проекта</div>
|
||||
<div class="exp-d" style="margin-bottom:10px">Прозрачно: за что и сколько. Интервью — бесплатно, дальше помодульно. Готовое ТЗ — после полной оплаты.</div>
|
||||
${EST_STAGES.map(s=>{
|
||||
const price=+sp[s.key]||0, isFree=price<=0, isPaid=!!pays[s.key], done=estStageDone(s.key);
|
||||
@ -780,15 +809,15 @@ function renderExportBar(){
|
||||
return renderEstimateCard()+`<div class="exp-bar"><div class="exp-h">📦 Готовые документы</div>
|
||||
<div class="exp-d">Долг закрыт — документы и ТЗ доступны для печати и выгрузки.</div>
|
||||
<div class="exp-btns">
|
||||
<button class="btn btn-p" onclick="printDoc()">🖨 Печать / PDF</button>
|
||||
<button class="btn btn-s" onclick="downloadTZ()">⬇ Скачать ТЗ</button>
|
||||
<button class="btn btn-p" onclick="printDoc()">${ic('printer',16)} Печать / PDF</button>
|
||||
<button class="btn btn-s" onclick="downloadTZ()">${ic('download',16)} Скачать ТЗ</button>
|
||||
<button class="btn btn-s" onclick="exportDev()">{ } Выгрузить для разработчика</button>
|
||||
</div></div>`;
|
||||
}
|
||||
const debt=state.debt||0, deal=state.deal_amount||0;
|
||||
const moneyStr=deal>0?`Сумма: ${deal.toLocaleString('ru')} ₽${debt>0?` · к оплате: <b>${debt.toLocaleString('ru')} ₽</b>`:''}`:'';
|
||||
return renderEstimateCard()+`<div class="exp-bar locked">
|
||||
<div class="exp-h">🔒 Документы готовы — доступны после оплаты</div>
|
||||
<div class="exp-h" style="display:flex;align-items:center;gap:7px">${ic('lock',17)} Документы готовы — доступны после оплаты</div>
|
||||
<div class="exp-d">Вы видите полный результат на экране. Печатный документ и выгрузка ТЗ для разработчика открываются после закрытия оплаты.<br>${moneyStr}</div>
|
||||
<div class="exp-btns"><button class="btn btn-p" onclick="(window.showPayModal||function(){alert('Оплата скоро будет доступна')})()">Оплатить и забрать документы →</button></div>
|
||||
</div>`;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user