Дата: Вторник, 10.02.2026, 14:24 | Сообщение # 1 |
|
Написал: Узнаваемый
Автор темы
Мурчанн
не в сети
Сообщений: 211
Описание работы скрипта «Плавающий помощник сообщений» Данный скрипт представляет собой плавающую панель-помощник для контроля личных сообщений пользователя в реальном времени. Он работает незаметно, не мешает просмотру сайта и появляется только тогда, когда действительно нужен.Принцип работы Панель выполняет роль мини-центра сообщений: Скрипт постоянно проверяет наличие новых личных сообщений Панель появляется только если сообщений больше 5 Если сообщений нет , панель автоматически скрывается Работает в фоне как «тихий помощник»Поведение панели Когда сообщений становится больше 5: В правом нижнем углу появляется плавающая панель уведомлений Показывается счётчик новых сообщений Отображаются: аватар отправителя имя текст сообщения датаПанель не мешает работе пользователя и остаётся поверх страницы. Сворачивание / разворачивание Скрипт работает как помощник просмотра: Можно развернуть панель и посмотреть сообщения Можно свернуть, чтобы она не мешала Скрипт запоминает состояние (свернуто / открыто) После обновления страницы панель остаётся в том же видеТо есть - открыл, посмотрел, свернул, живёшь дальше 👍Код
<?if($USER_LOGGED_IN$)?> <style> /* ======= СТИЛЬ СТАРОГО ВК ======= */ /* ======= OLD VK STYLE REWORK ======= */ .vk-notify{ position:fixed; right:20px; bottom:20px; width:300px; font-family:Tahoma, Arial, sans-serif; font-size:12px; border-radius:8px; overflow:hidden; display:none; z-index:9999; background:#e9edf3; box-shadow:0 8px 22px rgba(0,0,0,0.25); transition:all .25s ease; } /* ===== ШАПКА ===== */ .vk-notify-header{ background:linear-gradient(#5b84b6,#4a76a8); color:#fff; padding:9px 10px; font-weight:bold; cursor:pointer; display:flex; justify-content:space-between; align-items:center; border-bottom:1px solid rgba(0,0,0,0.15); } .vk-notify-header b{ background:#fff; color:#4a76a8; border-radius:50px; padding:1px 7px; font-weight:bold; box-shadow:0 1px 2px rgba(0,0,0,0.2); } #vkNotifyToggle{ background:none; border:none; color:#fff; font-size:12px; cursor:pointer; opacity:.85; transition:.15s; } #vkNotifyToggle:hover{ opacity:1; transform:scale(1.1); } /* ===== ТЕЛО ===== */ .vk-notify-body{ max-height:365px; overflow-y:auto; background:#f0f3f7; padding:4px; } /* СКРОЛЛ */ .vk-notify-body::-webkit-scrollbar{ width:6px; } .vk-notify-body::-webkit-scrollbar-thumb{ background:#c7ced8; border-radius:10px; } .vk-notify-body::-webkit-scrollbar-track{ background:transparent; } /* ===== СООБЩЕНИЕ ===== */ .vk-item{ display:flex; align-items:center; gap:8px; padding:8px 10px; margin:4px 2px; cursor:pointer; /* форма: слева капсула, справа почти ровно */ border-radius:10px 10px 8px 10px; /* мягкий светлый желтый */ background:linear-gradient(#fffbe6,#fff3b0); border:1px solid #eadf9b; /* объём */ box-shadow: inset 0 1px 0 rgba(255,255,255,0.75), 0 1px 2px rgba(0,0,0,0.08); transition:all .15s ease; } /* HOVER — мягкий old VK */ .vk-item:hover{ background:linear-gradient(#fff7c9,#ffe88c); border-color:#e2d276; box-shadow: inset 0 1px 0 rgba(255,255,255,0.85), 0 2px 5px rgba(0,0,0,0.12); transform:translateY(-1px); } /* HOVER как в старом VK */ .vk-item:hover{ background:linear-gradient(#fff7c9,#ffe88c); border-color:#e2d276; box-shadow: inset 0 1px 0 rgba(255,255,255,0.8), 0 2px 5px rgba(0,0,0,0.12); transform:translateY(-1px); } /* АВАТАР */ .vk-item img{ width:42px; height:42px; border-radius:50%; object-fit:cover; border:1px solid #cfd6e0; background:#fff; box-shadow:0 1px 2px rgba(0,0,0,0.2); } /* ТЕКСТ */ .vk-item-title{ font-weight:bold; color:#2a5885; margin-bottom:1px; } .vk-item-text{ color:#111; font-size:13px; line-height:1.25; } .vk-item-date{ color:#7c8796; font-size:11px; margin-top:2px; } .vk-notify-empty{ padding:12px; text-align:center; color:#6f7b8c; } /* ===== СВЕРНУТО ===== */ .vk-notify.collapsed .vk-notify-body{ max-height:0 !important; padding:0 !important; overflow:hidden; } </style> <div id="vkNotifyPanel" class="vk-notify"> <div class="vk-notify-header"> <span>Личные сообщения <b id="vkNotifyBadge">0</b></span> <button id="vkNotifyToggle">—</button> </div> <div class="vk-notify-body"> <div class="vk-notify-empty">Загрузка сообщений...</div> </div> </div> <script> window.friends = window.friends || {}; (function ($, friends) { const DEFAULT_AVA = "/files/person.png"; const CHECK_DELAY = 20000; const STORAGE_KEY = "vkNotifyCollapsed"; const avatarCache = {}; const panel = $("#vkNotifyPanel"); const body = panel.find(".vk-notify-body"); const badge = $("#vkNotifyBadge"); const toggleBtn = $("#vkNotifyToggle"); /* ================= СОСТОЯНИЕ ПАНЕЛИ ================= */ function setCollapsed(state){ if(state){ panel.addClass("collapsed").removeClass("expanded"); toggleBtn.text("+"); localStorage.setItem(STORAGE_KEY, "1"); }else{ panel.removeClass("collapsed").addClass("expanded"); toggleBtn.text("—"); localStorage.setItem(STORAGE_KEY, "0"); } } setCollapsed(localStorage.getItem(STORAGE_KEY) === "1"); toggleBtn.on("click", function(e){ e.stopPropagation(); setCollapsed(!panel.hasClass("collapsed")); }); panel.find(".vk-notify-header").on("click", function(e){ if($(e.target).is("#vkNotifyToggle")) return; toggleBtn.click(); }); /* ================= ПОЛУЧЕНИЕ АВАТАРА (С КЭШЕМ) ================= */ async function fetchAvatar(profileUrl){ if(!profileUrl) return DEFAULT_AVA; if(avatarCache[profileUrl]) return avatarCache[profileUrl]; try{ const html = await $.get(profileUrl + "?r=" + Math.random()); const bg = $(html).find(".profile-photo").first().css("background-image") || ""; const m = bg.match(/url\(['"]?(.*?)['"]?\)/i); avatarCache[profileUrl] = m ? m[1] : DEFAULT_AVA; return avatarCache[profileUrl]; }catch(e){ return DEFAULT_AVA; } } /* ================= ЗАГРУЗКА СООБЩЕНИЙ ================= */ async function loadMessages(){ try{ const html = await $.get("/index/14?" + Math.random()); const $dom = $("<div>").append($.parseHTML(html)); const $msgs = $dom.find("b.unread"); badge.text($msgs.length); if($msgs.length === 0){ panel.fadeOut(200); body.html('<div class="vk-notify-empty">Нет новых сообщений</div>'); return; } panel.fadeIn(200); const oldScroll = body.scrollTop(); const atBottom = body[0].scrollHeight - body.innerHeight() - oldScroll < 15; body.empty(); for(const el of $msgs.toArray()){ const $msg = $(el); const $row = $msg.closest("tr, li, div"); const title = $msg.text().trim() || "Новое сообщение"; const $nick = $row.find("a[href*='/index/8-0-']").last(); let sender = $nick.text().trim() || "Пользователь"; let profile = $nick.attr("href"); if(profile && profile.startsWith("/")) profile = location.origin + profile; const avatar = await fetchAvatar(profile); const dateText = $row.find("td:nth-child(3), .message-date, time") .first().text().trim() || ""; const link = $msg.parent().attr("href") || "#"; body.append(` <div class="vk-item" onclick="window.location.href='${link}'"> <img src="${avatar}" onerror="this.src='${DEFAULT_AVA}'"> <div> <div class="vk-item-title">${sender}</div> <div class="vk-item-text">${title}</div> <div class="vk-item-date">${dateText}</div> </div> </div> `); } /* сохраняем позицию скролла */ if(atBottom){ body.scrollTop(body[0].scrollHeight); }else{ body.scrollTop(oldScroll); } }catch(e){ console.error("PM Load Error:", e); body.html('<div class="vk-notify-empty">Ошибка загрузки</div>'); } } /* ================= АВТО ОБНОВЛЕНИЕ ================= */ friends.checkPm = function(){ loadMessages(); setTimeout(friends.checkPm, CHECK_DELAY); }; friends.checkPm(); })(jQuery, window.friends); </script> <?else?> <!-- Гости ничего не видят --> <?endif?>
Признаюсь, не знаю почему, но глядя на звезды мне всегда хочется мечтать.