Дата: Пятница, 20.02.2026, 12:50 | Сообщение # 1 |
|
Написал: Узнаваемый
Автор темы
Мурчанн
не в сети
Сообщений: 211
Логика работы скрипта была изменена. Ранее, при отсутствии фотографий, скрипт сначала выполнял проверку их количества, и только после завершения этой проверки отображалось системное уведомление о том, что фотографий нет и их необходимо добавить. Поскольку на выполнение проверки требовалось время, сообщение выводилось не сразу , пользователь сначала видел пустую область (белое окно), а затем появлялось системное уведомление. Такой сценарий создавал ощущение задержки и некорректной работы интерфейса. Новая логика построена по принципу работы реального серверного процесса. Интерфейс сразу получает состояние и отображает результат: если фотографии существуют , они показываются немедленно, если их нет ,мгновенно выводится системное сообщение об их отсутствии. Таким образом, мы эмулируем поведение настоящего сервера, обеспечивая быстрый отклик интерфейса и корректное отображение состояния данных без визуальных задержек. Не вижу смысла подробно описывать работу скрипта , это лишь займет время. Гораздо нагляднее показать видео с демонстрацией его работы в реальных условиях. В динамике видно, как всё происходит на практике, и поведение практически неотличимо от работы настоящих серверных процессов. Сейчас я сосредоточился на выявлении и устранении всех существующих проблем, недочётов и багов. Прежде чем двигаться дальше и добавлять новый функционал, необходимо довести до стабильного состояния работу всех текущих модулей и разделов. Например, требуется создать новую версию интерактивного окна сообщений. В текущей реализации обнаружен баг: система публикует новость, однако не учитывает параметр разрешения на комментарии , сообщения с комментариями не помечаются корректно, и настройка фактически игнорируется. Этот модуль требует срочной модернизации. После его доработки я продолжу аудит системы и поэтапное выявление остальных проблем, даже если это займёт дополнительное время.Исходной код: Код
<link rel="stylesheet" href="https://bro.usite.pro/css/vk-poss1.css" media="all"> <!-- Подключаем шрифт Roboto для аккуратного вида --> <link href="https://fonts.googleapis.com/css2?family=Roboto:wght@400;500;600&display=swap" rel="stylesheet"> <style> /* Сетка фото */ .profile-photo-grid { display: flex; gap: 8px; flex-wrap: wrap; justify-content: flex-start; } /* Карточка фото */ .profile-photo-grid .photo-card { width: 131px; height: 140px; border-radius: 2px; /* более мягкое скругление */ overflow: hidden; background: #f7f9fc; /* светлый фон */ box-shadow: 0 2px 4px rgba(0,0,0,0.08), 0 4px 12px rgba(0,0,0,0.12); transition: transform 0.25s ease, box-shadow 0.25s ease, border 0.25s ease; position: relative; cursor: pointer; } /* Ховер как в ВК */ .profile-photo-grid .photo-card:hover { transform: translateY(5px); box-shadow: 0 4px 14px rgba(0,0,0,0.18); } /* Картинка */ .profile-photo-grid .photo-card img { width: 100%; height: 100%; object-fit: cover; display: block; transition: transform 0.25s ease; } /* Лёгкий зум */ .profile-photo-grid .photo-card:hover img { transform: scale(1.01); } /* Градиентная обводка при hover */ .profile-photo-grid .photo-card::after { content: ""; position: absolute; inset: 0; border-radius: 0px; border: 1px solid transparent; pointer-events: none; transition: border-color 0.25s ease; } .profile-photo-grid .photo-card:hover::after { border-color: #e6c700; box-shadow: 0 0 12px rgba(59,130,246,0.4); } /* Оптимизация под мобильные экраны */ @media (max-width: 480px) { .profile-photo-grid .photo-card { width: 100px; height: 100px; border-radius: 10px; } } </style> <div id="user-photos"></div> <script> (function($){ $(function(){ if (typeof $ === 'undefined') return; const userId = "$USER_ID$" || '0'; const profileUrl = "$PERSONAL_PAGE_LINK$"; if (!userId || userId === '0') return; const maxPhotos = 4; const container = $("#user-photos"); const counter = $("#vkPhotosCount"); const LS_KEY_PHOTOS = 'user_photos_cache_' + userId; const LS_KEY_COUNT = 'user_photos_count_' + userId; const LS_KEY_ALBUM = 'user_photos_album_' + userId; let renderLock = false; let albumLinkGlobal = null; // для кликабельного счетчика function normalizeUrl(url){ try{ const u = new URL(url, location.origin); u.search = ''; u.hash = ''; return u.toString().replace(/\/$/, ''); }catch(e){ return url; } } // функция для кликабельного счетчика function makeCounterClickable(albumLink, count){ if(!counter.length) return; if(count && albumLink){ if(!counter.parent('a').length){ // Убираем target="_blank", чтобы открывалось в той же вкладке counter.wrap('<a href="'+albumLink+'" style="text-decoration:none;color:inherit;"></a>'); counter.css('cursor','pointer'); } } else { if(counter.parent('a').length){ counter.unwrap(); counter.css('cursor','default'); } } } // функция отрисовки фото function renderPhotos(items, realCount, albumLink){ if (renderLock) return; renderLock = true; albumLinkGlobal = albumLink; if (!items || !items.length){ container.html(` <div style=" padding:24px 16px; text-align:center; color:#666; font-size:15px; background:#fafafa; border-radius:10px; min-height:110px; display:flex; flex-direction:column; justify-content:center; gap:10px; "> <div style="font-size:1.1em;color:#555;font-weight:500;"> Пока здесь нет фотографий </div> <div style="font-size:.93em;color:#777;line-height:1.45;"> Добавьте свои снимки в<br> <a href="/photo/0-0-0-1-2" style=" color:#3b82f6; text-decoration:none; font-weight:500; ">Фотоальбом</a><br> и они красиво отобразятся в профиле </div> </div> `); if(counter.length) counter.text('0'); makeCounterClickable(null, 0); renderLock = false; return; } const grid = $('<div class="profile-photo-grid"></div>'); items.slice(0, maxPhotos).forEach(item=>{ const card = $('<a class="photo-card"></a>') .attr('href', item.link) .css({ cursor:'pointer', display:'block' }); const img = $('<img alt="Фото пользователя">').css({opacity:0}); const loader = new Image(); loader.onload = ()=>{ img.attr('src', item.src); requestAnimationFrame(()=>img.css('opacity',1)); }; loader.src = item.src; card.append(img); grid.append(card); }); container.empty().append(grid); if(counter.length) counter.text(realCount); makeCounterClickable(albumLink, realCount); renderLock = false; } /* ================= ПЕРВОЕ ОТОБРАЖЕНИЕ ИЗ КЭША ================= */ function showCacheOrEmpty(){ try{ const cachedPhotos = JSON.parse(localStorage.getItem(LS_KEY_PHOTOS) || '[]'); const cachedCount = parseInt(localStorage.getItem(LS_KEY_COUNT)) || 0; const cachedAlbum = localStorage.getItem(LS_KEY_ALBUM) || null; if(cachedPhotos.length){ renderPhotos(cachedPhotos, cachedCount, cachedAlbum); return true; }else{ renderPhotos([], 0, null); return false; } }catch(e){ renderPhotos([], 0, null); return false; } } /* ================= ЗАГРУЗКА И ОБНОВЛЕНИЕ ================= */ function loadProfileAndPhotos(){ $.get(profileUrl+'?_='+Date.now()) .done(function(html){ const $profile = $(html); let realCount = 0, albumLink = null; $profile.find('a').each(function(){ const t = $(this).text().trim(); const m = t.match(/^Фото\s*\((\d+)\)$/i); if(m){ realCount=parseInt(m[1],10); albumLink=this.href; return false; } }); if(!albumLink || realCount===0){ localStorage.setItem(LS_KEY_PHOTOS, JSON.stringify([])); localStorage.setItem(LS_KEY_COUNT, 0); localStorage.removeItem(LS_KEY_ALBUM); renderPhotos([], 0, null); return; } localStorage.setItem(LS_KEY_ALBUM, albumLink); const cachedCount = parseInt(localStorage.getItem(LS_KEY_COUNT)) || 0; if(cachedCount === realCount) return; // кэш актуален $.get(albumLink) .done(function(albumHtml){ const $page = $(albumHtml); const items = []; $page.find("a.photo-card-title").each(function(){ let link = $(this).attr("href"); if(!link) return; if(link.startsWith('/')) link = location.origin + link; link = normalizeUrl(link); if(link.includes("photo/0-0-") || link.includes("edit")) return; const img = $(this).closest('div.entry-card').find("img[src*='/_ph/']").attr("src"); if(!img) return; const src = normalizeUrl(img); items.push({src, link}); if(items.length >= maxPhotos) return false; }); localStorage.setItem(LS_KEY_PHOTOS, JSON.stringify(items)); localStorage.setItem(LS_KEY_COUNT, realCount); renderPhotos(items, realCount, albumLink); }); }); } /* ================= ИНИЦИАЛИЗАЦИЯ ================= */ showCacheOrEmpty(); loadProfileAndPhotos(); }); })(jQuery); </script>
Признаюсь, не знаю почему, но глядя на звезды мне всегда хочется мечтать.
Дата: Суббота, 21.02.2026, 13:12 | Сообщение # 2 |
|
Написал: Узнаваемый
Автор темы
Мурчанн
не в сети
Сообщений: 211
«Аккуратно упаковываем всё в отдельные файлы и подключаем к глобальному блоку.» Но можно оставить и в открытом виде в исходном коде , просто это будет занимать много места.Исходник; Код
<link rel="stylesheet" href="https://bro.usite.pro/css/vk-poss1.css" media="all"> <!-- Подключаем шрифт Roboto для аккуратного вида --> <link href="https://fonts.googleapis.com/css2?family=Roboto:wght@400;500;600&display=swap" rel="stylesheet"> <div id="user-photos"></div> <script> window.UCOZ_DATA = { userId: "$USER_ID$", profileUrl: "$PERSONAL_PAGE_LINK$" }; </script> <script src="https://bro.usite.pro/js/profile-photos.js?v=1.0"></script>
Когда нет ничего, выглядит оно примерно вот так.
Признаюсь, не знаю почему, но глядя на звезды мне всегда хочется мечтать.