Единый форум поддержки

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

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


Вы здесь » Единый форум поддержки » Администрирование форума » Общие вопросы по администрированию (7)


Общие вопросы по администрированию (7)

Сообщений 481 страница 500 из 574

1

В этой теме задаём вопросы по администрированию форума

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

Для запросов новых скриптов и их модификаций, пожалуйста, пишите в теме Запросы по скриптам #11
Если у вас возникли вопросы по оформлению форума, их можете задать в теме Общие вопросы по оформлению (65) #2
У вас возникла непредвиденная проблема с форумом, но самостоятельно вы её решить не можете? Создайте тему в разделе Проблемы с форумом, ознакомившись с правилами раздела.

Важная информация перед тем, как задать вопрос:

  • Ответы в теме дают другие участники форума по собственному желанию.

  • Администрация не может гарантировать моментальное решение или абсолютную корректность каждого ответа.

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

  • Грубое или требовательное отношение к участникам форума неприемлемо и может привести к отказу в помощи на всём форуме.

Подробно сформулируйте свой вопрос, чтобы повысить вероятность отклика помощи:

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

  • Опишите свой вопрос: Подробно и понятно изложите, что именно вас интересует или какая проблема возникла. Чем больше деталей вы предоставите, тем легче будет понять и помочь.

Если на ваш вопрос долго нет ответа, пожалуйста, напомните о своём вопросе через разумное время (например, через сутки), процитировав его. Избегайте излишней навязчивости.

Отредактировано Alex_63 (Ср, 2 Авг 2017 13:16:07)

+1

481

Виплич написал(а):

Да просто список ссылок, рассортированный по алфавиту.

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

Виплич написал(а):

Ну вот этот форум - на каком движке? И что такое - плагины для форума?
Что-то поиск по форуму никакой темы про плагины не находит... Что хоть это такое, надо понять.

Плагины - это расширения для форумного движка. Они дают возможности, которые официально не регламентированы для него. Сервис Майбб на основе форумного движка PunBB старой версии, и на сервисе Майбб установка плагинов для пользователей не доступна. На сервисе Майбб для пользователей доступно только установка javascript с некоторыми ограничениями, и css, а также ограничено HTML. Доступа к самому движку и к базе у пользователей Майбб нет.

0

482

kolobdur74 написал(а):

Плагины - это расширения для форумного движка. Они дают возможности, которые официально не регламентированы для него. Сервис Майбб на основе форумного движка PunBB старой версии, и на сервисе Майбб установка плагинов для пользователей не доступна. На сервисе Майбб для пользователей доступно только установка javascript с некоторыми ограничениями, и css, а также ограничено HTML. Доступа к самому движку и к базе у пользователей Майбб нет.

Понятно. Ох уж эта казуистика с названиями - "MyBB".

kolobdur74 написал(а):

вы можете создать подфорумы на каждый город и вывести ссылку на подфорум на главной странице под Названием основного форума

Тут тоже вмешалась казуистика с названиями - "форум".

Согласно общего расклада, у нас сам Форум (Весь форум) -- разбит на Категории (Раздел) -- далее разбито на Форумы (он же Подфорум) -- далее разбито на Темы

Получается, мне надо составить каталог ссылок на темы Подфорума.

Отредактировано Виплич (Вт, 18 Ноя 2025 16:41:27)

0

483

Виплич написал(а):

Понятно. Ох уж эта казуистика с названиями - "MyBB".

Ну, в свое время так решил создатель сервиса))

Виплич написал(а):

Согласно общего расклада, у нас сам Форум (Основной раздел) -- разбит на Категории (Раздел) -- далее разбито на Форумы (Подраздел, он же Подфорум) -- далее разбито на Темы

Получается, мне надо составить каталог ссылок на темы Подраздела.

Не совсем так. Категории -> Форумы -> Подфорумы -> Темы. И есть название Форум, под которым имеется ввиду вообще полностью весь вебсайт данной тематики и с данными возможностями))

0

484

kolobdur74 написал(а):

Не совсем так. Категории -> Форумы -> Подфорумы -> Темы.

В Администрировании мы создаём Категорию. Потом в Категории - создаём Форум. (Можно несколько создать). И уже в Форуме - идут Темы.

Какой ещё Подфорум?

