mirror of
https://github.com/wasrusgen/zashita-brandbook.git
synced 2026-06-03 14:24:48 +00:00
feat: email draft modal — counterparty email from contract, open in mail client
This commit is contained in:
parent
0382e97093
commit
a1de6c09ff
175
mockup.html
175
mockup.html
@ -4840,7 +4840,7 @@ var _DL_ACTIONS = {
|
||||
steps: [
|
||||
'Составьте письменное уведомление (могу помочь — нажмите «Составить»)',
|
||||
'Отправьте заказным письмом с уведомлением о вручении — это фиксирует дату <button onclick="event.stopPropagation();_showPostalForm()" style="background:var(--tint);color:var(--bg);border:1.5px solid rgba(159,18,57,.25);border-radius:7px;padding:3px 10px;font-size:11px;font-weight:700;cursor:pointer;font-family:inherit;vertical-align:middle;margin-left:6px">📄 Бланк ф.119</button>',
|
||||
'Продублируйте на email контрагента с запросом подтверждения получения',
|
||||
'Продублируйте на email контрагента — адрес из договора у нас есть <button onclick="event.stopPropagation();_prepareEmailDraft()" style="background:var(--tint);color:var(--bg);border:1.5px solid rgba(159,18,57,.25);border-radius:7px;padding:3px 10px;font-size:11px;font-weight:700;cursor:pointer;font-family:inherit;vertical-align:middle;margin-left:6px">📧 Подготовить письмо</button>',
|
||||
'Введите трек-номер после отправки:<div style="display:flex;gap:6px;margin-top:7px;flex-wrap:wrap"><input id="postal-track-input" placeholder="14 цифр..." maxlength="14" style="border:1.5px solid var(--line);border-radius:8px;padding:6px 10px;font-size:13px;font-family:inherit;width:160px;outline:none" oninput="_filterDigits(this)" /><button onclick="_saveTrackNumber()" style="background:var(--bg);color:#fff;border:none;border-radius:8px;padding:6px 12px;font-size:12px;font-weight:700;cursor:pointer;font-family:inherit">📮 Отследить</button></div>'
|
||||
],
|
||||
warn: 'Устное уведомление не имеет юридической силы — только письменное с подтверждением доставки.'
|
||||
@ -4951,9 +4951,12 @@ function _filterDigits(el) {
|
||||
el.value = el.value.replace(/[^0-9]/g, '');
|
||||
}
|
||||
|
||||
// Извлекает стороны и адреса из текста договора
|
||||
// Глобальный кэш данных сторон (заполняется при анализе и при открытии бланка)
|
||||
var _postalData = null;
|
||||
|
||||
// Извлекает стороны, адреса и email из текста договора
|
||||
function _extractParties(text) {
|
||||
var out = { counterparty: '', counterAddr: '', sender: '', senderAddr: '' };
|
||||
var out = { counterparty: '', counterAddr: '', counterEmail: '', sender: '', senderAddr: '', senderEmail: '' };
|
||||
if (!text) return out;
|
||||
|
||||
// Роли: [контрагент (кому шлём), сторона клиента]
|
||||
@ -4989,7 +4992,7 @@ function _extractParties(text) {
|
||||
return m ? m[1].replace(/^[\s,:—–]+/, '').trim() : '';
|
||||
}
|
||||
|
||||
// Извлекаем адрес: берём первые N символов после имени роли, ищем адресный блок
|
||||
// Извлекаем адрес из блока роли
|
||||
function extractAddr(role) {
|
||||
var roleIdx = text.search(new RegExp(role, 'i'));
|
||||
if (roleIdx < 0) return '';
|
||||
@ -4998,11 +5001,22 @@ function _extractParties(text) {
|
||||
return m ? m[1].trim() : '';
|
||||
}
|
||||
|
||||
// Извлекаем email из блока роли (500 символов вокруг упоминания)
|
||||
function extractEmail(role) {
|
||||
var roleIdx = text.search(new RegExp(role, 'i'));
|
||||
if (roleIdx < 0) return '';
|
||||
var chunk = text.slice(roleIdx, roleIdx + 500);
|
||||
var m = chunk.match(/[\w.+-]+@[\w.-]+\.[a-zа-яё]{2,}/i);
|
||||
return m ? m[0] : '';
|
||||
}
|
||||
|
||||
if (r1) {
|
||||
out.counterparty = (r1 ? r1 + ': ' : '') + extractName(r1);
|
||||
out.counterAddr = extractAddr(r1);
|
||||
out.sender = (r2 ? r2 + ': ' : '') + extractName(r2);
|
||||
out.senderAddr = extractAddr(r2);
|
||||
out.counterparty = (r1 ? r1 + ': ' : '') + extractName(r1);
|
||||
out.counterAddr = extractAddr(r1);
|
||||
out.counterEmail = extractEmail(r1);
|
||||
out.sender = (r2 ? r2 + ': ' : '') + extractName(r2);
|
||||
out.senderAddr = extractAddr(r2);
|
||||
out.senderEmail = extractEmail(r2);
|
||||
}
|
||||
|
||||
return out;
|
||||
@ -5031,11 +5045,22 @@ function _showPostalForm() {
|
||||
if (nameEl && nameEl.value) { senderName = nameEl.value; senderAddr = addrEl ? addrEl.value : ''; }
|
||||
}
|
||||
|
||||
// Сохраняем глобально для email-черновика
|
||||
_postalData = {
|
||||
counterparty: parties.counterparty || '',
|
||||
counterAddr: parties.counterAddr || '',
|
||||
counterEmail: parties.counterEmail || '',
|
||||
sender: senderName || parties.sender || '',
|
||||
senderAddr: senderAddr || parties.senderAddr || '',
|
||||
senderEmail: parties.senderEmail || '',
|
||||
about: about
|
||||
};
|
||||
|
||||
// Приоритет: договор > localStorage > пусто
|
||||
var recipientVal = parties.counterparty || '';
|
||||
var recAddrVal = parties.counterAddr || '';
|
||||
var senderVal = senderName || parties.sender || '';
|
||||
var sendAddrVal = senderAddr || parties.senderAddr || '';
|
||||
var recipientVal = _postalData.counterparty;
|
||||
var recAddrVal = _postalData.counterAddr;
|
||||
var senderVal = _postalData.sender;
|
||||
var sendAddrVal = _postalData.senderAddr;
|
||||
|
||||
var el = document.getElementById('postal-form-overlay');
|
||||
if (!el) return;
|
||||
@ -5104,6 +5129,76 @@ function _postalPrint() {
|
||||
w.document.close();
|
||||
}
|
||||
|
||||
function _prepareEmailDraft() {
|
||||
var pd = _postalData || {};
|
||||
var dlTitle = (_rcLastContext && _rcLastContext.dl) ? _rcLastContext.dl.title : 'уведомление';
|
||||
var caseName = (_rcLastContext && _rcLastContext.caseName) ? _rcLastContext.caseName : '';
|
||||
var toEmail = pd.counterEmail || '';
|
||||
var toName = pd.counterparty || 'контрагент';
|
||||
var fromName = pd.sender || 'клиент';
|
||||
var about = pd.about || dlTitle;
|
||||
|
||||
// Если _postalData не заполнен — попробуем распарсить сейчас
|
||||
if (!pd.counterparty) {
|
||||
var contractText = (document.getElementById('el-paste') || {}).value || '';
|
||||
var parties = _extractParties(contractText);
|
||||
toEmail = parties.counterEmail || '';
|
||||
toName = parties.counterparty || 'контрагент';
|
||||
fromName = parties.sender || fromName;
|
||||
_postalData = Object.assign({}, parties, { about: about });
|
||||
}
|
||||
|
||||
var subject = 'Уведомление: ' + dlTitle + (caseName ? ' · ' + caseName : '');
|
||||
var body =
|
||||
'Уважаемый(ая) ' + toName.replace(/^[^:]+:\s*/, '') + ',\n\n' +
|
||||
'Настоящим письмом уведомляю Вас о следующем:\n' +
|
||||
about + '.\n\n' +
|
||||
'Одновременно направляю настоящее уведомление заказным письмом ' +
|
||||
'с уведомлением о вручении (Почта России).\n\n' +
|
||||
'Прошу подтвердить получение данного письма ответным сообщением ' +
|
||||
'на адрес электронной почты отправителя.\n\n' +
|
||||
'С уважением,\n' + fromName.replace(/^[^:]+:\s*/, '') + '\n' +
|
||||
'Дата: ' + new Date().toLocaleDateString('ru-RU');
|
||||
|
||||
var ov = document.getElementById('email-draft-overlay');
|
||||
if (!ov) return;
|
||||
document.getElementById('ed-to').value = toEmail;
|
||||
document.getElementById('ed-subject').value = subject;
|
||||
document.getElementById('ed-body').value = body;
|
||||
|
||||
// Если email найден — подсветим зелёным, иначе — рамка предупреждения
|
||||
var toInp = document.getElementById('ed-to');
|
||||
toInp.style.borderColor = toEmail ? 'var(--ok)' : 'rgba(159,18,57,.4)';
|
||||
if (!toEmail) toInp.placeholder = 'Email не найден в договоре — введите вручную';
|
||||
|
||||
ov.classList.add('on');
|
||||
}
|
||||
|
||||
function _emailDraftClose() {
|
||||
var ov = document.getElementById('email-draft-overlay');
|
||||
if (ov) ov.classList.remove('on');
|
||||
}
|
||||
|
||||
function _emailCopy() {
|
||||
var to = (document.getElementById('ed-to') || {}).value || '';
|
||||
var subject = (document.getElementById('ed-subject') || {}).value || '';
|
||||
var body = (document.getElementById('ed-body') || {}).value || '';
|
||||
var full = 'Кому: ' + to + '\nТема: ' + subject + '\n\n' + body;
|
||||
navigator.clipboard.writeText(full).then(function(){
|
||||
toast('📋 Письмо скопировано — вставьте в почтовый клиент');
|
||||
_emailDraftClose();
|
||||
}).catch(function(){
|
||||
toast('Скопируйте текст вручную');
|
||||
});
|
||||
}
|
||||
|
||||
function _emailOpenClient() {
|
||||
var to = encodeURIComponent((document.getElementById('ed-to') || {}).value || '');
|
||||
var subject = encodeURIComponent((document.getElementById('ed-subject') || {}).value || '');
|
||||
var body = encodeURIComponent((document.getElementById('ed-body') || {}).value || '');
|
||||
window.open('mailto:' + to + '?subject=' + subject + '&body=' + body, '_blank');
|
||||
}
|
||||
|
||||
function _saveTrackNumber() {
|
||||
var input = document.getElementById('postal-track-input');
|
||||
var num = input ? input.value.replace(/\D/g,'') : '';
|
||||
@ -6021,6 +6116,62 @@ function tab(name){
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ── МОДАЛКА: ЧЕРНОВИК EMAIL КОНТРАГЕНТУ ── -->
|
||||
<style>
|
||||
#email-draft-overlay{display:none;position:fixed;inset:0;background:rgba(0,0,0,.5);z-index:9001;align-items:flex-end;justify-content:center}
|
||||
#email-draft-overlay.on{display:flex}
|
||||
</style>
|
||||
<div id="email-draft-overlay" onclick="if(event.target===this)_emailDraftClose()">
|
||||
<div onclick="event.stopPropagation()"
|
||||
style="background:#fff;border-radius:20px 20px 0 0;width:100%;max-width:500px;padding:22px 20px 32px;position:relative;box-shadow:0 -8px 40px rgba(0,0,0,.18);animation:slideUp .22s ease;max-height:92vh;overflow-y:auto">
|
||||
|
||||
<div style="display:flex;align-items:center;justify-content:space-between;margin-bottom:14px">
|
||||
<div>
|
||||
<div style="font-size:15px;font-weight:800;color:var(--ink)">📧 Черновик письма</div>
|
||||
<div style="font-size:12px;color:var(--mut)">Подтверждение получения уведомления</div>
|
||||
</div>
|
||||
<button onclick="_emailDraftClose()" style="background:var(--surf);border:none;border-radius:50%;width:30px;height:30px;font-size:14px;cursor:pointer;color:var(--mut)">✕</button>
|
||||
</div>
|
||||
|
||||
<div style="background:var(--tint);border-radius:10px;padding:9px 13px;font-size:12px;color:var(--dark);margin-bottom:14px;line-height:1.5">
|
||||
Email контрагента подтянут из договора. Отправьте это письмо параллельно с заказным — он дублирует вручение и создаёт цифровой след.
|
||||
</div>
|
||||
|
||||
<div style="display:flex;flex-direction:column;gap:10px">
|
||||
<div>
|
||||
<label style="font-size:11px;font-weight:700;color:var(--slate);display:block;margin-bottom:4px">КОМУ</label>
|
||||
<input id="ed-to" placeholder="email@counterparty.ru"
|
||||
style="width:100%;border:1.5px solid var(--line);border-radius:9px;padding:9px 12px;font-size:13px;font-family:inherit;outline:none;color:var(--ink)">
|
||||
</div>
|
||||
<div>
|
||||
<label style="font-size:11px;font-weight:700;color:var(--slate);display:block;margin-bottom:4px">ТЕМА</label>
|
||||
<input id="ed-subject"
|
||||
style="width:100%;border:1.5px solid var(--line);border-radius:9px;padding:9px 12px;font-size:13px;font-family:inherit;outline:none;color:var(--ink)">
|
||||
</div>
|
||||
<div>
|
||||
<label style="font-size:11px;font-weight:700;color:var(--slate);display:block;margin-bottom:4px">ТЕКСТ ПИСЬМА</label>
|
||||
<textarea id="ed-body" rows="9"
|
||||
style="width:100%;border:1.5px solid var(--line);border-radius:9px;padding:9px 12px;font-size:13px;font-family:inherit;outline:none;color:var(--ink);resize:vertical;line-height:1.55"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style="display:flex;gap:8px;margin-top:16px;flex-wrap:wrap">
|
||||
<button onclick="_emailOpenClient()"
|
||||
style="flex:1;min-width:150px;background:var(--bg);color:#fff;border:none;border-radius:11px;padding:11px;font-size:13px;font-weight:700;cursor:pointer;font-family:inherit">
|
||||
✉️ Открыть в почте
|
||||
</button>
|
||||
<button onclick="_emailCopy()"
|
||||
style="flex:1;min-width:120px;background:var(--surf);color:var(--ink);border:1.5px solid var(--line);border-radius:11px;padding:11px;font-size:13px;font-weight:600;cursor:pointer;font-family:inherit">
|
||||
📋 Копировать
|
||||
</button>
|
||||
<button onclick="_emailDraftClose()"
|
||||
style="background:var(--surf);color:var(--mut);border:1.5px solid var(--line);border-radius:11px;padding:11px 14px;font-size:13px;cursor:pointer;font-family:inherit">
|
||||
Отмена
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ── МОДАЛКА: БЛАНК Ф.119 (Почта России) ── -->
|
||||
<style>
|
||||
#postal-form-overlay{display:none;position:fixed;inset:0;background:rgba(0,0,0,.5);z-index:9000;align-items:flex-end;justify-content:center}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user