马上注册,免费下载更多dz插件网资源。
您需要 登录 才可以下载或查看,没有账号?立即注册
×
- <!DOCTYPE html><html lang="zh-CN"><head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>TXT转Sitemap生成器(支持大文件分割)</title> <link rel="stylesheet" > <style> * { margin: 0; padding: 0; box-sizing: border-box; font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; } body { background: linear-gradient(135deg, #6a11cb 0%, #2575fc 100%); color: #333; min-height: 100vh; padding: 20px; } .container { max-width: 1200px; margin: 0 auto; background-color: rgba(255, 255, 255, 0.95); border-radius: 15px; box-shadow: 0 10px 30px rgba(0, 0, 0, 0.2); overflow: hidden; } header { background: linear-gradient(to right, #2c3e50, #4a6491); color: white; padding: 25px 30px; text-align: center; } h1 { font-size: 2.5rem; margin-bottom: 10px; } .subtitle { font-size: 1.1rem; opacity: 0.9; margin-bottom: 5px; } .content { padding: 30px; display: flex; flex-direction: column; gap: 25px; } .input-section, .output-section { background-color: #f8f9fa; border-radius: 10px; padding: 25px; box-shadow: 0 4px 6px rgba(0, 0, 0, 0.05); } .section-title { display: flex; align-items: center; gap: 10px; font-size: 1.5rem; color: #2c3e50; margin-bottom: 20px; padding-bottom: 10px; border-bottom: 2px solid #eaeaea; } .section-title i { color: #3498db; } .input-methods { display: flex; flex-wrap: wrap; gap: 20px; margin-bottom: 20px; } .method { flex: 1; min-width: 300px; } .method h3 { margin-bottom: 15px; color: #2c3e50; font-size: 1.2rem; } .input-group { display: flex; flex-direction: column; gap: 10px; } input[type="url"], input[type="file"] { padding: 12px 15px; border: 2px solid #ddd; border-radius: 8px; font-size: 1rem; transition: all 0.3s; } input[type="url"]:focus, input[type="file"]:focus { border-color: #3498db; outline: none; } .btn { padding: 12px 25px; background: linear-gradient(to right, #3498db, #2980b9); color: white; border: none; border-radius: 8px; font-size: 1rem; cursor: pointer; transition: all 0.3s; display: inline-flex; align-items: center; justify-content: center; gap: 8px; font-weight: 600; } .btn:hover { background: linear-gradient(to right, #2980b9, #2575fc); transform: translateY(-2px); box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1); } .btn:active { transform: translateY(0); } .btn-secondary { background: linear-gradient(to right, #2ecc71, #27ae60); } .btn-secondary:hover { background: linear-gradient(to right, #27ae60, #219653); } .btn-warning { background: linear-gradient(to right, #f39c12, #e67e22); } .btn-warning:hover { background: linear-gradient(to right, #e67e22, #d35400); } .btn-danger { background: linear-gradient(to right, #e74c3c, #c0392b); } .btn-danger:hover { background: linear-gradient(to right, #c0392b, #a93226); } .actions { display: flex; flex-wrap: wrap; gap: 15px; margin-top: 20px; } .url-list { margin-top: 20px; max-height: 200px; overflow-y: auto; border: 1px solid #ddd; border-radius: 8px; padding: 10px; background-color: white; } .url-item { padding: 8px 12px; border-bottom: 1px solid #eee; font-family: monospace; font-size: 0.9rem; word-break: break-all; } .url-item:last-child { border-bottom: none; } .url-count { font-weight: bold; color: #3498db; margin-left: 5px; } .sitemap-list { margin-top: 20px; display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 15px; } .sitemap-card { background-color: white; border-radius: 8px; border: 1px solid #ddd; overflow: hidden; transition: all 0.3s; } .sitemap-card:hover { transform: translateY(-3px); box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1); } .sitemap-header { background-color: #2c3e50; color: white; padding: 12px 15px; display: flex; justify-content: space-between; align-items: center; } .sitemap-content { padding: 15px; } .sitemap-info { margin-bottom: 10px; } .sitemap-info span { display: block; margin-bottom: 5px; } .sitemap-actions { display: flex; flex-wrap: wrap; gap: 8px; } .sitemap-btn { padding: 8px 12px; background-color: #3498db; color: white; border: none; border-radius: 5px; font-size: 0.85rem; cursor: pointer; transition: background-color 0.3s; display: flex; align-items: center; gap: 5px; } .sitemap-btn:hover { background-color: #2980b9; } .sitemap-btn-secondary { background-color: #2ecc71; } .sitemap-btn-secondary:hover { background-color: #27ae60; } .sitemap-preview { margin-top: 20px; border: 1px solid #ddd; border-radius: 8px; overflow: hidden; } .preview-header { background-color: #2c3e50; color: white; padding: 10px 15px; display: flex; justify-content: space-between; align-items: center; } .preview-content { max-height: 300px; overflow-y: auto; padding: 15px; background-color: #f4f6f8; } pre { white-space: pre-wrap; word-wrap: break-word; font-family: monospace; font-size: 0.9rem; line-height: 1.5; } .empty-state { text-align: center; padding: 40px 20px; color: #7f8c8d; } .empty-state i { font-size: 3rem; margin-bottom: 15px; color: #bdc3c7; } .instructions { background-color: #e8f4fc; border-left: 4px solid #3498db; padding: 15px; border-radius: 0 8px 8px 0; margin-top: 20px; } .instructions h3 { margin-bottom: 10px; color: #2c3e50; } .instructions ul { padding-left: 20px; } .instructions li { margin-bottom: 8px; } .status-bar { display: flex; justify-content: space-between; align-items: center; padding: 10px 15px; background-color: #f0f7ff; border-radius: 8px; margin-bottom: 15px; border-left: 4px solid #3498db; } .progress-bar { height: 8px; background-color: #e0e0e0; border-radius: 4px; overflow: hidden; margin-top: 5px; flex-grow: 1; margin-right: 15px; } .progress-fill { height: 100%; background: linear-gradient(to right, #2ecc71, #27ae60); width: 0%; transition: width 0.5s ease; } footer { text-align: center; padding: 20px; color: #7f8c8d; font-size: 0.9rem; border-top: 1px solid #eee; } @media (max-width: 768px) { .container { border-radius: 10px; } .content { padding: 20px; } .input-methods { flex-direction: column; } .method { min-width: 100%; } h1 { font-size: 2rem; } .sitemap-list { grid-template-columns: 1fr; } .preview-header { flex-direction: column; gap: 10px; align-items: flex-start; } } </style></head><body> <div class="container"> <header> <h1><i class="fas fa-sitemap"></i> TXT转Sitemap生成器(大文件分割版)</h1> <p class="subtitle">将TXT文件中的URL列表转换为标准XML站点地图,自动分割超过5万条URL的大文件</p> <p class="subtitle">支持生成sitemap索引文件和批量下载</p> </header> <div class="content"> <section class="input-section"> <div class="section-title"> <i class="fas fa-upload"></i> <h2>输入URL列表</h2> </div> <div class="input-methods"> <div class="method"> <h3>通过TXT文件URL</h3> <div class="input-group"> <input type="url" id="txtUrl" placeholder="输入TXT文件的完整URL (例如: https://example.com/urls.txt)"> <button class="btn" id="fetchBtn"> <i class="fas fa-download"></i> 获取并解析URL </button> </div> </div> <div class="method"> <h3>上传TXT文件</h3> <div class="input-group"> <input type="file" id="fileInput" accept=".txt"> <button class="btn btn-secondary" id="uploadBtn"> <i class="fas fa-file-upload"></i> 上传并解析文件 </button> </div> </div> </div> <div id="statusBar" class="status-bar" style="display: none;"> <div> <div>处理进度: <span id="progressText">0%</span></div> <div class="progress-bar"> <div class="progress-fill" id="progressFill"></div> </div> </div> <div id="statusInfo">正在解析文件...</div> </div> <div class="instructions"> <h3><i class="fas fa-info-circle"></i> 使用说明</h3> <ul> <li>TXT文件应每行包含一个完整URL(例如:https://example.com/page1)</li> <li>支持HTTP和HTTPS协议的URL</li> <li>系统将自动验证URL格式并排除无效链接</li> <li>如果URL数量超过5万条,将自动分割为多个sitemap文件</li> <li>分割时会自动生成sitemap索引文件,便于搜索引擎抓取</li> <li>支持批量下载所有sitemap文件</li> </ul> </div> </section> <section class="output-section"> <div class="section-title"> <i class="fas fa-code"></i> <h2>生成的Sitemap</h2> <span id="urlCount" class="url-count" style="display: none;">0 个URL</span> </div> <div id="summaryInfo" style="display: none; margin-bottom: 15px; padding: 10px; background-color: #e8f4fc; border-radius: 8px;"> <p><strong>解析结果:</strong> 共找到 <span id="totalUrls">0</span> 个有效URL,已分割为 <span id="sitemapCount">0</span> 个sitemap文件。</p> <p id="splitNotice" style="color: #e67e22; font-weight: bold; margin-top: 5px;"></p> </div> <div id="urlListContainer" class="url-list" style="display: none;"> <h3>已解析的URL列表(前100条):</h3> <div id="urlList"></div> </div> <div id="sitemapList" class="sitemap-list" style="display: none;"></div> <div id="batchActions" class="actions" style="display: none;"> <button class="btn btn-secondary" id="downloadAllBtn"> <i class="fas fa-download"></i> 批量下载所有Sitemap文件 </button> <button class="btn" id="downloadIndexBtn"> <i class="fas fa-file-alt"></i> 下载Sitemap索引文件 </button> <button class="btn btn-danger" id="clearBtn"> <i class="fas fa-trash-alt"></i> 清除全部 </button> </div> <div id="sitemapPreviewContainer" class="sitemap-preview" style="display: none;"> <div class="preview-header"> <span id="previewTitle">XML Sitemap 预览</span> <div class="actions"> <button class="btn btn-secondary" id="copyBtn"> <i class="far fa-copy"></i> 复制XML </button> <button class="btn" id="closePreviewBtn"> <i class="fas fa-times"></i> 关闭预览 </button> </div> </div> <div class="preview-content"> <pre id="sitemapOutput"></pre> </div> </div> <div id="emptyState" class="empty-state"> <i class="fas fa-file-code"></i> <h3>等待生成Sitemap</h3> <p>输入TXT文件的URL或上传文件以开始生成XML站点地图</p> </div> </section> </div> <footer> <p>TXT转Sitemap生成器(大文件分割版) © 2023 | 本工具完全在浏览器中运行,不会上传任何数据到服务器</p> </footer> </div> <script> document.addEventListener('DOMContentLoaded', function() { const txtUrlInput = document.getElementById('txtUrl'); const fetchBtn = document.getElementById('fetchBtn'); const fileInput = document.getElementById('fileInput'); const uploadBtn = document.getElementById('uploadBtn'); const urlListContainer = document.getElementById('urlListContainer'); const urlList = document.getElementById('urlList'); const urlCount = document.getElementById('urlCount'); const sitemapList = document.getElementById('sitemapList'); const emptyState = document.getElementById('emptyState'); const copyBtn = document.getElementById('copyBtn'); const clearBtn = document.getElementById('clearBtn'); const downloadAllBtn = document.getElementById('downloadAllBtn'); const downloadIndexBtn = document.getElementById('downloadIndexBtn'); const sitemapPreviewContainer = document.getElementById('sitemapPreviewContainer'); const sitemapOutput = document.getElementById('sitemapOutput'); const closePreviewBtn = document.getElementById('closePreviewBtn'); const summaryInfo = document.getElementById('summaryInfo'); const totalUrlsElement = document.getElementById('totalUrls'); const sitemapCountElement = document.getElementById('sitemapCount'); const splitNotice = document.getElementById('splitNotice'); const batchActions = document.getElementById('batchActions'); const statusBar = document.getElementById('statusBar'); const progressText = document.getElementById('progressText'); const progressFill = document.getElementById('progressFill'); const statusInfo = document.getElementById('statusInfo'); const MAX_URLS_PER_SITEMAP = 50000; // 每个sitemap最多包含的URL数量 let urls = []; let sitemaps = []; // 存储生成的sitemap对象 let currentPreviewIndex = -1; // 从URL获取TXT文件 fetchBtn.addEventListener('click', async function() { const url = txtUrlInput.value.trim(); if (!url) { alert('请输入TXT文件的URL'); return; } if (!isValidUrl(url)) { alert('请输入有效的URL地址'); return; } fetchBtn.disabled = true; fetchBtn.innerHTML = '<i class="fas fa-spinner fa-spin"></i> 获取中...'; showStatusBar('正在获取TXT文件...', 10); try { const response = await fetch(url); if (!response.ok) { throw new Error(`HTTP错误: ${response.status}`); } const text = await response.text(); showStatusBar('正在解析文件内容...', 30); setTimeout(() => { processTextContent(text); }, 500); } catch (error) { alert(`获取文件失败: ${error.message}`); console.error('获取TXT文件失败:', error); hideStatusBar(); } finally { fetchBtn.disabled = false; fetchBtn.innerHTML = '<i class="fas fa-download"></i> 获取并解析URL'; } }); // 上传TXT文件 uploadBtn.addEventListener('click', function() { if (!fileInput.files || fileInput.files.length === 0) { alert('请选择要上传的TXT文件'); return; } const file = fileInput.files[0]; if (!file.name.endsWith('.txt')) { alert('请选择TXT文件'); return; } showStatusBar('正在读取文件...', 10); const reader = new FileReader(); reader.onload = function(e) { showStatusBar('正在解析文件内容...', 30); setTimeout(() => { processTextContent(e.target.result); }, 500); }; reader.onerror = function() { alert('读取文件失败'); hideStatusBar(); }; reader.readAsText(file); }); // 显示状态栏 function showStatusBar(message, progress) { statusBar.style.display = 'flex'; statusInfo.textContent = message; progressText.textContent = progress + '%'; progressFill.style.width = progress + '%'; } // 隐藏状态栏 function hideStatusBar() { statusBar.style.display = 'none'; } // 处理文本内容,提取URL function processTextContent(text) { showStatusBar('正在提取URL...', 50); // 按行分割,过滤空行和注释 const lines = text.split('\n') .map(line => line.trim()) .filter(line => line && !line.startsWith('#') && !line.startsWith('//')); showStatusBar('正在验证URL格式...', 70); // 提取有效的URL urls = lines .map(line => { // 尝试从行中提取URL const urlMatch = line.match(/https?:\/\/[^\s]+/i); return urlMatch ? urlMatch[0] : line; }) .filter(url => isValidUrl(url)); showStatusBar('正在生成Sitemap文件...', 90); if (urls.length === 0) { hideStatusBar(); alert('未在文件中找到有效的URL'); return; } setTimeout(() => { displayUrlList(); generateSitemaps(); hideStatusBar(); }, 500); } // 显示URL列表(仅显示前100条) function displayUrlList() { urlList.innerHTML = ''; const displayUrls = urls.slice(0, 100); displayUrls.forEach((url, index) => { const urlItem = document.createElement('div'); urlItem.className = 'url-item'; urlItem.textContent = `${index + 1}. ${url}`; urlList.appendChild(urlItem); }); if (urls.length > 100) { const moreItem = document.createElement('div'); moreItem.className = 'url-item'; moreItem.style.fontStyle = 'italic'; moreItem.style.color = '#7f8c8d'; moreItem.textContent = `... 以及另外 ${urls.length - 100} 个URL`; urlList.appendChild(moreItem); } urlCount.textContent = `${urls.length} 个URL`; urlCount.style.display = 'inline'; urlListContainer.style.display = 'block'; } // 生成多个sitemap(如果需要分割) function generateSitemaps() { sitemaps = []; // 计算需要分割成几个sitemap文件 const numSitemaps = Math.ceil(urls.length / MAX_URLS_PER_SITEMAP); // 更新摘要信息 totalUrlsElement.textContent = urls.length; sitemapCountElement.textContent = numSitemaps; summaryInfo.style.display = 'block'; if (numSitemaps > 1) { splitNotice.textContent = `注意:检测到 ${urls.length} 个URL,已自动分割为 ${numSitemaps} 个sitemap文件(每个最多 ${MAX_URLS_PER_SITEMAP} 个URL)。`; } else { splitNotice.textContent = ''; } // 生成每个sitemap文件 for (let i = 0; i < numSitemaps; i++) { const startIdx = i * MAX_URLS_PER_SITEMAP; const endIdx = Math.min(startIdx + MAX_URLS_PER_SITEMAP, urls.length); const chunkUrls = urls.slice(startIdx, endIdx); const sitemapXml = generateSingleSitemap(chunkUrls); const sitemapIndex = i + 1; sitemaps.push({ index: sitemapIndex, urls: chunkUrls, xml: sitemapXml, filename: `sitemap-${sitemapIndex}.xml` }); } // 生成sitemap索引文件(如果有多个sitemap) if (numSitemaps > 1) { const sitemapIndexXml = generateSitemapIndex(); sitemaps.push({ index: 0, urls: [], xml: sitemapIndexXml, filename: 'sitemap-index.xml', isIndex: true }); } displaySitemapList(); batchActions.style.display = 'flex'; emptyState.style.display = 'none'; } // 生成单个sitemap文件 function generateSingleSitemap(urlChunk) { const now = new Date().toISOString().split('T')[0]; let xml = '<?xml version="1.0" encoding="UTF-8"?>\n'; xml += '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">\n'; urlChunk.forEach(url => { xml += ' <url>\n'; xml += ` <loc>${escapeXml(url)}</loc>\n`; xml += ` <lastmod>${now}</lastmod>\n`; xml += ' <changefreq>weekly</changefreq>\n'; xml += ' <priority>0.8</priority>\n'; xml += ' </url>\n'; }); xml += '</urlset>'; return xml; } // 生成sitemap索引文件 function generateSitemapIndex() { const now = new Date().toISOString().split('T')[0]; let xml = '<?xml version="1.0" encoding="UTF-8"?>\n'; xml += '<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">\n'; // 为每个sitemap文件添加条目(排除索引文件本身) sitemaps.filter(s => !s.isIndex).forEach(sitemap => { xml += ' <sitemap>\n'; xml += ` <loc>${escapeXml(window.location.origin + '/' + sitemap.filename)}</loc>\n`; xml += ` <lastmod>${now}</lastmod>\n`; xml += ' </sitemap>\n'; }); xml += '</sitemapindex>'; return xml; } // 显示sitemap列表 function displaySitemapList() { sitemapList.innerHTML = ''; sitemapList.style.display = 'grid'; sitemaps.forEach(sitemap => { const card = document.createElement('div'); card.className = 'sitemap-card'; const header = document.createElement('div'); header.className = 'sitemap-header'; const title = document.createElement('div'); title.innerHTML = `<strong>${sitemap.isIndex ? 'Sitemap索引文件' : 'Sitemap ' + sitemap.index}</strong>`; const badge = document.createElement('span'); badge.style.background = sitemap.isIndex ? '#f39c12' : '#3498db'; badge.style.padding = '3px 8px'; badge.style.borderRadius = '10px'; badge.style.fontSize = '0.8rem'; badge.textContent = sitemap.isIndex ? '索引' : `${sitemap.urls.length}个URL`; header.appendChild(title); header.appendChild(badge); const content = document.createElement('div'); content.className = 'sitemap-content'; const info = document.createElement('div'); info.className = 'sitemap-info'; const filename = document.createElement('span'); filename.innerHTML = `<i class="fas fa-file"></i> 文件名: ${sitemap.filename}`; const size = document.createElement('span'); size.innerHTML = `<i class="fas fa-hashtag"></i> 大小: ${formatFileSize(sitemap.xml.length)}`; info.appendChild(filename); if (!sitemap.isIndex) { const urlCount = document.createElement('span'); urlCount.innerHTML = `<i class="fas fa-link"></i> URL数量: ${sitemap.urls.length}`; info.appendChild(urlCount); } info.appendChild(size); const actions = document.createElement('div'); actions.className = 'sitemap-actions'; const previewBtn = document.createElement('button'); previewBtn.className = 'sitemap-btn'; previewBtn.innerHTML = '<i class="fas fa-eye"></i> 预览'; previewBtn.addEventListener('click', () => previewSitemap(sitemap)); const downloadBtn = document.createElement('button'); downloadBtn.className = 'sitemap-btn sitemap-btn-secondary'; downloadBtn.innerHTML = '<i class="fas fa-download"></i> 下载'; downloadBtn.addEventListener('click', () => downloadSitemap(sitemap)); actions.appendChild(previewBtn); actions.appendChild(downloadBtn); content.appendChild(info); content.appendChild(actions); card.appendChild(header); card.appendChild(content); sitemapList.appendChild(card); }); } // 预览sitemap function previewSitemap(sitemap) { sitemapOutput.textContent = sitemap.xml; document.getElementById('previewTitle').textContent = `预览: ${sitemap.filename}`; sitemapPreviewContainer.style.display = 'block'; currentPreviewIndex = sitemap.index; // 滚动到预览区域 sitemapPreviewContainer.scrollIntoView({ behavior: 'smooth' }); } // 复制XML到剪贴板 copyBtn.addEventListener('click', function() { const xml = sitemapOutput.textContent; navigator.clipboard.writeText(xml) .then(() => { const originalText = copyBtn.innerHTML; copyBtn.innerHTML = '<i class="fas fa-check"></i> 已复制'; setTimeout(() => { copyBtn.innerHTML = originalText; }, 2000); }) .catch(err => { console.error('复制失败:', err); alert('复制失败,请手动选择并复制文本'); }); }); // 关闭预览 closePreviewBtn.addEventListener('click', function() { sitemapPreviewContainer.style.display = 'none'; currentPreviewIndex = -1; }); // 下载单个sitemap文件 function downloadSitemap(sitemap) { const blob = new Blob([sitemap.xml], { type: 'application/xml' }); const url = URL.createObjectURL(blob); const a = document.createElement('a'); a.href = url; a.download = sitemap.filename; document.body.appendChild(a); a.click(); document.body.removeChild(a); URL.revokeObjectURL(url); } // 批量下载所有sitemap文件 downloadAllBtn.addEventListener('click', function() { // 创建ZIP文件(使用JSZip库) if (typeof JSZip === 'undefined') { // 如果JSZip未加载,则逐个下载 alert('正在逐个下载sitemap文件...'); sitemaps.forEach(sitemap => { if (!sitemap.isIndex) { setTimeout(() => downloadSitemap(sitemap), 100); } }); return; } // 使用JSZip打包下载 downloadAllBtn.disabled = true; downloadAllBtn.innerHTML = '<i class="fas fa-spinner fa-spin"></i> 正在打包...'; const zip = new JSZip(); sitemaps.forEach(sitemap => { zip.file(sitemap.filename, sitemap.xml); }); zip.generateAsync({ type: 'blob' }) .then(function(content) { const url = URL.createObjectURL(content); const a = document.createElement('a'); a.href = url; a.download = 'sitemaps.zip'; document.body.appendChild(a); a.click(); document.body.removeChild(a); URL.revokeObjectURL(url); downloadAllBtn.disabled = false; downloadAllBtn.innerHTML = '<i class="fas fa-download"></i> 批量下载所有Sitemap文件'; }) .catch(function(error) { console.error('创建ZIP文件失败:', error); alert('创建ZIP文件失败,将逐个下载文件'); // 逐个下载 sitemaps.forEach(sitemap => { setTimeout(() => downloadSitemap(sitemap), 100); }); downloadAllBtn.disabled = false; downloadAllBtn.innerHTML = '<i class="fas fa-download"></i> 批量下载所有Sitemap文件'; }); }); // 下载索引文件 downloadIndexBtn.addEventListener('click', function() { const indexSitemap = sitemaps.find(s => s.isIndex); if (indexSitemap) { downloadSitemap(indexSitemap); } else { alert('没有生成索引文件(URL数量未超过5万条)'); } }); // 清除所有内容 clearBtn.addEventListener('click', function() { urls = []; sitemaps = []; txtUrlInput.value = ''; fileInput.value = ''; urlListContainer.style.display = 'none'; sitemapList.style.display = 'none'; sitemapPreviewContainer.style.display = 'none'; batchActions.style.display = 'none'; summaryInfo.style.display = 'none'; emptyState.style.display = 'block'; urlCount.style.display = 'none'; currentPreviewIndex = -1; }); // 验证URL格式 function isValidUrl(string) { try { const url = new URL(string); return url.protocol === 'http:' || url.protocol === 'https:'; } catch (_) { return false; } } // 转义XML特殊字符 function escapeXml(unsafe) { return unsafe .replace(/&/g, '&') .replace(/</g, '<') .replace(/>/g, '>') .replace(/"/g, '"') .replace(/'/g, '''); } // 格式化文件大小 function formatFileSize(bytes) { if (bytes === 0) return '0 Bytes'; const k = 1024; const sizes = ['Bytes', 'KB', 'MB', 'GB']; const i = Math.floor(Math.log(bytes) / Math.log(k)); return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i]; } // 示例URL填充(方便测试) txtUrlInput.value = ''; // 添加键盘快捷键支持 document.addEventListener('keydown', function(e) { if (e.ctrlKey && e.key === 'Enter') { if (document.activeElement === txtUrlInput) { fetchBtn.click(); } } if (e.key === 'Escape') { if (sitemapPreviewContainer.style.display === 'block') { closePreviewBtn.click(); } else { clearBtn.click(); } } }); // 动态加载JSZip库(如果需要) function loadJSZip() { if (typeof JSZip === 'undefined') { const script = document.createElement('script'); script.src = 'https://cdnjs.cloudflare.com/ajax/libs/jszip/3.10.1/jszip.min.js'; script.onload = function() { console.log('JSZip库加载完成'); }; document.head.appendChild(script); } } // 页面加载时尝试加载JSZip loadJSZip(); }); </script></body></html>
复制代码
©DZ插件网所发布的一切资源仅限用于学习和研究目的;不得将上述内容用于商业或者非法用途,否则,一切后果请用户自负。 本站内容为站长个人技术研究记录或网络,不提供用户交互功能,所有内容版权归原作者所有。您必须在下载后的24个小时之内,从您的电脑中彻底删除上述内容。如果您喜欢该程序,请支持正版软件,得到更好的正版服务。 您在本站任何的赞助购买、下载、查阅、回复等行为等均表示接受并同意签订《DZ插件网免责声明协议》。 如有侵权请邮件与我们联系处理: discuzaddons@vip.qq.com 并出示相关证明以便删除。敬请谅解!
|
|