diff --git a/docs/cabinet.html b/docs/cabinet.html index 88b20da..9ac4e60 100644 --- a/docs/cabinet.html +++ b/docs/cabinet.html @@ -406,7 +406,7 @@ function go(n){ 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(n===1)requestAnimationFrame(scrollChatBottom); // sv1 уже видим — высота посчитана, прыгаем вниз без «пролёта» - if(n===6)renderOpChat(); + if(n===6){renderOpChat();startOpPoll();}else{stopOpPoll();} if(n===3)renderDocs(); if(n===4)renderAnalysis(); if(n===5)renderSpecPane(); @@ -467,6 +467,10 @@ function renderOpChat(){const c=document.getElementById("opChat");if(!c)return;c async function opSend(){const inp=document.getElementById("opInp");const t=inp.value.trim();if(!t)return;inp.value="";inp.style.height="auto";opMsg("user",t);state.operator_chat=state.operator_chat||[];state.operator_chat.push({role:"user",content:t}); try{const r=await fetch(`${API}/api/operator-chat`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({token,message:t})});const d=await r.json();if(d.messages)state.operator_chat=d.messages;}catch(e){opMsg("elena","Не доставлено: "+e.message);} } +let opPollTimer=null; +async function opPollOnce(){try{const r=await fetch(`${API}/api/operator-chat?token=${encodeURIComponent(token)}`);const d=await r.json();if(d.messages&&d.messages.length!==(state.operator_chat||[]).length){state.operator_chat=d.messages;renderOpChat();}}catch(e){}} +function startOpPoll(){stopOpPoll();opPollOnce();opPollTimer=setInterval(opPollOnce,15000);} +function stopOpPoll(){if(opPollTimer){clearInterval(opPollTimer);opPollTimer=null;}} /* ── Спросить Елену (этапы 3-5) ── */ const STAGE_LBL={3:"о документах",4:"о стратегии и модели",5:"о ТЗ и плане"}; function toggleAsk(){document.getElementById("askDock").classList.toggle("open")} diff --git a/docs/crm.html b/docs/crm.html index 5428446..9e05138 100644 --- a/docs/crm.html +++ b/docs/crm.html @@ -320,9 +320,9 @@ async function submitNewClient(){ await loadProjects();openClient(d.token);toast('Клиент «'+name+'» создан','ok'); }catch(e){toast('Ошибка: '+e.message,'err');btn.disabled=false;btn.textContent='Создать →';} } -function setView(v){view=v;current=null;if(window.innerWidth<=680)closeSb();document.getElementById("nav-dash").classList.toggle("active",v==="dashboard");document.getElementById("nav-pipe").classList.toggle("active",v==="pipeline");renderClientList();render();} +function setView(v){stopCrmChatPoll();view=v;current=null;if(window.innerWidth<=680)closeSb();document.getElementById("nav-dash").classList.toggle("active",v==="dashboard");document.getElementById("nav-pipe").classList.toggle("active",v==="pipeline");renderClientList();render();} async function openClient(token){ - current=token;view="client";mainTab="deal";editPayIdx=-1;if(window.innerWidth<=680)closeSb();document.querySelectorAll(".nav-item").forEach(n=>n.classList.remove("active")); + stopCrmChatPoll();current=token;view="client";mainTab="deal";editPayIdx=-1;if(window.innerWidth<=680)closeSb();document.querySelectorAll(".nav-item").forEach(n=>n.classList.remove("active")); const r=await fetch(`${API}/api/project/${token}`);state=await r.json();renderClientList();render();syncPaymentReminders(); } function render(){ @@ -527,7 +527,7 @@ function renderClient(){
`; renderMainPanel(); } -function setMainTab(t){mainTab=t;editPayIdx=-1;renderMainPanel();document.querySelectorAll('.mtab').forEach((b,i)=>b.classList.toggle('active',MAINTABS[i].id===mainTab));} +function setMainTab(t){if(t!=='chat')stopCrmChatPoll();mainTab=t;editPayIdx=-1;renderMainPanel();document.querySelectorAll('.mtab').forEach((b,i)=>b.classList.toggle('active',MAINTABS[i].id===mainTab));} function renderDocsTab(){ const docs=state.documents||[]; let h=`