Interactive Gradient

Lorem ipsum dolor sit amet consectetur adipisicing elit. Ipsum tempore unde ex pariatur distinctio laboriosam, dolorem quibusdam aperiam expedita consequuntur dolorum porro vitae earum quos voluptates et maxime. Tempora, mollitia.

69%
test forum
Жанр творческой фотографии, очень сильно отличается от обычной фотожурналистики. Для многих фотография – способ самовыражения и общения, возможность высказаться и заявить о себе. Осень отлично подходит для фотографии, особенно если вы любите яркие цвета. Обратите внимание на то, как необычно и интересно может выглядеть портрет, если вы будете изменять ракурс.
Фотография дает человеку возможность объективно посмотреть на себя, свои чувства, эмоции.

hagalnaudbase1

Информация о пользователе

Привет, Гость! Войдите или зарегистрируйтесь.


Вы здесь » hagalnaudbase1 » просмотр » система управления оформлением профиля и учет твинков


система управления оформлением профиля и учет твинков

Сообщений 1 страница 5 из 5

1

Устали таскать ссылки на фоны и иконки в магазин, на личные страницы, в поля профиля пользователя?
Хотите, чтобы кто-то делал это за вас?
Для управления данным скриптом нужны базовые понятия о работе с html или просто внимательность.

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

Например, поле для введения ссылки на иконку будет выглядеть так:
https://upforme.ru/uploads/001b/d5/6a/2/206569.png
Нажмите на иконку - она добавится в поле профиля.

Чем это полезно для админа?

  • Вы устанавливаете оформления только один раз, в базу. Больше эти ссылки куда-то вставлять не придётся.

  • Вы можете выделить какие-то оформления в свободный доступ. Они будут доступны всем сразу.

  • Вы, как и прежде, ведёте учёт "багажа" оформлений, но на одной странице вместо сотни личных всплывающих страничек.

  • Вы можете поменять кому угодно фон, просто открыв профиль и нажав на нужный.

  • Вы можете в любой момент отказаться от использования скрипта: он просто помогает, а не меняет процессы необратимым образом.

Менее очевидные плюсы, спрятанные от первого взгляда:

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

  • Скрипт поддерживает буквально всё: иконки, фоны, плашки, в том числе плашки кодом.

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

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

  • Если вы используете личные страницы, скрипт может и ссылки сам расставить по профилям, и купленные иконки/фоны отобразить на страничках сам.

Инструкция по установке и использованию

Подготовка данных
Создайте страницу на форуме через панель Администрирование-Страницы. Используйте название и айди "0profili", чтобы не вносить изменения далее в коде. Можете указать и своё, но внимательно поменяйте на ваш айди все 0profili в моём коде, которые вы встретите!

Добавьте следующий шаблон:

Код:
<!------- База всех элементов оформления НАЧАЛО ------->
<div class="collections">

  <!------- Иконки ------->
  <div class="emojiicons" data-prof-id="1">

    <!------- Бесплатные------->
    <div class="pack0 free" data-pack-name="название">
      <img src="ссылка1.png" data-item-id="1">
      <img src="ссылка2.png" data-item-id="2">
    </div>

    <!------- Платные, первый набор ------->
    <div class="pack1" data-pack-name="название">
      <img src="ссылка3.png" data-item-id="1">
      <img src="ссылка4.png" data-item-id="2">
    </div>

    <!------- Пример личной коллекции пользователя ------->
    <div class="pack_idигрока limitedpack" data-pack-name="название">
      <img src="ссылка3.png" data-item-id="1">
      <img src="ссылка4.png" data-item-id="2">
    </div>

  </div>

</div>
<!------- База всех элементов оформления КОНЕЦ ------->


<!------- База всех персонажей НАЧАЛО ------->
<div class="personlist">

  <div class="person" data-perspage-id="айди_личной_страницы">
    <a href="profile.php?id=2">игрок</a>, <a href="profile.php?id=3">его твин</a>
    <div class="personitems">
      <div class="emojiicons">pack2:1,2</div>
    </div>
  </div>

</div>
<!------- База всех персонажей КОНЕЦ ------->

Пояснения к структуре:
База всех элементов оформления

База данных <div class="collections">:
Для каждого типа оформления (фон, иконки и т.д.) создайте внутри отдельный раздел (в примере это  <div class="emojiicons" data-prof-id="1">). Вы можете создавать сколько угодно вариантов. В данном примере я беру самый простой - картинки-иконки.