Отредактировано Виплич (Вт, 18 Ноя 2025 16:48:56)

0

485

Виплич
В форуме можно создать подфорум.
https://upforme.ru/uploads/0000/14/1c/32995/t780782.png

+2

486

Виплич написал(а):

В Администрировании мы создаём Категорию. Потом в Категории - создаём Форум. (Можно не сколько создать). И уже в Форуме - идут Темы.

Какой ещё Подфорум?

Откройте: Администрирование- Форумы - нужный вам Форум, там настройка: Категория или форум, с описанием: Выберите либо категорию для основного форума, либо родительский форум для подфорума. Выбираете нужный форум в качестве родительского, и исходный форум становится подфорумом выбранного родительского.

Алекс выше, указал и второй вариант. Создание подфорума в выбранном форуме. Можно так, а можно так сделать подфорумы.

+3

487

Виплич написал(а):

Задача: создать Каталог раздела - в виде списка ссылок на все темы раздела.


У меня тоже есть вариант ответа :)

Ставите код в HTML низ

Код
Код:
<script>
document.addEventListener("DOMContentLoaded", () => {
  // === НАСТРОЙКИ ===
  // Формат: 'post_id;forum_id,post_id;forum_id,...'
  const POSTS_AND_FORUMS = '30377;2,30379;5'; // ← Укажите нужные пары
  // === /НАСТРОЙКИ ===

  // Карта для хранения названий разделов
  const forumNames = new Map();

  // Сначала получаем названия всех указанных разделов
  const forumIds = [...new Set(
    POSTS_AND_FORUMS.split(',')
      .map(pair => pair.trim().split(';')[1])
      .filter(id => id)
  )];

  if (forumIds.length === 0) return;

  const fields = 'id,name';
  const url = `/api.php?method=board.getForums&${new URLSearchParams({
    id: forumIds.join(','),
    fields,
    charset: 'utf-8'
  })}`;

  fetch(url)
    .then(response => response.json())
    .then(data => {
      if (!data?.response || !Array.isArray(data.response)) {
        console.warn("API board.getForums вернул пустой ответ");
        fallbackToStatic(); // резерв
        processPairs();
        return;
      }

      data.response.forEach(forum => {
        forumNames.set(String(forum.id), forum.name);
      });

      processPairs();
    })
    .catch(err => {
      console.error("Ошибка загрузки названий разделов:", err);
      fallbackToStatic();
      processPairs();
    });

  // --- ОСНОВНАЯ ЛОГИКА ЗАМЕНЫ ПОСТОВ ---
  function processPairs() {
    const pairs = POSTS_AND_FORUMS.split(',')
      .map(pair => {
        const [postId, forumId] = pair.trim().split(';');
        return { postId, forumId };
      });

    pairs.forEach(({ postId, forumId }) => {
      // Находим контейнер тела поста
      const postBody = document.getElementById(`p${postId}-content`);
      if (!postBody) {
        console.warn(`Пост #p${postId}-content не найден.`);
        return;
      }

      // Получаем название раздела
      let forumName = forumNames.get(forumId) || `Раздел ${forumId}`;

      // Очищаем всё содержимое и вставляем новый каталог
      postBody.innerHTML = '';
      postBody.insertAdjacentHTML('beforeend', `
        <div id="topic-catalog-${postId}" style="background: #e8f1da; border-radius: 5px; padding: 10px; margin: 10px 0; max-height: 400px; overflow-y: auto;">
          <h3 style="margin-top: 0; color: #2e7d32; font-size: 1.2em;">Темы в разделе: ${forumName}</h3>
          <ul id="topic-list-${postId}" style="list-style: none; padding-left: 0;"></ul>
          <div id="loading-${postId}" style="font-style: italic; color: #666;">Загрузка тем…</div>
        </div>
      `);

      const list = document.getElementById(`topic-list-${postId}`);
      const loading = document.getElementById(`loading-${postId}`);

      // Запрашиваем темы из нужного раздела через API
      fetch(`/api.php?method=topic.get&forum_id=${forumId}&limit=50&fields=id,subject&sort_by=last_post&sort_dir=desc&charset=utf-8`)
        .then(response => {
          if (!response.ok) throw new Error(`HTTP ${response.status}`);
          return response.json();
        })
        .then(data => {
          if (!data?.response || !Array.isArray(data.response)) {
            throw new Error("API вернул пустой или некорректный ответ");
          }

          data.response.forEach(topic => {
            const title = topic.subject || '[Без названия]';
            const link = `/viewtopic.php?id=${topic.id}`;
            const li = document.createElement('li');
            li.style.padding = '5px 0';
            li.style.borderBottom = '1px solid #ccc';
            li.innerHTML = `<a href="${link}" target="_blank">${title}</a>`;
            list.appendChild(li);
          });

          loading.style.display = 'none';
        })
        .catch(err => {
          console.error(`Ошибка загрузки тем для поста ${postId}:`, err);
          loading.textContent = 'Не удалось загрузить темы.';
          loading.style.color = 'red';
        });
    });
  }
});
</script>

