mirror of
https://github.com/wasrusgen/zashita-brandbook.git
synced 2026-06-03 19:04:48 +00:00
CTYPES: detect contract type after scan, show contextual comment + highlight recommended deliverable
This commit is contained in:
parent
bebc6bf463
commit
fb19d6afd4
165
mockup.html
165
mockup.html
@ -124,6 +124,9 @@ body{font-family:var(--font-ui);background:var(--surf);color:var(--ink);line-hei
|
|||||||
.deliv-top{border-color:rgba(159,18,57,.3);background:var(--tint)}
|
.deliv-top{border-color:rgba(159,18,57,.3);background:var(--tint)}
|
||||||
.deliv-top .dn{color:var(--bg)}
|
.deliv-top .dn{color:var(--bg)}
|
||||||
.deliv-badge{font-size:10px;font-weight:700;background:var(--bg);color:#fff;border-radius:6px;padding:2px 7px;margin-left:auto;flex-shrink:0}
|
.deliv-badge{font-size:10px;font-weight:700;background:var(--bg);color:#fff;border-radius:6px;padding:2px 7px;margin-left:auto;flex-shrink:0}
|
||||||
|
.deliv-highlighted{border-color:var(--bg)!important;background:linear-gradient(135deg,#fff 0%,rgba(159,18,57,.06) 100%)!important;box-shadow:0 0 0 2px rgba(159,18,57,.15)!important}
|
||||||
|
.deliv-highlighted .dn{color:var(--bg)!important}
|
||||||
|
.ctype-note{display:block;font-size:13px;color:var(--mut);line-height:1.5;margin-bottom:6px;padding:8px 10px;background:var(--surf);border-radius:8px;border-left:3px solid var(--bg)}
|
||||||
/* ── план после выбора ── */
|
/* ── план после выбора ── */
|
||||||
.plan-what{background:var(--surf);border-radius:12px;padding:14px 16px;margin:16px 0;max-width:600px}
|
.plan-what{background:var(--surf);border-radius:12px;padding:14px 16px;margin:16px 0;max-width:600px}
|
||||||
.plan-what-title{font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:1.2px;color:var(--mut);margin-bottom:10px}
|
.plan-what-title{font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:1.2px;color:var(--mut);margin-bottom:10px}
|
||||||
@ -260,15 +263,16 @@ body{font-family:var(--font-ui);background:var(--surf);color:var(--ink);line-hei
|
|||||||
.upload-box{max-width:560px;margin:0 auto;padding:0 0 24px}
|
.upload-box{max-width:560px;margin:0 auto;padding:0 0 24px}
|
||||||
|
|
||||||
/* ── SCAN ANIMATION ── */
|
/* ── SCAN ANIMATION ── */
|
||||||
.scan-wrap{display:flex;flex-direction:column;align-items:center;padding:52px 24px 60px;text-align:center}
|
.scan-wrap{display:flex;flex-direction:column;align-items:center;padding:48px 24px 56px;text-align:center}
|
||||||
.scan-doc-outer{position:relative;width:86px;height:112px;margin:0 auto 36px}
|
.scan-doc-outer{position:relative;width:170px;height:220px;margin:0 auto 32px}
|
||||||
.scan-doc-card{width:86px;height:112px;background:var(--card);border:1.5px solid var(--line);border-radius:10px;overflow:hidden;position:relative;box-shadow:0 8px 28px rgba(0,0,0,.09)}
|
.scan-doc-card{width:170px;height:220px;background:var(--card);border:1.5px solid var(--line);border-radius:14px;overflow:hidden;position:relative;box-shadow:0 12px 40px rgba(0,0,0,.12)}
|
||||||
.scan-doc-card::before{content:'';position:absolute;left:12px;right:12px;top:16px;height:6px;background:var(--line);border-radius:3px;box-shadow:0 13px 0 var(--line),0 23px 0 var(--line),0 33px 0 var(--line),0 43px 0 var(--line),0 53px 0 var(--line),0 63px 0 rgba(159,18,57,.12)}
|
.scan-doc-card::before{content:'';position:absolute;left:22px;right:22px;top:22px;height:7px;background:var(--line);border-radius:4px;
|
||||||
.scan-beam{position:absolute;left:0;right:0;height:2px;background:linear-gradient(90deg,transparent 0%,rgba(159,18,57,.25) 15%,var(--bg) 50%,rgba(159,18,57,.25) 85%,transparent 100%);box-shadow:0 0 10px 4px rgba(159,18,57,.3);animation:beamDown 1.7s ease-in-out infinite}
|
box-shadow:0 16px 0 var(--line),0 29px 0 var(--line),0 42px 0 var(--line),0 55px 0 rgba(159,18,57,.15),0 68px 0 var(--line),0 81px 0 var(--line),0 94px 0 var(--line),0 107px 0 rgba(159,18,57,.1),0 120px 0 var(--line),0 133px 0 rgba(159,18,57,.08)}
|
||||||
@keyframes beamDown{0%{top:-2px;opacity:0}7%{opacity:1}93%{opacity:1}100%{top:114px;opacity:0}}
|
.scan-beam{position:absolute;left:0;right:0;height:3px;background:linear-gradient(90deg,transparent 0%,rgba(159,18,57,.2) 10%,var(--bg) 50%,rgba(159,18,57,.2) 90%,transparent 100%);box-shadow:0 0 14px 5px rgba(159,18,57,.28);animation:beamDown 2s ease-in-out infinite;z-index:2}
|
||||||
.scan-av{position:absolute;bottom:-16px;right:-16px;width:40px;height:40px;border-radius:50%;border:3px solid var(--surf);object-fit:cover;object-position:center 14%;animation:avPulse 2s ease-in-out infinite}
|
@keyframes beamDown{0%{top:-3px;opacity:0}6%{opacity:1}94%{opacity:1}100%{top:223px;opacity:0}}
|
||||||
@keyframes avPulse{0%,100%{box-shadow:0 0 0 0 rgba(159,18,57,.45)}60%{box-shadow:0 0 0 8px rgba(159,18,57,0)}}
|
.scan-av{position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);width:68px;height:68px;border-radius:50%;border:4px solid #fff;object-fit:cover;object-position:center 12%;box-shadow:0 4px 16px rgba(0,0,0,.18);z-index:3;animation:avPulse 2.2s ease-in-out infinite}
|
||||||
.scan-label{font-size:18px;font-weight:700;color:var(--dark);min-height:28px;margin-bottom:7px}
|
@keyframes avPulse{0%,100%{box-shadow:0 4px 16px rgba(0,0,0,.18),0 0 0 0 rgba(159,18,57,.4)}60%{box-shadow:0 4px 16px rgba(0,0,0,.18),0 0 0 10px rgba(159,18,57,0)}}
|
||||||
|
.scan-label{font-size:18px;font-weight:700;color:var(--dark);min-height:28px;margin-bottom:7px;transition:opacity .25s}
|
||||||
.scan-hint{font-size:13px;color:var(--mut);margin-bottom:20px}
|
.scan-hint{font-size:13px;color:var(--mut);margin-bottom:20px}
|
||||||
.scan-dots{display:flex;gap:8px;justify-content:center}
|
.scan-dots{display:flex;gap:8px;justify-content:center}
|
||||||
.scan-dot{width:7px;height:7px;border-radius:50%;background:var(--bg);opacity:.3;animation:dotB 1.4s ease-in-out infinite}
|
.scan-dot{width:7px;height:7px;border-radius:50%;background:var(--bg);opacity:.3;animation:dotB 1.4s ease-in-out infinite}
|
||||||
@ -352,7 +356,8 @@ body{font-family:var(--font-ui);background:var(--surf);color:var(--ink);line-hei
|
|||||||
<!-- ШАГ 2: результаты анализа (скрыт до сканирования) -->
|
<!-- ШАГ 2: результаты анализа (скрыт до сканирования) -->
|
||||||
<div id="el-step2" style="display:none">
|
<div id="el-step2" style="display:none">
|
||||||
<div class="msg"><div class="av"><img src="logos/elena-photo.jpg"></div><div class="bubble"><div class="nm">Елена</div>
|
<div class="msg"><div class="av"><img src="logos/elena-photo.jpg"></div><div class="bubble"><div class="nm">Елена</div>
|
||||||
Прочитала ваш договор 📄 Это <b>агентский договор на сборку мебели</b> (ЗОВ ↔ Агент).<br>
|
Прочитала ваш договор 📄 Это <b id="el-scan-type">агентский договор</b>.<br>
|
||||||
|
<span id="el-ctype-note" class="ctype-note"></span>
|
||||||
Нашла <b>12 моментов</b>, из них <b>5 критичных</b>. <span id="el-intro-tail"></span> Показываю 3:
|
Нашла <b>12 моментов</b>, из них <b>5 критичных</b>. <span id="el-intro-tail"></span> Показываю 3:
|
||||||
<div class="risk-mini">
|
<div class="risk-mini">
|
||||||
<div class="rn">п.1.1 · ст. 4–29 ЗоЗПП</div>
|
<div class="rn">п.1.1 · ст. 4–29 ЗоЗПП</div>
|
||||||
@ -373,22 +378,22 @@ body{font-family:var(--font-ui);background:var(--surf);color:var(--ink);line-hei
|
|||||||
</div></div>
|
</div></div>
|
||||||
<div class="msg"><div class="av"><img src="logos/elena-photo.jpg"></div><div class="bubble"><div class="nm">Елена</div><span id="el-fork-q"></span></div></div>
|
<div class="msg"><div class="av"><img src="logos/elena-photo.jpg"></div><div class="bubble"><div class="nm">Елена</div><span id="el-fork-q"></span></div></div>
|
||||||
<div class="deliverables">
|
<div class="deliverables">
|
||||||
<div class="deliv" onclick="selectDeliv('protocol')">
|
<div id="deliv-protocol" class="deliv" onclick="selectDeliv('protocol')">
|
||||||
<span class="di">📋</span>
|
<span class="di">📋</span>
|
||||||
<div><div class="dn">Протокол разногласий</div><div class="dd2">Список спорных пунктов + зачем менять каждый</div></div>
|
<div><div class="dn">Протокол разногласий</div><div class="dd2">Список спорных пунктов + зачем менять каждый</div></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="deliv" onclick="selectDeliv('redact')">
|
<div id="deliv-redact" class="deliv" onclick="selectDeliv('redact')">
|
||||||
<span class="di">✏️</span>
|
<span class="di">✏️</span>
|
||||||
<div><div class="dn">Переработка с комментариями</div><div class="dd2">Новая редакция каждого пункта + пояснение изменений</div></div>
|
<div><div class="dn">Переработка с комментариями</div><div class="dd2">Новая редакция каждого пункта + пояснение изменений</div></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="deliv" onclick="selectDeliv('clean')">
|
<div id="deliv-clean" class="deliv" onclick="selectDeliv('clean')">
|
||||||
<span class="di">✅</span>
|
<span class="di">✅</span>
|
||||||
<div><div class="dn">Чистая редакция</div><div class="dd2">Договор готов к подписанию — без лишних пояснений</div></div>
|
<div><div class="dn">Чистая редакция</div><div class="dd2">Договор готов к подписанию — без лишних пояснений</div></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="deliv deliv-top" onclick="selectDeliv('partner')">
|
<div id="deliv-partner" class="deliv deliv-top" onclick="selectDeliv('partner')">
|
||||||
<span class="di">🤝</span>
|
<span class="di">🤝</span>
|
||||||
<div><div class="dn">Партнёрская редакция</div><div class="dd2">Вариант, который устроит обе стороны — без конфликта</div></div>
|
<div><div class="dn">Партнёрская редакция</div><div class="dd2">Вариант, который устроит обе стороны — без конфликта</div></div>
|
||||||
<span class="deliv-badge">Рекомендуем</span>
|
<span class="deliv-badge" id="deliv-rec-badge">Рекомендуем</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -671,6 +676,126 @@ function setMode(mode) {
|
|||||||
window.scrollTo(0, 0);
|
window.scrollTo(0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ── ТИПЫ ДОГОВОРОВ ── */
|
||||||
|
const CTYPES = {
|
||||||
|
agent: {
|
||||||
|
emoji:'🤝', name:'агентский договор',
|
||||||
|
comment:'Агент действует от имени или за счёт другой стороны. Главные риски здесь — объём вашей ответственности перед третьими лицами и признаки трудовых отношений, которые могут всплыть при проверке.',
|
||||||
|
delivRec:'partner'
|
||||||
|
},
|
||||||
|
realty: {
|
||||||
|
emoji:'🏠', name:'договор купли-продажи недвижимости',
|
||||||
|
comment:'В недвижимости цена ошибки особенно высока. Проверяю обременения, условия передачи объекта и ответственность за скрытые дефекты — именно там чаще всего прячется главный риск.',
|
||||||
|
delivRec:'partner'
|
||||||
|
},
|
||||||
|
auto: {
|
||||||
|
emoji:'🚗', name:'договор купли-продажи автомобиля',
|
||||||
|
comment:'Смотрю на гарантии состояния, скрытые дефекты и условия передачи. Это три зоны, где покупатель чаще всего остаётся без защиты после подписания.',
|
||||||
|
delivRec:'clean'
|
||||||
|
},
|
||||||
|
construction: {
|
||||||
|
emoji:'🛋️', name:'договор подряда',
|
||||||
|
comment:'Договор подряда — здесь критичны сроки, критерии качества результата и ответственность за задержки. Разбираю ваши риски по каждому из этих блоков.',
|
||||||
|
delivRec:'redact'
|
||||||
|
},
|
||||||
|
services: {
|
||||||
|
emoji:'🎯', name:'договор оказания услуг',
|
||||||
|
comment:'В услугах часто размыт сам результат и ответственность исполнителя. Разберу что именно вы обязаны сделать и где вас можно поймать на формальном нарушении.',
|
||||||
|
delivRec:'redact'
|
||||||
|
},
|
||||||
|
labor: {
|
||||||
|
emoji:'📋', name:'трудовой договор',
|
||||||
|
comment:'Трудовой договор — смотрю на режим работы, зоны ответственности и условия расторжения. Здесь у работника есть обязательная защита по ТК, которую нельзя ужать без последствий.',
|
||||||
|
delivRec:'protocol'
|
||||||
|
},
|
||||||
|
loan: {
|
||||||
|
emoji:'💰', name:'договор займа',
|
||||||
|
comment:'Ключевые риски займа — скрытые проценты, штрафные санкции и условия досрочного требования. Часто самый опасный пункт написан мелким шрифтом в середине договора.',
|
||||||
|
delivRec:'redact'
|
||||||
|
},
|
||||||
|
supply: {
|
||||||
|
emoji:'📦', name:'договор поставки',
|
||||||
|
comment:'Поставка — проверяю условия приёмки, ответственность за качество товара и что происходит при просрочке. Именно здесь чаще всего возникают споры при исполнении.',
|
||||||
|
delivRec:'redact'
|
||||||
|
},
|
||||||
|
other: {
|
||||||
|
emoji:'📄', name:'договор',
|
||||||
|
comment:'Изучила структуру. Нашла пункты, которые стоит проверить внимательнее — показываю ключевые риски ниже.',
|
||||||
|
delivRec:null
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const CTYPES_KEYWORDS = {
|
||||||
|
agent: ['агент','принципал','агентск','от имени и за счёт','за счёт принципала'],
|
||||||
|
realty: ['квартир','недвижим','жиль','комнат','нежилое','земельн','ипотек','объект недвижим','жилой дом'],
|
||||||
|
auto: ['автомобил','транспортн средств','машин','птс','пробег','кузов'],
|
||||||
|
construction: ['подряд','мебел','изготовл','монтаж','строител','ремонт','подрядчик','заказчик','результат работ'],
|
||||||
|
services: ['оказани','услуг','исполнител','заказчик','сервис','консульт','разработ','дизайн'],
|
||||||
|
labor: ['трудов','работодател','работник','должност','оклад','отпуск','увольнен','рабочее время'],
|
||||||
|
loan: ['займ','заём','кредит','процент годов','долг','заемщик','заёмщик','сумма займа'],
|
||||||
|
supply: ['поставщик','покупател','товар','партия','поставка','отгрузк','накладн']
|
||||||
|
};
|
||||||
|
|
||||||
|
let _demoCtypeIdx = 0;
|
||||||
|
const _demoSeq = ['agent','realty','auto','construction','services','labor','loan','supply'];
|
||||||
|
|
||||||
|
function detectCtype(text) {
|
||||||
|
if (text && text.length > 30) {
|
||||||
|
const t = text.toLowerCase();
|
||||||
|
for (const [key, kws] of Object.entries(CTYPES_KEYWORDS)) {
|
||||||
|
if (kws.some(kw => t.includes(kw))) return key;
|
||||||
|
}
|
||||||
|
return 'other';
|
||||||
|
}
|
||||||
|
// демо-режим: каждый клик — новый тип
|
||||||
|
const key = _demoSeq[_demoCtypeIdx % _demoSeq.length];
|
||||||
|
_demoCtypeIdx++;
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
|
||||||
|
function showResults(ctypeKey) {
|
||||||
|
// спрятать предыдущие шаги на случай прямого вызова
|
||||||
|
['el-step-upload','el-step-scan','el-step1'].forEach(id => {
|
||||||
|
const el = document.getElementById(id);
|
||||||
|
if (el) el.style.display = 'none';
|
||||||
|
});
|
||||||
|
const ctype = CTYPES[ctypeKey] || CTYPES.other;
|
||||||
|
|
||||||
|
// тип договора в первой реплике
|
||||||
|
document.getElementById('el-scan-type').textContent = ctype.emoji + ' ' + ctype.name;
|
||||||
|
const noteEl = document.getElementById('el-ctype-note');
|
||||||
|
noteEl.textContent = ctype.comment;
|
||||||
|
noteEl.style.display = ctype.comment ? 'block' : 'none';
|
||||||
|
|
||||||
|
// убрать старую подсветку, поставить новую
|
||||||
|
document.querySelectorAll('.deliv').forEach(el => {
|
||||||
|
el.classList.remove('deliv-highlighted');
|
||||||
|
});
|
||||||
|
// убрать badge у всех, потом поставить на нужный
|
||||||
|
document.querySelectorAll('.deliv-badge').forEach(b => b.style.display = 'none');
|
||||||
|
|
||||||
|
if (ctype.delivRec) {
|
||||||
|
const recEl = document.getElementById('deliv-' + ctype.delivRec);
|
||||||
|
if (recEl) {
|
||||||
|
recEl.classList.add('deliv-highlighted');
|
||||||
|
let badge = recEl.querySelector('.deliv-badge');
|
||||||
|
if (!badge) {
|
||||||
|
badge = document.createElement('span');
|
||||||
|
badge.className = 'deliv-badge';
|
||||||
|
recEl.appendChild(badge);
|
||||||
|
}
|
||||||
|
badge.textContent = 'Рекомендуем';
|
||||||
|
badge.style.display = '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// показать результаты
|
||||||
|
document.getElementById('el-step-scan').style.display = 'none';
|
||||||
|
document.getElementById('el-step2').style.display = 'block';
|
||||||
|
document.getElementById('el-actbar').style.display = 'flex';
|
||||||
|
document.getElementById('el-step2').scrollIntoView({ behavior: 'smooth' });
|
||||||
|
}
|
||||||
|
|
||||||
/* ── СКАНИРОВАНИЕ ── */
|
/* ── СКАНИРОВАНИЕ ── */
|
||||||
const SCAN_PHRASES = [
|
const SCAN_PHRASES = [
|
||||||
'Читаю договор...',
|
'Читаю договор...',
|
||||||
@ -682,6 +807,9 @@ const SCAN_PHRASES = [
|
|||||||
];
|
];
|
||||||
|
|
||||||
function startScan() {
|
function startScan() {
|
||||||
|
const text = (document.getElementById('el-paste').value || '').trim();
|
||||||
|
const ctypeKey = detectCtype(text);
|
||||||
|
|
||||||
document.getElementById('el-step-upload').style.display = 'none';
|
document.getElementById('el-step-upload').style.display = 'none';
|
||||||
document.getElementById('el-step-scan').style.display = 'block';
|
document.getElementById('el-step-scan').style.display = 'block';
|
||||||
window.scrollTo(0, 0);
|
window.scrollTo(0, 0);
|
||||||
@ -697,12 +825,7 @@ function startScan() {
|
|||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
clearInterval(interval);
|
clearInterval(interval);
|
||||||
lbl.style.opacity = '0';
|
lbl.style.opacity = '0';
|
||||||
setTimeout(() => {
|
setTimeout(() => { showResults(ctypeKey); }, 200);
|
||||||
document.getElementById('el-step-scan').style.display = 'none';
|
|
||||||
document.getElementById('el-step2').style.display = 'block';
|
|
||||||
document.getElementById('el-actbar').style.display = 'flex';
|
|
||||||
document.getElementById('el-step2').scrollIntoView({ behavior: 'smooth' });
|
|
||||||
}, 200);
|
|
||||||
}, 4000);
|
}, 4000);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user