emojiicons - название типа оформления (может быть любым, но одним словом, если у вас несколько фонов, разделите название нижним подчёркиванием, например, fon_verh);
data-prof-id: номер поля профиля (fld1, fld2 и т.д.), куда нужно вставить данное оформление.

Внутри типа оформления расположены pack1, pack2 и так далее: удобное разделение по коллекциям, можно добавлять сколько хотите и назначать понятные названия, которые будут видны при редактировании профиля (data-pack-name="название").
Допишите к паку пометку free, чтобы такой пак стал полностью доступен всем по умолчанию.
Назовите пак по шаблону "pack_idигрока limitedpack", добавив id любого профиля игрока, чтобы такой пак был полностью доступен этому игроку и всем его твинам.

В каждый пак можно размещать элементы (фоны, иконки и т.д.), подписывая их по очереди (см. на data-item-id="1"). Вы можете добавлять не только картинки, но и элементы вроде плашек, главное - указать data-item-id. Например:
<div class="plashka" data-item-id="3">а тут текст</div>

База всех профилей

База данных <div class="personlist">:
Вы должны создать по одному person на каждого игрока, указав там всех твинов просто ссылками через запятую, а также его личную страницу в data-perspage-id, если вы их используете.

В personitems вы размещаете перечень элементов, которые этот игрок купил. Принцип предельно прост: например, при pack2:1,2 игроку доступны элементы номер 1 и номер 2 из группы pack2. Если он купит ещё третье, допишите номер 3, получится pack2:1,2,3. У кода также имеется защита от ошибок: вы можете указать элементы независимо друг от друга, например, pack2:1, pack3:2, pack2:2: здесь pack2 указан дважды. Вы можете не беспокоиться и не следить за чётким порядком в инвентаре, если только не захотите этого сами.

Этот инвентарь не виден простым пользователям - игроки увидят только список твинов.

Использование

  • Перейдите на страницу редактирования профиля в раздел "Дополнительно":

  • profile.php?section=fields&id=[ID_профиля]

  • Над каждым полем ввода появится "инвентарь" с доступными элементами, причём будут доступны только те элементы, которые игрок приобрёл + бесплатные элементы для всех, если есть

  • Кликните на нужный элемент (иконку, фон) - его код автоматически вставится в поле профиля

  • Сохраните изменения профиля

Если инвентарь не появляется:

  • Проверьте правильность ID страницы с данными в настройках скрипта

  • Убедитесь, что пользователь есть в базе данных

  • Проверьте соответствие data-prof-id с номерами полей профиля

Если появляются неправильные элементы в инвентаре:

  • Проверьте формат записи в personitems

  • Убедитесь, что data-item-id соответствуют реальным элементам

Рекомендации по управлению

  • Добавляйте новые элементы в коллекции по мере необходимости

  • Используйте осмысленные названия для групп (pack1, pack2 и т.д.)

  • Перед массовым применением протестируйте скрипт на одном профиле

0

2

Автоматическое подключение личных страниц

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

Это прямое дополнение к скрипту выше и без него работать не будет.

Чем это полезно в связке со скриптом из первого сообщения темы?

  • Экономит поле профиля, если общая кнопка открытия личной страницы занята им.

  • Экономит время по простановке ссылок на личные страницы твинов - если персонаж привязан к основному аккаунту в списке твинов, то на них страница тоже выставится автоматически.

  • Экономит время и снижает до нуля риск ошибок при ручном выставлении ссылок.

  • Позволяет в полную силу пользоваться первым скриптом - вы можете разрешить пользователям менять иконки и плашки, не рискуя, что они "потеряют" ссылку вокруг них.

Основные возможности

  • Работает и в темах, и при просмотре профиля.

  • Два режима работы: вставка новой ссылки перед указанными элементами или оборачивание существующих элементов в ссылку.

  • Данные профилей кэшируются (сохраняются в localStorage) для ускорения повторных загрузок.

  • Имеется возможность указания произвольных селекторов и шаблонов.

Установка
Добавьте код скрипта в html-низ ПЕРЕД основным скриптом для личных страничек. Перед ним - это важно!

Отредактируйте следующие переменные в начале скрипта:

Режимы работы

Код:
const ADD_MODE_SELECTOR = ".pa-author, li#profile-name";
// Селекторы элементов, перед которыми нужно добавить ссылку
// В данном примере добавляется новый элемент перед именем игрока на странице темы и на странице профиля
// Оставьте пустую строку "", если не нужно использовать этот режим

const MODIFY_MODE_SELECTOR = ".pa-fld1 img";
// Селекторы элементов, которые нужно обернуть в ссылку
// В данном примере ссылка появляется ссылка на картинке в первом поле профиля
// Оставьте пустую строку "", если не нужно использовать этот режим

