Files
My-scripts/Auto lead/tampermonkey scrypt61.txt
T
yasusan 9343b305ba Загрузить файлы в «Auto lead»
Скрипт тамперманки
2026-05-29 07:23:37 +00:00

285 lines
11 KiB
Plaintext

// ==UserScript==
// @name Автоподстановка лидов
// @namespace http://tampermonkey.net/
// @version 6.1
// @include https://admin2.gtn.ru/clients/new/newclient.php*
// @updateURL http://192.168.254.38:8765/lead_autofill.user.js
// @downloadURL http://192.168.254.38:8765/lead_autofill.user.js
// @grant none
// ==/UserScript==
(function() {
'use strict';
const SERVER_URL = 'http://192.168.254.38:8765';
let lastQueueSize = 0;
// Получение следующего лида (первый из очереди)
async function fetchNextLead() {
try {
const res = await fetch(`${SERVER_URL}/lead`);
const data = await res.json();
if (data.lead) {
fillForm(data.lead);
showNotification(`? Подставлено. Осталось: ${data.queue_size}`);
updateCounter(data.queue_size);
} else {
showNotification('?? Нет лидов в очереди');
}
} catch(e) {
console.error(e);
showNotification('? Сервер не доступен');
}
}
// Получение лида по индексу (из меню)
async function fetchLeadByIndex(index) {
try {
const res = await fetch(`${SERVER_URL}/lead?index=${index}`);
const data = await res.json();
if (data.lead) {
fillForm(data.lead);
showNotification(`? Подставлен выбранный лид. Осталось: ${data.queue_size}`);
updateCounter(data.queue_size);
} else {
showNotification('? Ошибка при загрузке лида');
}
} catch(e) {
console.error(e);
showNotification('? Сервер не доступен');
}
}
// Получение списка лидов для меню
async function fetchQueueList() {
try {
const res = await fetch(`${SERVER_URL}/queue_list`);
const data = await res.json();
return data.list || [];
} catch(e) {
console.error(e);
return [];
}
}
// Обновление счётчика на кнопке
async function updateCounter(forceSize = null) {
try {
if (forceSize !== null) {
lastQueueSize = forceSize;
} else {
const res = await fetch(`${SERVER_URL}/queue`);
const data = await res.json();
lastQueueSize = data.size;
}
const btn = document.getElementById('lead-queue-btn');
if (btn) {
btn.innerHTML = `?? Лиды (${lastQueueSize})`;
btn.style.background = lastQueueSize > 0 ? '#4CAF50' : '#9E9E9E';
}
} catch(e) {
console.error('Ошибка обновления счётчика:', e);
const btn = document.getElementById('lead-queue-btn');
if (btn) {
btn.innerHTML = `?? Ошибка`;
btn.style.background = '#f44336';
}
}
}
// Заполнение формы
function fillForm(lead) {
// Имя
const firstName = document.querySelector('[name="first_name"]');
if (firstName && lead.first_name) firstName.value = lead.first_name;
// Фамилия
const surname = document.querySelector('[name="surname"]');
if (surname && lead.surname) surname.value = lead.surname;
// Отчество
const secondName = document.querySelector('[name="second_name"]');
if (secondName && lead.second_name) secondName.value = lead.second_name;
// Телефон (только цифры, без +7)
const phoneField = document.querySelector('[name="phone[0]"]');
if (phoneField && lead.phone) {
let cleanPhone = lead.phone.replace(/[^\d]/g, '');
if (cleanPhone.startsWith('7') && cleanPhone.length === 11) {
cleanPhone = cleanPhone.substring(1);
}
phoneField.value = cleanPhone;
}
// Email
const emailField = document.querySelector('[name="email[0]"]');
if (emailField && lead.email) emailField.value = lead.email;
// Город
if (lead.town) {
const select = document.querySelector('select[name="town_id"]');
if (select) {
for (let opt of select.options) {
if (opt.text.toLowerCase().includes(lead.town.toLowerCase())) {
select.value = opt.value;
break;
}
}
}
}
// Тип клиента
if (lead.client_type) {
const clientType = document.querySelector('#client_type, select[name="client_type_id"]');
if (clientType) {
const typeLower = lead.client_type.toLowerCase();
if (typeLower.includes('физическое') || typeLower.includes('физ')) {
clientType.value = '1';
} else if (typeLower.includes('юридическое') || typeLower.includes('юр')) {
clientType.value = '2';
}
}
}
// Всё в комментарий
const commentField = document.querySelector('[name="address_comment"]');
if (commentField && lead.addition) {
commentField.value = lead.addition;
}
console.log('? Форма заполнена:', lead.first_name, lead.phone);
}
// Показать уведомление
function showNotification(text) {
const div = document.createElement('div');
div.textContent = text;
div.style.cssText = `
position: fixed;
top: 20px;
right: 20px;
background: #4CAF50;
color: white;
padding: 10px 20px;
border-radius: 5px;
z-index: 100000;
font-size: 14px;
font-family: sans-serif;
box-shadow: 0 2px 10px rgba(0,0,0,0.2);
`;
document.body.appendChild(div);
setTimeout(() => div.remove(), 3000);
}
// Показать меню со списком лидов
async function showMenu() {
const list = await fetchQueueList();
if (list.length === 0) {
showNotification('?? Нет лидов в очереди');
return;
}
// Удаляем старое меню, если есть
const oldMenu = document.getElementById('lead-menu');
if (oldMenu) oldMenu.remove();
let menuHtml = `
<div id="lead-menu" style="position:fixed; bottom:80px; right:20px; background:white; border:1px solid #ccc; border-radius:8px; box-shadow:0 2px 10px rgba(0,0,0,0.2); z-index:100000; width:320px; max-height:400px; overflow-y:auto;">
<div style="padding:10px; background:#2196F3; color:white; border-radius:8px 8px 0 0; font-weight:bold; cursor:pointer;" id="menu-header">?? Выберите лид (${list.length}) ?</div>
<div style="max-height:350px; overflow-y:auto;">
`;
list.forEach((lead, idx) => {
const name = lead.first_name || 'Без имени';
const phone = lead.phone || 'без телефона';
const email = lead.email || '';
const timeStr = lead.received_at ? ` [${escapeHtml(lead.received_at)}]` : '';
menuHtml += `
<div class="menu-item" data-index="${idx}" style="padding:10px 12px; border-bottom:1px solid #eee; cursor:pointer;">
<div><strong>${escapeHtml(name)}</strong>${timeStr}</div>
<div style="font-size:12px; color:#666;">${escapeHtml(phone)} ${email ? '| ' + escapeHtml(email) : ''}</div>
</div>
`;
});
menuHtml += `
</div>
</div>
`;
const menuDiv = document.createElement('div');
menuDiv.innerHTML = menuHtml;
document.body.appendChild(menuDiv);
// Закрытие по клику на крестик/заголовок
document.getElementById('menu-header').addEventListener('click', () => menuDiv.remove());
// Обработка выбора лида
menuDiv.querySelectorAll('.menu-item').forEach(item => {
item.addEventListener('click', () => {
const idx = parseInt(item.dataset.index);
fetchLeadByIndex(idx);
menuDiv.remove();
});
});
// Закрытие при клике вне меню
setTimeout(() => {
document.addEventListener('click', function closeMenu(e) {
if (!menuDiv.contains(e.target) && e.target.id !== 'lead-queue-btn') {
menuDiv.remove();
document.removeEventListener('click', closeMenu);
}
});
}, 100);
}
function escapeHtml(str) {
if (!str) return '';
return str.replace(/[&<>]/g, function(m) {
if (m === '&') return '&amp;';
if (m === '<') return '&lt;';
if (m === '>') return '&gt;';
return m;
});
}
// Создание кнопки
const btn = document.createElement('button');
btn.id = 'lead-queue-btn';
btn.textContent = '?? Лиды (0)';
btn.style.cssText = `
position: fixed;
bottom: 20px;
right: 20px;
z-index: 9999;
background: #9E9E9E;
color: white;
border: none;
padding: 12px 24px;
border-radius: 8px;
cursor: pointer;
font-size: 14px;
font-weight: bold;
font-family: sans-serif;
transition: all 0.2s;
box-shadow: 0 2px 5px rgba(0,0,0,0.2);
`;
// Клик левой кнопкой — показать меню
btn.onclick = showMenu;
// Клик правой кнопкой — взять следующий лид (без меню)
btn.oncontextmenu = (e) => {
e.preventDefault();
fetchNextLead();
return false;
};
window.addEventListener('load', () => {
document.body.appendChild(btn);
updateCounter();
setInterval(updateCounter, 10000);
});
})();