fix(cabinet): Этап 2 — рабочий чат с Еленой (продолжение беседы), вместо заглушки

This commit is contained in:
wasrusgen 2026-06-03 13:35:36 +03:00
parent 5ded2c7312
commit 492b1adae4

View File

@ -316,10 +316,15 @@ body{font-family:'Inter',sans-serif;background:var(--bg);color:var(--text);displ
</div> </div>
</div> </div>
<!-- Этап 2 — Диагностика --> <!-- Этап 2 — Диагностика (живой чат, продолжение беседы) -->
<div class="sv" id="sv2"> <div class="sv" id="sv2">
<div class="hero"><div class="hero-ic">🔍</div><div><div class="hero-tag">Этап 2 из 5</div><div class="hero-h">Диагностика</div><div class="hero-d">Елена уточняет детали — продолжайте разговор</div></div></div> <div class="hero"><div class="hero-ic">🔍</div><div><div class="hero-tag">Этап 2 из 5 · Диагностика</div><div class="hero-h">Углубляемся</div><div class="hero-d">Елена задаёт уточняющие вопросы — отвечайте. Это продолжение разговора с Этапа 1.</div></div></div>
<div class="scroll"><div class="pad"><div class="run-card"><div class="run-ic">🔍</div><div class="run-t">Диагностика идёт в чате</div><div class="run-d">Елена задаёт уточняющие вопросы прямо в интервью (Этап 1). Когда данных достаточно — переходите к Анализу.</div><button class="btn btn-p" onclick="go(1)">← Вернуться к интервью</button></div></div></div> <div class="scroll"><div class="chat" id="chat2"></div></div>
<div class="inbar">
<textarea class="inp" id="inp2" rows="1" placeholder="Ответьте Елене…" onkeydown="if(event.key==='Enter'&&!event.shiftKey){event.preventDefault();sendMsg2()}"></textarea>
<button class="icon-btn mic" id="mic2" onclick="toggleMic('inp2','mic2')" title="Голосом"><svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><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"/></svg></button>
<button class="icon-btn send" id="send2" onclick="sendMsg2()"><svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="#fff" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round"><line x1="22" y1="2" x2="11" y2="13"/><polygon points="22 2 15 22 11 13 2 9 22 2"/></svg></button>
</div>
</div> </div>
<!-- Этап 3 — Документы --> <!-- Этап 3 — Документы -->
@ -405,7 +410,8 @@ function go(n){
document.querySelectorAll('.si').forEach(s=>s.classList.remove('active')); document.querySelectorAll('.si').forEach(s=>s.classList.remove('active'));
document.getElementById('si'+n).classList.add('active'); document.getElementById('si'+n).classList.add('active');
if(PCTS[n]!=null){document.getElementById('pbPct').textContent=PCTS[n]+'%';document.getElementById('pbFill').style.width=PCTS[n]+'%';} if(PCTS[n]!=null){document.getElementById('pbPct').textContent=PCTS[n]+'%';document.getElementById('pbFill').style.width=PCTS[n]+'%';}
if(n===1)requestAnimationFrame(scrollChatBottom); // sv1 уже видим — высота посчитана, прыгаем вниз без «пролёта» if(n===1){renderChat1();requestAnimationFrame(scrollChatBottom);} // ре-рендер из общей беседы
if(n===2)renderChat2(); // продолжение того же диалога
if(n===6){renderOpChat();startOpPoll();}else{stopOpPoll();} if(n===6){renderOpChat();startOpPoll();}else{stopOpPoll();}
if(n===3)renderDocs(); if(n===3)renderDocs();
if(n===4)renderAnalysis(); if(n===4)renderAnalysis();
@ -582,11 +588,20 @@ async function handleFiles(files){
} }
function renderAll(){ function renderAll(){
if(state.client_name)document.getElementById("hdrClient").textContent="· "+state.client_name; if(state.client_name)document.getElementById("hdrClient").textContent="· "+state.client_name;
chat.innerHTML=""; renderChat1();
state.messages.forEach(m=>addMsg(m.role==="user"?"user":"elena",m.content));
unlockStages(); unlockStages();
checkPayment(); checkPayment();
} }
function renderChat1(){const c=document.getElementById("chat");if(!c)return;c.innerHTML="";(state.messages||[]).forEach(m=>addMsg(m.role==="user"?"user":"elena",m.content));}
/* ── Этап 2 — продолжение диалога (тот же state.messages) ── */
function addMsg2(role,text){const c=document.getElementById("chat2");if(!c)return;const m=document.createElement("div");m.className="msg "+(role==="user"?"user":"");m.innerHTML=`<div class="av ${role==='user'?'u':'e'}">${role==='user'?'Я':'Е'}</div><div class="bb ${role==='user'?'out':'in'}">${fmt(text)}</div>`;c.appendChild(m);const sc=c.parentElement;if(sc)sc.scrollTop=sc.scrollHeight;}
function renderChat2(){const c=document.getElementById("chat2");if(!c)return;c.innerHTML="";const m=state.messages||[];if(!m.length){c.innerHTML='<div style="text-align:center;color:#cbd5e1;font-size:13px;padding:24px 16px">Начните разговор на Этапе 1 — здесь Елена продолжит уточнять детали.</div>';return;}m.forEach(x=>addMsg2(x.role==="user"?"user":"elena",x.content));requestAnimationFrame(()=>{const sc=c.parentElement;if(sc)sc.scrollTop=sc.scrollHeight;});}
async function sendMsg2(){const i=document.getElementById("inp2");const t=i.value.trim();if(!t)return;if(recording)stopMic();i.value="";i.style.height="auto";addMsg2("user",t);state.messages.push({role:"user",content:t});
const btn=document.getElementById("send2");btn.disabled=true;
const tp=document.createElement("div");tp.className="msg";tp.id="typing2";tp.innerHTML='<div class="av e">Е</div><div class="typing"><span></span><span></span><span></span></div>';document.getElementById("chat2").appendChild(tp);const sc=document.getElementById("chat2").parentElement;if(sc)sc.scrollTop=sc.scrollHeight;
try{const r=await fetch(`${API}/api/chat`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({token,message:t})});const d=await r.json();const x=document.getElementById("typing2");if(x)x.remove();addMsg2("elena",d.reply||("Ошибка: "+(d.error||"?")));state.messages.push({role:"assistant",content:d.reply||""});unlockStages();}catch(e){const x=document.getElementById("typing2");if(x)x.remove();addMsg2("elena","Ошибка связи: "+e.message);}
btn.disabled=false;
}
function money(n){return (n||0).toLocaleString("ru-RU")+" ₽"} function money(n){return (n||0).toLocaleString("ru-RU")+" ₽"}
function checkPayment(){ function checkPayment(){
const crm=state.crm||{};const deal=crm.deal_amount||0; const crm=state.crm||{};const deal=crm.deal_amount||0;