上传文件至 frontend

This commit is contained in:
2025-11-26 14:32:55 +08:00
parent f631cdc844
commit 36fa1874d7
5 changed files with 5353 additions and 0 deletions

View File

@@ -0,0 +1,807 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>文章详情 - 易搜高</title>
<meta name="keywords" content="文章详情,自媒体文章,微信公众号,头条号,百家号">
<style>
/* 全局样式重置 */
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Microsoft YaHei', sans-serif;
background: #f5f6fa;
color: #333;
line-height: 1.6;
}
/* 头部样式 */
.header {
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;
}
.header-content {
max-width: 1200px;
margin: 0 auto;
padding: 0 20px;
display: flex;
align-items: center;
justify-content: space-between;
}
.logo {
font-size: 24px;
font-weight: bold;
text-decoration: none;
color: white;
}
.back-btn {
background: rgba(255, 255, 255, 0.2);
color: white;
border: 1px solid rgba(255, 255, 255, 0.3);
padding: 8px 16px;
border-radius: 6px;
cursor: pointer;
font-size: 14px;
transition: all 0.3s;
text-decoration: none;
display: flex;
align-items: center;
gap: 6px;
}
.back-btn:hover {
background: rgba(255, 255, 255, 0.3);
transform: translateY(-1px);
text-decoration: none;
color: white;
}
/* 导航菜单 */
.nav-menu {
display: flex;
gap: 15px;
align-items: center;
}
.nav-link {
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);
}
.nav-link:hover {
background: rgba(255, 255, 255, 0.2);
transform: translateY(-1px);
text-decoration: none;
color: white;
}
.nav-link.active {
background: rgba(255, 255, 255, 0.25);
border-color: rgba(255, 255, 255, 0.4);
}
/* 主容器 */
.container {
max-width: 1000px;
margin: 20px auto;
padding: 0 20px;
}
/* 文章卡片 */
.article-card {
background: white;
border-radius: 12px;
box-shadow: 0 4px 20px rgba(0,0,0,0.1);
overflow: hidden;
margin-bottom: 20px;
animation: fadeIn 0.5s ease-in;
}
@keyframes fadeIn {
from { opacity: 0; transform: translateY(20px); }
to { opacity: 1; transform: translateY(0); }
}
/* 文章头部信息 */
.article-header {
background: linear-gradient(135deg, #f8f9fa 0%, #e9ecef 100%);
padding: 30px;
border-bottom: 1px solid #e9ecef;
}
.article-title {
font-size: 28px;
font-weight: 700;
color: #2c3e50;
margin-bottom: 20px;
line-height: 1.3;
}
.article-meta {
display: flex;
gap: 20px;
flex-wrap: wrap;
align-items: center;
}
.meta-item {
display: flex;
align-items: center;
gap: 6px;
padding: 8px 16px;
background: white;
border-radius: 20px;
font-size: 14px;
color: #495057;
border: 1px solid #e9ecef;
box-shadow: 0 2px 4px rgba(0,0,0,0.05);
}
.meta-item.platform {
background: #e3f2fd;
color: #1976d2;
border-color: #bbdefb;
}
.meta-item.account {
background: #f3e5f5;
color: #7b1fa2;
border-color: #e1bee7;
}
.meta-item.field {
background: #e8f5e8;
color: #388e3c;
border-color: #c8e6c9;
}
.meta-item.date {
background: #fff3e0;
color: #f57c00;
border-color: #ffcc02;
}
/* 文章统计 */
.article-stats {
padding: 25px 30px;
background: #fafbfc;
border-bottom: 1px solid #e9ecef;
}
.stats-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
gap: 20px;
}
.stat-item {
text-align: center;
padding: 20px;
background: white;
border-radius: 8px;
box-shadow: 0 2px 8px rgba(0,0,0,0.08);
transition: transform 0.3s ease;
}
.stat-item:hover {
transform: translateY(-2px);
}
.stat-value {
display: block;
font-size: 24px;
font-weight: 700;
color: #667eea;
margin-bottom: 5px;
}
.stat-label {
font-size: 14px;
color: #6c757d;
}
/* 文章内容 */
.article-content {
padding: 30px;
}
.content-section {
margin-bottom: 30px;
}
.content-section h4 {
font-size: 18px;
color: #2c3e50;
margin-bottom: 15px;
padding-bottom: 8px;
border-bottom: 2px solid #667eea;
display: flex;
align-items: center;
gap: 8px;
}
.content-section p {
font-size: 16px;
line-height: 1.8;
color: #495057;
margin-bottom: 15px;
}
.content-section h3 {
font-size: 20px;
color: #2c3e50;
margin: 25px 0 15px 0;
padding-left: 15px;
border-left: 4px solid #667eea;
}
/* 文章操作按钮 */
.article-actions {
padding: 30px;
background: #f8f9fa;
border-top: 1px solid #e9ecef;
display: flex;
gap: 15px;
flex-wrap: wrap;
justify-content: center;
}
.action-btn {
padding: 12px 24px;
border: none;
border-radius: 8px;
font-size: 14px;
font-weight: 500;
cursor: pointer;
transition: all 0.3s ease;
text-decoration: none;
display: inline-flex;
align-items: center;
gap: 8px;
}
.btn-primary {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
}
.btn-primary:hover {
transform: translateY(-2px);
box-shadow: 0 4px 12px rgba(102, 126, 234, 0.4);
text-decoration: none;
color: white;
}
.btn-secondary {
background: white;
color: #495057;
border: 1px solid #dee2e6;
}
.btn-secondary:hover {
background: #f8f9fa;
border-color: #667eea;
color: #667eea;
text-decoration: none;
}
/* 加载状态 */
.loading {
text-align: center;
padding: 50px;
color: #6c757d;
}
.loading-spinner {
border: 4px solid #f3f3f3;
border-top: 4px solid #667eea;
border-radius: 50%;
width: 40px;
height: 40px;
animation: spin 1s linear infinite;
margin: 0 auto 20px;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
/* 错误状态 */
.error-message {
text-align: center;
padding: 50px;
color: #dc3545;
}
.error-icon {
font-size: 48px;
margin-bottom: 20px;
}
/* 响应式设计 */
@media (max-width: 768px) {
.container {
padding: 0 15px;
}
.article-header {
padding: 20px;
}
.article-title {
font-size: 22px;
}
.article-meta {
gap: 10px;
}
.meta-item {
font-size: 12px;
padding: 6px 12px;
}
.stats-grid {
grid-template-columns: repeat(2, 1fr);
gap: 15px;
}
.article-content {
padding: 20px;
}
.article-actions {
padding: 20px;
flex-direction: column;
}
.action-btn {
width: 100%;
justify-content: center;
}
}
</style>
</head>
<body>
<!-- 头部 -->
<header class="header">
<div class="header-content">
<a href="frontend.html" class="logo">🔍 易搜高</a>
<nav class="nav-menu">
<a href="frontend.html" class="nav-link">首页</a>
<a href="#" class="nav-link">监控中心</a>
<a href="#" class="nav-link">数据分析</a>
<a href="#" class="nav-link">帮助文档</a>
<a href="user-center.html" class="nav-link" id="userMenu" style="display: none;">👤 用户中心</a>
<a href="login.html" class="nav-link" id="loginLink">🔐 登录</a>
<a href="#" class="nav-link" id="logoutLink" style="display: none;" onclick="logout()">🚪 退出</a>
</nav>
</div>
</header>
<!-- 主容器 -->
<div class="container">
<!-- 加载状态 -->
<div id="loadingState" class="loading">
<div class="loading-spinner"></div>
<p>正在加载文章详情...</p>
</div>
<!-- 错误状态 -->
<div id="errorState" class="error-message" style="display: none;">
<div class="error-icon">⚠️</div>
<h2>文章不存在</h2>
<p>抱歉,您访问的文章不存在或已被删除。</p>
<a href="frontend.html" class="action-btn btn-primary" style="margin-top: 20px;">返回首页</a>
</div>
<!-- 文章内容 -->
<div id="articleContent" style="display: none;">
<div class="article-card">
<!-- 文章头部信息 -->
<div class="article-header">
<h1 class="article-title" id="articleTitle">文章标题</h1>
<div class="article-meta">
<div class="meta-item platform">
<span>📱</span>
<span id="articlePlatform">公众号</span>
</div>
<div class="meta-item account">
<span>👤</span>
<span id="articleAccount">账号名称</span>
</div>
<div class="meta-item field">
<span>🏷️</span>
<span id="articleField">领域</span>
</div>
<div class="meta-item date">
<span>📅</span>
<span id="articleDate">发布时间</span>
</div>
</div>
</div>
<!-- 文章统计 -->
<div class="article-stats">
<div class="stats-grid">
<div class="stat-item">
<span class="stat-value" id="readCount">0</span>
<span class="stat-label">阅读量</span>
</div>
<div class="stat-item">
<span class="stat-value" id="likeCount">0</span>
<span class="stat-label">点赞数</span>
</div>
<div class="stat-item">
<span class="stat-value" id="commentCount">0</span>
<span class="stat-label">评论数</span>
</div>
<div class="stat-item">
<span class="stat-value" id="shareCount">0</span>
<span class="stat-label">分享数</span>
</div>
</div>
</div>
<!-- 文章内容 -->
<div class="article-content">
<div class="content-section">
<h4>📝 文章摘要</h4>
<p id="articleSummary">文章摘要内容...</p>
</div>
<div class="content-section">
<h4>📄 正文内容</h4>
<div id="articleFullText">
<!-- 正文内容将在这里动态插入 -->
</div>
</div>
</div>
<!-- 文章操作按钮 -->
<div class="article-actions">
<button class="action-btn btn-primary" onclick="viewOriginalUrl()">
🔗 原文地址
</button>
<button class="action-btn btn-primary" onclick="exportFullText()">
📄 导出全文
</button>
<button class="action-btn btn-primary" onclick="viewHistoryArticles()">
📚 历史文章
</button>
<button class="action-btn btn-secondary" onclick="shareArticle()">
📤 分享文章
</button>
<button class="action-btn btn-secondary" onclick="collectArticle()">
⭐ 收藏文章
</button>
</div>
</div>
</div>
</div>
<script>
// 文章详细数据
const articleDetails = {
1: {
platform: '公众号',
account: '科技前沿',
field: '科技',
title: 'AI技术革命改变未来生活的十大趋势',
publishTime: '2024-01-15',
readCount: '10.5万',
likeCount: '2.3万',
commentCount: 856,
shareCount: 1250,
summary: '本文深入分析了人工智能技术在各个领域的应用前景探讨了AI如何改变我们的生活方式、工作模式和社会结构。从智能家居到自动驾驶从医疗诊断到金融分析AI的应用已经渗透到生活的方方面面。',
content: `
<p>随着科技的飞速发展人工智能技术正以前所未有的速度改变着我们的世界。从智能家居到自动驾驶从医疗诊断到金融分析AI的应用已经渗透到生活的方方面面。</p>
<h3>1. 智能家居的普及</h3>
<p>智能家居系统通过AI技术学习用户的生活习惯自动调节家居环境提供更加舒适便捷的生活体验。智能音箱、智能照明、智能安防等产品已经成为现代家庭的标准配置。</p>
<h3>2. 自动驾驶技术的突破</h3>
<p>自动驾驶汽车利用深度学习和计算机视觉技术,能够实时感知周围环境,做出安全的驾驶决策。多家科技公司和汽车制造商都在积极研发自动驾驶技术,预计在未来几年内将实现商业化应用。</p>
<h3>3. 医疗诊断的精准化</h3>
<p>AI辅助诊断系统能够分析医学影像识别疾病特征提高诊断的准确性和效率。在癌症筛查、心脏病诊断等领域AI已经展现出超越人类专家的能力。</p>
<h3>4. 金融服务的智能化</h3>
<p>AI技术在金融领域的应用包括风险评估、欺诈检测、智能投顾等。通过大数据分析和机器学习算法金融机构能够为客户提供更加个性化和精准的服务。</p>
<h3>5. 教育个性化的发展</h3>
<p>AI教育平台能够根据学生的学习进度和特点提供个性化的学习方案。智能辅导系统可以实时反馈学生的学习情况帮助教师更好地指导学生。</p>
`
},
2: {
platform: '头条号',
account: '娱乐八卦',
field: '娱乐',
title: '明星动态最新消息',
publishTime: '2024-01-14',
readCount: '8.2万',
likeCount: '1.8万',
commentCount: 432,
shareCount: 890,
summary: '最新娱乐圈动态,包括明星新作品发布、综艺节目表现、时尚活动红毯时刻等。本文为您带来娱乐圈的最新资讯和明星们的精彩表现。',
content: `
<p>娱乐圈总是充满新鲜事,明星们的每一个动态都牵动着粉丝的心。今天我们就来为大家带来最新的娱乐资讯。</p>
<h3>影视新作发布</h3>
<p>多位知名演员近期都有新作品上线,包括电影、电视剧和综艺节目。这些作品涵盖了不同的题材和风格,为观众带来丰富的视听享受。</p>
<h3>综艺节目精彩表现</h3>
<p>各大卫视和网络平台推出的综艺节目持续热播,明星嘉宾在节目中的精彩表现成为观众讨论的焦点。真人秀、音乐竞技、脱口秀等多种类型的节目为观众带来丰富的娱乐体验。</p>
<h3>时尚活动红毯时刻</h3>
<p>各大时尚活动和颁奖典礼上,明星们的红毯造型总是备受关注。从服装搭配到妆容发型,每一个细节都展现着明星的时尚品味和个人风格。</p>
<h3>明星公益行动</h3>
<p>越来越多的明星积极参与公益活动,用自己的影响力传递正能量。从教育扶贫到环保宣传,从关爱老人到帮助儿童,明星们用实际行动践行社会责任。</p>
`
},
3: {
platform: '公众号',
account: '美食生活',
field: '美食',
title: '传统美食文化传承',
publishTime: '2024-01-13',
readCount: '15.7万',
likeCount: '3.1万',
commentCount: 967,
shareCount: 2100,
summary: '中华美食文化源远流长,各地传统美食承载着深厚的历史文化底蕴。本文将带您走进传统美食的世界,了解美食背后的文化故事和制作工艺。',
content: `
<p>中华美食文化源远流长,各地传统美食承载着深厚的历史文化底蕴。每一道传统菜品都蕴含着丰富的历史文化内涵,反映了不同地区的风土人情和生活智慧。</p>
<h3>美食与文化的融合</h3>
<p>中国传统美食不仅仅是味觉的享受,更是文化的传承。每一道传统菜品都蕴含着丰富的历史文化内涵,反映了不同地区的风土人情和生活智慧。</p>
<h3>地方特色美食</h3>
<p>从北京的烤鸭到四川的火锅,从广东的早茶到陕西的肉夹馍,各地特色美食展现了中华饮食文化的多样性和地域特色。这些美食不仅是当地人的骄傲,也成为了吸引游客的重要名片。</p>
<h3>传统制作工艺</h3>
<p>传统美食的制作工艺往往需要经过多年的学习和实践才能掌握。从选材到烹饪,每一个环节都讲究精益求精,这种工匠精神正是传统美食文化的重要组成部分。</p>
<h3>美食文化的现代传承</h3>
<p>在现代化进程中,如何保护和传承传统美食文化成为重要课题。通过美食节、烹饪比赛、文化展示等多种形式,传统美食文化正在以新的方式焕发生机。</p>
<h3>美食与健康</h3>
<p>现代人在享受美食的同时,也越来越注重健康饮食。传统美食在保持原有风味的基础上,也在不断创新,推出更加健康、营养的菜品,满足现代人的饮食需求。</p>
`
}
};
// 获取URL参数
function getUrlParameter(name) {
const urlParams = new URLSearchParams(window.location.search);
return urlParams.get(name);
}
// 加载文章详情
function loadArticleDetail(articleId) {
const article = articleDetails[articleId];
if (!article) {
document.getElementById('loadingState').style.display = 'none';
document.getElementById('errorState').style.display = 'block';
return;
}
// 填充文章数据
document.getElementById('articleTitle').textContent = article.title;
document.getElementById('articlePlatform').textContent = article.platform;
document.getElementById('articleAccount').textContent = article.account;
document.getElementById('articleField').textContent = article.field;
document.getElementById('articleDate').textContent = article.publishTime;
document.getElementById('readCount').textContent = article.readCount;
document.getElementById('likeCount').textContent = article.likeCount;
document.getElementById('commentCount').textContent = article.commentCount;
document.getElementById('shareCount').textContent = article.shareCount || '0';
document.getElementById('articleSummary').textContent = article.summary;
document.getElementById('articleFullText').innerHTML = article.content;
// 显示文章内容,隐藏加载状态
document.getElementById('loadingState').style.display = 'none';
document.getElementById('articleContent').style.display = 'block';
}
// 查看原文地址
function viewOriginalUrl() {
const articleId = getUrlParameter('id');
console.log('查看原文地址文章ID:', articleId);
// 模拟原文地址
const originalUrls = {
1: 'https://mp.weixin.qq.com/s/tech-ai-trends-2024',
2: 'https://www.toutiao.com/article/entertainment-news-2024',
3: 'https://mp.weixin.qq.com/s/traditional-food-culture'
};
const url = originalUrls[articleId] || '#';
if (url !== '#') {
window.open(url, '_blank');
} else {
alert('原文地址暂未提供');
}
}
// 导出全文
function exportFullText() {
const articleId = getUrlParameter('id');
const article = articleDetails[articleId];
if (!article) {
alert('文章信息不存在');
return;
}
// 创建导出内容
const exportContent = `
文章标题:${article.title}
平台:${article.platform}
账号:${article.account}
领域:${article.field}
发布时间:${article.publishTime}
阅读量:${article.readCount}
点赞数:${article.likeCount}
评论数:${article.commentCount}
分享数:${article.shareCount}
摘要:
${article.summary}
正文:
${article.content.replace(/<[^>]*>/g, '')}
`.trim();
// 创建下载链接
const blob = new Blob([exportContent], { type: 'text/plain;charset=utf-8' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = `${article.title}.txt`;
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
URL.revokeObjectURL(url);
alert('文章已导出为文本文件!');
}
// 查看历史文章
function viewHistoryArticles() {
const articleId = getUrlParameter('id');
const article = articleDetails[articleId];
if (!article) {
alert('文章信息不存在');
return;
}
// 跳转到历史文章页面,传递账号信息
const accountMap = {
1: 1, // 科技前沿
2: 2, // 娱乐资讯
3: 3 // 美食文化
};
const accountId = accountMap[articleId] || articleId;
window.open(`history-articles.html?account=${accountId}`, '_blank');
}
// 分享文章
function shareArticle() {
const articleId = getUrlParameter('id');
console.log('分享文章文章ID:', articleId);
if (navigator.share) {
navigator.share({
title: document.getElementById('articleTitle').textContent,
text: document.getElementById('articleSummary').textContent,
url: window.location.href
});
} else {
alert('分享功能开发中...');
}
}
// 收藏文章
function collectArticle() {
const articleId = getUrlParameter('id');
console.log('收藏文章文章ID:', articleId);
alert('文章已收藏!');
}
// 登录状态管理
function checkLoginStatus() {
const isLoggedIn = localStorage.getItem('isLoggedIn') === 'true';
const username = localStorage.getItem('username');
if (isLoggedIn && username) {
showLoggedInState(username);
} else {
showLoggedOutState();
}
}
// 显示已登录状态
function showLoggedInState(username) {
document.getElementById('loginLink').style.display = 'none';
document.getElementById('userMenu').style.display = 'block';
document.getElementById('logoutLink').style.display = 'block';
// 为用户中心菜单添加点击事件
document.getElementById('userMenu').onclick = function() {
window.location.href = 'user-center.html';
};
}
// 显示未登录状态
function showLoggedOutState() {
document.getElementById('loginLink').style.display = 'block';
document.getElementById('userMenu').style.display = 'none';
document.getElementById('logoutLink').style.display = 'none';
}
// 登出功能
function logout() {
if (confirm('确定要退出登录吗?')) {
localStorage.removeItem('isLoggedIn');
localStorage.removeItem('username');
localStorage.removeItem('token');
sessionStorage.removeItem('userSession');
showLoggedOutState();
alert('已成功退出登录!');
// 如果在用户中心页面,跳转到首页
if (window.location.pathname.includes('user-center.html')) {
window.location.href = 'frontend.html';
}
}
}
// 页面加载完成后执行
document.addEventListener('DOMContentLoaded', function() {
// 检查登录状态
checkLoginStatus();
const articleId = getUrlParameter('id');
if (!articleId || !articleDetails[articleId]) {
// 显示错误状态
document.getElementById('loadingState').style.display = 'none';
document.getElementById('errorState').style.display = 'block';
return;
}
// 模拟加载延迟
setTimeout(() => {
loadArticleDetail(articleId);
}, 800);
});
</script>
</body>
</html>

2425
frontend/frontend.html Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,696 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>历史文章 - 微信文章访问系统</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', 'Helvetica Neue', Helvetica, Arial, sans-serif;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
min-height: 100vh;
padding: 20px;
}
.container {
max-width: 1200px;
margin: 0 auto;
background: white;
border-radius: 15px;
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.1);
overflow: hidden;
}
.header {
background: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%);
color: white;
padding: 30px;
text-align: center;
}
.header-content {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20px;
}
.logo {
font-size: 1.8em;
font-weight: 700;
color: white;
text-decoration: none;
display: flex;
align-items: center;
gap: 8px;
}
.logo:hover {
text-decoration: none;
color: white;
}
/* 导航菜单 */
.nav-menu {
display: flex;
gap: 15px;
align-items: center;
}
.nav-link {
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);
}
.nav-link:hover {
background: rgba(255, 255, 255, 0.2);
transform: translateY(-1px);
text-decoration: none;
color: white;
}
.nav-link.active {
background: rgba(255, 255, 255, 0.25);
border-color: rgba(255, 255, 255, 0.4);
}
.header h1 {
font-size: 2.5em;
margin-bottom: 10px;
font-weight: 700;
}
.account-info {
background: rgba(255, 255, 255, 0.1);
padding: 15px;
border-radius: 10px;
margin-top: 20px;
backdrop-filter: blur(10px);
}
.account-info h2 {
font-size: 1.5em;
margin-bottom: 10px;
}
.account-info p {
font-size: 1.1em;
opacity: 0.9;
}
.content {
padding: 30px;
}
.loading {
text-align: center;
padding: 50px;
font-size: 1.2em;
color: #666;
}
.articles-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(350px, 1fr));
gap: 20px;
margin-top: 20px;
}
.article-card {
background: white;
border: 1px solid #e1e5e9;
border-radius: 10px;
padding: 20px;
transition: all 0.3s ease;
cursor: pointer;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.05);
}
.article-card:hover {
transform: translateY(-5px);
box-shadow: 0 8px 25px rgba(0, 0, 0, 0.15);
border-color: #4facfe;
}
.article-title {
font-size: 1.2em;
font-weight: 600;
color: #2c3e50;
margin-bottom: 10px;
line-height: 1.4;
}
.article-meta {
display: flex;
justify-content: space-between;
align-items: center;
margin-top: 15px;
padding-top: 15px;
border-top: 1px solid #f0f0f0;
}
.article-date {
color: #7f8c8d;
font-size: 0.9em;
}
.article-stats {
display: flex;
gap: 15px;
font-size: 0.85em;
color: #95a5a6;
}
.stat-item {
display: flex;
align-items: center;
gap: 3px;
}
.back-button {
display: inline-flex;
align-items: center;
gap: 8px;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
padding: 12px 24px;
border: none;
border-radius: 8px;
cursor: pointer;
font-size: 1em;
font-weight: 500;
text-decoration: none;
transition: all 0.3s ease;
margin-bottom: 20px;
}
.back-button:hover {
transform: translateY(-2px);
box-shadow: 0 5px 15px rgba(102, 126, 234, 0.4);
}
.error-message {
text-align: center;
padding: 50px;
color: #e74c3c;
font-size: 1.1em;
}
.no-articles {
text-align: center;
padding: 50px;
color: #7f8c8d;
font-size: 1.1em;
}
.search-bar {
margin-bottom: 20px;
display: flex;
flex-direction: column;
gap: 15px;
}
.search-row {
display: flex;
gap: 10px;
}
.search-input {
flex: 1;
padding: 12px;
border: 2px solid #e1e5e9;
border-radius: 8px;
font-size: 1em;
transition: border-color 0.3s ease;
}
.search-input:focus {
outline: none;
border-color: #4facfe;
}
.search-button {
padding: 12px 24px;
background: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%);
color: white;
border: none;
border-radius: 8px;
cursor: pointer;
font-size: 1em;
font-weight: 500;
transition: all 0.3s ease;
}
.search-button:hover {
transform: translateY(-2px);
box-shadow: 0 5px 15px rgba(79, 172, 254, 0.4);
}
.time-filter {
display: flex;
gap: 10px;
flex-wrap: wrap;
}
.time-filter button {
padding: 8px 16px;
background: #f8f9fa;
border: 2px solid #e1e5e9;
border-radius: 20px;
cursor: pointer;
font-size: 0.9em;
transition: all 0.3s ease;
}
.time-filter button:hover {
background: #e9ecef;
}
.time-filter button.active {
background: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%);
color: white;
border-color: #4facfe;
}
@media (max-width: 768px) {
.articles-grid {
grid-template-columns: 1fr;
}
.header h1 {
font-size: 2em;
}
.content {
padding: 20px;
}
}
</style>
</head>
<body>
<div class="container">
<div class="header">
<div class="header-content">
<a href="frontend.html" class="logo">🔍 易搜高</a>
<nav class="nav-menu">
<a href="frontend.html" class="nav-link">首页</a>
<a href="#" class="nav-link">监控中心</a>
<a href="#" class="nav-link">数据分析</a>
<a href="#" class="nav-link">帮助文档</a>
<a href="user-center.html" class="nav-link" id="userMenu" style="display: none;">👤 用户中心</a>
<a href="login.html" class="nav-link" id="loginLink">🔐 登录</a>
<a href="#" class="nav-link" id="logoutLink" style="display: none;" onclick="logout()">🚪 退出</a>
</nav>
</div>
<h1>历史文章</h1>
<div class="account-info" id="accountInfo">
<h2 id="accountName">加载中...</h2>
<p id="accountPlatform">平台信息加载中...</p>
</div>
</div>
<div class="content">
<button class="back-button" onclick="goBack()">
← 返回上一页
</button>
<div class="search-bar">
<div class="time-filter">
<button onclick="filterByTime('all')" class="time-btn active" data-time="all">全部</button>
<button onclick="filterByTime('today')" class="time-btn" data-time="today">今天</button>
<button onclick="filterByTime('yesterday')" class="time-btn" data-time="yesterday">昨天</button>
<button onclick="filterByTime('3days')" class="time-btn" data-time="3days">三天前</button>
<button onclick="filterByTime('7days')" class="time-btn" data-time="7days">七天前</button>
</div>
<div class="search-row">
<input type="text" class="search-input" id="searchInput" placeholder="搜索文章标题...">
<button class="search-button" onclick="searchArticles()">搜索</button>
</div>
</div>
<div id="loadingState" class="loading">
正在加载历史文章...
</div>
<div id="articlesContainer" style="display: none;">
<div id="articlesGrid" class="articles-grid">
<!-- 文章列表将在这里动态生成 -->
</div>
</div>
<div id="errorState" class="error-message" style="display: none;">
加载历史文章失败,请稍后重试
</div>
<div id="noArticlesState" class="no-articles" style="display: none;">
暂无历史文章
</div>
</div>
</div>
<script>
// 模拟历史文章数据
const historyArticlesData = {
1: {
account: '科技前沿',
platform: '微信公众号',
field: '科技',
articles: [
{ id: 101, title: '机器学习在医疗领域的应用:从诊断到治疗的革命', date: '2025-01-24', readCount: 5234, likeCount: 189, commentCount: 45 },
{ id: 102, title: '量子计算的发展前景:突破传统计算极限', date: '2025-01-23', readCount: 3892, likeCount: 156, commentCount: 32 },
{ id: 103, title: '区块链技术的实际应用案例:不止是加密货币', date: '2025-01-22', readCount: 4123, likeCount: 178, commentCount: 38 },
{ id: 104, title: '人工智能伦理:技术发展的道德边界', date: '2025-01-21', readCount: 3567, likeCount: 145, commentCount: 29 },
{ id: 105, title: '5G技术的商业化应用改变生活方式', date: '2025-01-20', readCount: 4789, likeCount: 198, commentCount: 41 },
{ id: 106, title: '虚拟现实技术的教育应用前景', date: '2025-01-19', readCount: 2934, likeCount: 123, commentCount: 25 },
{ id: 107, title: '物联网安全:智能家居的隐私保护', date: '2025-01-18', readCount: 3456, likeCount: 167, commentCount: 33 },
{ id: 108, title: '边缘计算:下一代云计算架构', date: '2025-01-17', readCount: 2789, likeCount: 134, commentCount: 28 },
{ id: 109, title: 'ChatGPT对编程行业的影响分析', date: '2025-01-16', readCount: 4567, likeCount: 234, commentCount: 56 },
{ id: 110, title: '自动驾驶技术的最新进展', date: '2025-01-15', readCount: 3876, likeCount: 198, commentCount: 45 }
]
},
2: {
account: '娱乐资讯',
platform: '今日头条',
field: '娱乐',
articles: [
{ id: 201, title: '春节档电影票房分析:谁是最大赢家', date: '2025-01-24', readCount: 8934, likeCount: 456, commentCount: 123 },
{ id: 202, title: '综艺节目收视率排行榜:观众最爱看什么', date: '2025-01-23', readCount: 7234, likeCount: 389, commentCount: 98 },
{ id: 203, title: '明星时尚穿搭盘点2024年流行趋势', date: '2025-01-22', readCount: 6543, likeCount: 334, commentCount: 87 },
{ id: 204, title: '音乐节现场直击:年轻人的狂欢盛宴', date: '2025-01-21', readCount: 5432, likeCount: 278, commentCount: 76 },
{ id: 205, title: '电视剧口碑榜:哪些作品值得追', date: '2025-01-20', readCount: 4987, likeCount: 256, commentCount: 69 },
{ id: 206, title: '网红经济分析:流量变现的新模式', date: '2025-01-19', readCount: 4321, likeCount: 223, commentCount: 58 }
]
},
3: {
account: '美食文化',
platform: '微信公众号',
field: '美食',
articles: [
{ id: 301, title: '春节传统美食制作方法:家乡的味道', date: '2025-01-24', readCount: 6789, likeCount: 345, commentCount: 89 },
{ id: 302, title: '各地特色小吃推荐:舌尖上的中国', date: '2025-01-23', readCount: 5432, likeCount: 278, commentCount: 67 },
{ id: 303, title: '健康饮食新趋势:营养与美味的平衡', date: '2025-01-22', readCount: 4567, likeCount: 234, commentCount: 56 },
{ id: 304, title: '素食主义:环保与健康的双重选择', date: '2025-01-21', readCount: 3876, likeCount: 198, commentCount: 45 },
{ id: 305, title: '咖啡文化探索:从豆子到杯子的旅程', date: '2025-01-20', readCount: 3234, likeCount: 167, commentCount: 38 },
{ id: 306, title: '茶艺入门:中国传统文化的精髓', date: '2025-01-19', readCount: 2987, likeCount: 156, commentCount: 34 },
{ id: 307, title: '烘焙技巧分享:新手也能做出美味蛋糕', date: '2025-01-18', readCount: 2765, likeCount: 145, commentCount: 31 }
]
}
};
let currentArticles = [];
let filteredArticles = [];
let currentFilter = 'all';
// 返回到主页面
function goBack() {
// 直接跳转到 frontend.html 页面
window.location.href = 'frontend.html';
}
// 时间筛选功能
function filterByTime(timeRange) {
currentFilter = timeRange;
// 更新按钮状态
document.querySelectorAll('.time-btn').forEach(btn => {
btn.classList.remove('active');
});
document.querySelector(`[data-time="${timeRange}"]`).classList.add('active');
// 为了演示,我们使用文章数据中的最新日期作为"今天"
const latestArticle = currentArticles.reduce((latest, article) => {
return new Date(article.date) > new Date(latest.date) ? article : latest;
}, currentArticles[0]);
const today = new Date(latestArticle.date);
today.setHours(0, 0, 0, 0);
let startDate = new Date();
let endDate = new Date();
switch(timeRange) {
case 'today':
// 今天2025-1-24
startDate = new Date('2025-01-24');
endDate = new Date('2025-01-24');
endDate.setHours(23, 59, 59, 999);
break;
case 'yesterday':
// 昨天2025-1-23
startDate = new Date('2025-01-23');
endDate = new Date('2025-01-23');
endDate.setHours(23, 59, 59, 999);
break;
case '3days':
// 三天前2025-1-17到2025-1-22
startDate = new Date('2025-01-17');
endDate = new Date('2025-01-22');
endDate.setHours(23, 59, 59, 999);
break;
case '7days':
// 七天前2024-12-24到2025-1-16
startDate = new Date('2024-12-24');
endDate = new Date('2025-01-16');
endDate.setHours(23, 59, 59, 999);
break;
case 'all':
default:
// 显示所有文章
filteredArticles = [...currentArticles];
renderArticles(filteredArticles);
return;
}
// 根据时间筛选文章
filteredArticles = currentArticles.filter(article => {
const articleDate = new Date(article.date);
return articleDate >= startDate && articleDate <= endDate;
});
renderArticles(filteredArticles);
}
// 获取URL参数
function getUrlParameter(name) {
const urlParams = new URLSearchParams(window.location.search);
return urlParams.get(name);
}
// 格式化数字
function formatNumber(num) {
if (num >= 10000) {
return (num / 10000).toFixed(1) + 'w';
}
return num.toString();
}
// 加载历史文章
function loadHistoryArticles() {
const accountId = getUrlParameter('account');
console.log('加载历史文章账号ID:', accountId);
if (!accountId || !historyArticlesData[accountId]) {
document.getElementById('loadingState').style.display = 'none';
document.getElementById('errorState').style.display = 'block';
return;
}
const accountData = historyArticlesData[accountId];
// 更新账号信息
document.getElementById('accountName').textContent = accountData.account;
document.getElementById('accountPlatform').textContent = `${accountData.platform} · ${accountData.field}领域`;
// 设置当前文章列表
currentArticles = accountData.articles;
filteredArticles = [...currentArticles];
// 隐藏加载状态,显示文章列表
document.getElementById('loadingState').style.display = 'none';
document.getElementById('articlesContainer').style.display = 'block';
// 渲染文章列表
renderArticles(filteredArticles);
}
// 渲染文章列表
function renderArticles(articles) {
const articlesGrid = document.getElementById('articlesGrid');
if (articles.length === 0) {
document.getElementById('articlesContainer').style.display = 'none';
document.getElementById('noArticlesState').style.display = 'block';
return;
}
let articlesHtml = '';
articles.forEach(article => {
articlesHtml += `
<div class="article-card" onclick="viewArticle(${article.id})">
<div class="article-title">${article.title}</div>
<div class="article-meta">
<div class="article-date">${article.date}</div>
<div class="article-stats">
<div class="stat-item">
<span>👁</span>
<span>${formatNumber(article.readCount)}</span>
</div>
<div class="stat-item">
<span>👍</span>
<span>${formatNumber(article.likeCount)}</span>
</div>
<div class="stat-item">
<span>💬</span>
<span>${article.commentCount}</span>
</div>
</div>
</div>
</div>
`;
});
articlesGrid.innerHTML = articlesHtml;
}
// 查看文章详情
function viewArticle(articleId) {
// 跳转到文章详情页面
window.open(`article-detail.html?id=${articleId}`, '_blank');
}
// 搜索文章
function searchArticles() {
const searchTerm = document.getElementById('searchInput').value.toLowerCase().trim();
// 首先应用时间筛选
let articlesToSearch = [...currentArticles];
if (currentFilter !== 'all') {
let startDate = new Date();
let endDate = new Date();
switch(currentFilter) {
case 'today':
// 今天2025-1-24
startDate = new Date('2025-01-24');
endDate = new Date('2025-01-24');
endDate.setHours(23, 59, 59, 999);
break;
case 'yesterday':
// 昨天2025-1-23
startDate = new Date('2025-01-23');
endDate = new Date('2025-01-23');
endDate.setHours(23, 59, 59, 999);
break;
case '3days':
// 三天前2025-1-17到2025-1-22
startDate = new Date('2025-01-17');
endDate = new Date('2025-01-22');
endDate.setHours(23, 59, 59, 999);
break;
case '7days':
// 七天前2024-12-24到2025-1-16
startDate = new Date('2024-12-24');
endDate = new Date('2025-01-16');
endDate.setHours(23, 59, 59, 999);
break;
}
articlesToSearch = articlesToSearch.filter(article => {
const articleDate = new Date(article.date);
return articleDate >= startDate && articleDate <= endDate;
});
}
// 然后应用搜索
if (searchTerm === '') {
filteredArticles = articlesToSearch;
} else {
filteredArticles = articlesToSearch.filter(article =>
article.title.toLowerCase().includes(searchTerm)
);
}
renderArticles(filteredArticles);
}
// 登录状态管理
function checkLoginStatus() {
const isLoggedIn = localStorage.getItem('isLoggedIn') === 'true';
const username = localStorage.getItem('username');
if (isLoggedIn && username) {
showLoggedInState(username);
} else {
showLoggedOutState();
}
}
// 显示已登录状态
function showLoggedInState(username) {
document.getElementById('loginLink').style.display = 'none';
document.getElementById('userMenu').style.display = 'block';
document.getElementById('logoutLink').style.display = 'block';
// 为用户中心菜单添加点击事件
document.getElementById('userMenu').onclick = function() {
window.location.href = 'user-center.html';
};
}
// 显示未登录状态
function showLoggedOutState() {
document.getElementById('loginLink').style.display = 'block';
document.getElementById('userMenu').style.display = 'none';
document.getElementById('logoutLink').style.display = 'none';
}
// 登出功能
function logout() {
if (confirm('确定要退出登录吗?')) {
localStorage.removeItem('isLoggedIn');
localStorage.removeItem('username');
localStorage.removeItem('token');
sessionStorage.removeItem('userSession');
showLoggedOutState();
alert('已成功退出登录!');
// 如果在用户中心页面,跳转到首页
if (window.location.pathname.includes('user-center.html')) {
window.location.href = 'frontend.html';
}
}
}
// 监听搜索框回车事件
document.addEventListener('DOMContentLoaded', function() {
// 检查登录状态
checkLoginStatus();
const searchInput = document.getElementById('searchInput');
searchInput.addEventListener('keypress', function(e) {
if (e.key === 'Enter') {
searchArticles();
}
});
});
// 页面加载完成后加载历史文章
window.addEventListener('load', loadHistoryArticles);
</script>
</body>
</html>

