2025-12-2genxin
This commit is contained in:
@@ -112,11 +112,6 @@ function openInNewTab(url) {
|
||||
}
|
||||
|
||||
// 下载单篇文章
|
||||
function downloadSingleArticle() {
|
||||
alert('此功能需要后端命令行支持。\n\n请使用命令行程序:\n1. 运行 wechat-crawler.exe\n2. 选择对应功能进行下载');
|
||||
showResult('single', 'info', '请使用命令行程序执行下载功能');
|
||||
}
|
||||
|
||||
// 获取文章列表
|
||||
function getArticleList() {
|
||||
const accessToken = $('#access-token').val().trim();
|
||||
@@ -197,7 +192,7 @@ function batchDownload() {
|
||||
isTaskRunning = true;
|
||||
showResult('batch', 'loading', '正在批量下载文章,请稍候...');
|
||||
|
||||
// 调用后端API(同步等待)
|
||||
// 调用后端 API(同步等待)
|
||||
$.ajax({
|
||||
url: `${API_BASE_URL}/article/batch`,
|
||||
method: 'POST',
|
||||
@@ -217,9 +212,6 @@ function batchDownload() {
|
||||
<p><strong>公众号:</strong>${data.account}</p>
|
||||
<p><strong>文章数量:</strong>${data.articleCount} 篇</p>
|
||||
<p><strong>保存路径:</strong>${data.path}</p>
|
||||
<div style="margin-top: 15px;">
|
||||
<button class="btn btn-info" onclick="loadDataList()">📊 查看数据列表</button>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
showResult('batch', 'success', resultHtml);
|
||||
@@ -241,92 +233,190 @@ function batchDownload() {
|
||||
});
|
||||
}
|
||||
|
||||
// 加载数据列表
|
||||
function loadDataList() {
|
||||
showResult('data', 'loading', '正在加载数据列表...');
|
||||
// 获取文章详情(功能4)
|
||||
function getArticleDetail() {
|
||||
const accessToken = $('#detail-access-token').val().trim();
|
||||
const pages = parseInt($('#detail-pages').val()) || 0;
|
||||
const submitBtn = $('#section-detail .btn-success');
|
||||
|
||||
// 调用后端API
|
||||
// 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}/data/list`,
|
||||
method: 'GET',
|
||||
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) {
|
||||
displayDataList(response.data);
|
||||
hideResult('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('data', 'error', '加载失败');
|
||||
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) {
|
||||
let errorMsg = '请求失败:' + error;
|
||||
console.error('❌ 请求失败:', { xhr, status, error });
|
||||
|
||||
// 恢复任务状态和按钮
|
||||
isTaskRunning = false;
|
||||
submitBtn.prop('disabled', false)
|
||||
.removeClass('disabled')
|
||||
.html('开始获取');
|
||||
|
||||
let errorMsg = '请求失败';
|
||||
let errorDetail = '';
|
||||
|
||||
if (xhr.status === 0) {
|
||||
errorMsg = '无法连接到后端服务器,请确保 API 服务器已启动';
|
||||
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('data', 'error', errorMsg);
|
||||
}
|
||||
|
||||
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需要较长时间)
|
||||
});
|
||||
}
|
||||
|
||||
// 显示数据列表
|
||||
function displayDataList(dataList) {
|
||||
let html = '';
|
||||
// 加载示例 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&...';
|
||||
|
||||
if (!dataList || dataList.length === 0) {
|
||||
html = '<p class="text-center" style="padding: 20px; color: #666;">暂无数据,请先使用其他功能爬取文章</p>';
|
||||
} else {
|
||||
dataList.forEach(item => {
|
||||
const safeItemName = (item.name || '').replace(/'/g, "\\'");
|
||||
const safeItemPath = (item.path || '').replace(/'/g, "\\'").replace(/\\/g, '\\\\');
|
||||
html += `
|
||||
<div class="data-item">
|
||||
<h4><span class="status-indicator status-success"></span>${item.name || '未知'}</h4>
|
||||
<div class="data-item-info">
|
||||
<div class="data-item-stats">
|
||||
<div class="stat-item">
|
||||
<span>📊</span>
|
||||
<span>${item.articleCount || 0} 篇文章</span>
|
||||
</div>
|
||||
<div class="stat-item">
|
||||
<span>📅</span>
|
||||
<span>${item.lastUpdate || '未知'}</span>
|
||||
</div>
|
||||
<div class="stat-item">
|
||||
<span>📁</span>
|
||||
<span>${item.path || '未知'}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="data-item-actions">
|
||||
<button class="btn btn-info" onclick="viewArticles('${safeItemName}')">查看文章</button>
|
||||
<button class="btn btn-warning" onclick="alert('文件夹路径:${safeItemPath}')">查看路径</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
});
|
||||
}
|
||||
|
||||
$('#data-list').html(html);
|
||||
}
|
||||
|
||||
// 查看文章列表
|
||||
function viewArticles(accountName) {
|
||||
alert(`查看 ${accountName} 的文章列表
|
||||
|
||||
这里将展示该公众号的所有文章,包括:
|
||||
- 文章标题
|
||||
- 发布时间
|
||||
- 文件大小
|
||||
- 下载状态等`);
|
||||
}
|
||||
|
||||
// 打开文件夹
|
||||
function openFolder(path) {
|
||||
alert(`打开文件夹: ${path}\n\n在实际环境中,这里会调用系统命令打开文件资源管理器。`);
|
||||
}
|
||||
|
||||
// 打开数据文件夹
|
||||
function openDataFolder() {
|
||||
alert('打开数据文件夹\n\n在实际环境中,这里会打开data目录。');
|
||||
$('#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. 粘贴到此处');
|
||||
}
|
||||
|
||||
// 任务管理函数
|
||||
@@ -470,6 +560,9 @@ $(document).keydown(function(e) {
|
||||
case 'batch':
|
||||
batchDownload();
|
||||
break;
|
||||
case 'detail':
|
||||
getArticleDetail();
|
||||
break;
|
||||
case 'data':
|
||||
loadDataList();
|
||||
break;
|
||||
|
||||
Reference in New Issue
Block a user