@@ -1093,8 +1141,8 @@ function renderCustomStats() {
if (!el) {
el = document.createElement('div'); el.id = 'custom-stats-pill';
el.className = 'stats-pill'; el.style.bottom = '52px';
- el.title = 'Нажать — очистить';
- el.onclick = () => { localStorage.removeItem('zashita_custom_delivs'); renderCustomStats(); };
+ el.title = 'Открыть аналитику';
+ el.onclick = () => { renderCustomAdmin(); go('custom-admin'); };
document.body.appendChild(el);
}
el.style.display = 'block';
@@ -1164,8 +1212,148 @@ function selectPlan(n) {
}
}
+
+/* ── АНАЛИТИКА CUSTOM-ЗАПРОСОВ ── */
+const CA_STOPWORDS = new Set(['и','в','на','с','по','для','что','это','как','не','а','но','из','к','о','от','за','до','при','без','под','над','со','об','же','бы','ли','ещё','уже','когда','если','мне','мы','я','вы','он','она','они','то','так','ну','ладно','просто','только','очень','нет','да','быть','есть','это','свой','мой','ваш','наш','его','её','их','все','всё','один','одна','других','другой','которые','который','можно','нужно','надо','хочу','хочется','нужна','нужен','нужно','получить','сделать','чтобы','также']);
+
+function caWordFreq(arr) {
+ const freq = {};
+ arr.forEach(r => {
+ const words = (r.text || '').toLowerCase()
+ .replace(/[^а-яёa-z\s]/g, ' ')
+ .split(/\s+/)
+ .filter(w => w.length > 3 && !CA_STOPWORDS.has(w));
+ words.forEach(w => { freq[w] = (freq[w] || 0) + 1; });
+ });
+ return Object.entries(freq)
+ .sort((a, b) => b[1] - a[1])
+ .slice(0, 15);
+}
+
+function caFmtDate(ts) {
+ try {
+ const d = new Date(ts);
+ return d.toLocaleDateString('ru-RU', {day:'2-digit',month:'short',hour:'2-digit',minute:'2-digit'});
+ } catch(e) { return ts; }
+}
+
+function caAddToSystem(idx) {
+ const arr = JSON.parse(localStorage.getItem('zashita_custom_delivs') || '[]');
+ if (arr[idx]) { arr[idx].added = true; localStorage.setItem('zashita_custom_delivs', JSON.stringify(arr)); }
+ renderCustomAdmin();
+}
+
+function caCopyText(text) {
+ navigator.clipboard.writeText(text).catch(() => {});
+ showToast('Скопировано');
+}
+
+function caExportCSV() {
+ const arr = JSON.parse(localStorage.getItem('zashita_custom_delivs') || '[]');
+ if (!arr.length) return;
+ const rows = [['Дата','Тип договора','Запрос','Добавлено в систему']];
+ arr.forEach(r => rows.push([
+ r.ts || '', (r.ctype || '').replace(/,/g,''),
+ '"' + (r.text || '').replace(/"/g,'""') + '"',
+ r.added ? 'да' : 'нет'
+ ]));
+ const csv = rows.map(r => r.join(',')).join('\n');
+ const a = document.createElement('a');
+ a.href = 'data:text/csv;charset=utf-8,' + encodeURIComponent('' + csv);
+ a.download = 'zashita_custom_' + new Date().toISOString().slice(0,10) + '.csv';
+ a.click();
+}
+
+function caExportJSON() {
+ const arr = JSON.parse(localStorage.getItem('zashita_custom_delivs') || '[]');
+ navigator.clipboard.writeText(JSON.stringify(arr, null, 2))
+ .then(() => showToast('JSON скопирован в буфер'))
+ .catch(() => showToast('Ошибка копирования'));
+}
+
+function caClearAll() {
+ if (!confirm('Удалить все custom-запросы?')) return;
+ localStorage.removeItem('zashita_custom_delivs');
+ renderCustomStats();
+ renderCustomAdmin();
+}
+
+function renderCustomAdmin() {
+ const arr = JSON.parse(localStorage.getItem('zashita_custom_delivs') || '[]');
+ const body = document.getElementById('ca-body');
+ if (!body) return;
+
+ if (!arr.length) {
+ body.innerHTML = '
📭
Пока нет запросов.
Они появятся когда клиент нажмёт «Отправить запрос».
';
+ return;
+ }
+
+ const ctypes = [...new Set(arr.map(r => (r.ctype||'').trim()).filter(Boolean))];
+ const words = caWordFreq(arr);
+ const added = arr.filter(r => r.added).length;
+
+ // Статистика
+ let html = `
+
${arr.length}
Всего запросов
+
${ctypes.length || '—'}
Типов договора
+
${added}
Добавлено в систему
+
`;
+
+ // Частотный анализ
+ if (words.length) {
+ html += '
Частые темы запросов
';
+ const maxCnt = words[0][1];
+ words.forEach(([w, c]) => {
+ const isTop = c === maxCnt;
+ html += `
${w}${c}
`;
+ });
+ html += '
';
+ }
+
+ // Список запросов
+ html += '
Все запросы
';
+ arr.slice().reverse().forEach((r, i) => {
+ const realIdx = arr.length - 1 - i;
+ const ctypeLabel = (r.ctype||'').trim() || 'тип не определён';
+ html += `
+
+ ${ctypeLabel}
+ ${caFmtDate(r.ts)}
+
+
${r.text || ''}
+
+
+
+
+
`;
+ });
+
+ // Экспорт
+ html += `
+
+
+
+
`;
+
+ body.innerHTML = html;
+}
+
+function showToast(msg) {
+ let t = document.getElementById('ca-toast');
+ if (!t) {
+ t = document.createElement('div'); t.id = 'ca-toast';
+ t.style.cssText = 'position:fixed;bottom:90px;left:50%;transform:translateX(-50%);background:#0C0608;color:#fff;padding:9px 18px;border-radius:10px;font-size:13px;z-index:99999;pointer-events:none;transition:opacity .3s';
+ document.body.appendChild(t);
+ }
+ t.textContent = msg; t.style.opacity = '1';
+ clearTimeout(t._to); t._to = setTimeout(() => { t.style.opacity = '0'; }, 2000);
+}
+
window.addEventListener('DOMContentLoaded', renderStats);
window.addEventListener('DOMContentLoaded', renderCustomStats);
+window.addEventListener('DOMContentLoaded', renderCustomAdmin);
function tab(name){
document.querySelectorAll('.tabpane').forEach(p=>p.classList.toggle('on',p.id==='p-'+name));
document.querySelectorAll('.side a').forEach(a=>a.classList.remove('on'));