Параметры источника данных

Код:
const PROFILE_PAGE_ID = "0profili";
// ID страницы с данными
// Подставьте сюда ту же страницу, что в скрипте выше

const LINK_TEMPLATE = `<a class="modal-link" href="#" data-reveal-id="character" style="cursor: pointer;">ссылка</a>`;
// HTML-шаблон ссылки. ID личной страницы будет автоматически добавлен как id атрибут
// В данном примере, если добавляется новый элемент, то это будет ссылка. Если хотите поставить вместо слова "ссылка" общую иконку на всех, то ставьте её в этот шаблон

Примеры использования
Пример 1: Добавление нового поля профиля перед любым элементом в посте/профиле

Код:
const ADD_MODE_SELECTOR = ".pa-author";
const MODIFY_MODE_SELECTOR = "";

Результат: <li class="pa-page"> добавляется перед именем пользователя. Можно подключить также в строку "профиль-лс-email", переместить перед любым другим полем профиля, вставить даже в лз.

Пример 2: Оборачивание иконки или плашки в ссылку

Код:
const ADD_MODE_SELECTOR = "";
const MODIFY_MODE_SELECTOR = ".pa-fld1 img";

Результат: при нажатии на иконку в первом поле профиля открывается личная страница. Можно подключить также к плашкам, в т.ч. созданным через html.

Пример 3: Оба режима одновременно

Код:
const ADD_MODE_SELECTOR = "li#profile-name";
const MODIFY_MODE_SELECTOR = ".pa-fld1 img";

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

Особенности работы

  • При повторных загрузках страницы данные берутся из кэша;

  • Скрипт не прерывает выполнение при ошибках и продолжает работу с остальными элементами;

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

0

3

Загрузка на личные страницы

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

Есть два варианта:

  • Если нужно добавить всё - поставьте <div class="personitems_inventory"></div>. Все элементы оформления, купленные игроком, будут размещены в нём.

  • Если  вы хотите добавить иконки, фоны или плашки в разные разделы личных страниц, то используйте специализированные контейнеры с указанием типа оформления, например, <div class="emojiicons inv"></div>, <div class="fons inv"></div>. Вы можете разместить их на личной странице в любом порядке

Внимание! Установка происходит прямо в существующий скрипт открытия личной страницы. Будьте аккуратны и обязательно сделайте бэкап во избежание поломки основного кода.

Необходимо также скопировать в скрипт айди вашей страницы с оформлениями и твинками.
Найдите строку const DATA_PAGE_ID = "0profili"; и вставьте своё.

