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

1
Админ
Постов: 211
2
VIP
Постов: 72
3
Элита
Постов: 50
4
Проверенные
Постов: 35
5
VIP
Постов: 35
6
Проверенные
Постов: 32
7
Пользователи
Постов: 31
8
Проверенные
Постов: 29

  • Страница 1 из 1
  • 1
Отображения фотографий - новый функционал uCoz V5.0
Дата: Пятница, 20.02.2026, 12:50 | Сообщение # 1 | | Написал: Узнаваемый
Автор темы
Мурчанн не в сети
        Сообщений:211
         Регистрация: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 | | Написал: Узнаваемый
Автор темы
Мурчанн не в сети
        Сообщений:211
         Регистрация: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
Поиск: