// 全局变量 let isTaskRunning = false; let currentSection = 'home'; let taskCheckInterval; const API_BASE_URL = 'http://localhost:8080/api'; // API基础地址 // DOM加载完成后初始化 $(document).ready(function() { showSection('home'); console.log('✅ 微信公众号文章爬虫系统已加载'); }); // 显示指定区域 function showSection(sectionName) { // 隐藏所有区域 $('.section').hide(); $('.feature-cards').hide(); if (sectionName === 'home') { $('.feature-cards').show(); currentSection = 'home'; } else { $('#section-' + sectionName).show(); currentSection = sectionName; } } // 提取公众号主页相关函数 function extractHomepage() { const articleUrl = $('#homepage-url').val().trim(); if (!articleUrl) { showResult('homepage', 'error', '请输入文章链接'); return; } if (!articleUrl.includes('mp.weixin.qq.com')) { showResult('homepage', 'error', '请输入有效的微信公众号文章链接'); return; } if (isTaskRunning) { showResult('homepage', 'error', '有任务正在执行,请稍候...'); return; } isTaskRunning = true; showResult('homepage', 'loading', '正在提取公众号主页链接...'); // 调用后端API $.ajax({ url: `${API_BASE_URL}/homepage/extract`, method: 'POST', contentType: 'application/json', data: JSON.stringify({ url: articleUrl }), success: function(response) { isTaskRunning = false; if (response.success && response.data && response.data.homepage) { const homepageUrl = response.data.homepage; const safeUrl = homepageUrl.replace(/'/g, "\\'"); const resultHtml = `

✅ 提取成功

公众号主页链接:

${homepageUrl}
`; showResult('homepage', 'success', resultHtml); } else { showResult('homepage', 'error', response.message || '提取失败'); } }, error: function(xhr, status, error) { isTaskRunning = false; let errorMsg = '请求失败:' + error; if (xhr.status === 0) { errorMsg = '无法连接到后端服务器,请确保 API 服务器已启动(运行 api_server.exe)'; } showResult('homepage', 'error', errorMsg); } }); } // 生成模拟的公众号主页链接 function generateMockHomepageUrl(articleUrl) { // 从文章链接中提取__biz参数来模拟真实的主页链接 const bizMatch = articleUrl.match(/__biz=([^&]+)/); if (bizMatch) { const biz = bizMatch[1]; return `https://mp.weixin.qq.com/mp/profile_ext?action=home&__biz=${biz}&scene=124`; } // 如果无法提取,返回示例链接 return 'https://mp.weixin.qq.com/mp/profile_ext?action=home&__biz=MzI1NjEwMTM4OA==&scene=124'; } function loadExampleUrl() { const exampleUrl = 'https://mp.weixin.qq.com/s?__biz=MzI1NjEwMTM4OA==&mid=2651232405&idx=1&sn=7c8f5b2e3d4a1b9c8e7f6a5b4c3d2e1f&chksm=f1d7e8c4c6a061d2b9e8f7a6b5c4d3e2f1a0b9c8d7e6f5a4b3c2d1e0f9a8b7c6d5e4f3a2b1c0&scene=27'; $('#homepage-url').val(exampleUrl); showResult('homepage', 'info', '已加载文章链接示例,点击"提取主页链接"开始处理'); } // 打开链接的辅助函数 function openInNewTab(url) { window.open(url, '_blank'); } // 下载单篇文章 function downloadSingleArticle() { alert('此功能需要后端命令行支持。\n\n请使用命令行程序:\n1. 运行 wechat-crawler.exe\n2. 选择对应功能进行下载'); showResult('single', 'info', '请使用命令行程序执行下载功能'); } // 获取文章列表 function getArticleList() { const accessToken = $('#access-token').val().trim(); const pages = parseInt($('#pages').val()) || 0; if (!accessToken) { showResult('list', 'error', '请输入Access Token URL'); return; } if (isTaskRunning) { showResult('list', 'error', '有任务正在执行,请稍候...'); return; } isTaskRunning = true; showResult('list', 'loading', '正在获取文章列表,请稍候...'); // 调用后端API(同步等待) $.ajax({ url: `${API_BASE_URL}/article/list`, method: 'POST', contentType: 'application/json', data: JSON.stringify({ access_token: accessToken, pages: pages }), success: function(response) { isTaskRunning = false; if (response.success && response.data) { const data = response.data; const fileExt = data.filename.endsWith('.txt') ? 'TXT文件' : 'Excel文件'; const resultHtml = `