В блоке настроек:

const POSTS_AND_FORUMS = '30377;2,30379;5'; // ← Укажите нужные пары

Пишете парами через запятую: ID поста, где нужен список тем, и ID раздела, где берём список тем.

30377;2 → в пост 30377 вставить темы из раздела 2.
30379;5 → в пост 30379 вставить темы из раздела 5.

В указанных постах скрипт полностью заменяет содержимое поста на список тем заданного раздела.

Как это выглядит:

Посмотреть скриншот

https://upforme.ru/uploads/0000/14/1c/38891/93298.webp


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

Отредактировано Merlin777 (Пн, 24 Ноя 2025 01:16:49)

+1

Перевести488

...

Отредактировано bektau (Вс, 23 Ноя 2025 20:25:51)

0

489

@bektau

Вы спрашивали  про скрипт "10 последних сообщений".

Если вам нужен список тем вверху страницы, то рекомендую вот этот вариант: Скрипты от пользователей 3

А если у вас был список тем внизу страницы, то могу предложить Вам вот такую версию, она выводит список тем внизу главной страницы, по дизайну соответствует старому скрипту, но обеспечивает "живое" обновление списка тем (каждые 15 секунд в таблицу добавляются новые темы).

Скриншот

https://upforme.ru/uploads/0000/14/1c/38891/39684.webp

Нужно код CSS вставить в HTML верх, а JS в HTML низ.

