diff --git a/public/app.js b/public/app.js index 4c2e3ea..a33cd5c 100644 --- a/public/app.js +++ b/public/app.js @@ -3,7 +3,7 @@ let currentTable = null; let currentMeta = null; let table = null; let enterHandler = null; -let selectedRowsData = new Map(); +let selectedRowsDataGlobal = new Map(); // Только для "Выделить все" кросс-страничного async function api(url, method = 'GET', body) { const opts = { method, headers: { 'Content-Type': 'application/json' } }; @@ -19,7 +19,15 @@ async function api(url, method = 'GET', body) { function updateSelectionCounter() { const counter = document.getElementById('selectionCounter'); - const count = selectedRowsData.size; + + // Получаем количество выделенных строк + let count = 0; + if (table) { + const tabulatorSelected = table.getSelectedData(); + count = tabulatorSelected.length + selectedRowsDataGlobal.size; + } else { + count = selectedRowsDataGlobal.size; + } if (count > 0) { counter.textContent = `Выбрано: ${count}`; @@ -96,22 +104,13 @@ function escapeHtml(text) { function getRowKey(rowData) { if (!currentMeta || !currentMeta.primaryKey || currentMeta.primaryKey.length === 0) { - const key = JSON.stringify(rowData); - return key; + return JSON.stringify(rowData); } - const pkValues = currentMeta.primaryKey.map(pk => { - const value = rowData[pk]; - if (value === undefined || value === null) { - console.warn(`⚠️ getRowKey: PK field '${pk}' is undefined/null in rowData:`, rowData); - } - return value; - }).join('|'); - + const pkValues = currentMeta.primaryKey.map(pk => rowData[pk]).join('|'); return pkValues; } - document.getElementById('loginBtn').addEventListener('click', async () => { const user = document.getElementById('loginUser').value.trim(); const pass = document.getElementById('loginPass').value; @@ -186,7 +185,7 @@ async function selectTable(schema, tableName) { currentSchema = schema; currentTable = tableName; lastEditedRow = null; - selectedRowsData.clear(); + selectedRowsDataGlobal.clear(); // Очищаем при смене таблицы updateSelectionCounter(); if (enterHandler) { @@ -198,13 +197,6 @@ async function selectTable(schema, tableName) { `/api/table/meta?schema=${encodeURIComponent(schema)}&table=${encodeURIComponent(tableName)}` ); - console.log('📋 Метаданные таблицы загружены:', { - schema, - table: tableName, - primaryKey: currentMeta.primaryKey, - columnsCount: currentMeta.columns.length - }); - const columns = [ { formatter: "rowSelection", @@ -213,7 +205,6 @@ async function selectTable(schema, tableName) { headerSort: false, width: 40, cellClick: function(e, cell) { - console.log('📌 Клик на чекбокс ячейки'); cell.getRow().toggleSelect(); } }, @@ -279,80 +270,24 @@ async function selectTable(schema, tableName) { }; }, + // Обновляем счетчик при изменении выделения rowSelectionChanged: function(data, rows) { - console.group('🔔 rowSelectionChanged вызван'); - console.log('Параметры:', { - 'data.length (все выделенные)': data.length, - 'rows.length (изменённые)': rows.length, - 'selectedRowsData.size до': selectedRowsData.size - }); - - // Выводим первые 2 элемента из data для проверки - if (data.length > 0) { - console.log('Первая строка из data:', data[0]); - console.log('Проверка getRowKey для первой строки:', getRowKey(data[0])); - } - - // Выводим первые 2 элемента из rows для проверки - if (rows.length > 0) { - console.log('Первая строка из rows (Row объект):', rows[0]); - console.log('getData() первой строки из rows:', rows[0].getData()); - } - - // Получаем все строки текущей страницы - const currentPageRows = this.getRows(); - console.log('Строк на текущей странице:', currentPageRows.length); - - // Удаляем все строки текущей страницы из selectedRowsData - let deletedCount = 0; - currentPageRows.forEach(row => { - const rowData = row.getData(); - const key = getRowKey(rowData); - if (selectedRowsData.has(key)) { - selectedRowsData.delete(key); - deletedCount++; - } - }); - console.log('Удалено из selectedRowsData:', deletedCount); - - // Добавляем все выделенные строки из параметра data - let addedCount = 0; - data.forEach((rowData, index) => { - const key = getRowKey(rowData); - selectedRowsData.set(key, rowData); - addedCount++; - - if (index < 3) { - console.log(` Добавлена строка ${index + 1}: key="${key}"`); - } - }); - console.log('Добавлено в selectedRowsData:', addedCount); - - console.log('selectedRowsData.size после:', selectedRowsData.size); - console.log('Первые 3 ключа в selectedRowsData:', Array.from(selectedRowsData.keys()).slice(0, 3)); - console.groupEnd(); - updateSelectionCounter(); }, + // Восстанавливаем выделение для глобально выделенных строк dataLoaded: function(data) { - console.log('📄 dataLoaded: восстанавливаем выделение для', selectedRowsData.size, 'строк'); - - if (selectedRowsData.size > 0) { + if (selectedRowsDataGlobal.size > 0) { const rows = this.getRows(); - let restoredCount = 0; rows.forEach(row => { const rowData = row.getData(); const key = getRowKey(rowData); - if (selectedRowsData.has(key)) { + if (selectedRowsDataGlobal.has(key)) { row.select(); - restoredCount++; } }); - - console.log(' ✅ Восстановлено выделение для', restoredCount, 'строк на странице'); } }, @@ -393,7 +328,6 @@ async function selectTable(schema, tableName) { document.addEventListener('keydown', enterHandler); } - document.getElementById('btnSelectAll').addEventListener('click', async () => { if (!currentSchema || !currentTable || !table) { alert('Сначала выберите таблицу'); @@ -428,10 +362,10 @@ document.getElementById('btnSelectAll').addEventListener('click', async () => { if (!proceed) return; } - selectedRowsData.clear(); + selectedRowsDataGlobal.clear(); result.data.forEach(rowData => { const key = getRowKey(rowData); - selectedRowsData.set(key, rowData); + selectedRowsDataGlobal.set(key, rowData); }); const rows = table.getRows(); @@ -439,7 +373,7 @@ document.getElementById('btnSelectAll').addEventListener('click', async () => { const rowData = row.getData(); const key = getRowKey(rowData); - if (selectedRowsData.has(key)) { + if (selectedRowsDataGlobal.has(key)) { row.select(); } }); @@ -455,7 +389,7 @@ document.getElementById('btnSelectAll').addEventListener('click', async () => { document.getElementById('btnDeselectAll').addEventListener('click', () => { if (!table) return; - selectedRowsData.clear(); + selectedRowsDataGlobal.clear(); table.deselectRow(); updateSelectionCounter(); }); @@ -662,39 +596,39 @@ async function promptForForeignKeys(fkFields) { }); } +// ✅ УДАЛИТЬ - упрощенная версия document.getElementById('btnDelete').addEventListener('click', async () => { if (!table || !currentSchema || !currentTable) { alert('Сначала выберите таблицу'); return; } - const count = selectedRowsData.size; + // Получаем выделенные строки напрямую из Tabulator + const tabulatorSelected = table.getSelectedData(); + + // Объединяем с глобально выделенными (из "Выделить все") + const allSelectedData = new Map(); + + // Добавляем из Tabulator + tabulatorSelected.forEach(rowData => { + const key = getRowKey(rowData); + allSelectedData.set(key, rowData); + }); + + // Добавляем из глобального хранилища + selectedRowsDataGlobal.forEach((rowData, key) => { + allSelectedData.set(key, rowData); + }); + + const count = allSelectedData.size; console.log('🗑️ Удаление:', { - selectedRowsDataSize: count, - primaryKeys: currentMeta?.primaryKey + tabulatorSelected: tabulatorSelected.length, + globalSelected: selectedRowsDataGlobal.size, + total: count }); if (count === 0) { - const tabulatorSelected = table.getSelectedData(); - console.log('Tabulator selected rows:', tabulatorSelected.length); - - if (tabulatorSelected.length > 0) { - console.error('❌ Несоответствие: Tabulator имеет выделенные строки, но selectedRowsData пуст!'); - selectedRowsData.clear(); - tabulatorSelected.forEach(rowData => { - const key = getRowKey(rowData); - selectedRowsData.set(key, rowData); - }); - - updateSelectionCounter(); - - if (selectedRowsData.size > 0) { - alert(`Обнаружено ${selectedRowsData.size} выделенных строк. Попробуйте удалить снова.`); - return; - } - } - alert('Выберите строки для удаления'); return; } @@ -709,7 +643,7 @@ document.getElementById('btnDelete').addEventListener('click', async () => { document.body.appendChild(modal); try { - const rowsArray = Array.from(selectedRowsData.values()); + const rowsArray = Array.from(allSelectedData.values()); const result = await api('/api/table/delete-batch', 'POST', { schema: currentSchema, @@ -719,7 +653,8 @@ document.getElementById('btnDelete').addEventListener('click', async () => { document.body.removeChild(modal); - selectedRowsData.clear(); + selectedRowsDataGlobal.clear(); + table.deselectRow(); updateSelectionCounter(); await table.replaceData();