✅ 获取成功

公众号:${data.account}

文件:${data.filename}

📥 下载${fileExt}
`; showResult('list', 'success', resultHtml); // 自动触发下载 window.location.href = `${API_BASE_URL}${data.download}`; } else { showResult('list', 'error', response.message || '获取失败'); } }, error: function(xhr, status, error) { isTaskRunning = false; let errorMsg = '请求失败:' + error; if (xhr.status === 0) { errorMsg = '无法连接到后端服务器,请确保 API 服务器已启动'; } else if (xhr.responseJSON && xhr.responseJSON.message) { errorMsg = xhr.responseJSON.message; } showResult('list', 'error', errorMsg); }, timeout: 120000 // 2分钟超时 }); } // 批量下载文章 function batchDownload() { const officialAccount = $('#official-account').val().trim(); const saveImage = $('#batch-save-image').is(':checked'); const saveContent = $('#batch-save-content').is(':checked'); if (!officialAccount) { showResult('batch', 'error', '请输入公众号名称或文章链接'); return; } if (isTaskRunning) { showResult('batch', 'error', '有任务正在执行,请稍候...'); return; } isTaskRunning = true; showResult('batch', 'loading', '正在批量下载文章,请稍候...'); // 调用后端API(同步等待) $.ajax({ url: `${API_BASE_URL}/article/batch`, method: 'POST', contentType: 'application/json', data: JSON.stringify({ official_account: officialAccount, save_image: saveImage, save_content: saveContent }), success: function(response) { isTaskRunning = false; if (response.success && response.data) { const data = response.data; const resultHtml = `

✅ ${response.message}

公众号:${data.account}

文章数量:${data.articleCount} 篇

保存路径:${data.path}

`; showResult('batch', 'success', resultHtml); } else { showResult('batch', 'error', response.message || '批量下载失败'); } }, error: function(xhr, status, error) { isTaskRunning = false; let errorMsg = '请求失败:' + error; if (xhr.status === 0) { errorMsg = '无法连接到后端服务器,请确保 API 服务器已启动'; } else if (xhr.responseJSON && xhr.responseJSON.message) { errorMsg = xhr.responseJSON.message; } showResult('batch', 'error', errorMsg); }, timeout: 300000 // 5分钟超时 }); } // 加载数据列表 function loadDataList() { showResult('data', 'loading', '正在加载数据列表...'); // 调用后端API $.ajax({ url: `${API_BASE_URL}/data/list`, method: 'GET', success: function(response) { if (response.success && response.data) { displayDataList(response.data); hideResult('data'); } else { showResult('data', 'error', '加载失败'); } }, error: function(xhr, status, error) { let errorMsg = '请求失败:' + error; if (xhr.status === 0) { errorMsg = '无法连接到后端服务器,请确保 API 服务器已启动'; } showResult('data', 'error', errorMsg); } }); } // 显示数据列表 function displayDataList(dataList) { let html = ''; if (!dataList || dataList.length === 0) { html = '

暂无数据,请先使用其他功能爬取文章

'; } else { dataList.forEach(item => { const safeItemName = (item.name || '').replace(/'/g, "\\'"); const safeItemPath = (item.path || '').replace(/'/g, "\\'").replace(/\\/g, '\\\\'); html += `

${item.name || '未知'}

