document.addEventListener('DOMContentLoaded', () => { const numberInput = document.getElementById('numberInput'); const fileInput = document.getElementById('fileInput'); const dropzone = document.getElementById('dropzone'); const splitMode = document.getElementById('splitMode'); const splitValue = document.getElementById('splitValue'); const splitBtn = document.getElementById('splitBtn'); const autoDedupe = document.getElementById('autoDedupe'); const resultsContainer = document.getElementById('resultsContainer'); const totalCountEl = document.getElementById('totalCount'); const uniqueCountEl = document.getElementById('uniqueCount'); const dynamicCountsContainer = document.getElementById('dynamicCountsContainer'); const dynamicInputsList = document.getElementById('dynamicInputsList'); const unitText = document.getElementById('unitText'); const batchCountBadge = document.getElementById('batchCountBadge'); let allNumbers = []; // Helper: Extract numbers from text (Mobile number regex) const extractNumbers = (text) => { const matches = text.match(/1[3-9]\d{9}/g) || []; return matches; }; // Update stats and allNumbers array const updateStats = () => { const text = numberInput.value; const extracted = extractNumbers(text); const unique = [...new Set(extracted)]; totalCountEl.textContent = extracted.length.toLocaleString(); uniqueCountEl.textContent = unique.length.toLocaleString(); allNumbers = autoDedupe.checked ? unique : extracted; }; numberInput.addEventListener('input', updateStats); autoDedupe.addEventListener('change', updateStats); // Dynamic UI for split modes const updateSplitUI = () => { const mode = splitMode.value; if (mode === 'count') { unitText.textContent = '份'; dynamicCountsContainer.classList.remove('d-none'); generateDynamicInputs(); } else { unitText.textContent = '条'; dynamicCountsContainer.classList.add('d-none'); } }; const generateDynamicInputs = () => { const numBatches = parseInt(splitValue.value); dynamicInputsList.innerHTML = ''; if (isNaN(numBatches) || numBatches <= 1) { dynamicCountsContainer.classList.add('d-none'); return; } dynamicCountsContainer.classList.remove('d-none'); // Create N-1 inputs because the last one is always the remainder for (let i = 0; i < numBatches - 1; i++) { const div = document.createElement('div'); div.className = 'input-group input-group-sm dynamic-batch-input'; div.innerHTML = ` 第 ${i + 1} 份数量 `; dynamicInputsList.appendChild(div); } }; splitMode.addEventListener('change', updateSplitUI); splitValue.addEventListener('input', generateDynamicInputs); // File handling dropzone.addEventListener('click', () => fileInput.click()); fileInput.addEventListener('change', async (e) => { const file = e.target.files[0]; if (!file) return; if (file.name.endsWith('.txt') || file.name.endsWith('.csv')) { const reader = new FileReader(); reader.onload = (event) => { const content = event.target.result; numberInput.value += (numberInput.value ? '\n' : '') + content; updateStats(); fileInput.value = ''; }; reader.readAsText(file); } else { // Placeholder for Excel/Word/PDF if needed, but for now just inform alert('当前支持直接读取 .txt 和 .csv 文件。Word/Excel/PDF 请直接复制其中的号码并粘贴到输入框。'); } }); // Splitting logic splitBtn.addEventListener('click', () => { updateStats(); // Ensure we have latest data if (allNumbers.length === 0) { alert('请先导入或粘贴号码!'); return; } const mode = splitMode.value; const val = parseInt(splitValue.value); if (isNaN(val) || val <= 0) { alert('请输入有效的分批数值!'); return; } let batches = []; let tempNumbers = [...allNumbers]; if (mode === 'count') { const sizeInputs = document.querySelectorAll('.batch-size-input'); let hasSpecificSizes = false; let specificSizes = []; sizeInputs.forEach(input => { const s = parseInt(input.value); if (!isNaN(s) && s > 0) { hasSpecificSizes = true; specificSizes.push(s); } else { specificSizes.push(null); } }); if (hasSpecificSizes) { // Specific size splitting for (let i = 0; i < val - 1; i++) { const size = specificSizes[i]; if (size !== null && size > 0) { batches.push(tempNumbers.splice(0, size)); } else { // If one is empty but others are not, we need a strategy. // Let's treat empty as 0 for now or average the rest? // User said "if no number, system default split". // But if some have numbers and others don't, it's ambiguous. // We'll calculate the remaining needed batches. const remainingCount = val - batches.length; const avg = Math.ceil(tempNumbers.length / remainingCount); batches.push(tempNumbers.splice(0, avg)); } } // Add the remainder to the last batch if (tempNumbers.length > 0) { batches.push(tempNumbers); } else if (batches.length < val) { // If no numbers left but we need more batches, add empty ones while (batches.length < val) batches.push([]); } } else { // Average splitting const batchSize = Math.ceil(tempNumbers.length / val); for (let i = 0; i < val; i++) { if (tempNumbers.length > 0) { batches.push(tempNumbers.splice(0, batchSize)); } else { batches.push([]); } } } } else { // Split by fixed size per batch while (tempNumbers.length > 0) { batches.push(tempNumbers.splice(0, val)); } } renderResults(batches); }); const renderResults = (batches) => { resultsContainer.innerHTML = ''; batchCountBadge.textContent = `${batches.length} 个批次`; batchCountBadge.classList.remove('d-none'); batches.forEach((batch, index) => { const card = document.createElement('div'); card.className = 'card batch-card animate-fadeIn'; const previewText = batch.slice(0, 30).join(', '); const hasMore = batch.length > 30; card.innerHTML = `