602 lines
24 KiB
JavaScript
602 lines
24 KiB
JavaScript
// 全局变量
|
||
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 = `
|
||
<div style="background: #f8f9fa; padding: 15px; border-radius: 8px; margin-top: 10px;">
|
||
<h4 style="color: #28a745; margin-bottom: 10px;">✅ 提取成功</h4>
|
||
<p><strong>公众号主页链接:</strong></p>
|
||
<div style="background: white; padding: 10px; border: 1px solid #ddd; border-radius: 4px; word-break: break-all; font-family: monospace; font-size: 0.9em;">
|
||
${homepageUrl}
|
||
</div>
|
||
<div style="margin-top: 15px;">
|
||
<button class="btn btn-info" onclick="copyToClipboard('${safeUrl}')" style="margin-right: 10px;">📋 复制链接</button>
|
||
<button class="btn btn-warning" onclick="openInNewTab('${safeUrl}')">🔗 打开主页</button>
|
||
</div>
|
||
</div>
|
||
`;
|
||
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 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 = `
|
||
<div style="background: #f8f9fa; padding: 15px; border-radius: 8px; margin-top: 10px;">
|
||
<h4 style="color: #28a745; margin-bottom: 10px;">✅ 获取成功</h4>
|
||
<p><strong>公众号:</strong>${data.account}</p>
|
||
<p><strong>文件:</strong>${data.filename}</p>
|
||
<div style="margin-top: 15px;">
|
||
<a href="${API_BASE_URL}${data.download}" class="btn btn-success" download>📥 下载${fileExt}</a>
|
||
</div>
|
||
</div>
|
||
`;
|
||
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 = `
|
||
<div style="background: #f8f9fa; padding: 15px; border-radius: 8px; margin-top: 10px;">
|
||
<h4 style="color: #28a745; margin-bottom: 10px;">✅ ${response.message}</h4>
|
||
<p><strong>公众号:</strong>${data.account}</p>
|
||
<p><strong>文章数量:</strong>${data.articleCount} 篇</p>
|
||
<p><strong>保存路径:</strong>${data.path}</p>
|
||
</div>
|
||
`;
|
||
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分钟超时
|
||
});
|
||
}
|
||
|
||
// 获取文章详情(功能4)
|
||
function getArticleDetail() {
|
||
const accessToken = $('#detail-access-token').val().trim();
|
||
const pages = parseInt($('#detail-pages').val()) || 0;
|
||
const submitBtn = $('#section-detail .btn-success');
|
||
|
||
// 1. 验证输入
|
||
if (!accessToken) {
|
||
showResult('detail', 'error', '⚠️ 请输入Access Token URL');
|
||
// 高亮输入框
|
||
$('#detail-access-token').css('border-color', '#e74c3c').focus();
|
||
setTimeout(() => {
|
||
$('#detail-access-token').css('border-color', '');
|
||
}, 2000);
|
||
return;
|
||
}
|
||
|
||
// 2. 检查是否有任务正在执行
|
||
if (isTaskRunning) {
|
||
showResult('detail', 'error', '⚠️ 有任务正在执行,请稍候...');
|
||
return;
|
||
}
|
||
|
||
// 3. 设置任务状态并禁用按钮
|
||
isTaskRunning = true;
|
||
submitBtn.prop('disabled', true)
|
||
.addClass('disabled')
|
||
.html('⏳ 处理中...');
|
||
|
||
// 4. 构建提示信息
|
||
const pagesInfo = pages > 0 ? `前${pages}页(约${pages * 10}篇文章)` : '全部文章';
|
||
|
||
// 5. 显示加载状态
|
||
showResult('detail', 'loading', `
|
||
<div style="text-align: center;">
|
||
<div style="font-size: 1.2em; margin-bottom: 10px;">⏳ 正在获取文章详情,请耐心等待...</div>
|
||
<div style="background: #e3f2fd; padding: 12px; border-radius: 5px; margin: 15px 0; border-left: 4px solid #2196f3;">
|
||
<p style="margin: 5px 0; color: #1565c0;"><strong>📌 本次获取范围:</strong>${pagesInfo}</p>
|
||
</div>
|
||
<div style="background: #fff3cd; padding: 12px; border-radius: 5px; margin: 15px 0;">
|
||
<p style="margin: 5px 0; color: #856404;"><strong>📝 执行步骤:</strong></p>
|
||
<ol style="text-align: left; margin: 10px 0; padding-left: 30px; color: #856404;">
|
||
<li>正在获取公众号文章列表...</li>
|
||
<li>正在下载每篇文章的详细数据...</li>
|
||
<li>正在保存为TXT文件...</li>
|
||
</ol>
|
||
<p style="margin: 10px 0 0 0; color: #d9534f;"><strong>⚠️ 此过程可能需要几分钟,系统会自动延时避免被封禁</strong></p>
|
||
<p style="margin: 5px 0 0 0; color: #856404; font-size: 0.9em;">💡 提示:请不要关闭页面或刷新浏览器</p>
|
||
</div>
|
||
</div>
|
||
`);
|
||
|
||
console.log('🚀 开始获取文章详情...');
|
||
console.log('📄 获取页数:', pages === 0 ? '全部' : pages);
|
||
|
||
// 6. 调用后端 API
|
||
$.ajax({
|
||
url: `${API_BASE_URL}/article/detail`,
|
||
method: 'POST',
|
||
contentType: 'application/json',
|
||
data: JSON.stringify({
|
||
access_token: accessToken,
|
||
pages: pages
|
||
}),
|
||
beforeSend: function() {
|
||
console.log('📡 发送请求到后端 API...');
|
||
},
|
||
success: function(response) {
|
||
console.log('✅ 收到服务器响应:', response);
|
||
|
||
// 恢复任务状态和按钮
|
||
isTaskRunning = false;
|
||
submitBtn.prop('disabled', false)
|
||
.removeClass('disabled')
|
||
.html('开始获取');
|
||
|
||
if (response.success && response.data) {
|
||
const data = response.data;
|
||
const resultHtml = `
|
||
<div style="background: #f8f9fa; padding: 20px; border-radius: 8px; margin-top: 10px; border: 2px solid #28a745;">
|
||
<h4 style="color: #28a745; margin-bottom: 15px; font-size: 1.3em;">✅ 获取成功!</h4>
|
||
<div style="background: white; padding: 15px; border-radius: 5px; margin: 10px 0;">
|
||
<p style="margin: 8px 0;"><strong>📱 公众号:</strong><span style="color: #667eea;">${data.account}</span></p>
|
||
<p style="margin: 8px 0;"><strong>📊 文章数量:</strong><span style="color: #667eea;">${data.articleCount} 篇</span></p>
|
||
<p style="margin: 8px 0;"><strong>📁 保存路径:</strong><span style="color: #667eea; font-size: 0.9em;">${data.path}</span></p>
|
||
</div>
|
||
<div style="background: #e7f3ff; padding: 15px; border-radius: 5px; margin: 15px 0; border-left: 4px solid #3498db;">
|
||
<p style="margin: 5px 0; color: #0066cc; font-weight: bold;">📊 数据包含:</p>
|
||
<ul style="margin: 10px 0; padding-left: 25px; color: #0066cc;">
|
||
<li style="margin: 5px 0;">📄 文章文本内容</li>
|
||
<li style="margin: 5px 0;">👁️ 阅读量、点赞数、转发数、在看数</li>
|
||
<li style="margin: 5px 0;">💬 评论内容及评论点赞数</li>
|
||
</ul>
|
||
</div>
|
||
<p style="margin-top: 15px; text-align: center; color: #7f8c8d; font-size: 0.9em;">💡 数据已保存在 data/${data.account}/文章详细 目录下</p>
|
||
</div>
|
||
`;
|
||
showResult('detail', 'success', resultHtml);
|
||
} else {
|
||
showResult('detail', 'error', `
|
||
<div style="padding: 10px;">
|
||
<h4 style="color: #e74c3c; margin-bottom: 10px;">❌ 获取失败</h4>
|
||
<p style="margin: 10px 0;">${response.message || '未知错误,请稍后重试'}</p>
|
||
<div style="background: #fff3cd; padding: 12px; border-radius: 5px; margin-top: 15px;">
|
||
<p style="margin: 5px 0; color: #856404;"><strong>💡 可能的原因:</strong></p>
|
||
<ul style="margin: 10px 0; padding-left: 25px; color: #856404;">
|
||
<li>Access Token 已过期</li>
|
||
<li>公众号权限不足</li>
|
||
<li>网络连接问题</li>
|
||
</ul>
|
||
<p style="margin: 10px 0 0 0; color: #856404;">请重新从 Fiddler 获取 Access Token URL 并重试</p>
|
||
</div>
|
||
</div>
|
||
`);
|
||
}
|
||
},
|
||
error: function(xhr, status, error) {
|
||
console.error('❌ 请求失败:', { xhr, status, error });
|
||
|
||
// 恢复任务状态和按钮
|
||
isTaskRunning = false;
|
||
submitBtn.prop('disabled', false)
|
||
.removeClass('disabled')
|
||
.html('开始获取');
|
||
|
||
let errorMsg = '请求失败';
|
||
let errorDetail = '';
|
||
|
||
if (xhr.status === 0) {
|
||
errorMsg = '无法连接到后端服务器';
|
||
errorDetail = `
|
||
<div style="background: #f8d7da; padding: 12px; border-radius: 5px; margin-top: 15px; border-left: 4px solid #e74c3c;">
|
||
<p style="margin: 5px 0; color: #721c24;"><strong>🔧 解决方法:</strong></p>
|
||
<ol style="margin: 10px 0; padding-left: 25px; color: #721c24;">
|
||
<li>确认后端 API 服务器已启动</li>
|
||
<li>检查服务器地址:http://localhost:8080</li>
|
||
<li>查看服务器控制台是否有错误信息</li>
|
||
</ol>
|
||
</div>
|
||
`;
|
||
} else if (xhr.status === 404) {
|
||
errorMsg = '接口不存在';
|
||
errorDetail = `<p style="margin-top: 10px; color: #721c24;">请检查API路径配置是否正确</p>`;
|
||
} else if (xhr.status === 500) {
|
||
errorMsg = '服务器内部错误';
|
||
errorDetail = `<p style="margin-top: 10px; color: #721c24;">请查看服务器日志获取详细错误信息</p>`;
|
||
} else if (xhr.responseJSON && xhr.responseJSON.message) {
|
||
errorMsg = xhr.responseJSON.message;
|
||
} else if (status === 'timeout') {
|
||
errorMsg = '请求超时';
|
||
errorDetail = `
|
||
<p style="margin-top: 10px; color: #721c24;">
|
||
文章数量较多,处理时间超过10分钟。<br>
|
||
建议:减少文章数量或稍后查看服务器是否已生成文件。
|
||
</p>
|
||
`;
|
||
} else {
|
||
errorMsg += ': ' + (error || '未知错误');
|
||
}
|
||
|
||
showResult('detail', 'error', `
|
||
<div style="padding: 10px;">
|
||
<h4 style="color: #e74c3c; margin-bottom: 10px;">❌ ${errorMsg}</h4>
|
||
${errorDetail}
|
||
<p style="margin-top: 15px; color: #7f8c8d; font-size: 0.9em;">
|
||
错误状态码: ${xhr.status || 'N/A'}<br>
|
||
错误类型: ${status || 'N/A'}
|
||
</p>
|
||
</div>
|
||
`);
|
||
},
|
||
complete: function() {
|
||
console.log('🏁 请求完成');
|
||
},
|
||
timeout: 600000 // 10分钟超时(因为功能4需要较长时间)
|
||
});
|
||
}
|
||
|
||
// 加载示例 Access Token
|
||
function loadDetailExample() {
|
||
const exampleToken = 'https://mp.weixin.qq.com/mp/profile_ext?action=getmsg&__biz=MzI1NjEwMTM4OA==&uin=MTIzNDU2Nzg5&key=abcdef123456&pass_ticket=xyz789&...';
|
||
|
||
$('#detail-access-token').val(exampleToken);
|
||
showResult('detail', 'info', '已加载 Access Token 示例。<br><br><strong>注意:</strong>请从 Fiddler 中获取实际的 Access Token URL,示例仅供参考。<br><br><strong>获取步骤:</strong><br>1. 在微信客户端打开公众号主页<br>2. 在 Fiddler 中查找 URL 为 /mp/profile_ext?action=getmsg 的请求<br>3. 按 Ctrl+U 复制完整 URL<br>4. 粘贴到此处');
|
||
}
|
||
|
||
// 任务管理函数
|
||
function startTask(section, message) {
|
||
isTaskRunning = true;
|
||
showResult(section, 'loading', message);
|
||
|
||
// 显示进度条
|
||
const resultDiv = $(`#${section}-result`);
|
||
resultDiv.append(`
|
||
<div class="progress-container">
|
||
<div class="progress-bar">
|
||
<div class="progress-fill"></div>
|
||
</div>
|
||
<div class="progress-text">0%</div>
|
||
</div>
|
||
`);
|
||
|
||
// 禁用相关按钮
|
||
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 '<span class="loading-spinner" style="display:none;"></span>✅ ';
|
||
case 'error': return '<span class="loading-spinner" style="display:none;"></span>❌ ';
|
||
case 'info': return '<span class="loading-spinner" style="display:none;"></span>ℹ️ ';
|
||
case 'loading': return '<span class="loading-spinner"></span>';
|
||
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 'detail':
|
||
getArticleDetail();
|
||
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 执行当前操作
|
||
- 所有操作都会显示详细进度
|
||
====================================
|
||
`); |