Код CSS
Код:
<style>
.container.stats { margin-bottom: -13px; }
.stats table {
  padding: 0 !important;
  margin-top: 7px;
  width: 100%;
}
.stats table th { text-align: left; }
.stats table td {
  padding: .1em;
  border-top-style: solid;
  border-top-width: 1px;
}
.new-message {
  background-color: #e8f5e9 !important;
}
</style>
Код JS
Код:
<script>
(function () {
  'use strict';

  // 🔢 Настройки
  const maxBuffer = 10;
  const fetchMax = maxBuffer + 5;
  const newestAtBottom = true; // false = новые СВЕРХУ, true = новые СНИЗУ
  const retryDelay = 1500;
  const maxRetries = 10;

  let retryCount = 0;

  function initLivePanel($) {
    $(function () {
      if (window.location.pathname !== "/" && !window.location.pathname.endsWith("index.php")) return;

      let currentBuffer = [];
      let isFetching = false;

      // 🧱 HTML
      const html = `
        <div id="live-posts" class="stats section">
          <div class="live-posts-wrapper">
            <table class="container stats">
              <thead>
                <tr>
                  <th class="tcl">🧑💻 Автор</th>
                  <th class="tc2">🕒 Время</th>
                  <th class="tcr">💬 Последнее сообщение</th>
                </tr>
              </thead>
              <tbody class="hasicon live-posts-tbody">
                <tr><td colspan="3">Загрузка...</td></tr>
              </tbody>
            </table>
          </div>
        </div>
      `;

      if ($('.statscon').length) {
        $('.statscon').prepend(html);
      } else {
        $('body').append(html);
      }

      const $tbody = $('.live-posts-tbody');
      const $wrapper = $('.live-posts-wrapper');

      function showError(msg = "❌ Ошибка загрузки.") {
        $tbody.html(`<tr><td colspan="3">${msg}</td></tr>`);
      }

      function formatDate(timestamp) {
        const ts = new Date(1000 * timestamp);
        const mo = String(ts.getMonth() + 1).padStart(2, '0');
        const dd = String(ts.getDate()).padStart(2, '0');
        const hh = String(ts.getHours()).padStart(2, '0');
        const mm = String(ts.getMinutes()).padStart(2, '0');
        return `${dd}.${mo} ${hh}:${mm}`;
      }

      function createRow(item, isRecent = false) {
        const timeStr = formatDate(item[0]);
        const rowClass = isRecent ? "new-message" : "";
        return $(`
          <tr class="${rowClass}">
            <td class="tcl">🧑💻 ${item[1]}</td>
            <td class="tc2">🕒 ${timeStr}</td>
            <td class="tcr">💬 <a href="${item[2]}" target="_blank">${item[3]}</a></td>
          </tr>
        `);
      }

      function renderBuffer(newItemIds = new Set()) {
        const sortedAll = [...currentBuffer].sort((a, b) => a[0] - b[0]);
        const latestItems = sortedAll.slice(-maxBuffer);
        const displayItems = newestAtBottom
          ? latestItems
          : latestItems.reverse();

        $tbody.empty();
        displayItems.forEach(item => {
          const isNew = newItemIds.has(item[2]);
          const $row = createRow(item, isNew);
          $tbody.append($row);
        });

        if (newItemIds.size > 0) {
          $tbody.find('.new-message').each(function () {
            const $el = $(this);
            setTimeout(() => {
              $el.animate({ backgroundColor: "transparent" }, 2000, () => {
                $el.removeClass('new-message');
              });
            }, 100);
          });
        }

        if (newestAtBottom && newItemIds.size > 0) {
          $wrapper.scrollTop($wrapper[0].scrollHeight);
        }
      }

      function fetchLatestPosts(retryCountAjax = 0) {
        if (isFetching) return;
        isFetching = true;

        $.getScript(`/export.php?type=js&max=${fetchMax}&_=` + Date.now())
          .done(() => {
            isFetching = false;

            if (typeof content === "undefined" || !Array.isArray(content)) {
              if (retryCountAjax < 3) {
                setTimeout(() => fetchLatestPosts(retryCountAjax + 1), retryDelay);
              } else {
                showError();
              }
              return;
            }

            const freshItems = [];
            const newItemIds = new Set();

            content.forEach(item => {
              if (!item || item.length < 4) return;
              if (item[3].includes('·') || item[3].includes('¬')) return;
              freshItems.push(item);
            });

            freshItems.forEach(item => {
              const url = item[2];
              const wasMissing = !currentBuffer.some(msg => msg[2] === url);
              if (wasMissing) {
                newItemIds.add(url);
              }
            });

            currentBuffer = freshItems;

            if (currentBuffer.length > 100) {
              currentBuffer.sort((a, b) => a[0] - b[0]);
              currentBuffer = currentBuffer.slice(-100);
            }

            if (currentBuffer.length === 0) {
              $tbody.html('<tr><td colspan="3">Нет сообщений.</td></tr>');
              return;
            }

            renderBuffer(newItemIds);
          })
          .fail(() => {
            isFetching = false;
            if (retryCountAjax < 3) {
              setTimeout(() => fetchLatestPosts(retryCountAjax + 1), retryDelay);
            } else {
              showError();
            }
          });
      }

      fetchLatestPosts();
      setInterval(fetchLatestPosts, 15000);
    });
  }

  // 🔁 Ждём jQuery
  function waitForJQuery() {
    if (typeof jQuery !== 'undefined') {
      initLivePanel(jQuery);
    } else if (retryCount < maxRetries) {
      retryCount++;
      setTimeout(waitForJQuery, retryDelay);
    } else {
      console.error('[Live Panel] jQuery так и не загрузился. Скрипт остановлен.');
    }
  }

  waitForJQuery();
})();
</script>

В коде JS вы можете задать свои настройки:

// 🔢 Настройки
  const maxBuffer = 10;
  const fetchMax = maxBuffer + 5;
  const newestAtBottom = false; // false = новые СВЕРХУ, true = новые СНИЗУ

Здесь:
maxBuffer это количество выводимых тем на странице
fetchMax это переменная для логики работы скрипта (лучше не меняйте)
newestAtBottom  задаёт направление сортировки тем от старых к новым - новые темы будут сверху или снизу.


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

Отредактировано Merlin777 (Вт, 25 Ноя 2025 19:37:54)