📊 ${item.articleCount || 0} 篇文章
📅 ${item.lastUpdate || '未知'}
📁 ${item.path || '未知'}
`; }); } $('#data-list').html(html); } // 查看文章列表 function viewArticles(accountName) { alert(`查看 ${accountName} 的文章列表 这里将展示该公众号的所有文章,包括: - 文章标题 - 发布时间 - 文件大小 - 下载状态等`); } // 打开文件夹 function openFolder(path) { alert(`打开文件夹: ${path}\n\n在实际环境中,这里会调用系统命令打开文件资源管理器。`); } // 打开数据文件夹 function openDataFolder() { alert('打开数据文件夹\n\n在实际环境中,这里会打开data目录。'); } // 任务管理函数 function startTask(section, message) { isTaskRunning = true; showResult(section, 'loading', message); // 显示进度条 const resultDiv = $(`#${section}-result`); resultDiv.append(`
0%
`); // 禁用相关按钮 disableButtons(); } function updateTaskProgress(percent, message) { const progressFill = $('.progress-fill'); const progressText = $('.progress-text'); progressFill.css('width', percent + '%'); progressText.text(Math.floor(percent) + '% - ' + message); } function endTask(section, type, message) { isTaskRunning = false; // 移除进度条 $('.progress-container').remove(); showResult(section, type, message); enableButtons(); } function disableButtons() { $('.btn').prop('disabled', true).addClass('disabled'); } function enableButtons() { $('.btn').prop('disabled', false).removeClass('disabled'); } // 结果显示函数 function showResult(section, type, message) { const resultDiv = $(`#${section}-result`); resultDiv.removeClass('success error info loading') .addClass(type) .html(getResultIcon(type) + message) .show(); // 自动滚动到结果区域 resultDiv[0].scrollIntoView({ behavior: 'smooth' }); } function hideResult(section) { $(`#${section}-result`).hide(); } function getResultIcon(type) { switch (type) { case 'success': return '✅ '; case 'error': return '❌ '; case 'info': return 'ℹ️ '; case 'loading': return ''; default: return ''; } } // 表单验证函数 function validateUrl(url) { try { new URL(url); return true; } catch { return false; } } function validateInput(value, type) { switch (type) { case 'url': return validateUrl(value); case 'notEmpty': return value.trim().length > 0; case 'number': return !isNaN(value) && parseInt(value) > 0; default: return true; } } // 工具函数 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]; } function formatDate(dateString) { const date = new Date(dateString); return date.getFullYear() + '-' + String(date.getMonth() + 1).padStart(2, '0') + '-' + String(date.getDate()).padStart(2, '0'); } function copyToClipboard(text) { navigator.clipboard.writeText(text).then(() => { alert('已复制到剪贴板'); }).catch(() => { alert('复制失败,请手动复制'); }); } // 快捷键支持 $(document).keydown(function(e) { // ESC键返回首页 if (e.keyCode === 27 && currentSection !== 'home') { showSection('home'); } // Ctrl+Enter 执行当前页面的主要操作 if (e.ctrlKey && e.keyCode === 13) { switch (currentSection) { case 'homepage': extractHomepage(); break; case 'single': downloadSingleArticle(); break; case 'list': getArticleList(); break; case 'batch': batchDownload(); break; case 'data': loadDataList(); break; } } }); // 页面可见性变化时的处理 document.addEventListener('visibilitychange', function() { if (document.hidden) { console.log('页面已隐藏'); } else { console.log('页面已显示'); // 可以在这里刷新任务状态 } }); // 错误处理 window.onerror = function(message, source, lineno, colno, error) { console.error('页面错误:', message, '位置:', source + ':' + lineno); return false; }; // 控制台欢迎信息 console.log(` 🚀 微信公众号文章爬虫系统 Web界面 ==================================== 版本: 1.0.0 开发者: AI Assistant 更新时间: 2025-11-27 ==================================== 💡 提示: - 按 ESC 键返回首页 - 按 Ctrl+Enter 执行当前操作 - 所有操作都会显示详细进度 ==================================== `);