const XLSX = window.XLSX; let mainData = null; let templateData = null; let mainFileName = ''; let templateFileName = ''; let mappedResult = null; // Обработка выбора файла function handleFileSelect(event, type) { const file = event.target.files[0]; if (!file) return; const zone = document.getElementById(type + '-upload'); const info = document.getElementById(type + '-file-info'); zone.classList.add('has-file'); info.textContent = file.name + ' (' + formatFileSize(file.size) + ')'; if (type === 'main') { mainFileName = file.name; readExcel(file, (data) => { mainData = data; checkFilesReady(); }); } else { templateFileName = file.name; readExcel(file, (data) => { templateData = data; checkFilesReady(); }); } } function formatFileSize(bytes) { if (bytes < 1024) return bytes + ' Б'; if (bytes < 1024 * 1024) return (bytes / 1024).toFixed(1) + ' КБ'; return (bytes / (1024 * 1024)).toFixed(1) + ' МБ'; } function readExcel(file, callback) { const reader = new FileReader(); reader.onload = (e) => { const data = new Uint8Array(e.target.result); const workbook = XLSX.read(data, { type: 'array' }); const sheetName = workbook.SheetNames[0]; const worksheet = workbook.Sheets[sheetName]; const json = XLSX.utils.sheet_to_json(worksheet); callback(json); }; reader.readAsArrayBuffer(file); } function checkFilesReady() { const btn = document.getElementById('btn-mapping'); if (mainData && mainData.length > 0 && templateData && templateData.length > 0) { btn.disabled = false; } } function goToMapping() { if (!mainData || !templateData) return; document.getElementById('upload-section').classList.add('hidden'); document.getElementById('mapping-section').classList.remove('hidden'); document.getElementById('step1').classList.remove('active'); document.getElementById('step1').classList.add('completed'); document.getElementById('step2').classList.add('active'); populateFieldSelectors(); } function goBackToUpload() { document.getElementById('upload-section').classList.remove('hidden'); document.getElementById('mapping-section').classList.add('hidden'); document.getElementById('step1').classList.add('active'); document.getElementById('step2').classList.remove('active', 'completed'); } function populateFieldSelectors() { const mainFields = Object.keys(mainData[0] || {}); const templateFields = Object.keys(templateData[0] || {}); const mainSelect = document.getElementById('main-key-field'); const templateSelect = document.getElementById('template-key-field'); mainSelect.innerHTML = ''; templateSelect.innerHTML = ''; // Поиск полей с номером телефона и лицевым счетом const phoneFields = ['телефон', 'phone', 'tel', 'номер', 'number', 'лицевой', 'account', 'лс', 'флс']; phoneFields.forEach(field => { const mainMatch = mainFields.find(f => f.toLowerCase().includes(field)); const templateMatch = templateFields.find(f => f.toLowerCase().includes(field)); if (mainMatch && !mainSelect.querySelector(`[value="${mainMatch}"]`)) { mainSelect.add(new Option(mainMatch, mainMatch)); } if (templateMatch && !templateSelect.querySelector(`[value="${templateMatch}"]`)) { templateSelect.add(new Option(templateMatch, templateMatch)); } }); // Добавляем все остальные поля mainFields.forEach(field => { if (!mainSelect.querySelector(`[value="${field}"]`)) { mainSelect.add(new Option(field, field)); } }); templateFields.forEach(field => { if (!templateSelect.querySelector(`[value="${field}"]`)) { templateSelect.add(new Option(field, field)); } }); // Заполняем чекбоксы полей для заполнения const fieldsContainer = document.getElementById('fields-to-fill'); fieldsContainer.innerHTML = ''; templateFields.forEach(field => { const div = document.createElement('div'); div.style.cssText = 'display: inline-flex; align-items: center; gap: var(--kt-ai-space-2); margin-right: var(--kt-ai-space-3); margin-bottom: var(--kt-ai-space-2);'; const checkbox = document.createElement('input'); checkbox.type = 'checkbox'; checkbox.id = 'field-' + field; checkbox.value = field; checkbox.checked = true; // По умолчанию все поля выбраны checkbox.onchange = processMapping; const label = document.createElement('label'); label.htmlFor = 'field-' + field; label.textContent = field; label.style.fontSize = 'var(--kt-ai-text-sm)'; div.appendChild(checkbox); div.appendChild(label); fieldsContainer.appendChild(div); }); processMapping(); } function processMapping() { const mainKeyField = document.getElementById('main-key-field').value; const templateKeyField = document.getElementById('template-key-field').value; if (!mainKeyField || !templateKeyField) return; // Собираем поля для заполнения const fieldsToFill = []; document.querySelectorAll('#fields-to-fill input[type="checkbox"]:checked').forEach(cb => { fieldsToFill.push(cb.value); }); // Создаём карту соответствий const mainMap = new Map(); mainData.forEach(row => { const keyValue = normalizeValue(row[mainKeyField]); if (keyValue) { mainMap.set(keyValue, row); } }); // Сопоставляем данные let matched = 0; let notMatched = 0; let filled = 0; const previewRows = templateData.slice(0, 10).map((templateRow, index) => { const keyValue = normalizeValue(templateRow[templateKeyField]); const mainRow = mainMap.get(keyValue); if (mainRow) { matched++; // Заполняем пустые поля fieldsToFill.forEach(field => { if (!templateRow[field] && mainRow[field]) { filled++; templateRow[field] = mainRow[field]; } }); } else { notMatched++; } return { templateRow, mainRow, matched: !!mainRow }; }); // Статистика const total = templateData.length; const matchPercent = total > 0 ? Math.round((matched / total) * 100) : 0; document.getElementById('mapping-stats').innerHTML = `