Первый вариант с общим контейнером:
Код:
$(".modal-link").click(function() {
    var modId = $(this).attr('id');
    $('.modal_wrap').html('');

    $.get('pages/' + modId, function(data) {
        const $modalContent = $(data).find('.character');
        $('.modal_wrap').html($modalContent.html());

        $(".submenutext").hide();
        $(".submenutext:first").show();



        // ===== ВСПОМОГАТЕЛЬНАЯ ФУНКЦИЯ ДЛЯ ИНТЕЛЛЕКТУАЛЬНОГО ПАРСИНГА =====
        // Парсим доступные элементы из personitems (улучшенная версия)
        function parsePersonItemsIntelligentlyJQuery(personitemsElement, collectionType) {
            if (!personitemsElement || personitemsElement.length === 0) return {};
            
            const $collectionDiv = personitemsElement.find('.' + collectionType);
            if ($collectionDiv.length === 0) return {};
            
            const itemsText = $collectionDiv.text().trim();
            const items = {};
            
            // Разбираем формат: "pack2:1,2 pack3:1 pack2:2" с интеллектуальным объединением
            const packMatches = itemsText.match(/(\w+):([\d,]+)/g);
            
            if (packMatches) {
                packMatches.forEach(match => {
                    const [packPart, itemsPart] = match.split(':');
                    const itemIds = itemsPart.split(',').map(id => parseInt(id)).filter(id => !isNaN(id));
                    
                    if (items[packPart]) {
                        // Если пак уже существует, объединяем элементы (удаляем дубликаты)
                        items[packPart] = [...new Set([...items[packPart], ...itemIds])];
                    } else {
                        // Создаем новый пак
                        items[packPart] = itemIds;
                    }
                });
            }
            
            return items;
        }
        // ===== КОНЕЦ ВСПОМОГАТЕЛЬНОЙ ФУНКЦИИ =====

        // ===== ОПТИМИЗИРОВАННАЯ ФУНКЦИЯ ДЛЯ ОТОБРАЖЕНИЯ ИНВЕНТАРЯ =====
        // Загрузка и отображение инвентаря игрока в модальном окне
        const $personItemsInventory = $('.modal_wrap .personitems_inventory');
        
        if ($personItemsInventory.length > 0) {
            const DATA_PAGE_ID = "0profili";
            
            $.get('pages/' + DATA_PAGE_ID, function(collectionData) {
                const $collectionData = $(collectionData);
                const $person = $collectionData.find(`.person[data-perspage-id="${modId}"]`);
                
                if ($person.length > 0) {
                    const $personitems = $person.find('.personitems');
                    const $collections = $collectionData.find('.collections');
                    
                    // Парсим доступные элементы интеллектуально
                    // (остальные части кода остаются без изменений, кроме этой строки)
                    
                    $collections.find('[data-prof-id]').each(function() {
                        const $collection = $(this);
                        const collectionType = $collection.attr('class').split(' ')[0];
                        const profId = $collection.data('prof-id');
                        
                        const $inventoryContainer = $(`<div class="fldcontainer ${collectionType}" data-prof-id="${profId}"></div>`);
                        
                        $collection.find('[class*="pack"]:not(.free)').each(function() {
                            const $pack = $(this);
                            const packClasses = $pack.attr('class');
                            const packName = packClasses.split(' ')[0];
                            const packNameAttr = $pack.attr('data-pack-name') || packName;
                            const isLimited = $pack.hasClass('limitedpack');
                            
                            const $packClone = $pack.clone();
                            
                            if (packNameAttr) {
                                $packClone.attr('data-pack-name', packNameAttr);
                            }
                            
                            if (!isLimited) {
                                // Используем улучшенный парсинг
                                const availableItems = parsePersonItemsIntelligentlyJQuery($personitems, collectionType);
                                
                                if (availableItems[packName] && availableItems[packName].length > 0) {
                                    const allowedItems = availableItems[packName];
                                    
                                    $packClone.find('[data-item-id]').each(function() {
                                        const itemId = parseInt($(this).data('item-id'));
                                        if (!allowedItems.includes(itemId)) {
                                            $(this).remove();
                                        }
                                    });
                                } else {
                                    $packClone.remove();
                                    return;
                                }
                            }
                            
                            const itemsCount = $packClone.find('[data-item-id]').length;
                            
                            if (itemsCount > 0) {
                                $inventoryContainer.append($packClone);
                            } else {
                                $packClone.remove();
                            }
                        });
                        
                        const totalItems = $inventoryContainer.find('[data-item-id]').length;
                        
                        if (totalItems > 0) {
                            $personItemsInventory.append($inventoryContainer);
                        }
                    });
                }
            }).fail(function(jqXHR, textStatus, errorThrown) {
                console.error('Ошибка загрузки данных коллекций:', textStatus, errorThrown);
            });
        }
        // ===== КОНЕЦ ОПТИМИЗИРОВАННОЙ ФУНКЦИИ =====

    }).fail(function(jqxhr, textStatus, error) {
        console.error("Ошибка AJAX: " + textStatus + ", " + error);
        alert("Произошла ошибка при загрузке данных. Пожалуйста, попробуйте позже.");
    });

});
Второй вариант с отдельными контейнерами в разных местах:
Код:
$(".modal-link").click(function() {
    var modId = $(this).attr('id');
    $('.modal_wrap').html('');

    $.get('pages/' + modId, function(data) {
        const $modalContent = $(data).find('.character');
        $('.modal_wrap').html($modalContent.html());

        $(".submenutext").hide();
        $(".submenutext:first").show();

        // ===== УЛУЧШЕННАЯ ФУНКЦИЯ ДЛЯ ПОДСТАНОВКИ ЭЛЕМЕНТОВ В СУЩЕСТВУЮЩИЕ КОНТЕЙНЕРЫ =====
        // Вспомогательная функция для интеллектуального парсинга personitems
        function parsePersonItemsIntelligentlyJQuery(personitemsElement, collectionType) {
            if (!personitemsElement || personitemsElement.length === 0) return {};
            
            const $collectionDiv = personitemsElement.find('.' + collectionType);
            if ($collectionDiv.length === 0) return {};
            
            const itemsText = $collectionDiv.text().trim();
            const items = {};
            
            // Разбираем формат: "pack2:1,2 pack3:1 pack2:2" и т.д.
            const packMatches = itemsText.match(/(\w+):([\d,]+)/g);
            
            if (packMatches) {
                packMatches.forEach(match => {
                    const [packPart, itemsPart] = match.split(':');
                    const itemIds = itemsPart.split(',').map(id => parseInt(id)).filter(id => !isNaN(id));
                    
                    if (items[packPart]) {
                        // Если пак уже существует, объединяем элементы
                        items[packPart] = [...new Set([...items[packPart], ...itemIds])];
                    } else {
                        // Создаем новый пак
                        items[packPart] = itemIds;
                    }
                });
            }
            
            return items;
        }

        // Загрузка и подстановка элементов оформления в контейнеры с классами коллекций
        setTimeout(function() {
            const $modalWrap = $('.modal_wrap');
            // Ищем все элементы, которые могут быть контейнерами для коллекций
            const $collectionContainers = $modalWrap.find('[class*="inv"]').filter(function() {
                return $(this).hasClass('inv');
            });
            
            if ($collectionContainers.length > 0) {
                const DATA_PAGE_ID = "0profili";
                
                // Загружаем данные с страницы с коллекциями
                $.get('pages/' + DATA_PAGE_ID, function(collectionData) {
                    const $collectionData = $(collectionData);
                    const $person = $collectionData.find(`.person[data-perspage-id="${modId}"]`);
                    
                    if ($person.length > 0) {
                        const $personitems = $person.find('.personitems');
                        const $collections = $collectionData.find('.collections');
                        
                        // Для каждого найденного контейнера подставляем соответствующие элементы
                        $collectionContainers.each(function() {
                            const $container = $(this);
                            // Получаем класс коллекции (первый класс, не являющийся 'inv')
                            const containerClasses = $container.attr('class').split(' ');
                            const collectionType = containerClasses.find(cls => cls !== 'inv' && cls !== '') || containerClasses[0];
                            
                            if (collectionType && collectionType !== 'inv') {
                                // Ищем соответствующую коллекцию
                                const $collection = $collections.find(`.${collectionType}[data-prof-id]`);
                                
                                if ($collection.length > 0) {
                                    // Парсим доступные элементы интеллектуально
                                    const availableItems = parsePersonItemsIntelligentlyJQuery($personitems, collectionType);
                                    
                                    // Копируем элементы из коллекции (исключая free паки)
                                    $collection.find('[class*="pack"]:not(.free)').each(function() {
                                        const $pack = $(this);
                                        const packClasses = $pack.attr('class');
                                        const packName = packClasses.split(' ')[0];
                                        const packNameAttr = $pack.attr('data-pack-name') || packName;
                                        const isLimited = $pack.hasClass('limitedpack');
                                        
                                        // Создаем копию пака
                                        const $packClone = $pack.clone();
                                        
                                        // Сохраняем оригинальный data-pack-name
                                        if (packNameAttr) {
                                            $packClone.attr('data-pack-name', packNameAttr);
                                        }
                                        
                                        // Для обычных паков (не limited) фильтруем элементы
                                        if (!isLimited) {
                                            // Проверяем доступность элементов по personitems
                                            if (availableItems[packName] && availableItems[packName].length > 0) {
                                                const allowedItems = availableItems[packName];
                                                
                                                // Фильтруем элементы пака
                                                $packClone.find('[data-item-id]').each(function() {
                                                    const itemId = parseInt($(this).data('item-id'));
                                                    if (!allowedItems.includes(itemId)) {
                                                        $(this).remove();
                                                    }
                                                });
                                            } else {
                                                $packClone.remove();
                                                return;
                                            }
                                        }
                                        
                                        // Добавляем пак в контейнер, если в нем есть элементы
                                        const itemsCount = $packClone.find('[data-item-id]').length;
                                        
                                        if (itemsCount > 0) {
                                            $container.append($packClone);
                                        } else {
                                            $packClone.remove();
                                        }
                                    });
                                }
                            }
                        });
                    }
                }).fail(function(jqXHR, textStatus, errorThrown) {
                    console.error('Ошибка загрузки данных коллекций:', textStatus, errorThrown);
                });
            }
        }, 100);
        // ===== КОНЕЦ УЛУЧШЕННОЙ ФУНКЦИИ ДЛЯ ПОДСТАНОВКИ =====

    }).fail(function(jqxhr, textStatus, error) {
        console.error("Ошибка AJAX: " + textStatus + ", " + error);
        alert("Произошла ошибка при загрузке данных. Пожалуйста, попробуйте позже.");
    });

});

+1

4

pack3:1 pack2:2

anyname:1 pack2:2

купить

очистить корзину

0

5

0


Вы здесь » hagalnaudbase1 » просмотр » система управления оформлением профиля и учет твинков


Рейтинг форумов | Создать форум бесплатно