+3

490

Если вышенаписанные мной посты не соответствуют тематике раздела, то прошу модераторов форума перенести их в  соответствующее место  :)

0

491

Merlin777
Всё отлично :cool:
Единственное, на что стоит обратить внимание - подключение jQuery лишнее, поскольку в сервис уже встроен jQuery версии 1.7.2
(в вашей версия хоть и новее - 3.6.0, но в работу берется именно от сервиса, не зависимо каким образом его подключаете)

+1

492

Reysler
Добавлю, что некоторые способы подключения jQuery позволяют обойти ограничение от сервисе и включить свою версию поверх сервисной, но это с большой вероятностью приведёт к критическим конфликтам и поломке множества скриптов (в том числе и платных), рассчитанных на версию jQuery, которая установлена на сервисе. Поэтому да, подключение своей версии в любом варианте крайне не рекомендуется.

0

493

Alex_63
Совершенно верно, обходные пути всегда найдутся, разумеется имелось в виду простые подобные способы

+1

494

Reysler
Тот вариант подключения, что использовал @Merlin777 в своём коде, как раз проходит как обходной путь, сервисом не вырезается и будет вызывать конфликт.

0

495

Alex_63
Хм, потестировал, у меня при подобном способе вызов идёт из 1.7.2

+1

496

Reysler
Возможно и так, настолько подробно я не тестировал, но именно в предложенном коде ссылка на jQuery новой версии сервисом не вырезается и судя по всему она загружается, что может в конечном итоге вызвать непредсказуемые последствия в работе других скриптов ) Считаю, что @Merlin777 в любом случае стоит отредактировать этот код (а возможно и другие, использующие подобное подключение), чтобы он не подгружал альтернативных версий jQuery со сторонних источников, а использовал ту, что предоставляет сервис.

+1

497

Я не сразу обратил внимание, подключение хоть и не вырезается сервисом, но и не выполняется. А всё из-за строчки:

Код:
...
if (typeof jQuery !== "undefined") {
...
}
...

Убрав её, такой метод подключения сработает, но может привести к конфликту. Я в курсе за что он отвечает, не надо расписывать :D

Добавлено спустя 19 минут 56 секунд:

Скорее всего, добавлю эту информацию в Справочный раздел. В частности, при подключении новой версии jQuery, первым делом, что пользователи заметят - перестанут работать кнопки в форме ответа (это максимум, что необходимо знать тем, кто пользуется генерацией кода нейросетями). Поэтому следует быть очень аккуратным. Благо, тут попалась умная нейросеть, что добавила условие, исключающее такого конфликта ;)
(пока редактировал и добавлял к ответу новую инфу, случайно заруинил свой же ответ // вернул)

+1

498

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

+1

499

Убрал вызовы внешнего jquery. Сейчас if (typeof jQuery === 'undefined') просто не запускает скрипт и пишет ошибку в консоль  :)
Остальные скрипты проверю и отредактирую чуть попозже.

Alex_63
Кстати, а можно ли Вас попросить добавить "лайки" в AJAX-ответ автообновления (у "живых тем")? А то сейчас это доступно только для подписчиков  Мгновенные уведомления на форум  :)
Если это, конечно, не нарушает маркетинговых планов :)

0

500

Merlin777 написал(а):

Кстати, а можно ли Вас попросить добавить "лайки" в AJAX-ответ автообновления (у "живых тем")?

Это скорее в скрипт от сервиса нужно доработку вносить, с лайками работает именно он, с ним это будет сделать проще всего, добавив обработчик для события pun_post или pun_main_update: https://forumscripts.ru/post_voters/2.0.11/post_voters.js
Но учитывая, что каждое обновление оценок в постах потребует дополнительного запроса к серверу (достаточно тяжёлого, если постов на странице много), а чужие лайки вряд ли есть необходимость обновлять в реальном времени, целесообразность под сомнением. Мгновенные уведомления поддерживают обновление оценок (в реальном времени) именно в тех постах, на которые их автор получил уведомления, т.е. более адресно и с меньшей нагрузкой.

В общем, на досуге подумаю, но пока ничего не обещаю.

+1


Вы здесь » Единый форум поддержки » Администрирование форума » Общие вопросы по администрированию (7)