Разработка административного интерфейса массовых операций 1С-Битрикс
Менеджер выбирает 200 товаров в стандартном списке Битрикса, нажимает «Действия» — и видит только пять пунктов: активировать, деактивировать, удалить, изменить раздел, экспорт. Кастомных операций нет. Их нужно добавить через расширение административного интерфейса.
Архитектура административных страниц Битрикса
Административный список товаров строится компонентом bitrix:iblock.admin.element.list, расположенным в /bitrix/modules/iblock/admin/. Для добавления кастомных действий над выборкой не нужно редактировать системные файлы — есть механизм расширения через административный меню-файл и кастомный обработчик.
Кастомная административная страница размещается в /bitrix/admin/my_bulk_action.php. Она получает список ID через $_REQUEST['ID'][] — это стандарт для передачи выделенных элементов из списков Битрикса.
Добавление пункта в меню действий
Стандартный список инфоблока поддерживает добавление кнопок через файл admin_action.php модуля или через JavaScript-инъекцию. Более чистый путь — регистрация кастомного действия через CAdminContextMenu:
// В файле /bitrix/admin/my_module_actions.php
// Включается через /bitrix/php_interface/init.php
AddEventHandler('main', 'OnAdminListDisplay', function() {
global $APPLICATION;
$page = $APPLICATION->GetCurPage();
// Добавить кнопку только на странице списка элементов нужного инфоблока
if (strpos($page, 'iblock_list_admin.php') !== false
&& (int)$_GET['IBLOCK_ID'] === MY_CATALOG_IBLOCK_ID)
{
// Регистрация не делается через событие — используем JS
}
});
На практике проще добавить кнопку через JavaScript, внедрённый в конец страницы через $APPLICATION->AddHeadScript() или через включаемый файл в /bitrix/admin/.
JavaScript для добавления кнопки:
document.addEventListener('DOMContentLoaded', function () {
var toolbar = document.querySelector('.adm-toolbar-panel');
if (!toolbar) return;
var btn = document.createElement('input');
btn.type = 'button';
btn.value = 'Обновить цены';
btn.className = 'adm-btn';
btn.addEventListener('click', function () {
var form = document.getElementById('list_form');
var action = document.createElement('input');
action.type = 'hidden';
action.name = 'action';
action.value = 'bulk_price_update';
var target = document.createElement('input');
target.type = 'hidden';
target.name = 'target_url';
target.value = '/bitrix/admin/my_bulk_price_update.php';
form.appendChild(action);
form.appendChild(target);
form.submit();
});
toolbar.appendChild(btn);
});
Обработчик массовой операции
Файл /bitrix/admin/my_bulk_price_update.php — страница обработки:
<?php
require_once $_SERVER['DOCUMENT_ROOT'] . '/bitrix/modules/main/include/prolog_admin_before.php';
$APPLICATION->SetTitle('Массовое обновление цен');
// Проверить права
if (!\Bitrix\Main\Engine\CurrentUser::get()->isAdmin()) {
die('Access denied');
}
$ids = array_map('intval', (array)$_REQUEST['ID']);
$ids = array_filter($ids);
require_once $_SERVER['DOCUMENT_ROOT'] . '/bitrix/modules/main/include/prolog_admin_after.php';
if (!empty($ids) && $_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['confirm'])) {
// Выполнить операцию
$markup = (float)$_POST['markup'];
foreach (array_chunk($ids, 50) as $chunk) {
foreach ($chunk as $id) {
$purchase = getPurchasePrice($id);
if ($purchase > 0) {
updateRetailPrice($id, $purchase * (1 + $markup / 100));
}
}
}
LocalRedirect('/bitrix/admin/iblock_list_admin.php?IBLOCK_ID=' . MY_CATALOG_IBLOCK_ID . '&lang=ru');
}
?>
<!-- Форма подтверждения -->
<form method="post" action="">
<p>Выбрано товаров: <b><?= count($ids) ?></b></p>
<label>Наценка (%):
<input type="number" name="markup" value="40" min="0" max="500">
</label>
<?php foreach ($ids as $id): ?>
<input type="hidden" name="ID[]" value="<?= $id ?>">
<?php endforeach; ?>
<input type="hidden" name="confirm" value="Y">
<?= bitrix_sessid_post() ?>
<input type="submit" value="Обновить" class="adm-btn-green">
<a href="javascript:history.back()" class="adm-btn">Отмена</a>
</form>
<?php require_once $_SERVER['DOCUMENT_ROOT'] . '/bitrix/modules/main/include/epilog_admin.php'; ?>
Прогресс-бар для длительных операций
При обновлении 1000+ элементов нужен прогресс-индикатор. Битрикс реализует это через механизм CAdminProgress или через AJAX-пуллинг.
Паттерн с AJAX: операция разбивается на шаги, каждый шаг — AJAX-запрос, который обрабатывает батч и возвращает {processed: N, total: M}. JavaScript обновляет прогресс-бар и запускает следующий шаг. Сохранение очереди между шагами — через $_SESSION или b_option по временному ключу.
Контроль доступа
Каждый обработчик массовой операции проверяет:
- CSRF-токен через
check_bitrix_sessid(). - Права пользователя через
\Bitrix\Main\Engine\CurrentUser::get()->isAdmin()или через\Bitrix\Main\Access. - Принадлежность переданных ID к ожидаемому инфоблоку — защита от подстановки чужих ID.







