From 722fe6b5eaf023604ad44743f072b403e0e2d3e4 Mon Sep 17 00:00:00 2001 From: Michael Chus Date: Wed, 21 Jan 2026 04:35:23 +0300 Subject: [PATCH] =?UTF-8?q?fix:=20=D0=B8=D1=81=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=BB=D0=B5=D0=BD=D0=BE=20=D0=B2=D1=8B=D0=B4=D0=B5=D0=BB=D0=B5?= =?UTF-8?q?=D0=BD=D0=B8=D0=B5=20=D1=81=D1=82=D1=80=D0=BE=D0=BA=20=D1=87?= =?UTF-8?q?=D0=B5=D1=80=D0=B5=D0=B7=20header=20checkbox=20=D0=B8=20=D0=B8?= =?UTF-8?q?=D1=85=20=D1=83=D0=B4=D0=B0=D0=BB=D0=B5=D0=BD=D0=B8=D0=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Упрощен обработчик rowSelectionChanged (используется только параметр rows) - Добавлена отладочная информация для диагностики проблем - Исправлена логика синхронизации selectedRowsData - Добавлен console.log для отслеживания процесса выделения - Проверка работы getRowKey для корректной идентификации строк --- public/app.js | 93 +++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 76 insertions(+), 17 deletions(-) diff --git a/public/app.js b/public/app.js index 47627c7..85ed4e2 100644 --- a/public/app.js +++ b/public/app.js @@ -174,13 +174,24 @@ let lastEditedRow = null; function getRowKey(rowData) { if (!currentMeta || !currentMeta.primaryKey || currentMeta.primaryKey.length === 0) { // Если нет PK, используем все поля - return JSON.stringify(rowData); + const key = JSON.stringify(rowData); + console.log(' 🔑 getRowKey (no PK):', key.substring(0, 100)); + return key; } - const pkValues = currentMeta.primaryKey.map(pk => rowData[pk]).join('|'); + const pkValues = currentMeta.primaryKey.map(pk => { + const value = rowData[pk]; + if (value === undefined || value === null) { + console.warn(` ⚠️ PK field '${pk}' is undefined/null in rowData:`, rowData); + } + return value; + }).join('|'); + + console.log(' 🔑 getRowKey (PK):', pkValues, 'from fields:', currentMeta.primaryKey); return pkValues; } + async function selectTable(schema, tableName) { currentSchema = schema; currentTable = tableName; @@ -271,40 +282,52 @@ async function selectTable(schema, tableName) { }; }, - // ✅ ИСПРАВЛЕНО: Обработка выделения строк + // ✅ ИСПРАВЛЕНО: Простая и правильная обработка выделения rowSelectionChanged: function(data, rows) { - // Синхронизируем selectedRowsData с текущим состоянием ВСЕХ выделенных строк - // data - это массив данных ВСЕХ выбранных строк + console.log('🔔 rowSelectionChanged:', { + dataLength: data.length, + rowsLength: rows.length, + selectedRowsDataSizeBefore: selectedRowsData.size + }); - // Сначала удаляем все строки с текущей страницы из selectedRowsData - const currentPageRows = this.getRows(); - currentPageRows.forEach(row => { + // Обрабатываем только изменившиеся строки + rows.forEach(row => { const rowData = row.getData(); const key = getRowKey(rowData); - selectedRowsData.delete(key); - }); - - // Теперь добавляем все выделенные строки обратно - data.forEach(rowData => { - const key = getRowKey(rowData); - selectedRowsData.set(key, rowData); + const isSelected = row.isSelected(); + + console.log(` Row key: ${key}, isSelected: ${isSelected}`); + + if (isSelected) { + selectedRowsData.set(key, rowData); + } else { + selectedRowsData.delete(key); + } }); + console.log(' ✅ selectedRowsData size after:', selectedRowsData.size); updateSelectionCounter(); }, // После загрузки данных восстанавливаем выделение dataLoaded: function(data) { + console.log('📄 dataLoaded, восстанавливаем выделение для', selectedRowsData.size, 'строк'); + if (selectedRowsData.size > 0) { const rows = this.getRows(); + let restoredCount = 0; + rows.forEach(row => { const rowData = row.getData(); const key = getRowKey(rowData); if (selectedRowsData.has(key)) { row.select(); + restoredCount++; } }); + + console.log(' ✅ Восстановлено выделение для', restoredCount, 'строк на странице'); } }, @@ -629,11 +652,42 @@ async function promptForForeignKeys(fkFields) { // ✅ УДАЛИТЬ (оптимизированное с batch delete) document.getElementById('btnDelete').addEventListener('click', async () => { - if (!table || !currentSchema || !currentTable) return; + if (!table || !currentSchema || !currentTable) { + alert('Сначала выберите таблицу'); + return; + } const count = selectedRowsData.size; + console.log('🗑️ Удаление:', { + selectedRowsDataSize: count, + selectedRowsDataKeys: Array.from(selectedRowsData.keys()) + }); + if (count === 0) { + // Дополнительная проверка - может быть строки выделены в Tabulator, но не в selectedRowsData? + const tabulatorSelected = table.getSelectedData(); + console.log('Tabulator selected rows:', tabulatorSelected.length); + + if (tabulatorSelected.length > 0) { + console.error('❌ Несоответствие: Tabulator имеет выделенные строки, но selectedRowsData пуст!'); + console.log('Попытка синхронизации...'); + + // Синхронизируем + selectedRowsData.clear(); + tabulatorSelected.forEach(rowData => { + const key = getRowKey(rowData); + selectedRowsData.set(key, rowData); + }); + + updateSelectionCounter(); + + if (selectedRowsData.size > 0) { + alert(`Обнаружено ${selectedRowsData.size} выделенных строк. Попробуйте удалить снова.`); + return; + } + } + alert('Выберите строки для удаления'); return; } @@ -652,6 +706,8 @@ document.getElementById('btnDelete').addEventListener('click', async () => { // Преобразуем Map в массив const rowsArray = Array.from(selectedRowsData.values()); + console.log('Отправка на удаление:', rowsArray.length, 'строк'); + // Используем batch delete для оптимизации const result = await api('/api/table/delete-batch', 'POST', { schema: currentSchema, @@ -659,6 +715,8 @@ document.getElementById('btnDelete').addEventListener('click', async () => { rows: rowsArray }); + console.log('Результат удаления:', result); + document.body.removeChild(modal); selectedRowsData.clear(); @@ -676,11 +734,12 @@ document.getElementById('btnDelete').addEventListener('click', async () => { } } catch (e) { document.body.removeChild(modal); - console.error(e); + console.error('Ошибка удаления:', e); alert('Ошибка удаления: ' + e.message); } }); + // ========== ВСПОМОГАТЕЛЬНЫЕ ФУНКЦИИ CSV ========== function detectDelimiter(text) {