Files
yixiaogao/frontend/index.html
2025-12-02 14:58:52 +08:00

287 lines
16 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>微信公众号文章爬虫系统</title>
<link rel="stylesheet" href="css/style.css">
</head>
<body>
<!-- 头部导航 -->
<header class="top-navbar" style="background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; padding: 15px 0; box-shadow: 0 2px 10px rgba(0,0,0,0.1); position: sticky; top: 0; z-index: 100;">
<div class="navbar-content" style="max-width: 1200px; margin: 0 auto; padding: 0 20px; display: flex; align-items: center; justify-content: space-between;">
<a href="frontend.html" class="logo" style="font-size: 24px; font-weight: bold; text-decoration: none; color: white;">🔍 易搜高</a>
<nav class="nav-menu" style="display: flex; gap: 15px; align-items: center;">
<a href="frontend.html" class="nav-link" style="color: white; text-decoration: none; font-size: 14px; font-weight: 500; padding: 8px 16px; border-radius: 6px; transition: all 0.3s; background: rgba(255, 255, 255, 0.1); border: 1px solid rgba(255, 255, 255, 0.2);" onmouseover="this.style.background='rgba(255, 255, 255, 0.2)'" onmouseout="this.style.background='rgba(255, 255, 255, 0.1)'">首页</a>
<a href="#" class="nav-link" style="color: white; text-decoration: none; font-size: 14px; font-weight: 500; padding: 8px 16px; border-radius: 6px; transition: all 0.3s; background: rgba(255, 255, 255, 0.1); border: 1px solid rgba(255, 255, 255, 0.2);" onmouseover="this.style.background='rgba(255, 255, 255, 0.2)'" onmouseout="this.style.background='rgba(255, 255, 255, 0.1)'">监控中心</a>
<a href="#" class="nav-link" style="color: white; text-decoration: none; font-size: 14px; font-weight: 500; padding: 8px 16px; border-radius: 6px; transition: all 0.3s; background: rgba(255, 255, 255, 0.1); border: 1px solid rgba(255, 255, 255, 0.2);" onmouseover="this.style.background='rgba(255, 255, 255, 0.2)'" onmouseout="this.style.background='rgba(255, 255, 255, 0.1)'">数据分析</a>
<a href="#" class="nav-link" style="color: white; text-decoration: none; font-size: 14px; font-weight: 500; padding: 8px 16px; border-radius: 6px; transition: all 0.3s; background: rgba(255, 255, 255, 0.1); border: 1px solid rgba(255, 255, 255, 0.2);" onmouseover="this.style.background='rgba(255, 255, 255, 0.2)'" onmouseout="this.style.background='rgba(255, 255, 255, 0.1)'">帮助文档</a>
<a href="user-center.html" class="nav-link" id="userCenterLink" style="color: white; text-decoration: none; font-size: 14px; font-weight: 500; padding: 8px 16px; border-radius: 6px; transition: all 0.3s; background: rgba(255, 255, 255, 0.1); border: 1px solid rgba(255, 255, 255, 0.2);" onmouseover="this.style.background='rgba(255, 255, 255, 0.2)'" onmouseout="this.style.background='rgba(255, 255, 255, 0.1)'">👤 用户中心</a>
<a href="login.html" class="nav-link" id="loginLink" style="color: white; text-decoration: none; font-size: 14px; font-weight: 500; padding: 8px 16px; border-radius: 6px; transition: all 0.3s; background: rgba(255, 255, 255, 0.1); border: 1px solid rgba(255, 255, 255, 0.2);" onmouseover="this.style.background='rgba(255, 255, 255, 0.2)'" onmouseout="this.style.background='rgba(255, 255, 255, 0.1)'">🔐 登录</a>
<div id="userMenu" class="user-info" style="display: flex; align-items: center; gap: 10px;"></div>
</nav>
</div>
</header>
<div class="container">
<header class="header">
<h1>🚀 微信公众号文章爬虫系统</h1>
<p class="subtitle">Wechat Official Account Article Crawler</p>
</header>
<div class="main-content">
<!-- 功能选择卡片 -->
<div class="feature-cards">
<div class="card" id="card-homepage">
<div class="card-icon">🏠</div>
<h3>提取公众号主页</h3>
<p>输入文章链接获取公众号主页链接</p>
<button class="btn btn-primary" onclick="showSection('homepage')">进入</button>
</div>
<div class="card" id="card-list">
<div class="card-icon">📋</div>
<h3>获取文章列表</h3>
<p>获取公众号所有文章列表</p>
<button class="btn btn-primary" onclick="showSection('list')">进入</button>
</div>
<div class="card" id="card-batch">
<div class="card-icon">📦</div>
<h3>批量下载文章</h3>
<p>批量下载文章详细内容</p>
<button class="btn btn-primary" onclick="showSection('batch')">进入</button>
</div>
<div class="card" id="card-detail">
<div class="card-icon">📊</div>
<h3>获取文章详情</h3>
<p>获取文章阅读量、点赞数、评论等详细信息</p>
<button class="btn btn-primary" onclick="showSection('detail')">进入</button>
</div>
</div>
<!-- 提取公众号主页区域 -->
<div class="section" id="section-homepage" style="display:none;">
<div class="section-header">
<h2>🏠 提取公众号主页</h2>
<button class="btn btn-secondary" onclick="showSection('home')">返回</button>
</div>
<div class="form-group">
<label>公众号文章链接:</label>
<input type="text" id="homepage-url" placeholder="请输入公众号下任意一篇已发布的文章链接...">
<small>支持公众号文章完整URL无需Cookie即可获取公众号主页链接</small>
</div>
<div class="form-actions">
<button class="btn btn-success" onclick="extractHomepage()">提取主页链接</button>
<button class="btn btn-info" onclick="loadExampleUrl()">查看示例</button>
</div>
<div class="result" id="homepage-result"></div>
</div>
<!-- 获取文章列表区域 -->
<div class="section" id="section-list" style="display:none;">
<div class="section-header">
<h2>📋 获取文章列表</h2>
<button class="btn btn-secondary" onclick="showSection('home')">返回</button>
</div>
<div class="form-group">
<label>Access Token URL</label>
<textarea id="access-token" placeholder="请粘贴从Fiddler获取的完整URL..." rows="4"></textarea>
<small>包含 __biz, uin, key, pass_ticket 等参数的完整URL</small>
</div>
<div class="form-group">
<label>获取页数:</label>
<input type="number" id="pages" value="1" min="1" max="999">
<small>留空表示获取全部</small>
</div>
<div class="form-actions">
<button class="btn btn-success" onclick="getArticleList()">开始获取</button>
</div>
<div class="result" id="list-result"></div>
</div>
<!-- 批量下载区域 -->
<div class="section" id="section-batch" style="display:none;">
<div class="section-header">
<h2>📦 批量下载文章</h2>
<button class="btn btn-secondary" onclick="showSection('home')">返回</button>
</div>
<div class="form-group">
<label>公众号名称或文章链接:</label>
<input type="text" id="official-account" placeholder="请输入公众号名称或任意一篇文章链接...">
</div>
<div class="form-group">
<label class="checkbox-label">
<input type="checkbox" id="batch-save-image"> 保存图片
</label>
<label class="checkbox-label">
<input type="checkbox" id="batch-save-content" checked> 保存内容
</label>
</div>
<div class="form-actions">
<button class="btn btn-success" onclick="batchDownload()">开始批量下载</button>
</div>
<div class="result" id="batch-result"></div>
</div>
<!-- 获取文章详情区域 -->
<div class="section" id="section-detail" style="display:none;">
<div class="section-header">
<h2>📊 获取文章详情</h2>
<button class="btn btn-secondary" onclick="showSection('home')">返回</button>
</div>
<div class="help-text">
<p><strong>💡 功能说明:</strong></p>
<ul>
<li>📈 自动获取公众号所有文章列表</li>
<li>📊 下载每篇文章的阅读量、点赞数、分享数等统计数据</li>
<li>💬 获取文章评论信息(如果有)</li>
<li>📁 保存为TXT格式便于查看和分析</li>
</ul>
<p><strong>⚠️ 注意事项:</strong></p>
<ul>
<li>需要提供有效的Access Token URL包含登录凭证</li>
<li>处理时间较长,请耐心等待</li>
<li>数据将保存在 data/公众号名称/文章详细 目录下</li>
</ul>
</div>
<div class="form-group">
<label>Access Token URL</label>
<textarea id="detail-access-token" placeholder="请粘贴从Fiddler获取的完整URL...\n\n步骤\n1. 在浏览器中登录微信公众号平台\n2. 访问目标公众号主页\n3. 向下滚动加载文章列表\n4. 在Fiddler中找到profile_ext?action=getmsg请求\n5. 复制完整的URL包含__biz、uin、key、pass_ticket等参数" rows="6"></textarea>
<small>示例https://mp.weixin.qq.com/mp/profile_ext?action=getmsg&__biz=...&uin=...&key=...&pass_ticket=...</small>
</div>
<div class="form-group">
<label>获取页数:</label>
<input type="number" id="detail-pages" value="0" min="0" max="999" placeholder="留空或0表示获取全部">
<small>每页约10篇文章留空或输入0表示获取全部文章</small>
</div>
<div class="form-actions">
<button class="btn btn-success" onclick="getArticleDetail()">开始获取</button>
<button class="btn btn-info" onclick="loadDetailExample()">查看示例</button>
</div>
<div class="result" id="detail-result"></div>
</div>
</div>
<footer class="footer">
<p>© 2025 微信公众号文章爬虫系统 | 仅供学习使用</p>
</footer>
</div>
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script src="js/app.js"></script>
<script>
// 登录状态管理
function checkLoginStatus() {
// 检查认证数据
const authData = localStorage.getItem('authData') || sessionStorage.getItem('authData');
if (authData) {
try {
const auth = JSON.parse(authData);
const username = auth.user_info && auth.user_info.username ? auth.user_info.username : '用户';
showLoggedInState(username);
} catch (e) {
console.error('解析登录数据失败:', e);
showLoggedOutState();
}
} else {
showLoggedOutState();
}
}
// 显示已登录状态
function showLoggedInState(username) {
const loginLink = document.getElementById('loginLink');
const userMenu = document.getElementById('userMenu');
if (loginLink) loginLink.style.display = 'none';
if (userMenu) {
userMenu.innerHTML = `
<span style="margin-right: 10px;">👋 ${username}</span>
<button onclick="logout()" style="
background: rgba(255, 255, 255, 0.2);
color: white;
border: 1px solid rgba(255, 255, 255, 0.3);
padding: 6px 12px;
border-radius: 4px;
cursor: pointer;
font-size: 13px;
transition: all 0.3s;
" onmouseover="this.style.background='rgba(255, 255, 255, 0.3)'"
onmouseout="this.style.background='rgba(255, 255, 255, 0.2)'">
退出登录
</button>
`;
userMenu.style.display = 'flex';
}
}
// 显示未登录状态
function showLoggedOutState() {
const loginLink = document.getElementById('loginLink');
const userMenu = document.getElementById('userMenu');
if (loginLink) loginLink.style.display = 'inline';
if (userMenu) userMenu.innerHTML = '';
}
// 登出功能
function logout() {
if (confirm('确定要退出登录吗?')) {
// 获取认证数据
const authData = localStorage.getItem('authData') || sessionStorage.getItem('authData');
let token = '';
if (authData) {
try {
const auth = JSON.parse(authData);
token = auth.token || '';
} catch (e) {
console.error('解析token失败:', e);
}
}
// 调用后端登出API
fetch('http://localhost:8080/api/user/logout', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': token ? `Bearer ${token}` : ''
}
}).then(response => {
// 无论API调用成功与否都清除本地数据
localStorage.removeItem('authData');
localStorage.removeItem('isLoggedIn');
localStorage.removeItem('username');
localStorage.removeItem('token');
sessionStorage.removeItem('authData');
sessionStorage.removeItem('userSession');
alert('已成功退出登录!');
window.location.href = 'login.html';
}).catch(error => {
console.error('登出请求失败:', error);
// 即使API调用失败也清除本地数据
localStorage.removeItem('authData');
localStorage.removeItem('isLoggedIn');
localStorage.removeItem('username');
localStorage.removeItem('token');
sessionStorage.removeItem('authData');
sessionStorage.removeItem('userSession');
alert('已成功退出登录!');
window.location.href = 'login.html';
});
}
}
// 页面加载时检查登录状态
document.addEventListener('DOMContentLoaded', function() {
checkLoginStatus();
});
</script>
</body>
</html>