From eb67f2f5715e3b9999282b3e6c2bace268a9d10c Mon Sep 17 00:00:00 2001 From: WASRUSGEN Date: Sat, 30 May 2026 11:02:15 +0300 Subject: [PATCH] feat: conversational doc audit flow in cabinet chat after intake confirmation --- mockup.html | 229 +++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 218 insertions(+), 11 deletions(-) diff --git a/mockup.html b/mockup.html index b855dd1..1921dea 100644 --- a/mockup.html +++ b/mockup.html @@ -6673,26 +6673,27 @@ function _confirmIntake(intent, quote) { _chatHistory.push({role: 'user', content: quote}); _saveHistory(); - // Елена: фиксирует дело и спрашивает про договор + // Елена: фиксирует дело → запускает аудит документов setTimeout(function(){ _rcAddTyping(); var ctx = quote; - _elenaApi('Клиент подтвердил ситуацию: ' + ctx + '. Зафикисруй дело и спроси что нужно для помощи.', + _elenaApi('Клиент подтвердил ситуацию: ' + ctx + '. Зафиксируй и определи тип договора (аренда/подряд/купля-продажа/трудовой/займ/ДДУ/недвижимость) — одним словом.', intent, - function(apiReply, apiActions) { + function(apiReply) { _rcRemoveTyping(); - var reply = apiReply || 'Хорошо, зафиксировала. Есть ли у Вас договор на руках? Если загрузите — смогу сразу оценить риски и предложить конкретные действия.'; + var reply = apiReply || 'Хорошо, зафиксировала.'; _chatHistory.push({role: 'assistant', content: reply}); _saveHistory(); _rcAddBubble(reply, false); - if (apiActions && apiActions.length) { - var m = document.getElementById('rchat-msgs'); - if (m) _renderElenaActions(apiActions, m); - } - _rcShowControls(); - - // Обновляем досье _updateDossier({ facts: ['Зафиксировано дело: ' + ctx] }); + + // Определяем тип договора из ответа и запроса + var contractType = _detectContractType(ctx + ' ' + reply); + + // Пауза → показываем аудит документов в чате + setTimeout(function(){ + _showDocAuditInChat(contractType, intent); + }, 800); }); }, 400); } @@ -7688,6 +7689,212 @@ function _compressAsync(showToast) { .catch(function(){}); } +// ── ОПРЕДЕЛЕНИЕ ТИПА ДОГОВОРА ─────────────────────────────────────────────── +function _detectContractType(text) { + var t = (text || '').toLowerCase(); + if (/аренд|съезж|помещен|цех|офис|склад|депозит/.test(t)) return 'аренда'; + if (/подряд|услуг|ремонт|строит|разработ|дизайн|монтаж/.test(t)) return 'подряд'; + if (/дду|долев|новостройк|застройщ|214/.test(t)) return 'дду'; + if (/квартир|недвижим|вторич|комнат|дом|земл/.test(t)) return 'недвижимость'; + if (/трудов|работодат|уволь|зарплат|ип/.test(t)) return 'трудовой'; + if (/займ|расписк|долг|одолжил|кредит/.test(t)) return 'займ'; + if (/поставк|товар|купли-продаж|покупател|продавец/.test(t)) return 'купля-продажа'; + if (/риелтор|агентств|комисси|эксклюзив/.test(t)) return 'агент'; + return null; +} + +// ── АУДИТ ДОКУМЕНТОВ В ЧАТЕ ───────────────────────────────────────────────── +function _showDocAuditInChat(contractType, intent) { + var msgs = document.getElementById('rchat-msgs'); + if (!msgs) return; + + var cl = DOC_CHECKLISTS[contractType]; + if (!cl) { + // Тип не определён — спрашиваем + var ask = document.createElement('div'); + ask.className = 'hc-msg hc-elena'; + ask.innerHTML = '' + + '
Уточните — что за договор у Вас: аренда, подряд, купля-продажа, трудовой или что-то другое?
'; + msgs.appendChild(ask); + _rcShowControls(); + return; + } + + // Загружаем сохранённые отметки + var saved = {}; + try { saved = JSON.parse(localStorage.getItem('zashita_doccheck_' + contractType) || '{}'); } catch(e){} + + var critical = cl.docs.filter(function(d){ return !saved[d.id] && d.risk === 'critical'; }); + var high = cl.docs.filter(function(d){ return !saved[d.id] && d.risk === 'high'; }); + var all = cl.docs.length; + var have = Object.keys(saved).filter(function(k){ return saved[k]; }).length; + + // Вводная от Елены + var intro = document.createElement('div'); + intro.className = 'hc-msg hc-elena'; + var introText = critical.length + ? 'Сейчас проверим документы по Вашей ситуации. Сразу вижу ' + critical.length + ' критических пункта — это важно для защиты Ваших интересов.' + : 'Давайте быстро проверим документы — это займёт минуту.'; + intro.innerHTML = '
' + introText + '
'; + msgs.appendChild(intro); + + // Чеклист в пузыре + setTimeout(function(){ + var checkDiv = document.createElement('div'); + checkDiv.className = 'hc-msg hc-elena'; + + var docsHtml = '
' + cl.icon + ' ' + cl.label + ' — отметьте что есть:
'; + docsHtml += '
'; + + cl.docs.forEach(function(doc) { + var checked = !!saved[doc.id]; + var riskBadge = {critical:'🔴', high:'🟠', medium:'🟡'}[doc.risk] || '⚪'; + docsHtml += + ''; + }); + + docsHtml += '
'; + docsHtml += '
Отметьте всё что есть — покажу риски по каждому пропуску
'; + + checkDiv.innerHTML = '
' + docsHtml + '
'; + msgs.appendChild(checkDiv); + msgs.scrollTop = msgs.scrollHeight; + + // Если уже есть пропуски — сразу показываем что критично + if (critical.length) { + setTimeout(function(){ _showAuditGaps(contractType, intent); }, 1000); + } else { + _rcShowControls(); + } + }, 600); +} + +function _auditCheck(contractType, docId, checked, intent) { + // Обновляем состояние чеклиста + try { + var saved = JSON.parse(localStorage.getItem('zashita_doccheck_' + contractType) || '{}'); + saved[docId] = checked; + localStorage.setItem('zashita_doccheck_' + contractType, JSON.stringify(saved)); + } catch(e){} + + // Пересчитываем пропуски и показываем актуальные риски + setTimeout(function(){ _showAuditGaps(contractType, intent); }, 300); +} + +function _showAuditGaps(contractType, intent) { + var msgs = document.getElementById('rchat-msgs'); + if (!msgs) return; + + var cl = DOC_CHECKLISTS[contractType]; + if (!cl) return; + + var saved = {}; + try { saved = JSON.parse(localStorage.getItem('zashita_doccheck_' + contractType) || '{}'); } catch(e){} + + var missing = cl.docs.filter(function(d){ return !saved[d.id]; }); + var critical = missing.filter(function(d){ return d.risk === 'critical'; }); + + // Удаляем старый gap-блок + var old = document.getElementById('audit-gaps'); + if (old) old.remove(); + + if (!missing.length) { + var okDiv = document.createElement('div'); + okDiv.id = 'audit-gaps'; + okDiv.className = 'hc-msg hc-elena'; + okDiv.innerHTML = '' + + '
✅ Отличный пакет документов!
' + + 'Всё что нужно — в наличии. Можем сразу перейти к разбору ситуации.
'; + msgs.appendChild(okDiv); + _rcShowControls(); + return; + } + + var gapDiv = document.createElement('div'); + gapDiv.id = 'audit-gaps'; + gapDiv.className = 'hc-msg hc-elena'; + + var gapsHtml = ''; + if (critical.length) { + gapsHtml += '
⚠️ Критические пробелы:
'; + critical.forEach(function(d){ + gapsHtml += '
' + + '' + d.label + '
' + d.tip + '
'; + }); + } + + var nonCrit = missing.filter(function(d){ return d.risk !== 'critical'; }); + if (nonCrit.length && !critical.length) { + gapsHtml += '
Рекомендую получить:
'; + nonCrit.forEach(function(d){ + var c = d.risk === 'high' ? '#d97706' : '#2563eb'; + gapsHtml += '
' + d.label + '
'; + }); + } + + // Кнопки действий + gapsHtml += '
'; + if (critical.length) { + gapsHtml += ''; + } + gapsHtml += ''; + gapsHtml += '
'; + + gapDiv.innerHTML = '
' + gapsHtml + '
'; + msgs.appendChild(gapDiv); + msgs.scrollTop = msgs.scrollHeight; + _rcShowControls(); +} + +function _offerDocFix(contractType, intent) { + var msgs = document.getElementById('rchat-msgs'); + if (!msgs) return; + + var saved = {}; + try { saved = JSON.parse(localStorage.getItem('zashita_doccheck_' + contractType) || '{}'); } catch(e){} + var cl = DOC_CHECKLISTS[contractType] || {docs:[]}; + var critical = cl.docs.filter(function(d){ return !saved[d.id] && d.risk === 'critical'; }); + + var fix = document.createElement('div'); + fix.className = 'hc-msg hc-elena'; + + var fixes = ''; + critical.forEach(function(d) { + var canGenerate = /уведомлени|акт|претензи|расписк/.test(d.label.toLowerCase()); + fixes += '
' + + '
' + d.label + '
' + + (canGenerate + ? '' + : 'запросить у стороны') + + '
'; + }); + + fix.innerHTML = '' + + '
' + + '
Что можно сделать прямо сейчас:
' + + fixes + '
'; + msgs.appendChild(fix); + msgs.scrollTop = msgs.scrollHeight; +} + +function _docToTemplate(docId, contractType) { + var map = { + 'notice': 'notice_no_renewal', + 'act': 'act_acceptance', + 'act_out': 'act_acceptance', + 'receipt': 'notice_no_renewal', + }; + return map[docId] || 'claim_payment'; +} + // ── ЧЕКЛИСТ ДОКУМЕНТОВ ────────────────────────────────────────────────────── var DOC_CHECKLISTS = {