From 0d4e80837f20da2a9258be5ebefdde7e92a27aea Mon Sep 17 00:00:00 2001 From: Flatlogic Bot Date: Sat, 7 Feb 2026 07:39:19 +0000 Subject: [PATCH] =?UTF-8?q?=E5=8F=B7=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- assets/css/custom.css | 561 +++++++++++++++++++----------------------- assets/js/main.js | 290 +++++++++++++++++----- index.php | 312 ++++++++++++----------- 3 files changed, 661 insertions(+), 502 deletions(-) diff --git a/assets/css/custom.css b/assets/css/custom.css index 65a1626..9e119eb 100644 --- a/assets/css/custom.css +++ b/assets/css/custom.css @@ -1,346 +1,295 @@ :root { - --color-bg: #ffffff; - --color-text: #1a1a1a; - --color-primary: #2563EB; /* Vibrant Blue */ - --color-secondary: #000000; - --color-accent: #A3E635; /* Lime Green */ - --color-surface: #f8f9fa; - --font-heading: 'Space Grotesk', sans-serif; - --font-body: 'Inter', sans-serif; - --border-width: 2px; - --shadow-hard: 5px 5px 0px #000; - --shadow-hover: 8px 8px 0px #000; - --radius-pill: 50rem; - --radius-card: 1rem; + --primary-gradient: linear-gradient(135deg, #6366f1 0%, #a855f7 100%); + --accent-gradient: linear-gradient(135deg, #3b82f6 0%, #2dd4bf 100%); + --surface: #ffffff; + --background: #f8fafc; + --border: #e2e8f0; + --text-main: #0f172a; + --text-muted: #64748b; + --radius-lg: 16px; + --radius-md: 12px; + --radius-sm: 8px; + --shadow-subtle: 0 4px 6px -1px rgb(0 0 0 / 0.05), 0 2px 4px -2px rgb(0 0 0 / 0.05); + --shadow-md: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1); + --shadow-lg: 0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1); } body { - font-family: var(--font-body); - background-color: var(--color-bg); - color: var(--color-text); - overflow-x: hidden; + font-family: 'Inter', system-ui, -apple-system, sans-serif; + background-color: var(--background); + color: var(--text-main); + line-height: 1.6; + background-image: + radial-gradient(at 0% 0%, hsla(253,16%,7%,1) 0, transparent 50%), + radial-gradient(at 50% 0%, hsla(225,39%,30%,1) 0, transparent 50%), + radial-gradient(at 100% 0%, hsla(339,49%,30%,1) 0, transparent 50%); + background-attachment: fixed; + background-size: cover; + min-height: 100vh; } -h1, h2, h3, h4, h5, h6, .navbar-brand { - font-family: var(--font-heading); - letter-spacing: -0.03em; +/* Glassmorphism background */ +body::before { + content: ""; + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + background: rgba(248, 250, 252, 0.85); + backdrop-filter: blur(100px); + z-index: -1; } -/* Utilities */ -.text-primary { color: var(--color-primary) !important; } -.bg-black { background-color: #000 !important; } -.text-white { color: #fff !important; } -.shadow-hard { box-shadow: var(--shadow-hard); } -.border-2-black { border: var(--border-width) solid #000; } -.py-section { padding-top: 5rem; padding-bottom: 5rem; } - -/* Navbar */ .navbar { - background: rgba(255, 255, 255, 0.9); - backdrop-filter: blur(10px); - border-bottom: var(--border-width) solid transparent; - transition: all 0.3s; - padding-top: 1rem; - padding-bottom: 1rem; + background: rgba(255, 255, 255, 0.7); + backdrop-filter: blur(10px); + border-bottom: 1px solid rgba(255, 255, 255, 0.3); + padding: 1.25rem 0; + position: sticky; + top: 0; + z-index: 1000; } -.navbar.scrolled { - border-bottom-color: #000; - padding-top: 0.5rem; - padding-bottom: 0.5rem; +.navbar-brand { + font-weight: 800; + font-size: 1.5rem; + background: var(--primary-gradient); + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; + display: flex; + align-items: center; + gap: 0.75rem; } -.brand-text { - font-size: 1.5rem; - font-weight: 800; +.card { + background: rgba(255, 255, 255, 0.9); + backdrop-filter: blur(10px); + border: 1px solid rgba(255, 255, 255, 0.4); + border-radius: var(--radius-lg); + box-shadow: var(--shadow-subtle); + transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); } -.nav-link { - font-weight: 500; - color: var(--color-text); - margin-left: 1rem; - position: relative; +.card:hover { + transform: translateY(-2px); + box-shadow: var(--shadow-md); } -.nav-link:hover, .nav-link.active { - color: var(--color-primary); -} - -/* Buttons */ .btn { - font-weight: 700; - font-family: var(--font-heading); - padding: 0.8rem 2rem; - border-radius: var(--radius-pill); - border: var(--border-width) solid #000; - transition: all 0.2s cubic-bezier(0.25, 1, 0.5, 1); - box-shadow: var(--shadow-hard); -} - -.btn:hover { - transform: translate(-2px, -2px); - box-shadow: var(--shadow-hover); -} - -.btn:active { - transform: translate(2px, 2px); - box-shadow: 0 0 0 #000; + font-weight: 600; + border-radius: var(--radius-md); + padding: 0.75rem 1.5rem; + transition: all 0.2s ease; + display: inline-flex; + align-items: center; + justify-content: center; + gap: 0.625rem; + border: none; } .btn-primary { - background-color: var(--color-primary); - border-color: #000; - color: #fff; + background: var(--primary-gradient); + color: white; + box-shadow: 0 4px 12px rgba(99, 102, 241, 0.3); } .btn-primary:hover { - background-color: #1d4ed8; - border-color: #000; - color: #fff; + transform: scale(1.02); + box-shadow: 0 6px 20px rgba(99, 102, 241, 0.4); + background: var(--primary-gradient); + filter: brightness(1.1); } -.btn-outline-dark { - background-color: #fff; - color: #000; +.btn-light { + background: rgba(241, 245, 249, 0.8); + color: var(--text-main); } -.btn-cta { - background-color: var(--color-accent); - color: #000; -} - -.btn-cta:hover { - background-color: #8cc629; - color: #000; -} - -/* Hero Section */ -.hero-section { - min-height: 100vh; - padding-top: 80px; -} - -.background-blob { - position: absolute; - border-radius: 50%; - filter: blur(80px); - opacity: 0.6; - z-index: 1; -} - -.blob-1 { - top: -10%; - right: -10%; - width: 600px; - height: 600px; - background: radial-gradient(circle, var(--color-accent), transparent); -} - -.blob-2 { - bottom: 10%; - left: -10%; - width: 500px; - height: 500px; - background: radial-gradient(circle, var(--color-primary), transparent); -} - -.highlight-text { - background: linear-gradient(120deg, transparent 0%, transparent 40%, var(--color-accent) 40%, var(--color-accent) 100%); - background-repeat: no-repeat; - background-size: 100% 40%; - background-position: 0 88%; - padding: 0 5px; -} - -.dot { color: var(--color-primary); } - -.badge-pill { - display: inline-block; - padding: 0.5rem 1rem; - border: 2px solid #000; - border-radius: 50px; - font-weight: 700; - background: #fff; - box-shadow: 4px 4px 0 #000; - font-family: var(--font-heading); - font-size: 0.9rem; -} - -/* Marquee */ -.marquee-container { - overflow: hidden; - white-space: nowrap; - border-top: 2px solid #000; - border-bottom: 2px solid #000; -} - -.rotate-divider { - transform: rotate(-2deg) scale(1.05); - z-index: 10; - position: relative; - margin-top: -50px; - margin-bottom: 30px; -} - -.marquee-content { - display: inline-block; - animation: marquee 20s linear infinite; - font-family: var(--font-heading); - font-weight: 700; - font-size: 1.5rem; - letter-spacing: 2px; -} - -@keyframes marquee { - 0% { transform: translateX(0); } - 100% { transform: translateX(-50%); } -} - -/* Portfolio Cards */ -.project-card { - border: 2px solid #000; - border-radius: var(--radius-card); - overflow: hidden; - background: #fff; - transition: transform 0.3s ease; - box-shadow: var(--shadow-hard); - height: 100%; - display: flex; - flex-direction: column; -} - -.project-card:hover { - transform: translateY(-10px); - box-shadow: 8px 8px 0 #000; -} - -.card-img-holder { - height: 250px; - display: flex; - align-items: center; - justify-content: center; - border-bottom: 2px solid #000; - position: relative; - font-size: 4rem; -} - -.placeholder-art { - transition: transform 0.3s ease; -} - -.project-card:hover .placeholder-art { - transform: scale(1.2) rotate(10deg); -} - -.bg-soft-blue { background-color: #e0f2fe; } -.bg-soft-green { background-color: #dcfce7; } -.bg-soft-purple { background-color: #f3e8ff; } -.bg-soft-yellow { background-color: #fef9c3; } - -.category-tag { - position: absolute; - top: 15px; - right: 15px; - background: #000; - color: #fff; - padding: 5px 12px; - border-radius: 20px; - font-size: 0.75rem; - font-weight: 700; -} - -.card-body { padding: 1.5rem; } - -.link-arrow { - text-decoration: none; - color: #000; - font-weight: 700; - display: inline-flex; - align-items: center; - margin-top: auto; -} - -.link-arrow i { transition: transform 0.2s; margin-left: 5px; } -.link-arrow:hover i { transform: translateX(5px); } - -/* About */ -.about-image-stack { - position: relative; - height: 400px; - width: 100%; -} - -.stack-card { - position: absolute; - width: 80%; - height: 100%; - border-radius: var(--radius-card); - border: 2px solid #000; - box-shadow: var(--shadow-hard); - left: 10%; - transform: rotate(-3deg); - background-size: cover; -} - -/* Forms */ -.form-control { - border: 2px solid #000; - border-radius: 0.5rem; - padding: 1rem; - font-weight: 500; - background: #f8f9fa; +.form-control, .form-select { + border: 1px solid var(--border); + border-radius: var(--radius-md); + padding: 0.75rem 1rem; + background: rgba(255, 255, 255, 0.8); + transition: all 0.2s ease; } .form-control:focus { - box-shadow: 4px 4px 0 var(--color-primary); - border-color: #000; - background: #fff; + background: #fff; + border-color: #6366f1; + box-shadow: 0 0 0 4px rgba(99, 102, 241, 0.1); } -/* Animations */ -.animate-up { - opacity: 0; - transform: translateY(30px); - animation: fadeUp 0.8s ease forwards; +.dropzone { + border: 2px dashed #cbd5e1; + border-radius: var(--radius-md); + padding: 3.5rem 2rem; + background: rgba(248, 250, 252, 0.5); + cursor: pointer; + transition: all 0.3s ease; } -.delay-100 { animation-delay: 0.1s; } -.delay-200 { animation-delay: 0.2s; } - -@keyframes fadeUp { - to { - opacity: 1; - transform: translateY(0); - } +.dropzone:hover { + border-color: #6366f1; + background: rgba(99, 102, 241, 0.05); + transform: translateY(-2px); } -/* Social */ -.social-links a { - transition: transform 0.2s; - display: inline-block; -} -.social-links a:hover { - transform: scale(1.2) rotate(10deg); - color: var(--color-accent) !important; +.dropzone i { + background: var(--primary-gradient); + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; + font-size: 3rem; + margin-bottom: 1.5rem; } -/* Responsive */ -@media (max-width: 991px) { - .rotate-divider { - transform: rotate(0); - margin-top: 0; - margin-bottom: 2rem; - } - - .hero-section { - padding-top: 120px; - text-align: center; - min-height: auto; - padding-bottom: 100px; - } - - .display-1 { font-size: 3.5rem; } - - .blob-1 { width: 300px; height: 300px; right: -20%; } - .blob-2 { width: 300px; height: 300px; left: -20%; } +.stats-row { + display: grid; + grid-template-columns: 1fr 1fr; + gap: 1.25rem; + margin-bottom: 2rem; +} + +.stat-item { + background: white; + padding: 1.25rem; + border-radius: var(--radius-md); + border: 1px solid var(--border); + position: relative; + overflow: hidden; +} + +.stat-item::after { + content: ""; + position: absolute; + top: 0; + left: 0; + width: 4px; + height: 100%; + background: var(--primary-gradient); +} + +.stat-label { + font-size: 0.75rem; + font-weight: 700; + color: var(--text-muted); + text-transform: uppercase; + letter-spacing: 0.05em; + margin-bottom: 0.5rem; +} + +.stat-value { + font-size: 1.875rem; + font-weight: 800; + color: var(--text-main); + line-height: 1; +} + +.batch-card { + border: none; + background: white; + margin-bottom: 1.25rem; + position: relative; + overflow: hidden; +} + +.batch-card::before { + content: ""; + position: absolute; + top: 0; + left: 0; + width: 6px; + height: 100%; + background: var(--accent-gradient); +} + +.badge-count { + background: rgba(59, 130, 246, 0.1); + color: #2563eb; + font-weight: 700; + padding: 0.35rem 0.75rem; + border-radius: 9999px; +} + +.batch-header { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 1rem; +} + +.batch-title { + font-weight: 700; + color: var(--text-main); + display: flex; + align-items: center; + gap: 0.5rem; +} + +.dynamic-batch-input { + animation: fadeIn 0.3s ease-out; +} + +@keyframes fadeIn { + from { opacity: 0; transform: translateY(10px); } + to { opacity: 1; transform: translateY(0); } +} + +.sticky-panel { + position: sticky; + top: 6rem; +} + +footer { + background: transparent; + margin-top: 4rem; +} + +.hero-section { + text-align: center; + padding: 4rem 0 2rem; +} + +.hero-section h1 { + font-weight: 900; + font-size: 3rem; + letter-spacing: -0.05em; + margin-bottom: 1rem; + background: var(--primary-gradient); + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; +} + +.hero-section p { + color: var(--text-muted); + font-size: 1.25rem; + max-width: 600px; + margin: 0 auto; +} + +/* Custom Scrollbar */ +::-webkit-scrollbar { + width: 10px; +} +::-webkit-scrollbar-track { + background: #f1f5f9; +} +::-webkit-scrollbar-thumb { + background: #cbd5e1; + border-radius: 5px; +} +::-webkit-scrollbar-thumb:hover { + background: #94a3b8; +} + +/* Glass Detail Summary */ +details summary { + padding: 0.5rem 0; + color: var(--accent); + font-weight: 600; + cursor: pointer; + transition: all 0.2s; +} +details summary:hover { + filter: brightness(0.8); } diff --git a/assets/js/main.js b/assets/js/main.js index fdf2cfd..5fcc34f 100644 --- a/assets/js/main.js +++ b/assets/js/main.js @@ -1,73 +1,247 @@ 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'); - // Smooth scrolling for navigation links - document.querySelectorAll('a[href^="#"]').forEach(anchor => { - anchor.addEventListener('click', function (e) { - e.preventDefault(); - const targetId = this.getAttribute('href'); - if (targetId === '#') return; - - const targetElement = document.querySelector(targetId); - if (targetElement) { - // Close mobile menu if open - const navbarToggler = document.querySelector('.navbar-toggler'); - const navbarCollapse = document.querySelector('.navbar-collapse'); - if (navbarCollapse.classList.contains('show')) { - navbarToggler.click(); - } + let allNumbers = []; - // Scroll with offset - const offset = 80; - const elementPosition = targetElement.getBoundingClientRect().top; - const offsetPosition = elementPosition + window.pageYOffset - offset; + // Helper: Extract numbers from text (Mobile number regex) + const extractNumbers = (text) => { + const matches = text.match(/1[3-9]\d{9}/g) || []; + return matches; + }; - window.scrollTo({ - top: offsetPosition, - behavior: "smooth" - }); - } - }); - }); + // 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; + }; - // Navbar scroll effect - const navbar = document.querySelector('.navbar'); - window.addEventListener('scroll', () => { - if (window.scrollY > 50) { - navbar.classList.add('scrolled', 'shadow-sm', 'bg-white'); - navbar.classList.remove('bg-transparent'); + 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 { - navbar.classList.remove('scrolled', 'shadow-sm', 'bg-white'); - navbar.classList.add('bg-transparent'); + 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 请直接复制其中的号码并粘贴到输入框。'); } }); - // Intersection Observer for fade-up animations - const observerOptions = { - threshold: 0.1, - rootMargin: "0px 0px -50px 0px" - }; + // Splitting logic + splitBtn.addEventListener('click', () => { + updateStats(); // Ensure we have latest data + if (allNumbers.length === 0) { + alert('请先导入或粘贴号码!'); + return; + } - const observer = new IntersectionObserver((entries) => { - entries.forEach(entry => { - if (entry.isIntersecting) { - entry.target.classList.add('animate-up'); - entry.target.style.opacity = "1"; - observer.unobserve(entry.target); // Only animate once + 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([]); + } + } } - }); - }, observerOptions); + } else { + // Split by fixed size per batch + while (tempNumbers.length > 0) { + batches.push(tempNumbers.splice(0, val)); + } + } - // Select elements to animate (add a class 'reveal' to them in HTML if not already handled by CSS animation) - // For now, let's just make sure the hero animations run. - // If we want scroll animations, we'd add opacity: 0 to elements in CSS and reveal them here. - // Given the request, the CSS animation I added runs on load for Hero. - // Let's make the project cards animate in. - - const projectCards = document.querySelectorAll('.project-card'); - projectCards.forEach((card, index) => { - card.style.opacity = "0"; - card.style.animationDelay = `${index * 0.1}s`; - observer.observe(card); + 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 = ` +
+
+
+ 第 ${index + 1} 批 + ${batch.length.toLocaleString()} 条号码 +
+ +
+
+
+ + +
+
+
+ 查看部分预览 +
+ ${batch.length > 0 ? previewText + (hasMore ? ' ...' : '') : '此批次为空'} +
+
+
+ `; + + resultsContainer.appendChild(card); + + // Download handler + card.querySelector('.download-btn').addEventListener('click', () => { + if (batch.length === 0) { + alert('此批次没有号码可下载。'); + return; + } + const remark = card.querySelector('.remark-input').value.trim() || `批次_${index + 1}_${batch.length}条`; + const blob = new Blob([batch.join('\n')], { type: 'text/plain;charset=utf-8' }); + const url = URL.createObjectURL(blob); + const a = document.createElement('a'); + a.href = url; + a.download = `${remark}.txt`; + document.body.appendChild(a); + a.click(); + document.body.removeChild(a); + URL.revokeObjectURL(url); + }); + }); + + if (window.lucide) { + lucide.createIcons(); + } + + resultsContainer.scrollIntoView({ behavior: 'smooth', block: 'start' }); + }); + + // Initial UI Setup + updateSplitUI(); }); \ No newline at end of file diff --git a/index.php b/index.php index 7205f3d..90ec5f2 100644 --- a/index.php +++ b/index.php @@ -4,147 +4,183 @@ declare(strict_types=1); @error_reporting(E_ALL); @date_default_timezone_set('UTC'); -$phpVersion = PHP_VERSION; -$now = date('Y-m-d H:i:s'); +$projectDescription = $_SERVER['PROJECT_DESCRIPTION'] ?? '快速导入、自动去重、智能分批提取手机号码工具'; +$projectImageUrl = $_SERVER['PROJECT_IMAGE_URL'] ?? ''; +$projectName = $_SERVER['PROJECT_NAME'] ?? '号码分批大师'; ?> - + - - - New Style - - - - - - - - - - - - - - - - - - - + + + <?= htmlspecialchars($projectName) ?> - 专业级号码分批与去重工具 + + + + + + + + + + + + + + + + + + -
-
-

Analyzing your requirements and generating your website…

-
- Loading… -
-

AI is collecting your requirements and applying the first changes.

-

This page will update automatically as the plan is implemented.

-

Runtime: PHP — UTC

-
-
- + + + +
+

号码智能处理中心

+

支持万级号码导入、全自动去重、自定义灵活分批,提升您的工作效率。

+
+ +
+
+ +
+
+
+
+

1. 号码采集

+
+ 实时提取 +
+
+ +
+ +
拖放文件或点击上传
+

支持 TXT, CSV, EXCEL 格式内容提取

+ +
+ +
+ + +
+ +
+
+
识别总数
+
0
+
+
+
去重后
+
0
+
+
+ +
+
+ + +
+ +
+
+
+
+ + +
+
+
+
+

2. 拆分配置

+ +
+ + +
+ +
+ +
+ + +
+
+ + +
+ +
+ +
+
+ + +
+
+ +
+
+

3. 处理结果

+ 0 个批次 +
+
+
+
+ +
+

请完成上方配置并执行拆分

+
+
+
+
+
+
+
+ + + + + + + - + \ No newline at end of file