Список пользователей

1
Админ
Постов: 288
2
VIP
Постов: 75
3
Элита
Постов: 62
4
Проверенные
Постов: 46
5
Проверенные
Постов: 45
6
Проверенные
Постов: 39
7
VIP
Постов: 36
8
VIP
Постов: 35

  • Страница 1 из 1
  • 1
Отображения фотографий - новый функционал uCoz V5.0
Дата: Пятница, 20.02.2026, 12:50 | Сообщение # 1 | | Написал: Известный
Автор темы
Мурчанн не в сети
        Сообщений:288
         Регистрация:20.10.2016
За уважение окружающих За уважение окружающих За хорошее поведение За преданность форуму За любовь народа

Логика работы скрипта была изменена. Ранее, при отсутствии фотографий, скрипт сначала выполнял проверку их количества, и только после завершения этой проверки отображалось системное уведомление о том, что фотографий нет и их необходимо добавить.

Поскольку на выполнение проверки требовалось время, сообщение выводилось не сразу , пользователь сначала видел пустую область (белое окно), а затем появлялось системное уведомление. Такой сценарий создавал ощущение задержки и некорректной работы интерфейса.

Новая логика построена по принципу работы реального серверного процесса. Интерфейс сразу получает состояние и отображает результат: если фотографии существуют , они показываются немедленно, если их нет ,мгновенно выводится системное сообщение об их отсутствии.

Таким образом, мы эмулируем поведение настоящего сервера, обеспечивая быстрый отклик интерфейса и корректное отображение состояния данных без визуальных задержек.

Не вижу смысла подробно описывать работу скрипта , это лишь займет время. Гораздо нагляднее показать видео с демонстрацией его работы в реальных условиях. В динамике видно, как всё происходит на практике, и поведение практически неотличимо от работы настоящих серверных процессов.

Сейчас я сосредоточился на выявлении и устранении всех существующих проблем, недочётов и багов. Прежде чем двигаться дальше и добавлять новый функционал, необходимо довести до стабильного состояния работу всех текущих модулей и разделов.

Например, требуется создать новую версию интерактивного окна сообщений. В текущей реализации обнаружен баг: система публикует новость, однако не учитывает параметр разрешения на комментарии , сообщения с комментариями не помечаются корректно, и настройка фактически игнорируется.

Этот модуль требует срочной модернизации. После его доработки я продолжу аудит системы и поэтапное выявление остальных проблем, даже если это займёт дополнительное время.



Исходной код:

Код
<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 | | Написал: Известный
Автор темы
Мурчанн не в сети
        Сообщений:288
         Регистрация:20.10.2016
За уважение окружающих За уважение окружающих За хорошее поведение За преданность форуму За любовь народа

«Аккуратно упаковываем всё в отдельные файлы и подключаем к глобальному блоку.»

Но можно оставить и в открытом виде в исходном коде , просто это будет занимать много места.

Исходник;

Код
<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>



Когда нет ничего, выглядит оно примерно вот так.

Мурчанн

Признаюсь, не знаю почему, но глядя на звезды мне всегда хочется мечтать.
  • Страница 1 из 1
  • 1
Поиск: