From c001aed149267b5eddacc70f418e4086a71611b9 Mon Sep 17 00:00:00 2001 From: Mikhail Chusavitin Date: Fri, 23 Jan 2026 15:17:46 +0300 Subject: [PATCH] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=D0=B0=20=D1=80=D0=B0=D0=B1=D0=BE=D1=82=D0=B0=20?= =?UTF-8?q?=D1=87=D0=B5=D0=BA=D0=B1=D0=BE=D0=BA=D1=81=D0=BE=D0=B2=20=D0=B8?= =?UTF-8?q?=20=D0=BF=D0=B0=D0=B3=D0=B8=D0=BD=D0=B0=D1=86=D0=B8=D0=B8=20?= =?UTF-8?q?=D0=B2=20=D1=82=D0=B0=D0=B1=D0=BB=D0=B8=D1=86=D0=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Чекбоксы теперь работают только при клике на сам чекбокс (не на строку) - Повторный клик на чекбокс снимает выделение - Множественное выделение строк работает корректно - Исправлен выбор количества записей на странице (сервер читает параметр 'size') Co-Authored-By: Claude Opus 4.5 --- public/app.js | 67 ++++++++++++++++++++++++++++++++++++++++++------ public/index.php | 3 ++- 2 files changed, 61 insertions(+), 9 deletions(-) diff --git a/public/app.js b/public/app.js index 95274a3..6ddc009 100644 --- a/public/app.js +++ b/public/app.js @@ -440,8 +440,33 @@ async function selectTable(schema, tableName) { // ✅ Формируем колонки с правильными редакторами const columns = [ { - formatter: "rowSelection", - titleFormatter: "rowSelection", + // ✅ Кастомный чекбокс - работает только при клике на сам чекбокс + formatter: function(cell, formatterParams, onRendered) { + const row = cell.getRow(); + const checkbox = document.createElement("input"); + checkbox.type = "checkbox"; + checkbox.checked = row.isSelected(); + checkbox.style.cursor = "pointer"; + checkbox.style.width = "16px"; + checkbox.style.height = "16px"; + return checkbox; + }, + titleFormatter: function(cell, formatterParams, onRendered) { + const checkbox = document.createElement("input"); + checkbox.type = "checkbox"; + checkbox.style.cursor = "pointer"; + checkbox.style.width = "16px"; + checkbox.style.height = "16px"; + checkbox.addEventListener("click", function(e) { + e.stopPropagation(); + if (checkbox.checked) { + table.getRows().forEach(row => row.select()); + } else { + table.deselectRow(); + } + }); + return checkbox; + }, hozAlign: "center", headerHozAlign: "center", headerSort: false, @@ -449,8 +474,19 @@ async function selectTable(schema, tableName) { minWidth: 40, maxWidth: 40, resizable: false, - frozen: true - // ✅ Убран cellClick - Tabulator сам обрабатывает клики на rowSelection + frozen: true, + cellClick: function(e, cell) { + e.stopPropagation(); + const row = cell.getRow(); + const checkbox = cell.getElement().querySelector('input[type="checkbox"]'); + if (row.isSelected()) { + row.deselect(); + if (checkbox) checkbox.checked = false; + } else { + row.select(); + if (checkbox) checkbox.checked = true; + } + } }, ...currentMeta.columns.map(col => { // Определяем тип сортировщика на основе типа данных @@ -621,8 +657,7 @@ async function selectTable(schema, tableName) { console.log('🏗️ Создание Tabulator...'); table = new Tabulator("#table", { - selectableRows: true, // ✅ Включаем множественное выделение - selectableRowsRangeMode: "click", // ✅ Каждый клик добавляет/убирает строку + selectableRows: false, // ✅ Отключаем выделение по клику на строку - только через чекбокс selectableRowsPersistence: true, // ✅ Сохраняем выделение при сортировке/фильтрации columns: columns, @@ -819,14 +854,24 @@ async function selectTable(schema, tableName) { } } - // События (не меняются) + // События выделения table.on("rowSelectionChanged", function(data, rows) { + // ✅ Синхронизируем чекбоксы с состоянием выделения + table.getRows().forEach(row => { + const cells = row.getCells(); + if (cells.length > 0) { + const checkbox = cells[0].getElement().querySelector('input[type="checkbox"]'); + if (checkbox) { + checkbox.checked = row.isSelected(); + } + } + }); updateSelectionCounter(); }); table.on("dataLoaded", function(data) { console.log('📊 Данные загружены:', data.length, 'строк'); - + if (selectedRowsDataGlobal.size > 0) { const rows = table.getRows(); rows.forEach(row => { @@ -834,6 +879,12 @@ async function selectTable(schema, tableName) { const key = getRowKey(rowData); if (selectedRowsDataGlobal.has(key)) { row.select(); + // ✅ Обновляем чекбокс + const cell = row.getCells()[0]; + if (cell) { + const checkbox = cell.getElement().querySelector('input[type="checkbox"]'); + if (checkbox) checkbox.checked = true; + } } }); } diff --git a/public/index.php b/public/index.php index 946b91b..3cfcc74 100644 --- a/public/index.php +++ b/public/index.php @@ -97,7 +97,8 @@ $app->post('/api/table/data', function (Request $request, Response $response) us $schema = $payload['schema'] ?? ''; $table = $payload['table'] ?? ''; $page = (int)($payload['page'] ?? 1); - $pageSize = (int)($payload['pageSize'] ?? 50); + // Tabulator отправляет 'size', для обратной совместимости также проверяем 'pageSize' + $pageSize = (int)($payload['size'] ?? $payload['pageSize'] ?? 50); $filters = $payload['filters'] ?? []; $sort = $payload['sort'] ?? null; $columns = $payload['columns'] ?? [];