// ==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 = `
`; 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 '&'; if (m === '<') return '<'; if (m === '>') return '>'; 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); }); })();