2025-12-2genxin

This commit is contained in:
2025-12-02 14:58:52 +08:00
parent 4fef65bd93
commit be0954828c
36 changed files with 3352 additions and 1638 deletions

View File

@@ -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;