Дата: Понедельник, 30.03.2026, 03:54 | Сообщение # 1 |
|
Написал: Узнаваемый
Автор темы
Мурчанн
не в сети
Сообщений: 232
Новый этап развития блока друзей Проведена работа над улучшением интерфейса и визуальной составляющей. Основные изменения коснулись CSS-стилей и удобства взаимодействия. Во всплывающем окне переработана форма поиска: теперь при наведении она плавно расширяется, становится визуально шире и подсвечивается более ярким белым цветом. Поиск работает в реальном времени , достаточно ввести любую букву, и система мгновенно отобразит друзей, в чьём нике она встречается. Не нужно нажимать кнопку , форма достаточно умная и реагирует сразу на ввод. Аватары пользователей были скруглены до 50%, что придало интерфейсу более современный и аккуратный вид. Индикатор онлайн-статуса уменьшен акцент сделан на миниатюрность и компактность элементов. Удалось реализовать не всё из задуманного, хотелось добавить больше стеклянности и прозрачности интерфейсу. Вероятно, этот эффект будет доработан в следующей версии. Также обновлена логика кнопки удаления: крестик теперь появляется только при наведении курсора на область пользователя. Это делает интерфейс чище и удобнее , лишние элементы не отвлекают внимание, но всегда доступны при необходимости. Дополнительно улучшена обводка числовых индикаторов: при наведении добавлено лёгкое, почти незаметное увеличение, которое делает интерфейс более «живым». Размер блока был уменьшен с 400px до 390px. В дальнейшем планируется продолжить движение в сторону уменьшения, делая интерфейс ещё более компактным, минималистичным и визуально лёгким, с акцентом на прозрачность и стеклянные эффекты.Исходной код: Код
<!-- MINI BLOCK ДРУЗЬЯ --> <div class="vk-old-block"> <div class="vk-old-header">Друзья</div> <div class="vk-old-footer" id="friends-count">0 друзей</div> <div class="vk-old-content"> <div class="vk-friends"></div> </div> <div class="vk-old-footer" id="friends-footer" title="Показать всех друзей"> Показать всех друзей → </div> </div> <link rel="stylesheet" href="/css/friends01.css" media="all"> <div id="uc-online-list" style="display:none;"> $ONLINE_USERS_LIST$ </div> <script> (function(){ const USER_ID = window.UCOZ_DATA?.userId || "0"; if(USER_ID === "0") return; const $container = $('.vk-friends'); const $counter = $('#friends-count'); const $footer = $('#friends-footer'); const DEFAULT_AVA = '/.s/src/profile/img/profile_photo_thumbnail.png'; const LS_FRIENDS = 'friends_' + USER_ID; let allFriends = []; /* ========================= РЕНДЕР МИНИ-БЛОКА ========================= */ function renderMini(friends){ const onlineHtml = $('#uc-online-list').text().toLowerCase(); if(!friends || friends.length === 0){ const empty = document.createElement('div'); empty.className = 'vk-empty-wrap'; empty.innerHTML = ` <div class="vk-empty-icon"> <svg width="58" height="58" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <path d="M16 11c1.66 0 3-1.34 3-3S17.66 5 16 5s-3 1.34-3 3 1.34 3 3 3zM8 11c1.66 0 3-1.34 3-3S9.66 5 8 5 5 6.34 5 8s1.34 3 3 3z" fill="#99a2ad"/> <path d="M8 13c-2.67 0-8 1.34-8 4v2h10v-2c0-1.2.6-2.3 1.6-3.2C10.3 13.3 9 13 8 13zm8 0c-.9 0-2.3.2-3.6.8 1 .9 1.6 2 1.6 3.2v2h10v-2c0-2.66-5.33-4-8-4z" fill="#99a2ad"/> </svg> </div> <div class="vk-empty-title">У вас нет друзей</div> <div class="vk-empty-sub">Добавляйте людей, чтобы видеть их здесь</div> <div class="vk-empty-action"> <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"> <line x1="12" y1="5" x2="12" y2="19"></line> <line x1="5" y1="12" x2="19" y2="12"></line> </svg> Добавить друзей </div> `; empty.querySelector('.vk-empty-action').onclick = () => { location.href = '/index/15-2'; }; $container[0].replaceChildren(empty); $counter.html('0 друзей'); return; } /* Обычный список друзей */ $container.empty(); friends.slice(0, 6).forEach(f => { const isOnline = onlineHtml.includes(f.nick.toLowerCase()); const statusDot = `<span class="statusDot ${isOnline ? 'onlineDot' : 'offlineDot'}"></span>`; const card = $(` <div class="vk-friend" title="${f.nick}"> <img src="${f.ava}"> <span>${f.nick}</span> ${statusDot} </div> `); card.on('click', () => location.href = f.profile); $container.append(card); }); $counter.html(`${friends.length} друзей`); } /* ========================= POPUP (стрелка + удаление) ========================= */ function showPopup(){ if(!allFriends.length) return; const overlay = $('<div class="vk-ui-overlay"></div>'); const popup = $(` <div class="vk-ui-popup"> <div class="vk-ui-header"> <div class="vk-ui-title"> Друзья <span class="vk-ui-title-count">${allFriends.length}</span> </div> <div class="vk-ui-search"> <input type="text" placeholder="Поиск друзей" id="friend-search"> </div> <button class="vk-ui-close" title="Закрыть">×</button> </div> <div class="vk-ui-list"></div> </div> `); const list = popup.find('.vk-ui-list'); const onlineHtml = $('#uc-online-list').text().toLowerCase(); function renderList(filter = ''){ list.empty(); allFriends .filter(f => f.nick.toLowerCase().includes(filter.toLowerCase())) .forEach(f => { let badge = 'Без статуса', cls = 'nostatus', letter = ''; const g = f.group.toLowerCase(); if(g.includes('кумир')) { badge='Кумир'; cls='idol'; letter='К'; } else if(g.includes('друг')) { badge='Друг'; cls='friend'; letter='Д'; } else if(g.includes('сем')) { badge='Семья'; cls='family'; letter='С'; } else if(g.includes('знаком')) { badge='Знакомый'; cls='acquaintance'; letter='З'; } else if(g.includes('прият')) { badge='Приятель'; cls='buddy'; letter='П'; } const isOnline = onlineHtml.includes(f.nick.toLowerCase()); const row = $(` <div class="vk-ui-row ${cls}"> <!-- аватар --> <div class="vk-ui-ava"> <img src="${f.ava}"> ${letter ? `<span class="vk-ui-letter ${cls}">${letter}</span>` : ''} <span class="statusDot ${isOnline ? 'onlineDot' : 'offlineDot'}"></span> </div> <!-- инфо --> <div class="vk-ui-info"> <div class="vk-ui-name">${f.nick}</div> <div class="vk-ui-badge ${cls}">${badge}</div> </div> <!-- правая часть --> <div class="vk-ui-actions"> <!-- КОРЗИНА (удаление) --> <button class="vk-del-btn" title="Удалить">✕</button> <!-- СТРЕЛКА (переход) --> <div class="vk-ui-arrow">›</div> </div> </div> `); /* ========================= ПЕРЕХОД В ПРОФИЛЬ (стрелка + строка) ========================= */ row.on('click', () => location.href = f.profile); /* ========================= УДАЛЕНИЕ (крестик) ========================= */ row.find('.vk-del-btn').on('click', function(e){ e.stopPropagation(); if(!f.del){ alert('Ошибка: нет ссылки удаления'); return; } if(!confirm(`Удалить ${f.nick} из друзей?`)) return; const btn = $(this); btn.text('...'); $.get(f.del) .done(() => { allFriends = allFriends.filter(x => x.nick !== f.nick); row.fadeOut(200, () => row.remove()); renderMini(allFriends); $counter.html(`${allFriends.length} друзей`); localStorage.setItem(LS_FRIENDS, JSON.stringify(allFriends)); }) .fail(() => { alert('Ошибка удаления'); btn.text('✕'); }); }); list.append(row); }); } renderList(); popup.find('#friend-search').on('input', function(){ renderList($(this).val()); }); popup.find('.vk-ui-close').on('click', () => overlay.remove()); overlay.on('click', e => { if(e.target === overlay[0]) overlay.remove(); }); overlay.append(popup); $('body').append(overlay); } /* ========================= ЗАГРУЗКА ДАННЫХ С СЕРВЕРА ========================= */ function loadFriends(){ $.get(`/blog/0-0-1-0-17-${USER_ID}`, html => { const $tmp = $('<div>').html(html); const updated = []; $tmp.find('.friend').each(function(){ const $el = $(this); let group = $el.find('.gr').text().trim() || 'Без статуса'; const g = group.toLowerCase(); if(!['друг','кумир','семья','знакомый','приятель'].some(k => g.includes(k))) { group = 'Приятель'; } // ВАЖНО: добавляем ссылку удаления const delLink = $el.find('.del').text().trim(); updated.push({ nick: $el.find('.nick').text().trim(), ava: $el.find('.ava').text().trim() || DEFAULT_AVA, profile: $el.find('.url').text().trim(), group: group, del: delLink || null // ← теперь у каждого друга есть ссылка удаления }); }); // сравнение теперь учитывает del const changed = JSON.stringify(updated) !== JSON.stringify(allFriends); if(changed){ allFriends = updated; // сохраняем в кеш localStorage.setItem(LS_FRIENDS, JSON.stringify(allFriends)); // обновляем UI renderMini(allFriends); console.log('Друзья обновлены:', allFriends.length); } }) .fail(() => { console.warn('Не удалось загрузить список друзей'); }); } /* ========================= ИНИЦИАЛИЗАЦИЯ ========================= */ $counter.add($footer) .css('cursor','pointer') .attr('title','Показать всех друзей') .on('click', showPopup); // Показываем кэш сразу try { const cached = JSON.parse(localStorage.getItem(LS_FRIENDS) || "[]"); if(cached.length){ allFriends = cached; renderMini(allFriends); } else { renderMini([]); } } catch(e){ renderMini([]); } // Тихая загрузка актуальных данных setTimeout(loadFriends, 800); // небольшая задержка, чтобы страница успела загрузиться // Дополнительно обновляем каждые 30 секунд (на случай удаления/добавления друга) setInterval(loadFriends, 30000); })(); </script>
Признаюсь, не знаю почему, но глядя на звезды мне всегда хочется мечтать.