724
frontend/login.html Normal file
View File

@@ -0,0 +1,724 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>用户登录 - 易搜高</title>
<meta name="keywords" content="用户登录,易搜高,自媒体监控">
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Microsoft YaHei', sans-serif;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
padding: 20px;
}
.login-container {
background: white;
border-radius: 20px;
box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);
overflow: hidden;
width: 100%;
max-width: 900px;
min-height: 500px;
display: flex;
animation: slideUp 0.6s ease-out;
}
@keyframes slideUp {
from {
opacity: 0;
transform: translateY(30px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
.login-left {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
padding: 60px 40px;
flex: 1;
display: flex;
flex-direction: column;
justify-content: center;
position: relative;
overflow: hidden;
}
.login-left::before {
content: '';
position: absolute;
top: -50%;
right: -50%;
width: 200%;
height: 200%;
background: radial-gradient(circle, rgba(255,255,255,0.1) 0%, transparent 70%);
animation: rotate 30s linear infinite;
}
@keyframes rotate {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}
.login-left h1 {
font-size: 2.5em;
margin-bottom: 20px;
font-weight: 700;
position: relative;
z-index: 1;
}
.login-left p {
font-size: 1.1em;
line-height: 1.6;
opacity: 0.9;
margin-bottom: 30px;
position: relative;
z-index: 1;
}
.feature-list {
list-style: none;
position: relative;
z-index: 1;
}
.feature-list li {
padding: 10px 0;
display: flex;
align-items: center;
gap: 10px;
}
.feature-list li::before {
content: '✓';
background: rgba(255, 255, 255, 0.2);
width: 20px;
height: 20px;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
font-size: 12px;
}
.login-right {
flex: 1;
padding: 60px 40px;
display: flex;
flex-direction: column;
justify-content: center;
}
.login-header {
text-align: center;
margin-bottom: 40px;
}
.login-header h2 {
font-size: 2em;
color: #2c3e50;
margin-bottom: 10px;
font-weight: 600;
}
.login-header p {
color: #7f8c8d;
font-size: 1em;
}
.form-group {
margin-bottom: 25px;
}
.form-group label {
display: block;
margin-bottom: 8px;
color: #495057;
font-weight: 500;
font-size: 14px;
}
.form-group input {
width: 100%;
padding: 15px 20px;
border: 2px solid #e9ecef;
border-radius: 10px;
font-size: 16px;
transition: all 0.3s ease;
background: #f8f9fa;
}
.form-group input:focus {
outline: none;
border-color: #667eea;
background: white;
box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.1);
}
.form-group input::placeholder {
color: #adb5bd;
}
.password-group {
position: relative;
}
.password-toggle {
position: absolute;
right: 15px;
top: 50%;
transform: translateY(-50%);
background: none;
border: none;
color: #6c757d;
cursor: pointer;
font-size: 18px;
padding: 5px;
}
.password-toggle:hover {
color: #667eea;
}
.form-options {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 30px;
}
.remember-me {
display: flex;
align-items: center;
gap: 8px;
}
.remember-me input[type="checkbox"] {
width: 18px;
height: 18px;
accent-color: #667eea;
}
.remember-me label {
color: #495057;
font-size: 14px;
cursor: pointer;
}
.forgot-password {
color: #667eea;
text-decoration: none;
font-size: 14px;
transition: color 0.3s;
}
.forgot-password:hover {
color: #764ba2;
text-decoration: underline;
}
.login-btn {
width: 100%;
padding: 15px;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
border: none;
border-radius: 10px;
font-size: 16px;
font-weight: 600;
cursor: pointer;
transition: all 0.3s ease;
position: relative;
overflow: hidden;
}
.login-btn::before {
content: '';
position: absolute;
top: 0;
left: -100%;
width: 100%;
height: 100%;
background: linear-gradient(90deg, transparent, rgba(255,255,255,0.2), transparent);
transition: left 0.5s;
}
.login-btn:hover::before {
left: 100%;
}
.login-btn:hover {
transform: translateY(-2px);
box-shadow: 0 10px 25px rgba(102, 126, 234, 0.3);
}
.login-btn:active {
transform: translateY(0);
}
.divider {
text-align: center;
margin: 30px 0;
position: relative;
}
.divider::before {
content: '';
position: absolute;
top: 50%;
left: 0;
right: 0;
height: 1px;
background: #e9ecef;
}
.divider span {
background: white;
padding: 0 15px;
color: #6c757d;
font-size: 14px;
position: relative;
}
.social-login {
display: flex;
gap: 15px;
margin-bottom: 20px;
}
.social-btn {
flex: 1;
padding: 12px;
border: 2px solid #e9ecef;
background: white;
border-radius: 10px;
cursor: pointer;
transition: all 0.3s ease;
display: flex;
align-items: center;
justify-content: center;
gap: 8px;
font-size: 14px;
color: #495057;
}
.social-btn:hover {
border-color: #667eea;
background: #f8f9fa;
transform: translateY(-2px);
}
.register-link {
text-align: center;
color: #6c757d;
font-size: 14px;
}
.register-link a {
color: #667eea;
text-decoration: none;
font-weight: 600;
}
.register-link a:hover {
text-decoration: underline;
}
.back-to-home {
position: absolute;
top: 20px;
left: 20px;
background: rgba(255, 255, 255, 0.2);
color: white;
border: 1px solid rgba(255, 255, 255, 0.3);
padding: 10px 20px;
border-radius: 25px;
text-decoration: none;
font-size: 14px;
transition: all 0.3s;
display: flex;
align-items: center;
gap: 8px;
z-index: 10;
}
.back-to-home:hover {
background: rgba(255, 255, 255, 0.3);
transform: translateY(-2px);
text-decoration: none;
color: white;
}
/* 响应式设计 */
@media (max-width: 768px) {
.login-container {
flex-direction: column;
max-width: 400px;
min-height: auto;
}
.login-left {
padding: 40px 30px;
min-height: 200px;
}
.login-left h1 {
font-size: 2em;
}
.login-right {
padding: 40px 30px;
}
.login-header h2 {
font-size: 1.5em;
}
.social-login {
flex-direction: column;
}
}
/* 错误提示样式 */
.error-message {
background: #f8d7da;
color: #721c24;
padding: 12px 16px;
border-radius: 8px;
margin-bottom: 20px;
border: 1px solid #f5c6cb;
font-size: 14px;
display: none;
}
.success-message {
background: #d4edda;
color: #155724;
padding: 12px 16px;
border-radius: 8px;
margin-bottom: 20px;
border: 1px solid #c3e6cb;
font-size: 14px;
display: none;
}
</style>
</head>
<body>
<a href="frontend.html" class="back-to-home">
← 返回首页
</a>
<div class="login-container">
<div class="login-left">
<h1>🔍 易搜高</h1>
<p>专业的自媒体文章监控平台,让您轻松掌握行业动态</p>
<ul class="feature-list">
<li>实时监控多个自媒体平台</li>
<li>智能筛选热门文章</li>
<li>数据可视化分析</li>
<li>个性化推荐系统</li>
</ul>
</div>
<div class="login-right">
<div class="login-header">
<h2>欢迎登录</h2>
<p>请使用您的账号信息登录</p>
</div>
<div class="error-message" id="errorMessage"></div>
<div class="success-message" id="successMessage"></div>
<form id="loginForm">
<div class="form-group">
<label for="username">用户名 / 邮箱</label>
<input type="text" id="username" name="username" placeholder="请输入用户名或邮箱" required>
</div>
<div class="form-group">
<label for="password">密码</label>
<div class="password-group">
<input type="password" id="password" name="password" placeholder="请输入密码" required>
<button type="button" class="password-toggle" onclick="togglePassword()">👁️</button>
</div>
</div>
<div class="form-options">
<div class="remember-me">
<input type="checkbox" id="remember" name="remember">
<label for="remember">记住我</label>
</div>
<a href="#" class="forgot-password">忘记密码?</a>
</div>
<button type="submit" class="login-btn">登录</button>
</form>
<div class="divider">
<span>或使用其他方式登录</span>
</div>
<div class="social-login">
<button class="social-btn" onclick="socialLogin('wechat')">
💬 微信登录
</button>
<button class="social-btn" onclick="socialLogin('qq')">
🐧 QQ登录
</button>
</div>
<div class="register-link">
还没有账号?<a href="#">立即注册</a>
</div>
</div>
</div>
<script>
// 密码显示/隐藏切换
function togglePassword() {
const passwordInput = document.getElementById('password');
const toggleBtn = document.querySelector('.password-toggle');
if (passwordInput.type === 'password') {
passwordInput.type = 'text';
toggleBtn.textContent = '🙈';
} else {
passwordInput.type = 'password';
toggleBtn.textContent = '👁️';
}
}
// 显示错误消息
function showError(message) {
const errorDiv = document.getElementById('errorMessage');
const successDiv = document.getElementById('successMessage');
errorDiv.textContent = message;
errorDiv.style.display = 'block';
successDiv.style.display = 'none';
// 3秒后自动隐藏
setTimeout(() => {
errorDiv.style.display = 'none';
}, 3000);
}
// 显示成功消息
function showSuccess(message) {
const errorDiv = document.getElementById('errorMessage');
const successDiv = document.getElementById('successMessage');
successDiv.textContent = message;
successDiv.style.display = 'block';
errorDiv.style.display = 'none';
// 3秒后自动隐藏
setTimeout(() => {
successDiv.style.display = 'none';
}, 3000);
}
// 登录表单提交
document.getElementById('loginForm').addEventListener('submit', function(e) {
e.preventDefault();
const username = document.getElementById('username').value.trim();
const password = document.getElementById('password').value;
const remember = document.getElementById('remember').checked;
// 简单的验证
if (!username) {
showError('请输入用户名或邮箱');
return;
}
if (!password) {
showError('请输入密码');
return;
}
if (password.length < 6) {
showError('密码长度不能少于6位');
return;
}
// 实际登录请求
const loginBtn = document.querySelector('.login-btn');
loginBtn.textContent = '登录中...';
loginBtn.disabled = true;
// 准备请求数据
const loginData = {
username: username,
password: password
};
// 调用后端登录API
fetch('http://localhost:8000/api/user/login', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(loginData)
})
.then(response => {
if (!response.ok) {
// 处理HTTP错误状态码
if (response.status === 500) {
throw new Error('服务器内部错误');
} else if (response.status === 401) {
return response.json().then(data => {
throw new Error(data.msg || '用户名或密码错误');
});
} else if (response.status === 400) {
return response.json().then(data => {
throw new Error(data.msg || '请求参数错误');
});
} else {
throw new Error('网络响应异常');
}
}
return response.json();
})
.then(data => {
// 检查响应状态
if (data.code === 200) {
// 登录成功,存储认证信息
const authData = {
token: data.token,
user_id: data.user_id,
user_info: data.user_info,
loginTime: new Date().toISOString(),
remember: remember
};
// 根据记住我选项选择存储方式
if (remember) {
localStorage.setItem('authData', JSON.stringify(authData));
} else {
sessionStorage.setItem('authData', JSON.stringify(authData));
}
showSuccess('登录成功!正在跳转...');
// 延迟跳转,支持重定向
setTimeout(() => {
// 检查URL中是否有重定向参数
const urlParams = new URLSearchParams(window.location.search);
const redirectUrl = urlParams.get('redirect');
// 如果有重定向URL且是本站URL则跳转到该URL否则跳转到用户中心
if (redirectUrl && (redirectUrl.startsWith('/') || redirectUrl.includes(window.location.hostname))) {
window.location.href = decodeURIComponent(redirectUrl);
} else {
window.location.href = 'user-center.html';
}
}, 1500);
} else {
// 登录失败,显示错误信息
let errorMessage = '登录失败';
// 根据错误码显示不同的错误信息
switch(data.code) {
case 401:
errorMessage = data.msg || '用户名或密码错误';
break;
case 400:
errorMessage = data.msg || '请求参数错误,请检查输入';
break;
case 404:
errorMessage = data.msg || '账号不存在';
break;
case 500:
errorMessage = data.msg || '服务器内部错误,请稍后再试';
break;
default:
errorMessage = data.msg || '登录失败,请检查用户名和密码';
}
showError(errorMessage);
loginBtn.textContent = '登录';
loginBtn.disabled = false;
}
})
.catch(error => {
// 捕获网络或其他错误
console.error('登录请求失败:', error);
// 根据错误信息显示具体的错误提示
let errorMessage = '登录失败,请稍后再试';
if (error.message.includes('账号不存在')) {
errorMessage = '账号不存在,请先注册';
} else if (error.message.includes('密码错误')) {
errorMessage = '密码错误,请重新输入';
} else if (error.message.includes('服务器')) {
errorMessage = '服务器内部错误,请稍后再试';
} else if (error.message.includes('网络')) {
errorMessage = '网络连接异常,请检查您的网络';
} else if (error.message.includes('请求参数')) {
errorMessage = '请求参数错误,请检查输入';
}
showError(errorMessage);
loginBtn.textContent = '登录';
loginBtn.disabled = false;
});
});
// 社交登录
function socialLogin(platform) {
showSuccess(`${platform === 'wechat' ? '微信' : 'QQ'}登录功能开发中...`);
}
// 忘记密码
document.querySelector('.forgot-password').addEventListener('click', function(e) {
e.preventDefault();
showError('密码重置功能开发中...');
});
// 注册链接
document.querySelector('.register-link a').addEventListener('click', function(e) {
e.preventDefault();
window.location.href = 'register.html';
});
// 检查是否已登录
window.addEventListener('load', function() {
const authData = localStorage.getItem('authData') || sessionStorage.getItem('authData');
if (authData) {
const auth = JSON.parse(authData);
showSuccess(`欢迎回来,${auth.user_info.username}`);
// 如果已经登录,可以选择直接跳转
setTimeout(() => {
if (confirm('检测到您已登录,是否跳转到首页?')) {
window.location.href = 'frontend.html';
}
}, 1000);
}
});
// Enter键提交表单
document.addEventListener('keypress', function(e) {
if (e.key === 'Enter') {
document.getElementById('loginForm').dispatchEvent(new Event('submit'));
}
});
</script>
</body>
</html>

701
frontend/register.html Normal file
View File

@@ -0,0 +1,701 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>用户注册 - 易搜高</title>
<meta name="keywords" content="用户注册,易搜高,自媒体监控">
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Microsoft YaHei', sans-serif;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
padding: 20px;
}
.register-container {
background: white;
border-radius: 20px;
box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);
overflow: hidden;
width: 100%;
max-width: 900px;
min-height: 600px;
display: flex;
animation: slideUp 0.6s ease-out;
}
@keyframes slideUp {
from {
opacity: 0;
transform: translateY(30px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
.register-left {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
padding: 60px 40px;
flex: 1;
display: flex;
flex-direction: column;
justify-content: center;
position: relative;
overflow: hidden;
}
.register-left::before {
content: '';
position: absolute;
top: -50%;
right: -50%;
width: 200%;
height: 200%;
background: radial-gradient(circle, rgba(255,255,255,0.1) 0%, transparent 70%);
animation: rotate 30s linear infinite;
}
@keyframes rotate {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}
.register-left h1 {
font-size: 2.5em;
margin-bottom: 20px;
font-weight: 700;
position: relative;
z-index: 1;
}
.register-left p {
font-size: 1.1em;
line-height: 1.6;
opacity: 0.9;
margin-bottom: 30px;
position: relative;
z-index: 1;
}
.feature-list {
list-style: none;
position: relative;
z-index: 1;
}
.feature-list li {
padding: 10px 0;
display: flex;
align-items: center;
gap: 10px;
}
.feature-list li::before {
content: '✓';
background: rgba(255, 255, 255, 0.2);
width: 20px;
height: 20px;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
font-size: 12px;
}
.register-right {
flex: 1;
padding: 60px 40px;
display: flex;
flex-direction: column;
justify-content: center;
}
.register-header {
text-align: center;
margin-bottom: 40px;
}
.register-header h2 {
font-size: 2em;
color: #2c3e50;
margin-bottom: 10px;
font-weight: 600;
}
.register-header p {
color: #7f8c8d;
font-size: 1em;
}
.form-group {
margin-bottom: 25px;
}
.form-group label {
display: block;
margin-bottom: 8px;
color: #495057;
font-weight: 500;
font-size: 14px;
}
.form-group input {
width: 100%;
padding: 15px 20px;
border: 2px solid #e9ecef;
border-radius: 10px;
font-size: 16px;
transition: all 0.3s ease;
background: #f8f9fa;
}
.form-group input:focus {
outline: none;
border-color: #667eea;
background: white;
box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.1);
}
.form-group input::placeholder {
color: #adb5bd;
}
.password-group {
position: relative;
}
.password-toggle {
position: absolute;
right: 15px;
top: 50%;
transform: translateY(-50%);
background: none;
border: none;
color: #6c757d;
cursor: pointer;
font-size: 18px;
padding: 5px;
}
.password-toggle:hover {
color: #667eea;
}
.register-btn {
width: 100%;
padding: 15px;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
border: none;
border-radius: 10px;
font-size: 16px;
font-weight: 600;
cursor: pointer;
transition: all 0.3s ease;
position: relative;
overflow: hidden;
}
.register-btn::before {
content: '';
position: absolute;
top: 0;
left: -100%;
width: 100%;
height: 100%;
background: linear-gradient(90deg, transparent, rgba(255,255,255,0.2), transparent);
transition: left 0.5s;
}
.register-btn:hover::before {
left: 100%;
}
.register-btn:hover {
transform: translateY(-2px);
box-shadow: 0 10px 25px rgba(102, 126, 234, 0.3);
}
.register-btn:active {
transform: translateY(0);
}
.terms-agree {
margin: 20px 0 30px;
font-size: 14px;
color: #6c757d;
display: flex;
align-items: flex-start;
gap: 8px;
}
.terms-agree input[type="checkbox"] {
margin-top: 2px;
accent-color: #667eea;
}
.terms-agree a {
color: #667eea;
text-decoration: none;
}
.terms-agree a:hover {
text-decoration: underline;
}
.login-link {
text-align: center;
color: #6c757d;
font-size: 14px;
}
.login-link a {
color: #667eea;
text-decoration: none;
font-weight: 600;
}
.login-link a:hover {
text-decoration: underline;
}
.back-to-home {
position: absolute;
top: 20px;
left: 20px;
background: rgba(255, 255, 255, 0.2);
color: white;
border: 1px solid rgba(255, 255, 255, 0.3);
padding: 10px 20px;
border-radius: 25px;
text-decoration: none;
font-size: 14px;
transition: all 0.3s;
display: flex;
align-items: center;
gap: 8px;
z-index: 10;
}
.back-to-home:hover {
background: rgba(255, 255, 255, 0.3);
transform: translateY(-2px);
text-decoration: none;
color: white;
}
/* 响应式设计 */
@media (max-width: 768px) {
.register-container {
flex-direction: column;
max-width: 400px;
min-height: auto;
}
.register-left {
padding: 40px 30px;
min-height: 200px;
}
.register-left h1 {
font-size: 2em;
}
.register-right {
padding: 40px 30px;
}
.register-header h2 {
font-size: 1.5em;
}
}
/* 错误提示样式 */
.error-message {
background: #f8d7da;
color: #721c24;
padding: 12px 16px;
border-radius: 8px;
margin-bottom: 20px;
border: 1px solid #f5c6cb;
font-size: 14px;
display: none;
}
.success-message {
background: #d4edda;
color: #155724;
padding: 12px 16px;
border-radius: 8px;
margin-bottom: 20px;
border: 1px solid #c3e6cb;
font-size: 14px;
display: none;
}
/* 表单字段验证状态 */
.form-group.invalid input {
border-color: #dc3545;
background-color: #fff5f5;
}
.form-group.invalid .validation-message {
display: block;
}
.validation-message {
color: #dc3545;
font-size: 12px;
margin-top: 5px;
display: none;
}
</style>
</head>
<body>
<a href="frontend.html" class="back-to-home">
← 返回首页
</a>
<div class="register-container">
<div class="register-left">
<h1>🔍 易搜高</h1>
<p>专业的自媒体文章监控平台,让您轻松掌握行业动态</p>
<ul class="feature-list">
<li>实时监控多个自媒体平台</li>
<li>智能筛选热门文章</li>
<li>数据可视化分析</li>
<li>个性化推荐系统</li>
</ul>
</div>
<div class="register-right">
<div class="register-header">
<h2>创建账号</h2>
<p>加入我们,开启您的自媒体监控之旅</p>
</div>
<div class="error-message" id="errorMessage"></div>
<div class="success-message" id="successMessage"></div>
<form id="registerForm">
<div class="form-group" id="usernameGroup">
<label for="username">用户名</label>
<input type="text" id="username" name="username" placeholder="请设置用户名" required>
<div class="validation-message" id="usernameError"></div>
</div>
<div class="form-group" id="emailGroup">
<label for="email">电子邮箱</label>
<input type="email" id="email" name="email" placeholder="请输入邮箱地址" required>
<div class="validation-message" id="emailError"></div>
</div>
<div class="form-group" id="passwordGroup">
<label for="password">密码</label>
<div class="password-group">
<input type="password" id="password" name="password" placeholder="请设置密码" required>
<button type="button" class="password-toggle" onclick="togglePassword('password')">👁️</button>
</div>
<div class="validation-message" id="passwordError"></div>
</div>
<div class="form-group" id="confirmPasswordGroup">
<label for="confirmPassword">确认密码</label>
<div class="password-group">
<input type="password" id="confirmPassword" name="confirmPassword" placeholder="请再次输入密码" required>
<button type="button" class="password-toggle" onclick="togglePassword('confirmPassword')">👁️</button>
</div>
<div class="validation-message" id="confirmPasswordError"></div>
</div>
<div class="terms-agree">
<input type="checkbox" id="agreeTerms" name="agreeTerms" required>
<label for="agreeTerms">
我已阅读并同意 <a href="#" onclick="showTerms(event)">服务条款</a><a href="#" onclick="showPrivacy(event)">隐私政策</a>
</label>
</div>
<button type="submit" class="register-btn">注册账号</button>
</form>
<div class="login-link">
已有账号?<a href="login.html">立即登录</a>
</div>
</div>
</div>
<script>
// 密码显示/隐藏切换
function togglePassword(inputId) {
const passwordInput = document.getElementById(inputId);
const toggleBtn = passwordInput.parentElement.querySelector('.password-toggle');
if (passwordInput.type === 'password') {
passwordInput.type = 'text';
toggleBtn.textContent = '🙈';
} else {
passwordInput.type = 'password';
toggleBtn.textContent = '👁️';
}
}
// 显示错误消息
function showError(message) {
const errorDiv = document.getElementById('errorMessage');
const successDiv = document.getElementById('successMessage');
errorDiv.textContent = message;
errorDiv.style.display = 'block';
successDiv.style.display = 'none';
// 3秒后自动隐藏
setTimeout(() => {
errorDiv.style.display = 'none';
}, 3000);
}
// 显示成功消息
function showSuccess(message) {
const errorDiv = document.getElementById('errorMessage');
const successDiv = document.getElementById('successMessage');
successDiv.textContent = message;
successDiv.style.display = 'block';
errorDiv.style.display = 'none';
// 3秒后自动隐藏
setTimeout(() => {
successDiv.style.display = 'none';
}, 3000);
}
// 显示字段验证错误
function showFieldError(fieldId, message) {
const group = document.getElementById(fieldId + 'Group');
const errorElement = document.getElementById(fieldId + 'Error');
group.classList.add('invalid');
errorElement.textContent = message;
errorElement.style.display = 'block';
}
// 清除字段验证错误
function clearFieldError(fieldId) {
const group = document.getElementById(fieldId + 'Group');
const errorElement = document.getElementById(fieldId + 'Error');
group.classList.remove('invalid');
errorElement.style.display = 'none';
}
// 验证用户名
function validateUsername(username) {
if (!username || username.trim().length === 0) {
showFieldError('username', '请输入用户名');
return false;
}
if (username.length < 3 || username.length > 20) {
showFieldError('username', '用户名长度必须在3-20个字符之间');
return false;
}
if (!/^[a-zA-Z0-9_]+$/.test(username)) {
showFieldError('username', '用户名只能包含字母、数字和下划线');
return false;
}
clearFieldError('username');
return true;
}
// 验证邮箱
function validateEmail(email) {
if (!email || email.trim().length === 0) {
showFieldError('email', '请输入邮箱地址');
return false;
}
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
if (!emailRegex.test(email)) {
showFieldError('email', '请输入有效的邮箱地址');
return false;
}
clearFieldError('email');
return true;
}
// 验证密码
function validatePassword(password) {
if (!password) {
showFieldError('password', '请设置密码');
return false;
}
if (password.length < 8) {
showFieldError('password', '密码长度不能少于8位');
return false;
}
if (!/^(?=.*[a-zA-Z])(?=.*[0-9])/.test(password)) {
showFieldError('password', '密码必须包含字母和数字');
return false;
}
clearFieldError('password');
return true;
}
// 验证确认密码
function validateConfirmPassword(confirmPassword) {
const password = document.getElementById('password').value;
if (!confirmPassword) {
showFieldError('confirmPassword', '请确认密码');
return false;
}
if (confirmPassword !== password) {
showFieldError('confirmPassword', '两次输入的密码不一致');
return false;
}
clearFieldError('confirmPassword');
return true;
}
// 添加实时验证
document.getElementById('username').addEventListener('input', function() {
validateUsername(this.value);
});
document.getElementById('email').addEventListener('input', function() {
validateEmail(this.value);
});
document.getElementById('password').addEventListener('input', function() {
validatePassword(this.value);
// 当密码改变时,验证确认密码
if (document.getElementById('confirmPassword').value) {
validateConfirmPassword(document.getElementById('confirmPassword').value);
}
});
document.getElementById('confirmPassword').addEventListener('input', function() {
validateConfirmPassword(this.value);
});
// 注册表单提交
document.getElementById('registerForm').addEventListener('submit', function(e) {
e.preventDefault();
const username = document.getElementById('username').value.trim();
const email = document.getElementById('email').value.trim();
const password = document.getElementById('password').value;
const confirmPassword = document.getElementById('confirmPassword').value;
const agreeTerms = document.getElementById('agreeTerms').checked;
// 验证所有字段
let isValid = true;
if (!validateUsername(username)) isValid = false;
if (!validateEmail(email)) isValid = false;
if (!validatePassword(password)) isValid = false;
if (!validateConfirmPassword(confirmPassword)) isValid = false;
if (!agreeTerms) {
showError('请阅读并同意服务条款和隐私政策');
isValid = false;
}
if (!isValid) {
return;
}
// 实际注册请求
const registerBtn = document.querySelector('.register-btn');
registerBtn.textContent = '注册中...';
registerBtn.disabled = true;
// 准备请求数据
const registerData = {
username: username,
email: email,
password: password
};
// 调用后端注册API
fetch('http://localhost:8000/api/user/register', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(registerData)
})
.then(response => {
if (!response.ok) {
throw new Error('网络响应异常');
}
return response.json();
})
.then(data => {
// 检查响应状态
if (data.code === 200) {
// 注册成功
showSuccess('注册成功!正在跳转到登录页面...');
// 延迟跳转到登录页
setTimeout(() => {
window.location.href = 'login.html';
}, 1500);
} else {
// 注册失败,显示错误信息
showError(data.msg || '注册失败,请稍后重试');
registerBtn.textContent = '注册账号';
registerBtn.disabled = false;
}
})
.catch(error => {
// 捕获网络或其他错误
console.error('注册请求失败:', error);
showError('注册失败,请稍后重试');
registerBtn.textContent = '注册账号';
registerBtn.disabled = false;
});
});
// 显示服务条款
function showTerms(e) {
e.preventDefault();
showError('服务条款功能开发中...');
}
// 显示隐私政策
function showPrivacy(e) {
e.preventDefault();
showError('隐私政策功能开发中...');
}
// Enter键提交表单
document.addEventListener('keypress', function(e) {
if (e.key === 'Enter') {
document.getElementById('registerForm').dispatchEvent(new Event('submit'));
}
});
</script>
</body>
</html>