继续更新
This commit is contained in:
@@ -2,42 +2,32 @@
|
||||
body {
|
||||
background: linear-gradient(
|
||||
135deg,
|
||||
#ff6b6b 0%,
|
||||
#4ecdc4 12.5%,
|
||||
#45b7d1 25%,
|
||||
#96ceb4 37.5%,
|
||||
#feca57 50%,
|
||||
#ff9ff3 62.5%,
|
||||
#54a0ff 75%,
|
||||
#5f27cd 87.5%,
|
||||
#00d2d3 100%
|
||||
#e8f5e8 0%,
|
||||
#f1f8e9 25%,
|
||||
#dcedc8 50%,
|
||||
#c8e6c8 75%,
|
||||
#e8f5e8 100%
|
||||
);
|
||||
background-size: 400% 400%;
|
||||
animation: rainbowGradient 15s ease infinite;
|
||||
background-size: 200% 200%;
|
||||
animation: gentleGradient 20s ease infinite;
|
||||
background-attachment: fixed;
|
||||
min-height: 100vh;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
@keyframes rainbowGradient {
|
||||
@keyframes gentleGradient {
|
||||
0% {
|
||||
background-position: 0% 50%;
|
||||
}
|
||||
25% {
|
||||
background-position: 100% 50%;
|
||||
}
|
||||
50% {
|
||||
background-position: 100% 100%;
|
||||
}
|
||||
75% {
|
||||
background-position: 0% 100%;
|
||||
background-position: 100% 50%;
|
||||
}
|
||||
100% {
|
||||
background-position: 0% 50%;
|
||||
}
|
||||
}
|
||||
|
||||
/* 彩虹装饰层 */
|
||||
/* 淡雅绿色装饰层 */
|
||||
body::before {
|
||||
content: '';
|
||||
position: fixed;
|
||||
@@ -46,17 +36,15 @@ body::before {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background:
|
||||
radial-gradient(circle at 20% 20%, rgba(255, 107, 107, 0.15) 0%, transparent 50%),
|
||||
radial-gradient(circle at 80% 80%, rgba(78, 205, 196, 0.15) 0%, transparent 50%),
|
||||
radial-gradient(circle at 40% 80%, rgba(69, 183, 209, 0.12) 0%, transparent 40%),
|
||||
radial-gradient(circle at 60% 20%, rgba(150, 206, 180, 0.12) 0%, transparent 40%),
|
||||
radial-gradient(circle at 80% 40%, rgba(254, 202, 87, 0.1) 0%, transparent 35%);
|
||||
radial-gradient(circle at 20% 20%, rgba(129, 199, 132, 0.08) 0%, transparent 50%),
|
||||
radial-gradient(circle at 80% 80%, rgba(165, 214, 167, 0.06) 0%, transparent 50%),
|
||||
radial-gradient(circle at 40% 80%, rgba(200, 230, 201, 0.05) 0%, transparent 40%),
|
||||
radial-gradient(circle at 60% 20%, rgba(220, 237, 200, 0.04) 0%, transparent 40%);
|
||||
pointer-events: none;
|
||||
z-index: -1;
|
||||
animation: float 20s ease-in-out infinite alternate;
|
||||
}
|
||||
|
||||
/* 彩虹粒子效果 */
|
||||
/* 淡雅绿色点缀 */
|
||||
body::after {
|
||||
content: '';
|
||||
position: fixed;
|
||||
@@ -65,42 +53,13 @@ body::after {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-image:
|
||||
radial-gradient(circle at 10% 10%, rgba(255, 107, 107, 0.8) 2px, transparent 2px),
|
||||
radial-gradient(circle at 30% 20%, rgba(78, 205, 196, 0.8) 1.5px, transparent 1.5px),
|
||||
radial-gradient(circle at 50% 30%, rgba(69, 183, 209, 0.8) 1px, transparent 1px),
|
||||
radial-gradient(circle at 70% 40%, rgba(150, 206, 180, 0.8) 2px, transparent 2px),
|
||||
radial-gradient(circle at 90% 50%, rgba(254, 202, 87, 0.8) 1.5px, transparent 1.5px),
|
||||
radial-gradient(circle at 20% 60%, rgba(255, 159, 243, 0.8) 1px, transparent 1px),
|
||||
radial-gradient(circle at 40% 70%, rgba(84, 160, 255, 0.8) 2px, transparent 2px),
|
||||
radial-gradient(circle at 60% 80%, rgba(95, 39, 205, 0.8) 1.5px, transparent 1.5px),
|
||||
radial-gradient(circle at 80% 90%, rgba(0, 210, 211, 0.8) 1px, transparent 1px);
|
||||
background-size: 200px 200px, 250px 250px, 180px 180px, 300px 300px, 220px 220px, 160px 160px, 280px 280px, 240px 240px, 200px 200px;
|
||||
animation: sparkle 25s linear infinite;
|
||||
radial-gradient(circle at 15% 15%, rgba(129, 199, 132, 0.3) 1px, transparent 1px),
|
||||
radial-gradient(circle at 45% 25%, rgba(165, 214, 167, 0.25) 1px, transparent 1px),
|
||||
radial-gradient(circle at 75% 35%, rgba(200, 230, 201, 0.2) 1px, transparent 1px),
|
||||
radial-gradient(circle at 25% 65%, rgba(220, 237, 200, 0.15) 1px, transparent 1px),
|
||||
radial-gradient(circle at 85% 75%, rgba(129, 199, 132, 0.2) 1px, transparent 1px);
|
||||
background-size: 300px 300px, 400px 400px, 350px 350px, 450px 450px, 380px 380px;
|
||||
pointer-events: none;
|
||||
z-index: -1;
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
@keyframes float {
|
||||
0% {
|
||||
transform: translateY(0px) rotate(0deg);
|
||||
}
|
||||
100% {
|
||||
transform: translateY(-15px) rotate(2deg);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes sparkle {
|
||||
0%, 100% {
|
||||
transform: translateX(0) translateY(0) scale(1);
|
||||
}
|
||||
25% {
|
||||
transform: translateX(-10px) translateY(-5px) scale(1.1);
|
||||
}
|
||||
50% {
|
||||
transform: translateX(10px) translateY(-10px) scale(0.9);
|
||||
}
|
||||
75% {
|
||||
transform: translateX(-5px) translateY(-15px) scale(1.05);
|
||||
}
|
||||
opacity: 0.4;
|
||||
}
|
||||
|
||||
@@ -18,11 +18,11 @@
|
||||
height: 200%;
|
||||
background: linear-gradient(
|
||||
135deg,
|
||||
rgba(64, 169, 255, 0.4) 0%,
|
||||
rgba(120, 192, 255, 0.3) 25%,
|
||||
rgba(255, 175, 64, 0.2) 50%,
|
||||
rgba(255, 140, 50, 0.3) 75%,
|
||||
rgba(255, 122, 69, 0.4) 100%
|
||||
rgba(129, 199, 132, 0.4) 0%,
|
||||
rgba(165, 214, 167, 0.3) 25%,
|
||||
rgba(200, 230, 201, 0.2) 50%,
|
||||
rgba(220, 237, 200, 0.3) 75%,
|
||||
rgba(232, 245, 233, 0.4) 100%
|
||||
);
|
||||
animation: gradient-flow 20s ease-in-out infinite;
|
||||
border-radius: 30% 70% 70% 30% / 30% 30% 70% 70%;
|
||||
@@ -37,11 +37,11 @@
|
||||
height: 100%;
|
||||
background: radial-gradient(
|
||||
circle at 30% 70%,
|
||||
rgba(64, 169, 255, 0.5) 0%,
|
||||
rgba(129, 199, 132, 0.5) 0%,
|
||||
transparent 50%
|
||||
), radial-gradient(
|
||||
circle at 70% 30%,
|
||||
rgba(255, 140, 50, 0.4) 0%,
|
||||
rgba(165, 214, 167, 0.4) 0%,
|
||||
transparent 50%
|
||||
);
|
||||
animation: pulse-effect 15s ease-in-out infinite alternate;
|
||||
@@ -123,7 +123,7 @@ header, .header {
|
||||
}
|
||||
|
||||
header h1, .title {
|
||||
background: linear-gradient(135deg, #4096ff, #ff7a45);
|
||||
background: linear-gradient(135deg, #66bb6a, #81c784);
|
||||
-webkit-background-clip: text;
|
||||
background-clip: text;
|
||||
color: transparent;
|
||||
@@ -170,9 +170,9 @@ header h1, .title {
|
||||
}
|
||||
|
||||
.tab-btn.active {
|
||||
background: linear-gradient(135deg, #4096ff, #40a9ff);
|
||||
background: linear-gradient(135deg, #66bb6a, #81c784);
|
||||
color: white;
|
||||
box-shadow: 0 4px 16px rgba(64, 150, 255, 0.3);
|
||||
box-shadow: 0 4px 16px rgba(102, 187, 106, 0.3);
|
||||
}
|
||||
|
||||
.tab-icon {
|
||||
@@ -180,7 +180,7 @@ header h1, .title {
|
||||
}
|
||||
|
||||
.refresh-btn {
|
||||
background: linear-gradient(135deg, #52c41a, #73d13d);
|
||||
background: linear-gradient(135deg, #81c784, #a5d6a7);
|
||||
border: none;
|
||||
padding: 12px 24px;
|
||||
border-radius: 25px;
|
||||
@@ -193,12 +193,12 @@ header h1, .title {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
box-shadow: 0 4px 12px rgba(82, 196, 26, 0.3);
|
||||
box-shadow: 0 4px 12px rgba(129, 199, 132, 0.3);
|
||||
}
|
||||
|
||||
.refresh-btn:hover {
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 6px 16px rgba(82, 196, 26, 0.4);
|
||||
box-shadow: 0 6px 16px rgba(129, 199, 132, 0.4);
|
||||
}
|
||||
|
||||
.btn-icon {
|
||||
@@ -238,17 +238,17 @@ header h1, .title {
|
||||
.hot-item:hover {
|
||||
transform: translateY(-3px);
|
||||
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.08);
|
||||
border-color: rgba(64, 169, 255, 0.3);
|
||||
border-color: rgba(129, 199, 132, 0.3);
|
||||
}
|
||||
|
||||
.hot-rank {
|
||||
font-size: 1.2rem;
|
||||
font-weight: bold;
|
||||
color: #4096ff;
|
||||
color: #66bb6a;
|
||||
margin-right: 18px;
|
||||
min-width: 38px;
|
||||
text-align: center;
|
||||
background-color: rgba(64, 169, 255, 0.1);
|
||||
background-color: rgba(129, 199, 132, 0.1);
|
||||
border-radius: 50%;
|
||||
width: 38px;
|
||||
height: 38px;
|
||||
@@ -258,18 +258,18 @@ header h1, .title {
|
||||
}
|
||||
|
||||
.hot-rank.top-1 {
|
||||
background: linear-gradient(135deg, #ff4d4f, #ff7a45);
|
||||
background: linear-gradient(135deg, #66bb6a, #81c784);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.hot-rank.top-2 {
|
||||
background: linear-gradient(135deg, #ff7a45, #ffa940);
|
||||
background: linear-gradient(135deg, #81c784, #a5d6a7);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.hot-rank.top-3 {
|
||||
background: linear-gradient(135deg, #ffa940, #ffec3d);
|
||||
color: white;
|
||||
background: linear-gradient(135deg, #a5d6a7, #c8e6c9);
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.hot-content {
|
||||
@@ -288,7 +288,7 @@ header h1, .title {
|
||||
}
|
||||
|
||||
.hot-title:hover {
|
||||
color: #4096ff;
|
||||
color: #66bb6a;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
@@ -310,13 +310,10 @@ header h1, .title {
|
||||
.rainbow-spinner {
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
border: 4px solid transparent;
|
||||
border-top: 4px solid #4096ff;
|
||||
border: 4px solid rgba(129, 199, 132, 0.2);
|
||||
border-top: 4px solid #81c784;
|
||||
border-radius: 50%;
|
||||
animation: spin 1s linear infinite;
|
||||
background: linear-gradient(45deg, #ff6b6b, #4ecdc4, #45b7d1, #96ceb4, #feca57, #ff9ff3, #54a0ff, #5f27cd);
|
||||
background-size: 400% 400%;
|
||||
animation: spin 1s linear infinite, rainbowGradient 3s ease infinite;
|
||||
}
|
||||
|
||||
@keyframes spin {
|
||||
@@ -356,7 +353,7 @@ header h1, .title {
|
||||
.loading-dots span {
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
background: #4096ff;
|
||||
background: #81c784;
|
||||
border-radius: 50%;
|
||||
animation: loadingDots 1.4s ease-in-out infinite both;
|
||||
}
|
||||
@@ -396,7 +393,7 @@ header h1, .title {
|
||||
.news-item:hover {
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 6px 20px rgba(0, 0, 0, 0.1);
|
||||
border-color: rgba(64, 169, 255, 0.2);
|
||||
border-color: rgba(129, 199, 132, 0.3);
|
||||
}
|
||||
|
||||
/* 排名容器 */
|
||||
@@ -423,21 +420,21 @@ header h1, .title {
|
||||
}
|
||||
|
||||
.news-rank.rank-1 {
|
||||
background: linear-gradient(135deg, #ff4d4f, #ff7a45);
|
||||
background: linear-gradient(135deg, #66bb6a, #81c784);
|
||||
color: white;
|
||||
box-shadow: 0 4px 12px rgba(255, 77, 79, 0.3);
|
||||
box-shadow: 0 4px 12px rgba(102, 187, 106, 0.3);
|
||||
}
|
||||
|
||||
.news-rank.rank-2 {
|
||||
background: linear-gradient(135deg, #ff7a45, #ffa940);
|
||||
background: linear-gradient(135deg, #81c784, #a5d6a7);
|
||||
color: white;
|
||||
box-shadow: 0 4px 12px rgba(255, 122, 69, 0.3);
|
||||
box-shadow: 0 4px 12px rgba(129, 199, 132, 0.3);
|
||||
}
|
||||
|
||||
.news-rank.rank-3 {
|
||||
background: linear-gradient(135deg, #ffa940, #ffec3d);
|
||||
background: linear-gradient(135deg, #a5d6a7, #c8e6c9);
|
||||
color: #333;
|
||||
box-shadow: 0 4px 12px rgba(255, 169, 64, 0.3);
|
||||
box-shadow: 0 4px 12px rgba(165, 214, 167, 0.3);
|
||||
}
|
||||
|
||||
.rank-number {
|
||||
@@ -478,7 +475,7 @@ header h1, .title {
|
||||
}
|
||||
|
||||
.news-title:hover {
|
||||
color: #4096ff;
|
||||
color: #66bb6a;
|
||||
}
|
||||
|
||||
/* 元信息行 */
|
||||
@@ -524,7 +521,7 @@ header h1, .title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
background: linear-gradient(135deg, #ff6b6b, #4ecdc4);
|
||||
background: linear-gradient(135deg, #81c784, #a5d6a7);
|
||||
color: white;
|
||||
padding: 4px 10px;
|
||||
border-radius: 12px;
|
||||
@@ -545,7 +542,7 @@ header h1, .title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
background: linear-gradient(135deg, #4096ff, #40a9ff);
|
||||
background: linear-gradient(135deg, #66bb6a, #81c784);
|
||||
color: white;
|
||||
text-decoration: none;
|
||||
padding: 6px 12px;
|
||||
@@ -553,13 +550,13 @@ header h1, .title {
|
||||
font-size: 0.75rem;
|
||||
font-weight: 600;
|
||||
transition: all 0.3s ease;
|
||||
box-shadow: 0 2px 6px rgba(64, 150, 255, 0.3);
|
||||
box-shadow: 0 2px 6px rgba(102, 187, 106, 0.3);
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.news-link:hover {
|
||||
transform: translateY(-1px);
|
||||
box-shadow: 0 4px 10px rgba(64, 150, 255, 0.4);
|
||||
box-shadow: 0 4px 10px rgba(102, 187, 106, 0.4);
|
||||
text-decoration: none;
|
||||
color: white;
|
||||
}
|
||||
@@ -592,7 +589,7 @@ header h1, .title {
|
||||
}
|
||||
|
||||
.error-content h3 {
|
||||
color: #ff4d4f;
|
||||
color: #66bb6a;
|
||||
margin: 0;
|
||||
font-size: 1.3rem;
|
||||
}
|
||||
@@ -604,7 +601,7 @@ header h1, .title {
|
||||
}
|
||||
|
||||
.retry-btn {
|
||||
background: linear-gradient(135deg, #ff4d4f, #ff7a45);
|
||||
background: linear-gradient(135deg, #66bb6a, #81c784);
|
||||
border: none;
|
||||
padding: 12px 24px;
|
||||
border-radius: 25px;
|
||||
@@ -616,12 +613,12 @@ header h1, .title {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
box-shadow: 0 4px 12px rgba(255, 77, 79, 0.3);
|
||||
box-shadow: 0 4px 12px rgba(102, 187, 106, 0.3);
|
||||
}
|
||||
|
||||
.retry-btn:hover {
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 6px 16px rgba(255, 77, 79, 0.4);
|
||||
box-shadow: 0 6px 16px rgba(102, 187, 106, 0.4);
|
||||
}
|
||||
|
||||
footer {
|
||||
@@ -855,9 +852,9 @@ footer {
|
||||
.modern-gradient {
|
||||
background: linear-gradient(
|
||||
135deg,
|
||||
rgba(64, 169, 255, 0.3) 0%,
|
||||
rgba(255, 175, 64, 0.2) 50%,
|
||||
rgba(255, 122, 69, 0.25) 100%
|
||||
rgba(129, 199, 132, 0.3) 0%,
|
||||
rgba(200, 230, 201, 0.2) 50%,
|
||||
rgba(232, 245, 233, 0.25) 100%
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -3,39 +3,33 @@
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>🔥 HackerNews 热门榜单</title>
|
||||
<title>HackerNews 热门榜单</title>
|
||||
<link rel="stylesheet" href="css/background.css">
|
||||
<link rel="stylesheet" href="css/style.css">
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<header class="header">
|
||||
<div class="header-icon">🌈</div>
|
||||
<h1 class="title">🔥 HackerNews 热门榜单 💻</h1>
|
||||
<h1 class="title">HackerNews 热门榜单</h1>
|
||||
<p class="subtitle">全球技术社区 · 实时热门话题</p>
|
||||
|
||||
<div class="tab-container">
|
||||
<button class="tab-btn active" data-type="top">
|
||||
<span class="tab-icon">🏆</span>
|
||||
热门榜
|
||||
</button>
|
||||
<button class="tab-btn" data-type="new">
|
||||
<span class="tab-icon">🆕</span>
|
||||
最新榜
|
||||
</button>
|
||||
<button class="tab-btn" data-type="best">
|
||||
<span class="tab-icon">⭐</span>
|
||||
最佳榜
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="update-time">
|
||||
<span class="time-icon">⏰</span>
|
||||
<span id="updateTime">加载中...</span>
|
||||
</div>
|
||||
|
||||
<button id="refreshBtn" class="refresh-btn">
|
||||
<span class="btn-icon">🔄</span>
|
||||
刷新数据
|
||||
</button>
|
||||
</header>
|
||||
@@ -44,7 +38,6 @@
|
||||
<div class="loading-content">
|
||||
<div class="rainbow-spinner"></div>
|
||||
<div class="loading-text">
|
||||
<span class="loading-emoji">🚀</span>
|
||||
<p>正在获取最新榜单...</p>
|
||||
<div class="loading-dots">
|
||||
<span></span>
|
||||
@@ -61,11 +54,9 @@
|
||||
|
||||
<div class="error-message" id="errorMessage" style="display: none;">
|
||||
<div class="error-content">
|
||||
<div class="error-icon">💥</div>
|
||||
<h3>加载失败了</h3>
|
||||
<p>网络连接出现问题,请稍后重试</p>
|
||||
<button onclick="loadNewsList()" class="retry-btn">
|
||||
<span>🔄</span>
|
||||
重新加载
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@@ -118,35 +118,26 @@ function createNewsItem(item, rank) {
|
||||
const formattedScore = formatScore(item.score);
|
||||
const formattedTime = formatTime(item.created);
|
||||
|
||||
// 根据排名添加特殊标识
|
||||
let rankEmoji = '';
|
||||
if (rank === 1) rankEmoji = '🏆';
|
||||
else if (rank === 2) rankEmoji = '🥈';
|
||||
else if (rank === 3) rankEmoji = '🥉';
|
||||
|
||||
// 根据评分添加热度指示
|
||||
let heatLevel = '';
|
||||
if (item.score >= 1000) heatLevel = '🔥🔥🔥';
|
||||
else if (item.score >= 500) heatLevel = '🔥🔥';
|
||||
else if (item.score >= 100) heatLevel = '🔥';
|
||||
else heatLevel = '💫';
|
||||
if (item.score >= 1000) heatLevel = 'HOT';
|
||||
else if (item.score >= 500) heatLevel = 'WARM';
|
||||
else if (item.score >= 100) heatLevel = 'COOL';
|
||||
else heatLevel = 'NEW';
|
||||
|
||||
newsItem.innerHTML = `
|
||||
<div class="news-rank-container">
|
||||
<div class="${rankClass}">
|
||||
<span class="rank-number">${rank}</span>
|
||||
<span class="rank-emoji">${rankEmoji}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="news-content-wrapper">
|
||||
<h3 class="news-title">${escapeHtml(item.title)}</h3>
|
||||
<div class="news-meta-row">
|
||||
<div class="news-author">
|
||||
<span class="meta-icon">👤</span>
|
||||
<span class="meta-text">${escapeHtml(item.author)}</span>
|
||||
</div>
|
||||
<div class="news-time">
|
||||
<span class="meta-icon">🕒</span>
|
||||
<span class="meta-text">${formattedTime}</span>
|
||||
</div>
|
||||
</div>
|
||||
@@ -156,7 +147,6 @@ function createNewsItem(item, rank) {
|
||||
<span class="score-text">${formattedScore} 分</span>
|
||||
</div>
|
||||
<a href="${item.link}" target="_blank" class="news-link">
|
||||
<span class="link-icon">🚀</span>
|
||||
<span class="link-text">阅读全文</span>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
@@ -16,11 +16,11 @@
|
||||
height: 200%;
|
||||
background: linear-gradient(
|
||||
135deg,
|
||||
rgba(240, 20, 20, 0.3) 0%,
|
||||
rgba(255, 60, 60, 0.2) 25%,
|
||||
rgba(255, 100, 100, 0.1) 50%,
|
||||
rgba(255, 150, 150, 0.2) 75%,
|
||||
rgba(240, 20, 20, 0.3) 100%
|
||||
rgba(168, 230, 207, 0.3) 0%,
|
||||
rgba(220, 237, 193, 0.2) 25%,
|
||||
rgba(200, 245, 200, 0.1) 50%,
|
||||
rgba(180, 235, 180, 0.2) 75%,
|
||||
rgba(168, 230, 207, 0.3) 100%
|
||||
);
|
||||
animation: green-flow 20s ease-in-out infinite;
|
||||
}
|
||||
@@ -34,11 +34,11 @@
|
||||
height: 100%;
|
||||
background: radial-gradient(
|
||||
circle at 30% 70%,
|
||||
rgba(255, 45, 45, 0.4) 0%,
|
||||
rgba(129, 199, 132, 0.3) 0%,
|
||||
transparent 50%
|
||||
), radial-gradient(
|
||||
circle at 70% 30%,
|
||||
rgba(255, 100, 100, 0.3) 0%,
|
||||
rgba(165, 214, 167, 0.25) 0%,
|
||||
transparent 50%
|
||||
);
|
||||
animation: green-pulse 15s ease-in-out infinite alternate;
|
||||
|
||||
@@ -18,11 +18,11 @@
|
||||
height: 200%;
|
||||
background: linear-gradient(
|
||||
135deg,
|
||||
rgba(64, 169, 255, 0.4) 0%,
|
||||
rgba(120, 192, 255, 0.3) 25%,
|
||||
rgba(255, 175, 64, 0.2) 50%,
|
||||
rgba(255, 140, 50, 0.3) 75%,
|
||||
rgba(255, 122, 69, 0.4) 100%
|
||||
rgba(168, 230, 207, 0.3) 0%,
|
||||
rgba(220, 237, 193, 0.25) 25%,
|
||||
rgba(200, 245, 200, 0.15) 50%,
|
||||
rgba(180, 235, 180, 0.25) 75%,
|
||||
rgba(168, 230, 207, 0.3) 100%
|
||||
);
|
||||
animation: gradient-flow 20s ease-in-out infinite;
|
||||
border-radius: 30% 70% 70% 30% / 30% 30% 70% 70%;
|
||||
@@ -37,11 +37,11 @@
|
||||
height: 100%;
|
||||
background: radial-gradient(
|
||||
circle at 30% 70%,
|
||||
rgba(64, 169, 255, 0.5) 0%,
|
||||
rgba(129, 199, 132, 0.4) 0%,
|
||||
transparent 50%
|
||||
), radial-gradient(
|
||||
circle at 70% 30%,
|
||||
rgba(255, 140, 50, 0.4) 0%,
|
||||
rgba(165, 214, 167, 0.3) 0%,
|
||||
transparent 50%
|
||||
);
|
||||
animation: pulse-effect 15s ease-in-out infinite alternate;
|
||||
@@ -106,13 +106,13 @@ body {
|
||||
}
|
||||
|
||||
.geometric-decoration {
|
||||
font-size: 20px;
|
||||
color: #f04040;
|
||||
margin: 0 15px;
|
||||
font-weight: bold;
|
||||
letter-spacing: 5px;
|
||||
text-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
||||
animation: float-effect 3s ease-in-out infinite alternate;
|
||||
font-size: 16px;
|
||||
color: #81c784;
|
||||
margin: 0 10px;
|
||||
font-weight: normal;
|
||||
letter-spacing: 3px;
|
||||
text-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
.geometric-decoration.left {
|
||||
@@ -140,10 +140,13 @@ body {
|
||||
}
|
||||
|
||||
.time-decoration {
|
||||
color: #f04040;
|
||||
font-size: 18px;
|
||||
margin: 0 10px;
|
||||
animation: pulse 2s infinite;
|
||||
font-size: 14px;
|
||||
color: #a5d6a7;
|
||||
margin: 0 8px;
|
||||
font-weight: normal;
|
||||
letter-spacing: 2px;
|
||||
text-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
@keyframes pulse {
|
||||
@@ -163,11 +166,11 @@ body {
|
||||
|
||||
.geometric-header, .geometric-footer {
|
||||
text-align: center;
|
||||
color: #f04040;
|
||||
margin: 15px 0;
|
||||
font-size: 16px;
|
||||
letter-spacing: 3px;
|
||||
opacity: 0.8;
|
||||
color: #a5d6a7;
|
||||
margin: 10px 0;
|
||||
font-size: 14px;
|
||||
letter-spacing: 2px;
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
.geometric-header {
|
||||
@@ -188,7 +191,7 @@ body {
|
||||
border-radius: 16px;
|
||||
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.08);
|
||||
backdrop-filter: blur(10px);
|
||||
border: 2px solid rgba(240, 64, 64, 0.3);
|
||||
border: 1px solid rgba(129, 199, 132, 0.2);
|
||||
position: relative;
|
||||
}
|
||||
|
||||
@@ -198,7 +201,7 @@ body {
|
||||
position: absolute;
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
border-color: #f04040;
|
||||
border-color: #a5d6a7;
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
@@ -226,7 +229,7 @@ header {
|
||||
}
|
||||
|
||||
header h1 {
|
||||
background: linear-gradient(135deg, #4096ff, #ff7a45);
|
||||
background: linear-gradient(135deg, #66bb6a, #81c784);
|
||||
-webkit-background-clip: text;
|
||||
background-clip: text;
|
||||
color: transparent;
|
||||
@@ -245,7 +248,7 @@ header h1 {
|
||||
display: inline-block;
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.04);
|
||||
position: relative;
|
||||
border: 1px dashed rgba(240, 64, 64, 0.3);
|
||||
border: 1px dashed rgba(129, 199, 132, 0.3);
|
||||
}
|
||||
|
||||
.update-time::before {
|
||||
@@ -255,7 +258,7 @@ header h1 {
|
||||
left: -5px;
|
||||
right: -5px;
|
||||
bottom: -5px;
|
||||
border: 1px solid rgba(240, 64, 64, 0.3);
|
||||
border: 1px solid rgba(129, 199, 132, 0.3);
|
||||
border-radius: 28px;
|
||||
animation: pulse-border 2s infinite;
|
||||
pointer-events: none;
|
||||
@@ -299,9 +302,9 @@ header h1 {
|
||||
position: absolute;
|
||||
top: 5px;
|
||||
right: 10px;
|
||||
color: #f04040;
|
||||
opacity: 0.2;
|
||||
font-size: 14px;
|
||||
color: #a5d6a7;
|
||||
opacity: 0.15;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.hot-item::after {
|
||||
@@ -309,32 +312,33 @@ header h1 {
|
||||
position: absolute;
|
||||
bottom: 5px;
|
||||
left: 10px;
|
||||
color: #f04040;
|
||||
opacity: 0.2;
|
||||
font-size: 14px;
|
||||
color: #a5d6a7;
|
||||
opacity: 0.15;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.even-item {
|
||||
border-left: 3px solid #f04040;
|
||||
border-left: 2px solid #81c784;
|
||||
}
|
||||
|
||||
.odd-item {
|
||||
border-right: 3px solid #f04040;
|
||||
border-right: 2px solid #81c784;
|
||||
}
|
||||
|
||||
.title-decoration {
|
||||
color: #f04040;
|
||||
font-weight: bold;
|
||||
color: #81c784;
|
||||
font-weight: normal;
|
||||
margin-right: 5px;
|
||||
display: inline-block;
|
||||
transform: translateY(1px);
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
.source-icon, .time-icon {
|
||||
color: #f04040;
|
||||
color: #81c784;
|
||||
font-size: 14px;
|
||||
margin-right: 3px;
|
||||
opacity: 0.8;
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
.hot-title {
|
||||
@@ -353,17 +357,17 @@ header h1 {
|
||||
.hot-item:hover {
|
||||
transform: translateY(-3px);
|
||||
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.08);
|
||||
border-color: rgba(64, 169, 255, 0.3);
|
||||
border-color: rgba(129, 199, 132, 0.4);
|
||||
}
|
||||
|
||||
.hot-rank {
|
||||
font-size: 1.2rem;
|
||||
font-weight: bold;
|
||||
color: #4096ff;
|
||||
color: #66bb6a;
|
||||
margin-right: 18px;
|
||||
min-width: 38px;
|
||||
text-align: center;
|
||||
background-color: rgba(64, 169, 255, 0.1);
|
||||
background-color: rgba(129, 199, 132, 0.1);
|
||||
border-radius: 50%;
|
||||
width: 38px;
|
||||
height: 38px;
|
||||
@@ -373,17 +377,17 @@ header h1 {
|
||||
}
|
||||
|
||||
.hot-rank.top-1 {
|
||||
background: linear-gradient(135deg, #ff4d4f, #ff7a45);
|
||||
background: linear-gradient(135deg, #4caf50, #66bb6a);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.hot-rank.top-2 {
|
||||
background: linear-gradient(135deg, #ff7a45, #ffa940);
|
||||
background: linear-gradient(135deg, #66bb6a, #81c784);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.hot-rank.top-3 {
|
||||
background: linear-gradient(135deg, #ffa940, #ffec3d);
|
||||
background: linear-gradient(135deg, #81c784, #a5d6a7);
|
||||
color: white;
|
||||
}
|
||||
|
||||
@@ -403,7 +407,7 @@ header h1 {
|
||||
}
|
||||
|
||||
.hot-title:hover {
|
||||
color: #4096ff;
|
||||
color: #66bb6a;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
@@ -431,11 +435,10 @@ footer {
|
||||
}
|
||||
|
||||
.geo-symbol {
|
||||
color: #f04040;
|
||||
font-size: 16px;
|
||||
opacity: 0.7;
|
||||
color: #a5d6a7;
|
||||
font-size: 14px;
|
||||
opacity: 0.5;
|
||||
transition: all 0.3s ease;
|
||||
animation: color-shift 5s infinite alternate;
|
||||
}
|
||||
|
||||
.geo-symbol:hover {
|
||||
@@ -443,17 +446,7 @@ footer {
|
||||
transform: scale(1.2) rotate(15deg);
|
||||
}
|
||||
|
||||
@keyframes color-shift {
|
||||
0% {
|
||||
color: #f04040;
|
||||
}
|
||||
50% {
|
||||
color: #ff7a45;
|
||||
}
|
||||
100% {
|
||||
color: #ff4d4f;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* 响应式设计 */
|
||||
@media (max-width: 1024px) and (min-width: 768px) {
|
||||
@@ -570,9 +563,9 @@ footer {
|
||||
.modern-gradient {
|
||||
background: linear-gradient(
|
||||
135deg,
|
||||
rgba(64, 169, 255, 0.3) 0%,
|
||||
rgba(255, 175, 64, 0.2) 50%,
|
||||
rgba(255, 122, 69, 0.25) 100%
|
||||
rgba(168, 230, 207, 0.25) 0%,
|
||||
rgba(200, 245, 200, 0.15) 50%,
|
||||
rgba(180, 235, 180, 0.2) 100%
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,12 +1,12 @@
|
||||
/* 背景相关样式 */
|
||||
body {
|
||||
background: linear-gradient(135deg, #e8f5e8 0%, #c8e6c9 25%, #a5d6a7 50%, #81c784 75%, #66bb6a 100%);
|
||||
background: linear-gradient(135deg, #f1f8e9 0%, #dcedc8 25%, #c8e6c9 50%, #a8e6cf 75%, #81c784 100%);
|
||||
background-attachment: fixed;
|
||||
min-height: 100vh;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
/* 背景装饰元素 */
|
||||
/* 简化的背景装饰元素 */
|
||||
body::before {
|
||||
content: '';
|
||||
position: fixed;
|
||||
@@ -15,15 +15,13 @@ body::before {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-image:
|
||||
radial-gradient(circle at 20% 80%, rgba(120, 200, 120, 0.15) 0%, transparent 50%),
|
||||
radial-gradient(circle at 80% 20%, rgba(100, 180, 100, 0.15) 0%, transparent 50%),
|
||||
radial-gradient(circle at 40% 40%, rgba(140, 220, 140, 0.1) 0%, transparent 50%),
|
||||
radial-gradient(circle at 60% 70%, rgba(160, 240, 160, 0.08) 0%, transparent 40%);
|
||||
radial-gradient(circle at 20% 80%, rgba(76, 175, 80, 0.08) 0%, transparent 40%),
|
||||
radial-gradient(circle at 80% 20%, rgba(129, 199, 132, 0.06) 0%, transparent 40%);
|
||||
pointer-events: none;
|
||||
z-index: -1;
|
||||
}
|
||||
|
||||
/* 浮动装饰圆点 */
|
||||
/* 简化的浮动装饰 */
|
||||
body::after {
|
||||
content: '';
|
||||
position: fixed;
|
||||
@@ -32,12 +30,10 @@ body::after {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-image:
|
||||
radial-gradient(circle at 10% 10%, rgba(76, 175, 80, 0.1) 2px, transparent 2px),
|
||||
radial-gradient(circle at 90% 90%, rgba(76, 175, 80, 0.08) 1px, transparent 1px),
|
||||
radial-gradient(circle at 30% 80%, rgba(76, 175, 80, 0.06) 1.5px, transparent 1.5px),
|
||||
radial-gradient(circle at 70% 20%, rgba(76, 175, 80, 0.05) 1px, transparent 1px);
|
||||
background-size: 100px 100px, 150px 150px, 80px 80px, 120px 120px;
|
||||
animation: float 20s ease-in-out infinite alternate;
|
||||
radial-gradient(circle at 30% 70%, rgba(76, 175, 80, 0.04) 1px, transparent 1px),
|
||||
radial-gradient(circle at 70% 30%, rgba(129, 199, 132, 0.03) 1px, transparent 1px);
|
||||
background-size: 120px 120px, 180px 180px;
|
||||
animation: float 25s ease-in-out infinite alternate;
|
||||
pointer-events: none;
|
||||
z-index: -1;
|
||||
}
|
||||
|
||||
@@ -18,14 +18,14 @@
|
||||
height: 200%;
|
||||
background: linear-gradient(
|
||||
135deg,
|
||||
rgba(64, 169, 255, 0.4) 0%,
|
||||
rgba(120, 192, 255, 0.3) 25%,
|
||||
rgba(255, 175, 64, 0.2) 50%,
|
||||
rgba(255, 140, 50, 0.3) 75%,
|
||||
rgba(255, 122, 69, 0.4) 100%
|
||||
rgba(76, 175, 80, 0.15) 0%,
|
||||
rgba(129, 199, 132, 0.1) 25%,
|
||||
rgba(165, 214, 167, 0.08) 50%,
|
||||
rgba(200, 230, 201, 0.06) 75%,
|
||||
rgba(232, 245, 233, 0.05) 100%
|
||||
);
|
||||
animation: gradient-flow 20s ease-in-out infinite;
|
||||
border-radius: 30% 70% 70% 30% / 30% 30% 70% 70%;
|
||||
animation: gradient-flow 30s ease-in-out infinite;
|
||||
border-radius: 40% 60% 60% 40% / 40% 40% 60% 60%;
|
||||
}
|
||||
|
||||
.modern-gradient::before {
|
||||
@@ -37,15 +37,15 @@
|
||||
height: 100%;
|
||||
background: radial-gradient(
|
||||
circle at 30% 70%,
|
||||
rgba(64, 169, 255, 0.5) 0%,
|
||||
transparent 50%
|
||||
rgba(76, 175, 80, 0.1) 0%,
|
||||
transparent 40%
|
||||
), radial-gradient(
|
||||
circle at 70% 30%,
|
||||
rgba(255, 140, 50, 0.4) 0%,
|
||||
transparent 50%
|
||||
rgba(129, 199, 132, 0.08) 0%,
|
||||
transparent 40%
|
||||
);
|
||||
animation: pulse-effect 15s ease-in-out infinite alternate;
|
||||
border-radius: 30% 70% 70% 30% / 30% 30% 70% 70%;
|
||||
animation: pulse-effect 25s ease-in-out infinite alternate;
|
||||
border-radius: 40% 60% 60% 40% / 40% 40% 60% 60%;
|
||||
}
|
||||
|
||||
@keyframes gradient-flow {
|
||||
@@ -103,21 +103,22 @@ body {
|
||||
padding: 24px;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
background-color: rgba(255, 255, 255, 0.85);
|
||||
background-color: rgba(255, 255, 255, 0.9);
|
||||
border-radius: 16px;
|
||||
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.08);
|
||||
backdrop-filter: blur(10px);
|
||||
box-shadow: 0 8px 24px rgba(76, 175, 80, 0.08);
|
||||
backdrop-filter: blur(12px);
|
||||
border: 1px solid rgba(76, 175, 80, 0.1);
|
||||
}
|
||||
|
||||
header {
|
||||
text-align: center;
|
||||
margin-bottom: 28px;
|
||||
padding-bottom: 20px;
|
||||
border-bottom: 1px solid rgba(0, 0, 0, 0.06);
|
||||
border-bottom: 1px solid rgba(76, 175, 80, 0.15);
|
||||
}
|
||||
|
||||
header h1 {
|
||||
background: linear-gradient(135deg, #4096ff, #ff7a45);
|
||||
background: linear-gradient(135deg, #2e7d32, #4caf50, #66bb6a);
|
||||
-webkit-background-clip: text;
|
||||
background-clip: text;
|
||||
color: transparent;
|
||||
@@ -128,13 +129,56 @@ header h1 {
|
||||
}
|
||||
|
||||
.update-time {
|
||||
color: #666;
|
||||
color: #4caf50;
|
||||
font-size: 0.9rem;
|
||||
background-color: rgba(0, 0, 0, 0.03);
|
||||
background-color: rgba(76, 175, 80, 0.08);
|
||||
padding: 8px 16px;
|
||||
border-radius: 24px;
|
||||
display: inline-block;
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.04);
|
||||
box-shadow: 0 2px 8px rgba(76, 175, 80, 0.1);
|
||||
border: 1px solid rgba(76, 175, 80, 0.15);
|
||||
}
|
||||
|
||||
.refresh-btn {
|
||||
background: linear-gradient(135deg, #4caf50, #66bb6a);
|
||||
color: white;
|
||||
border: none;
|
||||
padding: 10px 20px;
|
||||
border-radius: 24px;
|
||||
font-size: 0.9rem;
|
||||
font-weight: 600;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
margin-top: 12px;
|
||||
box-shadow: 0 4px 12px rgba(76, 175, 80, 0.25);
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
}
|
||||
|
||||
.refresh-btn:hover {
|
||||
background: linear-gradient(135deg, #388e3c, #4caf50);
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 6px 16px rgba(76, 175, 80, 0.35);
|
||||
}
|
||||
|
||||
.refresh-btn:active {
|
||||
transform: translateY(0);
|
||||
box-shadow: 0 2px 8px rgba(76, 175, 80, 0.3);
|
||||
}
|
||||
|
||||
.btn-icon {
|
||||
font-size: 1rem;
|
||||
animation: rotate 2s linear infinite paused;
|
||||
}
|
||||
|
||||
.refresh-btn:hover .btn-icon {
|
||||
animation-play-state: running;
|
||||
}
|
||||
|
||||
@keyframes rotate {
|
||||
from { transform: rotate(0deg); }
|
||||
to { transform: rotate(360deg); }
|
||||
}
|
||||
|
||||
/* 热搜列表 - 移动端优先设计 */
|
||||
@@ -143,13 +187,13 @@ header h1 {
|
||||
}
|
||||
|
||||
.hot-item {
|
||||
background: white;
|
||||
background: rgba(255, 255, 255, 0.95);
|
||||
border-radius: 16px;
|
||||
padding: 16px;
|
||||
margin-bottom: 12px;
|
||||
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.06);
|
||||
box-shadow: 0 2px 12px rgba(76, 175, 80, 0.08);
|
||||
transition: all 0.3s ease;
|
||||
border: 1px solid rgba(0, 0, 0, 0.05);
|
||||
border: 1px solid rgba(76, 175, 80, 0.1);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
@@ -159,8 +203,9 @@ header h1 {
|
||||
|
||||
.hot-item:hover {
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 6px 20px rgba(0, 0, 0, 0.1);
|
||||
border-color: rgba(64, 169, 255, 0.2);
|
||||
box-shadow: 0 6px 20px rgba(76, 175, 80, 0.15);
|
||||
border-color: rgba(76, 175, 80, 0.25);
|
||||
background: rgba(255, 255, 255, 1);
|
||||
}
|
||||
|
||||
/* 排名容器 */
|
||||
@@ -186,21 +231,21 @@ header h1 {
|
||||
}
|
||||
|
||||
.hot-rank.rank-1 {
|
||||
background: linear-gradient(135deg, #ff4d4f, #ff7a45);
|
||||
background: linear-gradient(135deg, #4caf50, #66bb6a);
|
||||
color: white;
|
||||
box-shadow: 0 4px 12px rgba(255, 77, 79, 0.3);
|
||||
box-shadow: 0 4px 12px rgba(76, 175, 80, 0.3);
|
||||
}
|
||||
|
||||
.hot-rank.rank-2 {
|
||||
background: linear-gradient(135deg, #ff7a45, #ffa940);
|
||||
background: linear-gradient(135deg, #66bb6a, #81c784);
|
||||
color: white;
|
||||
box-shadow: 0 4px 12px rgba(255, 122, 69, 0.3);
|
||||
box-shadow: 0 4px 12px rgba(102, 187, 106, 0.3);
|
||||
}
|
||||
|
||||
.hot-rank.rank-3 {
|
||||
background: linear-gradient(135deg, #ffa940, #ffec3d);
|
||||
color: #333;
|
||||
box-shadow: 0 4px 12px rgba(255, 169, 64, 0.3);
|
||||
background: linear-gradient(135deg, #81c784, #a5d6a7);
|
||||
color: #2e7d32;
|
||||
box-shadow: 0 4px 12px rgba(129, 199, 132, 0.3);
|
||||
}
|
||||
|
||||
.rank-number {
|
||||
@@ -242,7 +287,7 @@ header h1 {
|
||||
}
|
||||
|
||||
.hot-title:hover {
|
||||
color: #4096ff;
|
||||
color: #4caf50;
|
||||
}
|
||||
|
||||
/* 底部行 */
|
||||
@@ -277,13 +322,13 @@ header h1 {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
background: linear-gradient(135deg, #ff6b6b, #4ecdc4);
|
||||
color: white;
|
||||
background: linear-gradient(135deg, #81c784, #a5d6a7);
|
||||
color: #2e7d32;
|
||||
padding: 4px 10px;
|
||||
border-radius: 12px;
|
||||
font-size: 0.75rem;
|
||||
font-weight: 600;
|
||||
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.1);
|
||||
box-shadow: 0 2px 6px rgba(76, 175, 80, 0.15);
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
@@ -309,7 +354,7 @@ header h1 {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
background: linear-gradient(135deg, #4096ff, #40a9ff);
|
||||
background: linear-gradient(135deg, #4caf50, #66bb6a);
|
||||
color: white;
|
||||
text-decoration: none;
|
||||
padding: 6px 12px;
|
||||
@@ -317,15 +362,16 @@ header h1 {
|
||||
font-size: 0.75rem;
|
||||
font-weight: 600;
|
||||
transition: all 0.3s ease;
|
||||
box-shadow: 0 2px 6px rgba(64, 150, 255, 0.3);
|
||||
box-shadow: 0 2px 6px rgba(76, 175, 80, 0.3);
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.hot-link:hover {
|
||||
transform: translateY(-1px);
|
||||
box-shadow: 0 4px 10px rgba(64, 150, 255, 0.4);
|
||||
box-shadow: 0 4px 10px rgba(76, 175, 80, 0.4);
|
||||
text-decoration: none;
|
||||
color: white;
|
||||
background: linear-gradient(135deg, #388e3c, #4caf50);
|
||||
}
|
||||
|
||||
.link-icon {
|
||||
@@ -339,16 +385,31 @@ header h1 {
|
||||
.loading {
|
||||
text-align: center;
|
||||
padding: 40px;
|
||||
color: #666;
|
||||
color: #4caf50;
|
||||
font-size: 1.1rem;
|
||||
}
|
||||
|
||||
.spinner {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
border: 4px solid rgba(76, 175, 80, 0.2);
|
||||
border-top: 4px solid #4caf50;
|
||||
border-radius: 50%;
|
||||
animation: spin 1s linear infinite;
|
||||
margin: 0 auto 16px;
|
||||
}
|
||||
|
||||
@keyframes spin {
|
||||
0% { transform: rotate(0deg); }
|
||||
100% { transform: rotate(360deg); }
|
||||
}
|
||||
|
||||
footer {
|
||||
text-align: center;
|
||||
margin-top: 30px;
|
||||
padding-top: 20px;
|
||||
border-top: 1px solid rgba(0, 0, 0, 0.06);
|
||||
color: #666;
|
||||
border-top: 1px solid rgba(76, 175, 80, 0.15);
|
||||
color: #4caf50;
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
|
||||
@@ -10,15 +10,12 @@
|
||||
<body>
|
||||
<div class="container">
|
||||
<header class="header">
|
||||
<div class="header-icon">🔥</div>
|
||||
<h1 class="title">📱 抖音热搜榜 🎵</h1>
|
||||
<h1 class="title">抖音热搜榜</h1>
|
||||
<p class="subtitle">实时热门话题 · 紧跟潮流趋势</p>
|
||||
<div class="update-time">
|
||||
<span class="time-icon">⏰</span>
|
||||
<span id="updateTime">加载中...</span>
|
||||
</div>
|
||||
<button id="refreshBtn" class="refresh-btn">
|
||||
<span class="btn-icon">🔄</span>
|
||||
刷新数据
|
||||
</button>
|
||||
</header>
|
||||
@@ -48,7 +45,6 @@
|
||||
<h3>加载失败了</h3>
|
||||
<p>网络连接出现问题,请稍后重试</p>
|
||||
<button onclick="loadHotList()" class="retry-btn">
|
||||
<span>🔄</span>
|
||||
重新加载
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@@ -137,8 +137,8 @@ function createHotItem(item, rank) {
|
||||
|
||||
// 根据热度值添加火焰等级
|
||||
let fireLevel = '';
|
||||
if (item.hot_value >= 10000000) fireLevel = '🔥🔥🔥';
|
||||
else if (item.hot_value >= 5000000) fireLevel = '🔥🔥';
|
||||
if (item.hot_value >= 10000000) fireLevel = '🔥';
|
||||
else if (item.hot_value >= 5000000) fireLevel = '🔥';
|
||||
else fireLevel = '🔥';
|
||||
|
||||
hotItem.innerHTML = `
|
||||
@@ -153,7 +153,6 @@ function createHotItem(item, rank) {
|
||||
<div class="hot-title">${escapeHtml(item.title)}</div>
|
||||
<div class="hot-bottom-row">
|
||||
<div class="hot-time">
|
||||
<span class="meta-icon">⏰</span>
|
||||
<span class="meta-text">${formattedTime}</span>
|
||||
</div>
|
||||
<div class="hot-value">
|
||||
@@ -161,7 +160,6 @@ function createHotItem(item, rank) {
|
||||
<span class="value-text">${formattedHotValue}</span>
|
||||
</div>
|
||||
<a href="${item.link}" target="_blank" class="hot-link">
|
||||
<span class="link-icon">🎬</span>
|
||||
<span class="link-text">观看视频</span>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
.background-container {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
z-index: -1;
|
||||
overflow: hidden;
|
||||
background: linear-gradient(180deg, #f0f9f2 0%, #f7fff8 55%, #eef7f1 100%);
|
||||
}
|
||||
|
||||
.floating-blob {
|
||||
position: absolute;
|
||||
width: 420px;
|
||||
height: 420px;
|
||||
border-radius: 55% 45% 60% 40% / 50% 50% 45% 55%;
|
||||
filter: blur(0px);
|
||||
opacity: 0.28;
|
||||
background: radial-gradient(circle at 30% 30%, rgba(129, 199, 132, 0.6), rgba(129, 199, 132, 0));
|
||||
animation: drift 36s ease-in-out infinite;
|
||||
}
|
||||
|
||||
.blob-1 {
|
||||
top: -120px;
|
||||
left: -160px;
|
||||
animation-delay: 0s;
|
||||
}
|
||||
|
||||
.blob-2 {
|
||||
right: -120px;
|
||||
bottom: -160px;
|
||||
animation-delay: 8s;
|
||||
background: radial-gradient(circle at 70% 70%, rgba(76, 175, 80, 0.5), rgba(76, 175, 80, 0));
|
||||
}
|
||||
|
||||
.blob-3 {
|
||||
top: 45%;
|
||||
left: 55%;
|
||||
animation-delay: 16s;
|
||||
background: radial-gradient(circle at 40% 60%, rgba(165, 214, 167, 0.5), rgba(165, 214, 167, 0));
|
||||
}
|
||||
|
||||
@keyframes drift {
|
||||
0% {
|
||||
transform: translate3d(0, 0, 0) scale(1);
|
||||
}
|
||||
33% {
|
||||
transform: translate3d(30px, -40px, 0) scale(1.05);
|
||||
}
|
||||
66% {
|
||||
transform: translate3d(-25px, 30px, 0) scale(0.95);
|
||||
}
|
||||
100% {
|
||||
transform: translate3d(0, 0, 0) scale(1);
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.floating-blob {
|
||||
width: 260px;
|
||||
height: 260px;
|
||||
opacity: 0.22;
|
||||
}
|
||||
|
||||
.blob-1 {
|
||||
top: -80px;
|
||||
left: -120px;
|
||||
}
|
||||
|
||||
.blob-2 {
|
||||
right: -140px;
|
||||
bottom: -140px;
|
||||
}
|
||||
|
||||
.blob-3 {
|
||||
top: 55%;
|
||||
left: 48%;
|
||||
}
|
||||
}
|
||||
432
InfoGenie-frontend/public/60sapi/热搜榜单/猫眼电影实时票房/css/style.css
Normal file
432
InfoGenie-frontend/public/60sapi/热搜榜单/猫眼电影实时票房/css/style.css
Normal file
@@ -0,0 +1,432 @@
|
||||
:root {
|
||||
--primary-50: #f0f9f2;
|
||||
--primary-100: #d8f3d8;
|
||||
--primary-200: #bce5c1;
|
||||
--primary-300: #a0d8a8;
|
||||
--primary-400: #7fcf8e;
|
||||
--primary-500: #66bb6a;
|
||||
--primary-600: #5aa75f;
|
||||
--primary-700: #4a8c50;
|
||||
--primary-text: #103a2b;
|
||||
--muted-text: #49705d;
|
||||
--card-bg: rgba(255, 255, 255, 0.85);
|
||||
--border-soft: rgba(102, 187, 106, 0.18);
|
||||
--shadow-soft: 0 12px 40px rgba(48, 94, 60, 0.12);
|
||||
--shadow-hover: 0 18px 50px rgba(48, 94, 60, 0.16);
|
||||
color-scheme: light;
|
||||
}
|
||||
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: "PingFang SC", "Microsoft YaHei", "Helvetica Neue", Arial, sans-serif;
|
||||
background: transparent;
|
||||
color: var(--primary-text);
|
||||
line-height: 1.6;
|
||||
min-height: 100vh;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
}
|
||||
|
||||
.page {
|
||||
position: relative;
|
||||
margin: 0 auto;
|
||||
width: min(100%, 960px);
|
||||
padding: 20px 16px 72px;
|
||||
}
|
||||
|
||||
.page-header {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 16px;
|
||||
padding: 20px 18px;
|
||||
border-radius: 18px;
|
||||
background: var(--card-bg);
|
||||
box-shadow: var(--shadow-soft);
|
||||
border: 1px solid var(--border-soft);
|
||||
backdrop-filter: blur(18px);
|
||||
}
|
||||
|
||||
.title-block {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 6px;
|
||||
}
|
||||
|
||||
.label-pill {
|
||||
align-self: flex-start;
|
||||
padding: 4px 12px;
|
||||
font-size: 0.82rem;
|
||||
font-weight: 600;
|
||||
color: var(--primary-700);
|
||||
background: rgba(102, 187, 106, 0.15);
|
||||
border-radius: 999px;
|
||||
letter-spacing: 0.06em;
|
||||
}
|
||||
|
||||
.page-header h1 {
|
||||
font-size: 1.6rem;
|
||||
font-weight: 700;
|
||||
line-height: 1.3;
|
||||
}
|
||||
|
||||
.meta-block {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.update-time {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
padding: 6px 12px;
|
||||
font-size: 0.9rem;
|
||||
color: var(--muted-text);
|
||||
background: rgba(255, 255, 255, 0.7);
|
||||
border-radius: 10px;
|
||||
border: 1px solid rgba(102, 187, 106, 0.22);
|
||||
}
|
||||
|
||||
.refresh-button {
|
||||
align-self: flex-start;
|
||||
padding: 10px 18px;
|
||||
font-size: 0.92rem;
|
||||
font-weight: 600;
|
||||
color: #fff;
|
||||
background: linear-gradient(135deg, var(--primary-500), var(--primary-600));
|
||||
border: none;
|
||||
border-radius: 999px;
|
||||
cursor: pointer;
|
||||
box-shadow: 0 10px 24px rgba(102, 187, 106, 0.35);
|
||||
transition: transform 0.2s ease, box-shadow 0.2s ease;
|
||||
}
|
||||
|
||||
.refresh-button:active {
|
||||
transform: scale(0.97);
|
||||
}
|
||||
|
||||
.summary-section {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
gap: 14px;
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.summary-card {
|
||||
padding: 18px 16px;
|
||||
background: var(--card-bg);
|
||||
border-radius: 16px;
|
||||
border: 1px solid var(--border-soft);
|
||||
box-shadow: var(--shadow-soft);
|
||||
backdrop-filter: blur(12px);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.card-label {
|
||||
font-size: 0.92rem;
|
||||
color: var(--muted-text);
|
||||
letter-spacing: 0.04em;
|
||||
}
|
||||
|
||||
.card-value {
|
||||
font-size: 1.4rem;
|
||||
font-weight: 700;
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
gap: 6px;
|
||||
color: var(--primary-700);
|
||||
}
|
||||
|
||||
.card-value .unit {
|
||||
font-size: 0.88rem;
|
||||
font-weight: 500;
|
||||
color: var(--muted-text);
|
||||
}
|
||||
|
||||
.list-section {
|
||||
margin-top: 28px;
|
||||
padding: 22px 18px 26px;
|
||||
background: var(--card-bg);
|
||||
border-radius: 20px;
|
||||
border: 1px solid var(--border-soft);
|
||||
box-shadow: var(--shadow-soft);
|
||||
backdrop-filter: blur(16px);
|
||||
}
|
||||
|
||||
.section-header {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 6px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.section-header h2 {
|
||||
font-size: 1.3rem;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.section-subtitle {
|
||||
font-size: 0.88rem;
|
||||
color: var(--muted-text);
|
||||
}
|
||||
|
||||
.movie-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 16px;
|
||||
}
|
||||
|
||||
.loading,
|
||||
.error-message {
|
||||
padding: 18px 16px;
|
||||
text-align: center;
|
||||
color: var(--muted-text);
|
||||
background: rgba(255, 255, 255, 0.7);
|
||||
border-radius: 14px;
|
||||
border: 1px dashed rgba(102, 187, 106, 0.35);
|
||||
}
|
||||
|
||||
.movie-item {
|
||||
display: grid;
|
||||
grid-template-columns: auto 1fr;
|
||||
gap: 14px;
|
||||
padding: 16px;
|
||||
border-radius: 18px;
|
||||
background: rgba(255, 255, 255, 0.95);
|
||||
border: 1px solid rgba(102, 187, 106, 0.18);
|
||||
box-shadow: 0 12px 28px rgba(48, 94, 60, 0.08);
|
||||
transition: transform 0.2s ease, box-shadow 0.2s ease;
|
||||
}
|
||||
|
||||
.movie-item:hover {
|
||||
transform: translateY(-2px);
|
||||
box-shadow: var(--shadow-hover);
|
||||
}
|
||||
|
||||
.movie-rank {
|
||||
width: 46px;
|
||||
height: 46px;
|
||||
border-radius: 14px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-weight: 700;
|
||||
font-size: 1.1rem;
|
||||
color: #fff;
|
||||
background: var(--primary-500);
|
||||
}
|
||||
|
||||
.movie-rank.top-1 {
|
||||
background: linear-gradient(135deg, #4caf50, #43a047);
|
||||
}
|
||||
|
||||
.movie-rank.top-2 {
|
||||
background: linear-gradient(135deg, #66bb6a, #5aa75f);
|
||||
}
|
||||
|
||||
.movie-rank.top-3 {
|
||||
background: linear-gradient(135deg, #81c784, #66bb6a);
|
||||
}
|
||||
|
||||
.movie-body {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.movie-heading {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 6px;
|
||||
}
|
||||
|
||||
.movie-title {
|
||||
font-size: 1.1rem;
|
||||
font-weight: 700;
|
||||
color: var(--primary-text);
|
||||
}
|
||||
|
||||
.release-info {
|
||||
font-size: 0.9rem;
|
||||
color: var(--muted-text);
|
||||
}
|
||||
|
||||
.movie-stats {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
gap: 10px 14px;
|
||||
}
|
||||
|
||||
.stat {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 2px;
|
||||
}
|
||||
|
||||
.stat-label {
|
||||
font-size: 0.83rem;
|
||||
color: var(--muted-text);
|
||||
letter-spacing: 0.02em;
|
||||
}
|
||||
|
||||
.stat-value {
|
||||
font-size: 1rem;
|
||||
font-weight: 600;
|
||||
color: var(--primary-700);
|
||||
}
|
||||
|
||||
.progress-metrics {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
margin-top: 6px;
|
||||
}
|
||||
|
||||
.progress-group {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 4px;
|
||||
}
|
||||
|
||||
.progress-label {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
font-size: 0.8rem;
|
||||
color: var(--muted-text);
|
||||
}
|
||||
|
||||
.progress-bar {
|
||||
width: 100%;
|
||||
height: 6px;
|
||||
border-radius: 6px;
|
||||
background: rgba(102, 187, 106, 0.16);
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.progress-bar span {
|
||||
display: block;
|
||||
height: 100%;
|
||||
border-radius: inherit;
|
||||
background: linear-gradient(135deg, rgba(102, 187, 106, 0.9), rgba(76, 175, 80, 0.85));
|
||||
width: 0;
|
||||
transition: width 0.5s ease;
|
||||
}
|
||||
|
||||
/* Tablet */
|
||||
@media (min-width: 600px) {
|
||||
.page {
|
||||
padding: 28px 20px 84px;
|
||||
}
|
||||
|
||||
.page-header {
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.title-block h1 {
|
||||
font-size: 1.8rem;
|
||||
}
|
||||
|
||||
.meta-block {
|
||||
align-items: flex-end;
|
||||
}
|
||||
|
||||
.summary-section {
|
||||
grid-template-columns: repeat(4, minmax(0, 1fr));
|
||||
}
|
||||
|
||||
.movie-item {
|
||||
grid-template-columns: 80px 1fr;
|
||||
padding: 18px 20px;
|
||||
}
|
||||
|
||||
.movie-rank {
|
||||
width: 54px;
|
||||
height: 54px;
|
||||
font-size: 1.25rem;
|
||||
}
|
||||
|
||||
.movie-heading {
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.release-info {
|
||||
font-size: 0.88rem;
|
||||
}
|
||||
|
||||
.movie-stats {
|
||||
grid-template-columns: repeat(4, minmax(0, 1fr));
|
||||
}
|
||||
|
||||
.progress-metrics {
|
||||
flex-direction: row;
|
||||
gap: 16px;
|
||||
}
|
||||
|
||||
.progress-group {
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Desktop */
|
||||
@media (min-width: 1024px) {
|
||||
.page {
|
||||
padding: 36px 24px 96px;
|
||||
}
|
||||
|
||||
.page-header {
|
||||
padding: 26px 30px;
|
||||
}
|
||||
|
||||
.page-header h1 {
|
||||
font-size: 2.1rem;
|
||||
}
|
||||
|
||||
.summary-card {
|
||||
padding: 20px 22px;
|
||||
}
|
||||
|
||||
.card-value {
|
||||
font-size: 1.6rem;
|
||||
}
|
||||
|
||||
.list-section {
|
||||
padding: 28px 30px 34px;
|
||||
}
|
||||
|
||||
.movie-item {
|
||||
grid-template-columns: 96px 1fr;
|
||||
padding: 22px 26px;
|
||||
border-radius: 20px;
|
||||
}
|
||||
|
||||
.movie-title {
|
||||
font-size: 1.25rem;
|
||||
}
|
||||
|
||||
.movie-stats {
|
||||
grid-template-columns: repeat(5, minmax(0, 1fr));
|
||||
}
|
||||
|
||||
.progress-metrics {
|
||||
gap: 18px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
* {
|
||||
animation-duration: 0.01ms !important;
|
||||
animation-iteration-count: 1 !important;
|
||||
transition-duration: 0.01ms !important;
|
||||
scroll-behavior: auto !important;
|
||||
}
|
||||
}
|
||||
67
InfoGenie-frontend/public/60sapi/热搜榜单/猫眼电影实时票房/index.html
Normal file
67
InfoGenie-frontend/public/60sapi/热搜榜单/猫眼电影实时票房/index.html
Normal file
@@ -0,0 +1,67 @@
|
||||
<!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/background.css">
|
||||
<link rel="stylesheet" href="./css/style.css">
|
||||
</head>
|
||||
<body>
|
||||
<div class="background-container">
|
||||
<div class="floating-blob blob-1"></div>
|
||||
<div class="floating-blob blob-2"></div>
|
||||
<div class="floating-blob blob-3"></div>
|
||||
</div>
|
||||
|
||||
<div class="page">
|
||||
<header class="page-header">
|
||||
<div class="title-block">
|
||||
<span class="label-pill">实时票房</span>
|
||||
<h1>猫眼电影实时票房</h1>
|
||||
</div>
|
||||
<div class="meta-block">
|
||||
<span id="updateTime" class="update-time">正在获取最新更新...</span>
|
||||
<button type="button" id="refreshButton" class="refresh-button">手动刷新</button>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<section class="summary-section" id="summarySection">
|
||||
<div class="summary-card">
|
||||
<p class="card-label" id="summaryTitle">实时大盘</p>
|
||||
<p class="card-value">
|
||||
<span id="totalBoxOffice">--</span>
|
||||
<span class="unit" id="totalBoxOfficeUnit"></span>
|
||||
</p>
|
||||
</div>
|
||||
<div class="summary-card">
|
||||
<p class="card-label">综合票房</p>
|
||||
<p class="card-value">
|
||||
<span id="combinedBoxOffice">--</span>
|
||||
<span class="unit" id="combinedBoxOfficeUnit"></span>
|
||||
</p>
|
||||
</div>
|
||||
<div class="summary-card">
|
||||
<p class="card-label">排片场次</p>
|
||||
<p class="card-value" id="showCount">--</p>
|
||||
</div>
|
||||
<div class="summary-card">
|
||||
<p class="card-label">观影人次</p>
|
||||
<p class="card-value" id="viewCount">--</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="list-section">
|
||||
<div class="section-header">
|
||||
<h2>影片实时表现</h2>
|
||||
<span class="section-subtitle">数据每 5 秒同步一次</span>
|
||||
</div>
|
||||
<div id="movieList" class="movie-list">
|
||||
<div class="loading">正在加载实时票房...</div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<script src="./js/main.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
297
InfoGenie-frontend/public/60sapi/热搜榜单/猫眼电影实时票房/js/main.js
Normal file
297
InfoGenie-frontend/public/60sapi/热搜榜单/猫眼电影实时票房/js/main.js
Normal file
@@ -0,0 +1,297 @@
|
||||
const API_ENDPOINTS = [
|
||||
"https://60s.api.shumengya.top/v2/maoyan/realtime/movie"
|
||||
];
|
||||
|
||||
const FALLBACK_ENDPOINT = "./返回接口.json";
|
||||
const REFRESH_INTERVAL = 5000;
|
||||
const MAX_MOVIES_TO_RENDER = 40;
|
||||
|
||||
const updateTimeEl = document.getElementById("updateTime");
|
||||
const refreshButton = document.getElementById("refreshButton");
|
||||
const summaryTitleEl = document.getElementById("summaryTitle");
|
||||
const totalBoxOfficeEl = document.getElementById("totalBoxOffice");
|
||||
const totalBoxOfficeUnitEl = document.getElementById("totalBoxOfficeUnit");
|
||||
const combinedBoxOfficeEl = document.getElementById("combinedBoxOffice");
|
||||
const combinedBoxOfficeUnitEl = document.getElementById("combinedBoxOfficeUnit");
|
||||
const showCountEl = document.getElementById("showCount");
|
||||
const viewCountEl = document.getElementById("viewCount");
|
||||
const movieListEl = document.getElementById("movieList");
|
||||
|
||||
let autoRefreshTimer = null;
|
||||
let isLoading = false;
|
||||
|
||||
function escapeHtml(value) {
|
||||
if (value === undefined || value === null) {
|
||||
return "";
|
||||
}
|
||||
|
||||
return String(value)
|
||||
.replace(/&/g, "&")
|
||||
.replace(/</g, "<")
|
||||
.replace(/>/g, ">")
|
||||
.replace(/"/g, """)
|
||||
.replace(/'/g, "'");
|
||||
}
|
||||
|
||||
function safeText(value) {
|
||||
if (value === undefined || value === null || value === "") {
|
||||
return "--";
|
||||
}
|
||||
return escapeHtml(value);
|
||||
}
|
||||
|
||||
function parseRate(rateText) {
|
||||
if (!rateText || typeof rateText !== "string") {
|
||||
return { text: "--", ratio: 0 };
|
||||
}
|
||||
|
||||
const trimmed = rateText.trim();
|
||||
const numeric = parseFloat(trimmed.replace(/[^0-9.]/g, ""));
|
||||
let ratio = Number.isFinite(numeric) ? Math.max(0, Math.min(numeric, 100)) : 0;
|
||||
|
||||
if (trimmed.startsWith("<")) {
|
||||
ratio = Math.max(3, ratio);
|
||||
}
|
||||
|
||||
return { text: escapeHtml(trimmed), ratio };
|
||||
}
|
||||
|
||||
function formatUpdateTime(data) {
|
||||
if (data && typeof data.updated === "string" && data.updated.trim().length > 0) {
|
||||
return data.updated.trim();
|
||||
}
|
||||
|
||||
if (data && typeof data.updated_at === "number" && !Number.isNaN(data.updated_at)) {
|
||||
return new Date(data.updated_at).toLocaleString("zh-CN", {
|
||||
hour12: false
|
||||
});
|
||||
}
|
||||
|
||||
return new Date().toLocaleString("zh-CN", { hour12: false });
|
||||
}
|
||||
|
||||
function renderSummary(data) {
|
||||
summaryTitleEl.textContent = data?.title ? data.title : "实时大盘";
|
||||
totalBoxOfficeEl.textContent = data?.split_box_office ? data.split_box_office : "--";
|
||||
totalBoxOfficeUnitEl.textContent = data?.split_box_office_unit ? data.split_box_office_unit : "";
|
||||
combinedBoxOfficeEl.textContent = data?.box_office ? data.box_office : "--";
|
||||
combinedBoxOfficeUnitEl.textContent = data?.box_office_unit ? data.box_office_unit : "";
|
||||
showCountEl.textContent = data?.show_count_desc ? data.show_count_desc : "--";
|
||||
viewCountEl.textContent = data?.view_count_desc ? data.view_count_desc : "--";
|
||||
}
|
||||
|
||||
function createStat(label, value) {
|
||||
return `
|
||||
<div class="stat">
|
||||
<span class="stat-label">${label}</span>
|
||||
<span class="stat-value">${safeText(value)}</span>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
function createMovieItem(movie, index) {
|
||||
const item = document.createElement("article");
|
||||
item.className = "movie-item";
|
||||
|
||||
const topClass = index < 3 ? ` top-${index + 1}` : "";
|
||||
const name = safeText(movie?.movie_name || "未命名影片");
|
||||
const releaseInfo = movie?.release_info ? `<div class="release-info">${safeText(movie.release_info)}</div>` : "";
|
||||
|
||||
const boxOfficeDesc = movie?.box_office_desc || (movie?.box_office ? `${movie.box_office}${movie.box_office_unit || ""}` : "--");
|
||||
const splitBoxOfficeDesc = movie?.split_box_office_desc || (movie?.split_box_office ? `${movie.split_box_office}${movie.split_box_office_unit || ""}` : "--");
|
||||
const totalBoxOfficeDesc = movie?.sum_box_desc ?? "--";
|
||||
const totalSplitBoxOfficeDesc = movie?.sum_split_box_desc ?? "--";
|
||||
|
||||
let showCountText = "--";
|
||||
if (movie?.show_count !== undefined && movie.show_count !== null && movie.show_count !== "") {
|
||||
const numericShowCount = Number(movie.show_count);
|
||||
showCountText = Number.isFinite(numericShowCount)
|
||||
? `${numericShowCount.toLocaleString("zh-CN")} 场`
|
||||
: movie.show_count;
|
||||
}
|
||||
|
||||
const avgShowView = movie?.avg_show_view ?? "--";
|
||||
const avgSeatView = movie?.avg_seat_view ?? "--";
|
||||
|
||||
const boxRate = parseRate(movie?.box_office_rate);
|
||||
const showRate = parseRate(movie?.show_count_rate);
|
||||
|
||||
item.innerHTML = `
|
||||
<div class="movie-rank${topClass}">${index + 1}</div>
|
||||
<div class="movie-body">
|
||||
<div class="movie-heading">
|
||||
<div>
|
||||
<div class="movie-title">${name}</div>
|
||||
${releaseInfo}
|
||||
</div>
|
||||
</div>
|
||||
<div class="movie-stats">
|
||||
${createStat("单日综合票房", boxOfficeDesc)}
|
||||
${createStat("单日分账票房", splitBoxOfficeDesc)}
|
||||
${createStat("累计综合票房", totalBoxOfficeDesc)}
|
||||
${createStat("累计分账票房", totalSplitBoxOfficeDesc)}
|
||||
${createStat("排片场次", showCountText)}
|
||||
${createStat("场均人次", avgShowView)}
|
||||
${createStat("上座率", avgSeatView)}
|
||||
</div>
|
||||
<div class="progress-metrics">
|
||||
<div class="progress-group">
|
||||
<div class="progress-label">
|
||||
<span>综合票房占比</span>
|
||||
<span>${boxRate.text}</span>
|
||||
</div>
|
||||
<div class="progress-bar"><span></span></div>
|
||||
</div>
|
||||
<div class="progress-group">
|
||||
<div class="progress-label">
|
||||
<span>排片占比</span>
|
||||
<span>${showRate.text}</span>
|
||||
</div>
|
||||
<div class="progress-bar"><span></span></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
const progressBars = item.querySelectorAll(".progress-bar span");
|
||||
if (progressBars[0]) {
|
||||
progressBars[0].style.width = `${boxRate.ratio}%`;
|
||||
}
|
||||
if (progressBars[1]) {
|
||||
progressBars[1].style.width = `${showRate.ratio}%`;
|
||||
}
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
function renderMovieList(list) {
|
||||
movieListEl.innerHTML = "";
|
||||
|
||||
if (!Array.isArray(list) || list.length === 0) {
|
||||
const empty = document.createElement("div");
|
||||
empty.className = "error-message";
|
||||
empty.textContent = "暂时没有可展示的实时票房数据";
|
||||
movieListEl.appendChild(empty);
|
||||
return;
|
||||
}
|
||||
|
||||
const sliced = list.slice(0, MAX_MOVIES_TO_RENDER);
|
||||
sliced.forEach((movie, index) => {
|
||||
movieListEl.appendChild(createMovieItem(movie, index));
|
||||
});
|
||||
}
|
||||
|
||||
async function requestJson(url) {
|
||||
const response = await fetch(url, {
|
||||
cache: "no-store"
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`请求失败: ${response.status}`);
|
||||
}
|
||||
|
||||
return response.json();
|
||||
}
|
||||
|
||||
async function retrieveData() {
|
||||
for (const endpoint of API_ENDPOINTS) {
|
||||
try {
|
||||
const result = await requestJson(endpoint);
|
||||
if (result?.code === 200 && result?.data) {
|
||||
return result.data;
|
||||
}
|
||||
} catch (error) {
|
||||
console.warn("主接口请求失败", error);
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
const fallbackResult = await requestJson(FALLBACK_ENDPOINT);
|
||||
if (fallbackResult?.data) {
|
||||
return fallbackResult.data;
|
||||
}
|
||||
} catch (error) {
|
||||
console.warn("本地示例数据读取失败", error);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
async function loadData(isManual = false) {
|
||||
if (isLoading) {
|
||||
return;
|
||||
}
|
||||
|
||||
isLoading = true;
|
||||
|
||||
if (isManual) {
|
||||
refreshButton.disabled = true;
|
||||
refreshButton.textContent = "刷新中...";
|
||||
}
|
||||
|
||||
if (!movieListEl.children.length) {
|
||||
movieListEl.innerHTML = '<div class="loading">正在加载实时票房...</div>';
|
||||
}
|
||||
|
||||
try {
|
||||
const data = await retrieveData();
|
||||
if (!data) {
|
||||
throw new Error("无法获取数据");
|
||||
}
|
||||
|
||||
renderSummary(data);
|
||||
renderMovieList(Array.isArray(data.list) ? data.list : []);
|
||||
updateTimeEl.textContent = `最近更新 ${formatUpdateTime(data)}`;
|
||||
} catch (error) {
|
||||
console.error("加载数据失败", error);
|
||||
movieListEl.innerHTML = "";
|
||||
const err = document.createElement("div");
|
||||
err.className = "error-message";
|
||||
err.textContent = "数据获取暂时遇到问题,系统会稍后自动重试";
|
||||
movieListEl.appendChild(err);
|
||||
updateTimeEl.textContent = "最近更新 --";
|
||||
renderSummary(null);
|
||||
} finally {
|
||||
if (isManual) {
|
||||
refreshButton.disabled = false;
|
||||
refreshButton.textContent = "手动刷新";
|
||||
}
|
||||
isLoading = false;
|
||||
}
|
||||
}
|
||||
|
||||
function startAutoRefresh() {
|
||||
if (autoRefreshTimer) {
|
||||
clearInterval(autoRefreshTimer);
|
||||
}
|
||||
autoRefreshTimer = setInterval(() => {
|
||||
loadData(false);
|
||||
}, REFRESH_INTERVAL);
|
||||
}
|
||||
|
||||
refreshButton.addEventListener("click", () => {
|
||||
loadData(true);
|
||||
});
|
||||
|
||||
document.addEventListener("visibilitychange", () => {
|
||||
if (document.hidden) {
|
||||
if (autoRefreshTimer) {
|
||||
clearInterval(autoRefreshTimer);
|
||||
autoRefreshTimer = null;
|
||||
}
|
||||
} else {
|
||||
startAutoRefresh();
|
||||
loadData(false);
|
||||
}
|
||||
});
|
||||
|
||||
function init() {
|
||||
loadData(false);
|
||||
startAutoRefresh();
|
||||
}
|
||||
|
||||
if (document.readyState === "loading") {
|
||||
document.addEventListener("DOMContentLoaded", init);
|
||||
} else {
|
||||
init();
|
||||
}
|
||||
1861
InfoGenie-frontend/public/60sapi/热搜榜单/猫眼电影实时票房/返回接口.json
Normal file
1861
InfoGenie-frontend/public/60sapi/热搜榜单/猫眼电影实时票房/返回接口.json
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,79 @@
|
||||
.background-layer {
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
overflow: hidden;
|
||||
z-index: -1;
|
||||
background: linear-gradient(180deg, #e8f5e8 0%, #f0f8e8 55%, #e8f5e8 100%);
|
||||
}
|
||||
|
||||
.aurora {
|
||||
position: absolute;
|
||||
width: 480px;
|
||||
height: 480px;
|
||||
border-radius: 58% 42% 53% 47% / 52% 46% 54% 48%;
|
||||
filter: blur(0px);
|
||||
opacity: 0.28;
|
||||
background: radial-gradient(circle at 40% 40%, rgba(168, 230, 207, 0.4), rgba(168, 230, 207, 0));
|
||||
animation: float 32s ease-in-out infinite;
|
||||
}
|
||||
|
||||
.aurora-1 {
|
||||
top: -160px;
|
||||
left: -140px;
|
||||
animation-delay: 0s;
|
||||
}
|
||||
|
||||
.aurora-2 {
|
||||
top: 50%;
|
||||
left: 60%;
|
||||
animation-delay: 6s;
|
||||
background: radial-gradient(circle at 60% 60%, rgba(220, 237, 193, 0.35), rgba(220, 237, 193, 0));
|
||||
}
|
||||
|
||||
.aurora-3 {
|
||||
bottom: -180px;
|
||||
right: -160px;
|
||||
animation-delay: 12s;
|
||||
background: radial-gradient(circle at 50% 50%, rgba(129, 199, 132, 0.3), rgba(129, 199, 132, 0));
|
||||
}
|
||||
|
||||
@keyframes float {
|
||||
0% {
|
||||
transform: translate3d(0, 0, 0) scale(1);
|
||||
}
|
||||
25% {
|
||||
transform: translate3d(40px, -30px, 0) scale(1.05);
|
||||
}
|
||||
50% {
|
||||
transform: translate3d(-35px, 25px, 0) scale(0.95);
|
||||
}
|
||||
75% {
|
||||
transform: translate3d(20px, 35px, 0) scale(1.08);
|
||||
}
|
||||
100% {
|
||||
transform: translate3d(0, 0, 0) scale(1);
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.aurora {
|
||||
width: 280px;
|
||||
height: 280px;
|
||||
opacity: 0.24;
|
||||
}
|
||||
|
||||
.aurora-1 {
|
||||
top: -110px;
|
||||
left: -130px;
|
||||
}
|
||||
|
||||
.aurora-2 {
|
||||
top: 45%;
|
||||
left: 35%;
|
||||
}
|
||||
|
||||
.aurora-3 {
|
||||
bottom: -140px;
|
||||
right: -120px;
|
||||
}
|
||||
}
|
||||
414
InfoGenie-frontend/public/60sapi/热搜榜单/猫眼电视收视排行/css/style.css
Normal file
414
InfoGenie-frontend/public/60sapi/热搜榜单/猫眼电视收视排行/css/style.css
Normal file
@@ -0,0 +1,414 @@
|
||||
:root {
|
||||
--bg-base: rgba(255, 255, 255, 0.85);
|
||||
--panel-bg: rgba(248, 252, 248, 0.9);
|
||||
--panel-border: rgba(129, 199, 132, 0.25);
|
||||
--accent-1: #4caf50;
|
||||
--accent-2: #81c784;
|
||||
--accent-3: #a5d6a7;
|
||||
--text-primary: #2e7d32;
|
||||
--text-secondary: #558b2f;
|
||||
--chip-bg: rgba(76, 175, 80, 0.15);
|
||||
--shadow-soft: 0 16px 40px rgba(46, 125, 50, 0.15);
|
||||
color-scheme: light;
|
||||
}
|
||||
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
body {
|
||||
background: transparent;
|
||||
color: var(--text-primary);
|
||||
font-family: "PingFang SC", "Microsoft YaHei", "Helvetica Neue", Arial, sans-serif;
|
||||
line-height: 1.6;
|
||||
min-height: 100vh;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
}
|
||||
|
||||
.screen {
|
||||
width: min(100%, 840px);
|
||||
margin: 0 auto;
|
||||
padding: 18px 16px 72px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 18px;
|
||||
}
|
||||
|
||||
.screen-header {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 18px;
|
||||
padding: 20px 18px;
|
||||
border-radius: 20px;
|
||||
background: var(--bg-base);
|
||||
border: 1px solid var(--panel-border);
|
||||
box-shadow: var(--shadow-soft);
|
||||
backdrop-filter: blur(18px);
|
||||
}
|
||||
|
||||
.title-group {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.eyebrow {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
padding: 4px 12px;
|
||||
font-size: 0.8rem;
|
||||
letter-spacing: 0.08em;
|
||||
text-transform: uppercase;
|
||||
border-radius: 999px;
|
||||
color: var(--accent-1);
|
||||
background: var(--chip-bg);
|
||||
}
|
||||
|
||||
.screen-header h1 {
|
||||
font-size: 1.6rem;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.tagline {
|
||||
font-size: 0.95rem;
|
||||
color: var(--text-secondary);
|
||||
}
|
||||
|
||||
.actions {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 10px;
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
.refresh {
|
||||
padding: 10px 20px;
|
||||
border-radius: 999px;
|
||||
border: none;
|
||||
background: linear-gradient(135deg, rgba(76, 175, 80, 0.9), rgba(129, 199, 132, 0.9));
|
||||
color: var(--text-primary);
|
||||
font-size: 0.92rem;
|
||||
font-weight: 600;
|
||||
cursor: pointer;
|
||||
transition: transform 0.2s ease, box-shadow 0.2s ease;
|
||||
box-shadow: 0 12px 30px rgba(76, 175, 80, 0.25);
|
||||
}
|
||||
|
||||
.refresh:active {
|
||||
transform: scale(0.97);
|
||||
}
|
||||
|
||||
.refresh:disabled {
|
||||
opacity: 0.6;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
.timestamp {
|
||||
font-size: 0.85rem;
|
||||
color: var(--text-secondary);
|
||||
}
|
||||
|
||||
.insights {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.insight-card {
|
||||
padding: 16px 18px;
|
||||
background: var(--panel-bg);
|
||||
border-radius: 16px;
|
||||
border: 1px solid rgba(129, 199, 132, 0.3);
|
||||
box-shadow: var(--shadow-soft);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 6px;
|
||||
}
|
||||
|
||||
.insight-label {
|
||||
font-size: 0.85rem;
|
||||
color: var(--text-secondary);
|
||||
letter-spacing: 0.02em;
|
||||
}
|
||||
|
||||
.insight-value {
|
||||
font-size: 1.3rem;
|
||||
font-weight: 700;
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
gap: 4px;
|
||||
color: var(--text-primary);
|
||||
}
|
||||
|
||||
.insight-value .unit {
|
||||
font-size: 0.9rem;
|
||||
font-weight: 500;
|
||||
color: var(--text-secondary);
|
||||
}
|
||||
|
||||
.ranking {
|
||||
padding: 22px 18px 28px;
|
||||
background: var(--bg-base);
|
||||
border-radius: 24px;
|
||||
border: 1px solid var(--panel-border);
|
||||
box-shadow: var(--shadow-soft);
|
||||
backdrop-filter: blur(22px);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 18px;
|
||||
}
|
||||
|
||||
.ranking-header {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 6px;
|
||||
}
|
||||
|
||||
.ranking-header h2 {
|
||||
font-size: 1.25rem;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.subtitle {
|
||||
font-size: 0.88rem;
|
||||
color: var(--text-secondary);
|
||||
}
|
||||
|
||||
.programme-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 14px;
|
||||
}
|
||||
|
||||
.loading,
|
||||
.error-message,
|
||||
.empty-message {
|
||||
padding: 18px 16px;
|
||||
text-align: center;
|
||||
color: var(--text-secondary);
|
||||
border-radius: 14px;
|
||||
border: 1px dashed rgba(129, 199, 132, 0.4);
|
||||
background: rgba(248, 252, 248, 0.6);
|
||||
}
|
||||
|
||||
.programme-item {
|
||||
display: grid;
|
||||
grid-template-columns: auto 1fr;
|
||||
gap: 14px;
|
||||
padding: 16px;
|
||||
border-radius: 18px;
|
||||
background: rgba(248, 252, 248, 0.95);
|
||||
border: 1px solid rgba(129, 199, 132, 0.3);
|
||||
box-shadow: 0 14px 30px rgba(46, 125, 50, 0.1);
|
||||
transition: transform 0.2s ease, box-shadow 0.2s ease;
|
||||
}
|
||||
|
||||
.programme-item:hover {
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 18px 36px rgba(46, 125, 50, 0.15);
|
||||
}
|
||||
|
||||
.rank-badge {
|
||||
width: 44px;
|
||||
height: 44px;
|
||||
border-radius: 14px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-weight: 700;
|
||||
font-size: 1.05rem;
|
||||
color: #ffffff;
|
||||
background: linear-gradient(135deg, rgba(76, 175, 80, 0.9), rgba(129, 199, 132, 0.9));
|
||||
}
|
||||
|
||||
.rank-badge.top-1 {
|
||||
background: linear-gradient(135deg, #2e7d32, #4caf50);
|
||||
}
|
||||
|
||||
.rank-badge.top-2 {
|
||||
background: linear-gradient(135deg, #388e3c, #66bb6a);
|
||||
}
|
||||
|
||||
.rank-badge.top-3 {
|
||||
background: linear-gradient(135deg, #4caf50, #81c784);
|
||||
}
|
||||
|
||||
.programme-body {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.programme-head {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 6px;
|
||||
}
|
||||
|
||||
.programme-name {
|
||||
font-size: 1.05rem;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.channel-name {
|
||||
font-size: 0.9rem;
|
||||
color: var(--text-secondary);
|
||||
}
|
||||
|
||||
.metric-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.metric {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 2px;
|
||||
}
|
||||
|
||||
.metric-label {
|
||||
font-size: 0.78rem;
|
||||
color: var(--text-secondary);
|
||||
letter-spacing: 0.04em;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.metric-value {
|
||||
font-size: 0.98rem;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.progress-trend {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
margin-top: 4px;
|
||||
}
|
||||
|
||||
.progress-row {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 4px;
|
||||
}
|
||||
|
||||
.progress-label {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
font-size: 0.8rem;
|
||||
color: var(--text-secondary);
|
||||
}
|
||||
|
||||
.progress-bar {
|
||||
width: 100%;
|
||||
height: 6px;
|
||||
border-radius: 6px;
|
||||
background: rgba(116, 210, 255, 0.16);
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.progress-bar span {
|
||||
display: block;
|
||||
height: 100%;
|
||||
border-radius: inherit;
|
||||
background: linear-gradient(135deg, rgba(116, 210, 255, 0.95), rgba(122, 185, 255, 0.95));
|
||||
width: 0;
|
||||
transition: width 0.5s ease;
|
||||
}
|
||||
|
||||
.progress-row.attention .progress-bar span {
|
||||
background: linear-gradient(135deg, rgba(244, 156, 224, 0.95), rgba(116, 210, 255, 0.9));
|
||||
}
|
||||
|
||||
/* Tablet layout */
|
||||
@media (min-width: 600px) {
|
||||
.screen {
|
||||
padding: 24px 20px 88px;
|
||||
gap: 20px;
|
||||
}
|
||||
|
||||
.screen-header {
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 26px 28px;
|
||||
}
|
||||
|
||||
.screen-header h1 {
|
||||
font-size: 1.9rem;
|
||||
}
|
||||
|
||||
.tagline {
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
.actions {
|
||||
align-items: flex-end;
|
||||
}
|
||||
|
||||
.insights {
|
||||
grid-template-columns: repeat(4, minmax(0, 1fr));
|
||||
gap: 16px;
|
||||
}
|
||||
|
||||
.programme-item {
|
||||
grid-template-columns: 72px 1fr;
|
||||
padding: 18px 20px;
|
||||
}
|
||||
|
||||
.rank-badge {
|
||||
width: 54px;
|
||||
height: 54px;
|
||||
font-size: 1.25rem;
|
||||
}
|
||||
|
||||
.metric-grid {
|
||||
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||||
}
|
||||
}
|
||||
|
||||
/* Desktop layout */
|
||||
@media (min-width: 1024px) {
|
||||
.screen {
|
||||
width: min(100%, 960px);
|
||||
padding: 32px 28px 104px;
|
||||
}
|
||||
|
||||
.insight-card {
|
||||
padding: 20px 22px;
|
||||
}
|
||||
|
||||
.insight-value {
|
||||
font-size: 1.6rem;
|
||||
}
|
||||
|
||||
.ranking {
|
||||
padding: 30px 32px 36px;
|
||||
}
|
||||
|
||||
.programme-item {
|
||||
grid-template-columns: 96px 1fr;
|
||||
padding: 22px 26px;
|
||||
border-radius: 22px;
|
||||
}
|
||||
|
||||
.programme-name {
|
||||
font-size: 1.25rem;
|
||||
}
|
||||
|
||||
.metric-grid {
|
||||
grid-template-columns: repeat(4, minmax(0, 1fr));
|
||||
}
|
||||
}
|
||||
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
* {
|
||||
animation-duration: 0.01ms !important;
|
||||
animation-iteration-count: 1 !important;
|
||||
transition-duration: 0.01ms !important;
|
||||
scroll-behavior: auto !important;
|
||||
}
|
||||
}
|
||||
62
InfoGenie-frontend/public/60sapi/热搜榜单/猫眼电视收视排行/index.html
Normal file
62
InfoGenie-frontend/public/60sapi/热搜榜单/猫眼电视收视排行/index.html
Normal file
@@ -0,0 +1,62 @@
|
||||
<!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/background.css">
|
||||
<link rel="stylesheet" href="./css/style.css">
|
||||
</head>
|
||||
<body>
|
||||
<div class="background-layer">
|
||||
<div class="aurora aurora-1"></div>
|
||||
<div class="aurora aurora-2"></div>
|
||||
<div class="aurora aurora-3"></div>
|
||||
</div>
|
||||
|
||||
<div class="screen">
|
||||
<header class="screen-header">
|
||||
<div class="title-group">
|
||||
<span class="eyebrow">实时收视</span>
|
||||
<h1>猫眼电视收视排行</h1>
|
||||
<p class="tagline">聚焦全国频道实时关注度,让你不错过热门节目</p>
|
||||
</div>
|
||||
<div class="actions">
|
||||
<button id="refreshButton" class="refresh">手动刷新</button>
|
||||
<span id="updateTime" class="timestamp">正在同步最新数据...</span>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<section class="insights" id="insightPanel">
|
||||
<div class="insight-card">
|
||||
<p class="insight-label">节目数量</p>
|
||||
<p class="insight-value" id="programmeCount">--</p>
|
||||
</div>
|
||||
<div class="insight-card">
|
||||
<p class="insight-label">最高市场份额</p>
|
||||
<p class="insight-value"><span id="topMarketRate">--</span><span class="unit">%</span></p>
|
||||
</div>
|
||||
<div class="insight-card">
|
||||
<p class="insight-label">最高关注指数</p>
|
||||
<p class="insight-value"><span id="topAttentionRate">--</span><span class="unit">%</span></p>
|
||||
</div>
|
||||
<div class="insight-card">
|
||||
<p class="insight-label">官方刷新频率</p>
|
||||
<p class="insight-value" id="refreshGap">--</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="ranking">
|
||||
<div class="ranking-header">
|
||||
<h2>频道节目排行榜</h2>
|
||||
<span class="subtitle">实时榜单,数据持续刷新</span>
|
||||
</div>
|
||||
<div id="programmeList" class="programme-list">
|
||||
<div class="loading">正在载入电视收视排行...</div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<script src="./js/main.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
290
InfoGenie-frontend/public/60sapi/热搜榜单/猫眼电视收视排行/js/main.js
Normal file
290
InfoGenie-frontend/public/60sapi/热搜榜单/猫眼电视收视排行/js/main.js
Normal file
@@ -0,0 +1,290 @@
|
||||
const API_ENDPOINTS = [
|
||||
"https://60s.api.shumengya.top/v2/maoyan/realtime/tv"
|
||||
];
|
||||
|
||||
const FALLBACK_ENDPOINT = "./返回接口.json";
|
||||
const REFRESH_INTERVAL = 4000;
|
||||
const MAX_ITEMS = 40;
|
||||
|
||||
const refreshButton = document.getElementById("refreshButton");
|
||||
const updateTimeEl = document.getElementById("updateTime");
|
||||
const programmeListEl = document.getElementById("programmeList");
|
||||
const programmeCountEl = document.getElementById("programmeCount");
|
||||
const topMarketRateEl = document.getElementById("topMarketRate");
|
||||
const topAttentionRateEl = document.getElementById("topAttentionRate");
|
||||
const refreshGapEl = document.getElementById("refreshGap");
|
||||
|
||||
let isLoading = false;
|
||||
let autoTimer = null;
|
||||
|
||||
function escapeHtml(value) {
|
||||
if (value === undefined || value === null) {
|
||||
return "";
|
||||
}
|
||||
return String(value)
|
||||
.replace(/&/g, "&")
|
||||
.replace(/</g, "<")
|
||||
.replace(/>/g, ">")
|
||||
.replace(/"/g, """)
|
||||
.replace(/'/g, "'");
|
||||
}
|
||||
|
||||
function safeText(value, fallback = "--") {
|
||||
if (value === undefined || value === null || value === "") {
|
||||
return fallback;
|
||||
}
|
||||
return escapeHtml(value);
|
||||
}
|
||||
|
||||
function formatNumber(value, fractionDigits = 2) {
|
||||
const numeric = Number(value);
|
||||
if (!Number.isFinite(numeric)) {
|
||||
return "--";
|
||||
}
|
||||
return numeric.toFixed(fractionDigits);
|
||||
}
|
||||
|
||||
function formatGapText(seconds) {
|
||||
const numeric = Number(seconds);
|
||||
if (!Number.isFinite(numeric) || numeric <= 0) {
|
||||
return "--";
|
||||
}
|
||||
if (numeric < 60) {
|
||||
return `约每 ${Math.round(numeric)} 秒`;
|
||||
}
|
||||
const minutes = Math.floor(numeric / 60);
|
||||
const remaining = Math.round(numeric % 60);
|
||||
if (remaining === 0) {
|
||||
return `约每 ${minutes} 分钟`;
|
||||
}
|
||||
return `约每 ${minutes} 分 ${remaining} 秒`;
|
||||
}
|
||||
|
||||
function parseRate(value) {
|
||||
const numeric = Number(value);
|
||||
if (Number.isFinite(numeric) && numeric >= 0) {
|
||||
return {
|
||||
text: numeric.toFixed(4).replace(/0+$/, "").replace(/\.$/, ""),
|
||||
ratio: Math.max(0, Math.min(numeric, 100))
|
||||
};
|
||||
}
|
||||
return { text: "--", ratio: 0 };
|
||||
}
|
||||
|
||||
function formatUpdateTime(data) {
|
||||
if (data && typeof data.updated === "string" && data.updated.trim().length > 0) {
|
||||
return data.updated.trim();
|
||||
}
|
||||
if (data && typeof data.updated_at === "number" && Number.isFinite(data.updated_at)) {
|
||||
return new Date(data.updated_at).toLocaleString("zh-CN", { hour12: false });
|
||||
}
|
||||
return new Date().toLocaleString("zh-CN", { hour12: false });
|
||||
}
|
||||
|
||||
function renderInsights(list, gapSecond) {
|
||||
const total = Array.isArray(list) ? list.length : 0;
|
||||
programmeCountEl.textContent = total ? total.toString() : "--";
|
||||
|
||||
if (total) {
|
||||
const topMarket = list.reduce((max, item) => {
|
||||
const value = Number(item?.market_rate);
|
||||
return value > max ? value : max;
|
||||
}, 0);
|
||||
const topAttention = list.reduce((max, item) => {
|
||||
const value = Number(item?.attention_rate);
|
||||
return value > max ? value : max;
|
||||
}, 0);
|
||||
|
||||
topMarketRateEl.textContent = topMarket ? topMarket.toFixed(2) : "--";
|
||||
topAttentionRateEl.textContent = topAttention ? topAttention.toFixed(2) : "--";
|
||||
} else {
|
||||
topMarketRateEl.textContent = "--";
|
||||
topAttentionRateEl.textContent = "--";
|
||||
}
|
||||
|
||||
refreshGapEl.textContent = formatGapText(gapSecond);
|
||||
}
|
||||
|
||||
function createMetric(label, value) {
|
||||
return `
|
||||
<div class="metric">
|
||||
<span class="metric-label">${label}</span>
|
||||
<span class="metric-value">${safeText(value)}</span>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
function createProgrammeItem(programme, index) {
|
||||
const article = document.createElement("article");
|
||||
article.className = "programme-item";
|
||||
|
||||
const topClass = index < 3 ? ` top-${index + 1}` : "";
|
||||
const name = safeText(programme?.programme_name || "未命名节目");
|
||||
const channel = safeText(programme?.channel_name || "--");
|
||||
|
||||
const market = parseRate(programme?.market_rate);
|
||||
const attention = parseRate(programme?.attention_rate);
|
||||
const marketDesc = safeText(programme?.market_rate_desc || formatNumber(programme?.market_rate));
|
||||
const attentionDesc = safeText(programme?.attention_rate_desc || formatNumber(programme?.attention_rate));
|
||||
|
||||
article.innerHTML = `
|
||||
<div class="rank-badge${topClass}">${index + 1}</div>
|
||||
<div class="programme-body">
|
||||
<div class="programme-head">
|
||||
<div class="programme-name">${name}</div>
|
||||
<div class="channel-name">${channel}</div>
|
||||
</div>
|
||||
<div class="metric-grid">
|
||||
${createMetric("市场占有率", marketDesc)}
|
||||
${createMetric("关注指数", attentionDesc)}
|
||||
${createMetric("排序位置", `第 ${index + 1} 名`)}
|
||||
${createMetric("排名趋势", programme?.rank_trend ? safeText(programme.rank_trend) : "--")}
|
||||
</div>
|
||||
<div class="progress-trend">
|
||||
<div class="progress-row market">
|
||||
<div class="progress-label">
|
||||
<span>市场份额</span>
|
||||
<span>${market.text === "--" ? "--" : `${market.text}%`}</span>
|
||||
</div>
|
||||
<div class="progress-bar"><span style="width: ${market.ratio}%"></span></div>
|
||||
</div>
|
||||
<div class="progress-row attention">
|
||||
<div class="progress-label">
|
||||
<span>关注份额</span>
|
||||
<span>${attention.text === "--" ? "--" : `${attention.text}%`}</span>
|
||||
</div>
|
||||
<div class="progress-bar"><span style="width: ${attention.ratio}%"></span></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
return article;
|
||||
}
|
||||
|
||||
function renderProgrammeList(list) {
|
||||
programmeListEl.innerHTML = "";
|
||||
|
||||
if (!Array.isArray(list) || list.length === 0) {
|
||||
const empty = document.createElement("div");
|
||||
empty.className = "empty-message";
|
||||
empty.textContent = "暂时没有可展示的节目数据";
|
||||
programmeListEl.appendChild(empty);
|
||||
return;
|
||||
}
|
||||
|
||||
list.slice(0, MAX_ITEMS).forEach((item, index) => {
|
||||
programmeListEl.appendChild(createProgrammeItem(item, index));
|
||||
});
|
||||
}
|
||||
|
||||
async function requestJson(url) {
|
||||
const response = await fetch(url, { cache: "no-store" });
|
||||
if (!response.ok) {
|
||||
throw new Error(`请求失败: ${response.status}`);
|
||||
}
|
||||
return response.json();
|
||||
}
|
||||
|
||||
async function retrieveData() {
|
||||
for (const endpoint of API_ENDPOINTS) {
|
||||
try {
|
||||
const result = await requestJson(endpoint);
|
||||
if (result?.code === 200 && result?.data) {
|
||||
return result.data;
|
||||
}
|
||||
} catch (error) {
|
||||
console.warn("主接口请求失败", error);
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
const fallbackResult = await requestJson(FALLBACK_ENDPOINT);
|
||||
if (fallbackResult?.data) {
|
||||
return fallbackResult.data;
|
||||
}
|
||||
} catch (fallbackError) {
|
||||
console.warn("本地示例数据读取失败", fallbackError);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
async function loadData(isManual = false) {
|
||||
if (isLoading) {
|
||||
return;
|
||||
}
|
||||
|
||||
isLoading = true;
|
||||
|
||||
if (isManual) {
|
||||
refreshButton.disabled = true;
|
||||
refreshButton.textContent = "刷新中...";
|
||||
}
|
||||
|
||||
if (!programmeListEl.children.length) {
|
||||
programmeListEl.innerHTML = '<div class="loading">正在载入电视收视排行...</div>';
|
||||
}
|
||||
|
||||
try {
|
||||
const data = await retrieveData();
|
||||
if (!data) {
|
||||
throw new Error("无法获取数据");
|
||||
}
|
||||
|
||||
renderProgrammeList(Array.isArray(data.list) ? data.list : []);
|
||||
renderInsights(data.list, data.update_gap_second);
|
||||
updateTimeEl.textContent = `最近更新 ${formatUpdateTime(data)}`;
|
||||
} catch (error) {
|
||||
console.error("加载数据失败", error);
|
||||
programmeListEl.innerHTML = '';
|
||||
const errorBox = document.createElement("div");
|
||||
errorBox.className = "error-message";
|
||||
errorBox.textContent = "数据获取暂时不可用,系统稍后会自动重试";
|
||||
programmeListEl.appendChild(errorBox);
|
||||
updateTimeEl.textContent = "最近更新 --";
|
||||
renderInsights([], 0);
|
||||
} finally {
|
||||
if (isManual) {
|
||||
refreshButton.disabled = false;
|
||||
refreshButton.textContent = "手动刷新";
|
||||
}
|
||||
isLoading = false;
|
||||
}
|
||||
}
|
||||
|
||||
function startAutoRefresh() {
|
||||
if (autoTimer) {
|
||||
clearInterval(autoTimer);
|
||||
}
|
||||
autoTimer = setInterval(() => {
|
||||
loadData(false);
|
||||
}, REFRESH_INTERVAL);
|
||||
}
|
||||
|
||||
refreshButton.addEventListener("click", () => {
|
||||
loadData(true);
|
||||
});
|
||||
|
||||
document.addEventListener("visibilitychange", () => {
|
||||
if (document.hidden) {
|
||||
if (autoTimer) {
|
||||
clearInterval(autoTimer);
|
||||
autoTimer = null;
|
||||
}
|
||||
} else {
|
||||
startAutoRefresh();
|
||||
loadData(false);
|
||||
}
|
||||
});
|
||||
|
||||
function init() {
|
||||
loadData(false);
|
||||
startAutoRefresh();
|
||||
}
|
||||
|
||||
if (document.readyState === "loading") {
|
||||
document.addEventListener("DOMContentLoaded", init);
|
||||
} else {
|
||||
init();
|
||||
}
|
||||
435
InfoGenie-frontend/public/60sapi/热搜榜单/猫眼电视收视排行/返回接口.json
Normal file
435
InfoGenie-frontend/public/60sapi/热搜榜单/猫眼电视收视排行/返回接口.json
Normal file
@@ -0,0 +1,435 @@
|
||||
{
|
||||
"code": 200,
|
||||
"message": "获取成功。数据来自官方/权威源头,以确保稳定与实时。开源地址 https://github.com/vikiboss/60s,反馈群 595941841",
|
||||
"data": {
|
||||
"update_gap_second": 3,
|
||||
"updated": "2025-09-26 16:22:45",
|
||||
"updated_at": 1758874965018,
|
||||
"list": [
|
||||
{
|
||||
"programme_name": "六姊妹37",
|
||||
"channel_name": "CCTV-1",
|
||||
"market_rate": 16.1709,
|
||||
"market_rate_desc": "16.1709%",
|
||||
"attention_rate": 1.2816,
|
||||
"attention_rate_desc": "1.2816%"
|
||||
},
|
||||
{
|
||||
"programme_name": "太行山上6",
|
||||
"channel_name": "CCTV-4",
|
||||
"market_rate": 8.2684,
|
||||
"market_rate_desc": "8.2684%",
|
||||
"attention_rate": 0.6553,
|
||||
"attention_rate_desc": "0.6553%"
|
||||
},
|
||||
{
|
||||
"programme_name": "星推荐",
|
||||
"channel_name": "CCTV-8",
|
||||
"market_rate": 7.3725,
|
||||
"market_rate_desc": "7.3725%",
|
||||
"attention_rate": 0.5843,
|
||||
"attention_rate_desc": "0.5843%"
|
||||
},
|
||||
{
|
||||
"programme_name": "炮兵司令朱瑞",
|
||||
"channel_name": "CCTV-6",
|
||||
"market_rate": 7.3315,
|
||||
"market_rate_desc": "7.3315%",
|
||||
"attention_rate": 0.5811,
|
||||
"attention_rate_desc": "0.5811%"
|
||||
},
|
||||
{
|
||||
"programme_name": "新闻直播间",
|
||||
"channel_name": "CCTV-13",
|
||||
"market_rate": 4.4396,
|
||||
"market_rate_desc": "4.4396%",
|
||||
"attention_rate": 0.3519,
|
||||
"attention_rate_desc": "0.3519%"
|
||||
},
|
||||
{
|
||||
"programme_name": "百姓剧场二:征服15",
|
||||
"channel_name": "浙江卫视",
|
||||
"market_rate": 4.3651,
|
||||
"market_rate_desc": "4.3651%",
|
||||
"attention_rate": 0.346,
|
||||
"attention_rate_desc": "0.346%"
|
||||
},
|
||||
{
|
||||
"programme_name": "新相亲大会精华版",
|
||||
"channel_name": "江苏卫视",
|
||||
"market_rate": 4.0919,
|
||||
"market_rate_desc": "4.0919%",
|
||||
"attention_rate": 0.3243,
|
||||
"attention_rate_desc": "0.3243%"
|
||||
},
|
||||
{
|
||||
"programme_name": "青春独播剧场:底线11",
|
||||
"channel_name": "湖南卫视",
|
||||
"market_rate": 3.9014,
|
||||
"market_rate_desc": "3.9014%",
|
||||
"attention_rate": 0.3092,
|
||||
"attention_rate_desc": "0.3092%"
|
||||
},
|
||||
{
|
||||
"programme_name": "全景自然:黄石公园-飞翔的生命",
|
||||
"channel_name": "CCTV-9",
|
||||
"market_rate": 2.504,
|
||||
"market_rate_desc": "2.504%",
|
||||
"attention_rate": 0.1985,
|
||||
"attention_rate_desc": "0.1985%"
|
||||
},
|
||||
{
|
||||
"programme_name": "运动一起赢",
|
||||
"channel_name": "CCTV-5",
|
||||
"market_rate": 2.0781,
|
||||
"market_rate_desc": "2.0781%",
|
||||
"attention_rate": 0.1647,
|
||||
"attention_rate_desc": "0.1647%"
|
||||
},
|
||||
{
|
||||
"programme_name": "小日子19",
|
||||
"channel_name": "东方卫视",
|
||||
"market_rate": 1.9804,
|
||||
"market_rate_desc": "1.9804%",
|
||||
"attention_rate": 0.157,
|
||||
"attention_rate_desc": "0.157%"
|
||||
},
|
||||
{
|
||||
"programme_name": "向幸福出发",
|
||||
"channel_name": "CCTV-3",
|
||||
"market_rate": 1.8832,
|
||||
"market_rate_desc": "1.8832%",
|
||||
"attention_rate": 0.1493,
|
||||
"attention_rate_desc": "0.1493%"
|
||||
},
|
||||
{
|
||||
"programme_name": "浴血十四年16",
|
||||
"channel_name": "CCTV-7",
|
||||
"market_rate": 1.8485,
|
||||
"market_rate_desc": "1.8485%",
|
||||
"attention_rate": 0.1465,
|
||||
"attention_rate_desc": "0.1465%"
|
||||
},
|
||||
{
|
||||
"programme_name": "正点财经",
|
||||
"channel_name": "CCTV-2",
|
||||
"market_rate": 1.7255,
|
||||
"market_rate_desc": "1.7255%",
|
||||
"attention_rate": 0.1368,
|
||||
"attention_rate_desc": "0.1368%"
|
||||
},
|
||||
{
|
||||
"programme_name": "热播剧场:太行山上6",
|
||||
"channel_name": "深圳卫视",
|
||||
"market_rate": 1.6132,
|
||||
"market_rate_desc": "1.6132%",
|
||||
"attention_rate": 0.1279,
|
||||
"attention_rate_desc": "0.1279%"
|
||||
},
|
||||
{
|
||||
"programme_name": "爱家剧场:父母爱情37",
|
||||
"channel_name": "山东卫视",
|
||||
"market_rate": 1.5558,
|
||||
"market_rate_desc": "1.5558%",
|
||||
"attention_rate": 0.1233,
|
||||
"attention_rate_desc": "0.1233%"
|
||||
},
|
||||
{
|
||||
"programme_name": "刘家媳妇4",
|
||||
"channel_name": "CCTV-17",
|
||||
"market_rate": 1.3905,
|
||||
"market_rate_desc": "1.3905%",
|
||||
"attention_rate": 0.1102,
|
||||
"attention_rate_desc": "0.1102%"
|
||||
},
|
||||
{
|
||||
"programme_name": "午茶剧场:归队8",
|
||||
"channel_name": "北京卫视",
|
||||
"market_rate": 1.1078,
|
||||
"market_rate_desc": "1.1078%",
|
||||
"attention_rate": 0.0878,
|
||||
"attention_rate_desc": "0.0878%"
|
||||
},
|
||||
{
|
||||
"programme_name": "吉视剧场:武工队传奇46",
|
||||
"channel_name": "吉林卫视",
|
||||
"market_rate": 0.9407,
|
||||
"market_rate_desc": "0.9407%",
|
||||
"attention_rate": 0.0745,
|
||||
"attention_rate_desc": "0.0745%"
|
||||
},
|
||||
{
|
||||
"programme_name": "情感剧场:朱元璋64",
|
||||
"channel_name": "河北卫视",
|
||||
"market_rate": 0.9211,
|
||||
"market_rate_desc": "0.9211%",
|
||||
"attention_rate": 0.073,
|
||||
"attention_rate_desc": "0.073%"
|
||||
},
|
||||
{
|
||||
"programme_name": "下午剧场:战火青春3",
|
||||
"channel_name": "广东卫视",
|
||||
"market_rate": 0.9211,
|
||||
"market_rate_desc": "0.9211%",
|
||||
"attention_rate": 0.073,
|
||||
"attention_rate_desc": "0.073%"
|
||||
},
|
||||
{
|
||||
"programme_name": "探索.发现-奥秘54",
|
||||
"channel_name": "CCTV-10",
|
||||
"market_rate": 0.822,
|
||||
"market_rate_desc": "0.822%",
|
||||
"attention_rate": 0.0652,
|
||||
"attention_rate_desc": "0.0652%"
|
||||
},
|
||||
{
|
||||
"programme_name": "一线",
|
||||
"channel_name": "CCTV-12",
|
||||
"market_rate": 0.7949,
|
||||
"market_rate_desc": "0.7949%",
|
||||
"attention_rate": 0.063,
|
||||
"attention_rate_desc": "0.063%"
|
||||
},
|
||||
{
|
||||
"programme_name": "海豚真情剧场:重案六组Ⅱ-45",
|
||||
"channel_name": "安徽卫视",
|
||||
"market_rate": 0.7684,
|
||||
"market_rate_desc": "0.7684%",
|
||||
"attention_rate": 0.0609,
|
||||
"attention_rate_desc": "0.0609%"
|
||||
},
|
||||
{
|
||||
"programme_name": "中国女子围棋甲级联赛-第10轮",
|
||||
"channel_name": "CCTV-5+",
|
||||
"market_rate": 0.7621,
|
||||
"market_rate_desc": "0.7621%",
|
||||
"attention_rate": 0.0604,
|
||||
"attention_rate_desc": "0.0604%"
|
||||
},
|
||||
{
|
||||
"programme_name": "休闲剧场:女子特战队2",
|
||||
"channel_name": "天津卫视",
|
||||
"market_rate": 0.6694,
|
||||
"market_rate_desc": "0.6694%",
|
||||
"attention_rate": 0.0531,
|
||||
"attention_rate_desc": "0.0531%"
|
||||
},
|
||||
{
|
||||
"programme_name": "动画大放映:猪猪侠之超星五灵侠第八季",
|
||||
"channel_name": "CCTV-14",
|
||||
"market_rate": 0.6637,
|
||||
"market_rate_desc": "0.6637%",
|
||||
"attention_rate": 0.0526,
|
||||
"attention_rate_desc": "0.0526%"
|
||||
},
|
||||
{
|
||||
"programme_name": "昆仑剧场:康熙微服私访记第三部30",
|
||||
"channel_name": "青海卫视",
|
||||
"market_rate": 0.6511,
|
||||
"market_rate_desc": "0.6511%",
|
||||
"attention_rate": 0.0516,
|
||||
"attention_rate_desc": "0.0516%"
|
||||
},
|
||||
{
|
||||
"programme_name": "京剧电影工程-大闹天宫",
|
||||
"channel_name": "CCTV-11",
|
||||
"market_rate": 0.6069,
|
||||
"market_rate_desc": "0.6069%",
|
||||
"attention_rate": 0.0481,
|
||||
"attention_rate_desc": "0.0481%"
|
||||
},
|
||||
{
|
||||
"programme_name": "温情剧场:神探狄仁杰Ⅱ-14",
|
||||
"channel_name": "陕西卫视",
|
||||
"market_rate": 0.571,
|
||||
"market_rate_desc": "0.571%",
|
||||
"attention_rate": 0.0453,
|
||||
"attention_rate_desc": "0.0453%"
|
||||
},
|
||||
{
|
||||
"programme_name": "下午剧场:狙击部队30",
|
||||
"channel_name": "贵州卫视",
|
||||
"market_rate": 0.5558,
|
||||
"market_rate_desc": "0.5558%",
|
||||
"attention_rate": 0.0441,
|
||||
"attention_rate_desc": "0.0441%"
|
||||
},
|
||||
{
|
||||
"programme_name": "白天剧场:西游记26",
|
||||
"channel_name": "湖北卫视",
|
||||
"market_rate": 0.5463,
|
||||
"market_rate_desc": "0.5463%",
|
||||
"attention_rate": 0.0433,
|
||||
"attention_rate_desc": "0.0433%"
|
||||
},
|
||||
{
|
||||
"programme_name": "中国爱大剧场:神枪21",
|
||||
"channel_name": "四川卫视",
|
||||
"market_rate": 0.5388,
|
||||
"market_rate_desc": "0.5388%",
|
||||
"attention_rate": 0.0427,
|
||||
"attention_rate_desc": "0.0427%"
|
||||
},
|
||||
{
|
||||
"programme_name": "全民开麦",
|
||||
"channel_name": "CCTV-15",
|
||||
"market_rate": 0.4915,
|
||||
"market_rate_desc": "0.4915%",
|
||||
"attention_rate": 0.039,
|
||||
"attention_rate_desc": "0.039%"
|
||||
},
|
||||
{
|
||||
"programme_name": "下午剧场:仁心俱乐部10",
|
||||
"channel_name": "东南卫视",
|
||||
"market_rate": 0.4858,
|
||||
"market_rate_desc": "0.4858%",
|
||||
"attention_rate": 0.0385,
|
||||
"attention_rate_desc": "0.0385%"
|
||||
},
|
||||
{
|
||||
"programme_name": "生活服务",
|
||||
"channel_name": "江西卫视",
|
||||
"market_rate": 0.4113,
|
||||
"market_rate_desc": "0.4113%",
|
||||
"attention_rate": 0.0326,
|
||||
"attention_rate_desc": "0.0326%"
|
||||
},
|
||||
{
|
||||
"programme_name": "白天剧场:神医喜来乐25",
|
||||
"channel_name": "宁夏卫视",
|
||||
"market_rate": 0.4044,
|
||||
"market_rate_desc": "0.4044%",
|
||||
"attention_rate": 0.032,
|
||||
"attention_rate_desc": "0.032%"
|
||||
},
|
||||
{
|
||||
"programme_name": "传奇剧场:铁血玫瑰15",
|
||||
"channel_name": "黑龙江卫视",
|
||||
"market_rate": 0.4031,
|
||||
"market_rate_desc": "0.4031%",
|
||||
"attention_rate": 0.032,
|
||||
"attention_rate_desc": "0.032%"
|
||||
},
|
||||
{
|
||||
"programme_name": "经典剧场:亮剑30",
|
||||
"channel_name": "广西卫视",
|
||||
"market_rate": 0.3836,
|
||||
"market_rate_desc": "0.3836%",
|
||||
"attention_rate": 0.0304,
|
||||
"attention_rate_desc": "0.0304%"
|
||||
},
|
||||
{
|
||||
"programme_name": "中国网球公开赛-女单-第二轮",
|
||||
"channel_name": "CCTV-16",
|
||||
"market_rate": 0.3539,
|
||||
"market_rate_desc": "0.3539%",
|
||||
"attention_rate": 0.0281,
|
||||
"attention_rate_desc": "0.0281%"
|
||||
},
|
||||
{
|
||||
"programme_name": "生活服务",
|
||||
"channel_name": "河南卫视",
|
||||
"market_rate": 0.3413,
|
||||
"market_rate_desc": "0.3413%",
|
||||
"attention_rate": 0.0271,
|
||||
"attention_rate_desc": "0.0271%"
|
||||
},
|
||||
{
|
||||
"programme_name": "生活服务",
|
||||
"channel_name": "辽宁卫视",
|
||||
"market_rate": 0.3318,
|
||||
"market_rate_desc": "0.3318%",
|
||||
"attention_rate": 0.0263,
|
||||
"attention_rate_desc": "0.0263%"
|
||||
},
|
||||
{
|
||||
"programme_name": "传奇剧场:狼烟21",
|
||||
"channel_name": "内蒙古卫视",
|
||||
"market_rate": 0.3262,
|
||||
"market_rate_desc": "0.3262%",
|
||||
"attention_rate": 0.0258,
|
||||
"attention_rate_desc": "0.0258%"
|
||||
},
|
||||
{
|
||||
"programme_name": "炫酷剧场:薛平贵与王宝钏19",
|
||||
"channel_name": "云南卫视",
|
||||
"market_rate": 0.3079,
|
||||
"market_rate_desc": "0.3079%",
|
||||
"attention_rate": 0.0244,
|
||||
"attention_rate_desc": "0.0244%"
|
||||
},
|
||||
{
|
||||
"programme_name": "休闲剧场:历史转折中的邓小平17",
|
||||
"channel_name": "兵团卫视",
|
||||
"market_rate": 0.3035,
|
||||
"market_rate_desc": "0.3035%",
|
||||
"attention_rate": 0.0241,
|
||||
"attention_rate_desc": "0.0241%"
|
||||
},
|
||||
{
|
||||
"programme_name": "亮剑12",
|
||||
"channel_name": "重庆卫视",
|
||||
"market_rate": 0.2656,
|
||||
"market_rate_desc": "0.2656%",
|
||||
"attention_rate": 0.0211,
|
||||
"attention_rate_desc": "0.0211%"
|
||||
},
|
||||
{
|
||||
"programme_name": "阳光剧场:飞哥大英雄39",
|
||||
"channel_name": "海南卫视",
|
||||
"market_rate": 0.2643,
|
||||
"market_rate_desc": "0.2643%",
|
||||
"attention_rate": 0.021,
|
||||
"attention_rate_desc": "0.021%"
|
||||
},
|
||||
{
|
||||
"programme_name": "劫中劫15-17",
|
||||
"channel_name": "厦门卫视",
|
||||
"market_rate": 0.246,
|
||||
"market_rate_desc": "0.246%",
|
||||
"attention_rate": 0.0195,
|
||||
"attention_rate_desc": "0.0195%"
|
||||
},
|
||||
{
|
||||
"programme_name": "生活服务",
|
||||
"channel_name": "甘肃卫视",
|
||||
"market_rate": 0.2448,
|
||||
"market_rate_desc": "0.2448%",
|
||||
"attention_rate": 0.0194,
|
||||
"attention_rate_desc": "0.0194%"
|
||||
},
|
||||
{
|
||||
"programme_name": "花季剧场:神枪7",
|
||||
"channel_name": "中国教育台-1",
|
||||
"market_rate": 0.1703,
|
||||
"market_rate_desc": "0.1703%",
|
||||
"attention_rate": 0.0135,
|
||||
"attention_rate_desc": "0.0135%"
|
||||
},
|
||||
{
|
||||
"programme_name": "雪莲剧场:南来北往21",
|
||||
"channel_name": "西藏卫视",
|
||||
"market_rate": 0.1634,
|
||||
"market_rate_desc": "0.1634%",
|
||||
"attention_rate": 0.013,
|
||||
"attention_rate_desc": "0.013%"
|
||||
},
|
||||
{
|
||||
"programme_name": "生活服务",
|
||||
"channel_name": "山西卫视",
|
||||
"market_rate": 0.1438,
|
||||
"market_rate_desc": "0.1438%",
|
||||
"attention_rate": 0.0114,
|
||||
"attention_rate_desc": "0.0114%"
|
||||
},
|
||||
{
|
||||
"programme_name": "生活服务",
|
||||
"channel_name": "新疆卫视",
|
||||
"market_rate": 0.0656,
|
||||
"market_rate_desc": "0.0656%",
|
||||
"attention_rate": 0.0052,
|
||||
"attention_rate_desc": "0.0052%"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -52,7 +52,7 @@ body {
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', sans-serif;
|
||||
line-height: 1.6;
|
||||
color: var(--text-primary);
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
background: linear-gradient(135deg, #a8e6cf 0%, #dcedc1 50%, #ffd3a5 100%);
|
||||
min-height: 100vh;
|
||||
position: relative;
|
||||
overflow-x: hidden;
|
||||
@@ -67,11 +67,11 @@ body::before {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background:
|
||||
radial-gradient(circle at 20% 80%, rgba(120, 119, 198, 0.3) 0%, transparent 50%),
|
||||
radial-gradient(circle at 80% 20%, rgba(255, 119, 198, 0.3) 0%, transparent 50%),
|
||||
radial-gradient(circle at 40% 40%, rgba(120, 219, 255, 0.2) 0%, transparent 50%);
|
||||
radial-gradient(circle at 20% 80%, rgba(168, 230, 207, 0.15) 0%, transparent 40%),
|
||||
radial-gradient(circle at 80% 20%, rgba(220, 237, 193, 0.12) 0%, transparent 40%),
|
||||
radial-gradient(circle at 40% 40%, rgba(255, 211, 165, 0.1) 0%, transparent 40%);
|
||||
z-index: -1;
|
||||
animation: backgroundShift 20s ease-in-out infinite;
|
||||
animation: backgroundShift 30s ease-in-out infinite;
|
||||
}
|
||||
|
||||
@keyframes backgroundShift {
|
||||
@@ -90,11 +90,11 @@ body::before {
|
||||
max-width: 900px;
|
||||
margin: var(--space-lg) auto;
|
||||
padding: var(--space-xl);
|
||||
background: rgba(255, 255, 255, 0.95);
|
||||
backdrop-filter: blur(20px);
|
||||
background: rgba(255, 255, 255, 0.92);
|
||||
backdrop-filter: blur(15px);
|
||||
border-radius: var(--radius-xl);
|
||||
box-shadow: var(--shadow-xl);
|
||||
border: 1px solid rgba(255, 255, 255, 0.2);
|
||||
box-shadow: 0 8px 32px rgba(76, 175, 80, 0.15);
|
||||
border: 1px solid rgba(168, 230, 207, 0.3);
|
||||
position: relative;
|
||||
animation: slideUp 0.8s ease-out;
|
||||
}
|
||||
@@ -127,7 +127,7 @@ body::before {
|
||||
transform: translateX(-50%);
|
||||
width: 60px;
|
||||
height: 4px;
|
||||
background: linear-gradient(90deg, var(--primary-color), var(--secondary-color));
|
||||
background: linear-gradient(90deg, #4caf50, #81c784);
|
||||
border-radius: 2px;
|
||||
}
|
||||
|
||||
@@ -162,7 +162,7 @@ body::before {
|
||||
}
|
||||
|
||||
.header h1 .title-text {
|
||||
background: linear-gradient(135deg, var(--primary-color), var(--primary-light));
|
||||
background: linear-gradient(135deg, #2e7d32, #4caf50);
|
||||
-webkit-background-clip: text;
|
||||
background-clip: text;
|
||||
color: transparent;
|
||||
@@ -171,12 +171,12 @@ body::before {
|
||||
|
||||
.header h1 .update-badge {
|
||||
font-size: 0.4em;
|
||||
background: linear-gradient(135deg, var(--accent-color), var(--secondary-color));
|
||||
background: linear-gradient(135deg, #66bb6a, #a5d6a7);
|
||||
color: white;
|
||||
padding: var(--space-xs) var(--space-md);
|
||||
border-radius: var(--radius-xl);
|
||||
font-weight: 600;
|
||||
box-shadow: var(--shadow-md);
|
||||
box-shadow: 0 4px 6px rgba(76, 175, 80, 0.3);
|
||||
animation: pulse 3s infinite;
|
||||
white-space: nowrap;
|
||||
}
|
||||
@@ -210,8 +210,8 @@ body::before {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
margin: 0 auto var(--space-md);
|
||||
border: 3px solid var(--bg-tertiary);
|
||||
border-top: 3px solid var(--primary-color);
|
||||
border: 3px solid rgba(76, 175, 80, 0.2);
|
||||
border-top: 3px solid #4caf50;
|
||||
border-radius: 50%;
|
||||
animation: spin 1s linear infinite;
|
||||
}
|
||||
@@ -274,15 +274,15 @@ body::before {
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: linear-gradient(135deg, transparent 0%, rgba(102, 126, 234, 0.02) 100%);
|
||||
background: linear-gradient(135deg, transparent 0%, rgba(76, 175, 80, 0.03) 100%);
|
||||
opacity: 0;
|
||||
transition: opacity 0.3s ease;
|
||||
}
|
||||
|
||||
.movie-item:hover {
|
||||
transform: translateY(-4px);
|
||||
box-shadow: var(--shadow-lg);
|
||||
border-color: rgba(102, 126, 234, 0.2);
|
||||
box-shadow: 0 10px 25px rgba(76, 175, 80, 0.15);
|
||||
border-color: rgba(76, 175, 80, 0.3);
|
||||
}
|
||||
|
||||
.movie-item:hover::before {
|
||||
@@ -291,18 +291,18 @@ body::before {
|
||||
|
||||
/* 特殊排名样式 */
|
||||
.movie-item.top-1 {
|
||||
background: linear-gradient(135deg, rgba(255, 215, 0, 0.1) 0%, var(--bg-primary) 100%);
|
||||
border-color: rgba(255, 215, 0, 0.3);
|
||||
background: linear-gradient(135deg, rgba(76, 175, 80, 0.08) 0%, var(--bg-primary) 100%);
|
||||
border-color: rgba(76, 175, 80, 0.4);
|
||||
}
|
||||
|
||||
.movie-item.top-2 {
|
||||
background: linear-gradient(135deg, rgba(192, 192, 192, 0.1) 0%, var(--bg-primary) 100%);
|
||||
border-color: rgba(192, 192, 192, 0.3);
|
||||
background: linear-gradient(135deg, rgba(129, 199, 132, 0.06) 0%, var(--bg-primary) 100%);
|
||||
border-color: rgba(129, 199, 132, 0.3);
|
||||
}
|
||||
|
||||
.movie-item.top-3 {
|
||||
background: linear-gradient(135deg, rgba(205, 127, 50, 0.1) 0%, var(--bg-primary) 100%);
|
||||
border-color: rgba(205, 127, 50, 0.3);
|
||||
background: linear-gradient(135deg, rgba(165, 214, 167, 0.05) 0%, var(--bg-primary) 100%);
|
||||
border-color: rgba(165, 214, 167, 0.3);
|
||||
}
|
||||
|
||||
/* 排名徽章 */
|
||||
@@ -325,27 +325,27 @@ body::before {
|
||||
}
|
||||
|
||||
.movie-rank.gold {
|
||||
background: linear-gradient(135deg, #ffd700, #ffb700);
|
||||
background: linear-gradient(135deg, #2e7d32, #4caf50);
|
||||
color: white;
|
||||
box-shadow: 0 4px 15px rgba(255, 215, 0, 0.4);
|
||||
box-shadow: 0 4px 15px rgba(46, 125, 50, 0.4);
|
||||
}
|
||||
|
||||
.movie-rank.silver {
|
||||
background: linear-gradient(135deg, #c0c0c0, #a0a0a0);
|
||||
background: linear-gradient(135deg, #388e3c, #66bb6a);
|
||||
color: white;
|
||||
box-shadow: 0 4px 15px rgba(192, 192, 192, 0.4);
|
||||
box-shadow: 0 4px 15px rgba(56, 142, 60, 0.4);
|
||||
}
|
||||
|
||||
.movie-rank.bronze {
|
||||
background: linear-gradient(135deg, #cd7f32, #b06728);
|
||||
background: linear-gradient(135deg, #4caf50, #81c784);
|
||||
color: white;
|
||||
box-shadow: 0 4px 15px rgba(205, 127, 50, 0.4);
|
||||
box-shadow: 0 4px 15px rgba(76, 175, 80, 0.4);
|
||||
}
|
||||
|
||||
.movie-rank.regular {
|
||||
background: linear-gradient(135deg, var(--primary-color), var(--accent-color));
|
||||
background: linear-gradient(135deg, #66bb6a, #a5d6a7);
|
||||
color: white;
|
||||
box-shadow: 0 4px 15px rgba(102, 126, 234, 0.3);
|
||||
box-shadow: 0 4px 15px rgba(102, 187, 106, 0.3);
|
||||
}
|
||||
|
||||
/* 电影内容 */
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
.background-canvas {
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
z-index: -1;
|
||||
overflow: hidden;
|
||||
background: linear-gradient(180deg, #f4fff6 0%, #e7f8eb 45%, #def1e4 100%);
|
||||
}
|
||||
|
||||
.glow {
|
||||
position: absolute;
|
||||
width: 420px;
|
||||
height: 420px;
|
||||
border-radius: 55% 45% 60% 40% / 48% 52% 45% 55%;
|
||||
opacity: 0.25;
|
||||
filter: blur(0px);
|
||||
background: radial-gradient(circle at 35% 35%, rgba(140, 214, 167, 0.65), rgba(140, 214, 167, 0));
|
||||
animation: floaty 32s ease-in-out infinite;
|
||||
}
|
||||
|
||||
.glow-1 {
|
||||
top: -140px;
|
||||
left: -160px;
|
||||
animation-delay: 0s;
|
||||
}
|
||||
|
||||
.glow-2 {
|
||||
top: 55%;
|
||||
left: 60%;
|
||||
animation-delay: 8s;
|
||||
background: radial-gradient(circle at 60% 60%, rgba(120, 192, 152, 0.55), rgba(120, 192, 152, 0));
|
||||
}
|
||||
|
||||
.glow-3 {
|
||||
bottom: -160px;
|
||||
right: -120px;
|
||||
animation-delay: 16s;
|
||||
background: radial-gradient(circle at 40% 40%, rgba(176, 229, 197, 0.6), rgba(176, 229, 197, 0));
|
||||
}
|
||||
|
||||
@keyframes floaty {
|
||||
0% {
|
||||
transform: translate3d(0, 0, 0) scale(1);
|
||||
}
|
||||
30% {
|
||||
transform: translate3d(35px, -25px, 0) scale(1.05);
|
||||
}
|
||||
60% {
|
||||
transform: translate3d(-30px, 30px, 0) scale(0.95);
|
||||
}
|
||||
100% {
|
||||
transform: translate3d(0, 0, 0) scale(1);
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.glow {
|
||||
width: 260px;
|
||||
height: 260px;
|
||||
opacity: 0.22;
|
||||
}
|
||||
|
||||
.glow-1 {
|
||||
top: -110px;
|
||||
left: -140px;
|
||||
}
|
||||
|
||||
.glow-2 {
|
||||
top: 48%;
|
||||
left: 38%;
|
||||
}
|
||||
|
||||
.glow-3 {
|
||||
bottom: -140px;
|
||||
right: -120px;
|
||||
}
|
||||
}
|
||||
393
InfoGenie-frontend/public/60sapi/热搜榜单/猫眼网剧实时热度/css/style.css
Normal file
393
InfoGenie-frontend/public/60sapi/热搜榜单/猫眼网剧实时热度/css/style.css
Normal file
@@ -0,0 +1,393 @@
|
||||
:root {
|
||||
--surface-base: rgba(255, 255, 255, 0.85);
|
||||
--surface-soft: rgba(248, 253, 249, 0.9);
|
||||
--border-soft: rgba(120, 192, 152, 0.22);
|
||||
--accent-strong: #4caf7a;
|
||||
--accent-soft: #8fd5a4;
|
||||
--accent-pale: #c6efd5;
|
||||
--text-primary: #134a32;
|
||||
--text-muted: #528169;
|
||||
--chip-bg: rgba(140, 214, 167, 0.18);
|
||||
--shadow-soft: 0 16px 40px rgba(31, 74, 53, 0.14);
|
||||
color-scheme: light;
|
||||
}
|
||||
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
body {
|
||||
font-family: "PingFang SC", "Microsoft YaHei", "Helvetica Neue", Arial, sans-serif;
|
||||
color: var(--text-primary);
|
||||
background: transparent;
|
||||
line-height: 1.6;
|
||||
min-height: 100vh;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
}
|
||||
|
||||
.app {
|
||||
width: min(100%, 930px);
|
||||
margin: 0 auto;
|
||||
padding: 20px 16px 80px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 18px;
|
||||
}
|
||||
|
||||
.hero {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 18px;
|
||||
background: var(--surface-base);
|
||||
border: 1px solid var(--border-soft);
|
||||
border-radius: 22px;
|
||||
padding: 22px 18px;
|
||||
box-shadow: var(--shadow-soft);
|
||||
backdrop-filter: blur(16px);
|
||||
}
|
||||
|
||||
.hero-text {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.badge {
|
||||
align-self: flex-start;
|
||||
padding: 4px 12px;
|
||||
font-size: 0.82rem;
|
||||
letter-spacing: 0.08em;
|
||||
border-radius: 999px;
|
||||
background: var(--chip-bg);
|
||||
color: var(--accent-strong);
|
||||
}
|
||||
|
||||
.hero h1 {
|
||||
font-size: 1.65rem;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.subtitle {
|
||||
color: var(--text-muted);
|
||||
font-size: 0.96rem;
|
||||
}
|
||||
|
||||
.hero-actions {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.refresh {
|
||||
padding: 10px 20px;
|
||||
border-radius: 999px;
|
||||
border: none;
|
||||
background: linear-gradient(135deg, #66bb86, #4caf7a);
|
||||
color: #ffffff;
|
||||
font-size: 0.95rem;
|
||||
font-weight: 600;
|
||||
cursor: pointer;
|
||||
box-shadow: 0 12px 30px rgba(76, 175, 122, 0.36);
|
||||
transition: transform 0.2s ease, box-shadow 0.2s ease;
|
||||
}
|
||||
|
||||
.refresh:active {
|
||||
transform: scale(0.97);
|
||||
}
|
||||
|
||||
.refresh:disabled {
|
||||
opacity: 0.65;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
.update-time {
|
||||
font-size: 0.85rem;
|
||||
color: var(--text-muted);
|
||||
}
|
||||
|
||||
.quick-stats {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.stat-card {
|
||||
background: var(--surface-soft);
|
||||
border-radius: 18px;
|
||||
border: 1px solid rgba(143, 213, 164, 0.24);
|
||||
padding: 16px 18px;
|
||||
box-shadow: var(--shadow-soft);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 6px;
|
||||
}
|
||||
|
||||
.stat-label {
|
||||
font-size: 0.84rem;
|
||||
color: var(--text-muted);
|
||||
letter-spacing: 0.04em;
|
||||
}
|
||||
|
||||
.stat-value {
|
||||
font-size: 1.35rem;
|
||||
font-weight: 700;
|
||||
color: var(--accent-strong);
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
gap: 4px;
|
||||
}
|
||||
|
||||
.stat-value .unit {
|
||||
font-size: 0.9rem;
|
||||
font-weight: 500;
|
||||
color: var(--text-muted);
|
||||
}
|
||||
|
||||
.list-section {
|
||||
background: var(--surface-base);
|
||||
border: 1px solid var(--border-soft);
|
||||
border-radius: 24px;
|
||||
padding: 24px 18px 28px;
|
||||
box-shadow: var(--shadow-soft);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 18px;
|
||||
}
|
||||
|
||||
.list-header {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 6px;
|
||||
}
|
||||
|
||||
.list-header h2 {
|
||||
font-size: 1.28rem;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.list-tag {
|
||||
font-size: 0.88rem;
|
||||
color: var(--text-muted);
|
||||
}
|
||||
|
||||
.series-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 14px;
|
||||
}
|
||||
|
||||
.loading,
|
||||
.error-message,
|
||||
.empty-message {
|
||||
padding: 18px 16px;
|
||||
text-align: center;
|
||||
color: var(--text-muted);
|
||||
background: rgba(255, 255, 255, 0.75);
|
||||
border-radius: 14px;
|
||||
border: 1px dashed rgba(120, 192, 152, 0.32);
|
||||
}
|
||||
|
||||
.series-item {
|
||||
display: grid;
|
||||
grid-template-columns: auto 1fr;
|
||||
gap: 14px;
|
||||
background: rgba(255, 255, 255, 0.92);
|
||||
border-radius: 20px;
|
||||
border: 1px solid rgba(120, 192, 152, 0.2);
|
||||
padding: 16px;
|
||||
box-shadow: 0 14px 32px rgba(31, 74, 53, 0.12);
|
||||
transition: transform 0.2s ease, box-shadow 0.2s ease;
|
||||
}
|
||||
|
||||
.series-item:hover {
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 18px 40px rgba(31, 74, 53, 0.16);
|
||||
}
|
||||
|
||||
.rank-pill {
|
||||
width: 44px;
|
||||
height: 44px;
|
||||
border-radius: 14px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-weight: 700;
|
||||
font-size: 1.05rem;
|
||||
color: #ffffff;
|
||||
background: linear-gradient(135deg, #7ed49b, #5cc88a);
|
||||
}
|
||||
|
||||
.rank-pill.top-1 {
|
||||
background: linear-gradient(135deg, #5cc88a, #3da36b);
|
||||
}
|
||||
|
||||
.rank-pill.top-2 {
|
||||
background: linear-gradient(135deg, #72d0a0, #55be85);
|
||||
}
|
||||
|
||||
.rank-pill.top-3 {
|
||||
background: linear-gradient(135deg, #8fe0b4, #6fd09a);
|
||||
}
|
||||
|
||||
.series-body {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.series-head {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 6px;
|
||||
}
|
||||
|
||||
.series-name {
|
||||
font-size: 1.05rem;
|
||||
font-weight: 700;
|
||||
color: var(--text-primary);
|
||||
}
|
||||
|
||||
.series-meta {
|
||||
font-size: 0.9rem;
|
||||
color: var(--text-muted);
|
||||
}
|
||||
|
||||
.metric-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
gap: 10px 14px;
|
||||
}
|
||||
|
||||
.metric {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 2px;
|
||||
}
|
||||
|
||||
.metric-label {
|
||||
font-size: 0.78rem;
|
||||
color: var(--text-muted);
|
||||
letter-spacing: 0.04em;
|
||||
}
|
||||
|
||||
.metric-value {
|
||||
font-size: 0.98rem;
|
||||
font-weight: 600;
|
||||
color: var(--accent-strong);
|
||||
}
|
||||
|
||||
.progress-wrap {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 6px;
|
||||
margin-top: 6px;
|
||||
}
|
||||
|
||||
.progress-row {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 4px;
|
||||
}
|
||||
|
||||
.progress-label {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
font-size: 0.8rem;
|
||||
color: var(--text-muted);
|
||||
}
|
||||
|
||||
.progress-bar {
|
||||
width: 100%;
|
||||
height: 6px;
|
||||
border-radius: 6px;
|
||||
background: rgba(120, 192, 152, 0.18);
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.progress-bar span {
|
||||
display: block;
|
||||
height: 100%;
|
||||
border-radius: inherit;
|
||||
background: linear-gradient(135deg, rgba(120, 192, 152, 0.9), rgba(76, 175, 122, 0.95));
|
||||
width: 0;
|
||||
transition: width 0.45s ease;
|
||||
}
|
||||
|
||||
/* Tablet */
|
||||
@media (min-width: 600px) {
|
||||
.app {
|
||||
padding: 26px 20px 96px;
|
||||
gap: 22px;
|
||||
}
|
||||
|
||||
.hero {
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 26px 28px;
|
||||
}
|
||||
|
||||
.hero h1 {
|
||||
font-size: 1.9rem;
|
||||
}
|
||||
|
||||
.hero-actions {
|
||||
align-items: flex-end;
|
||||
}
|
||||
|
||||
.quick-stats {
|
||||
grid-template-columns: repeat(4, minmax(0, 1fr));
|
||||
gap: 16px;
|
||||
}
|
||||
|
||||
.series-item {
|
||||
grid-template-columns: 70px 1fr;
|
||||
padding: 18px 22px;
|
||||
}
|
||||
|
||||
.rank-pill {
|
||||
width: 54px;
|
||||
height: 54px;
|
||||
font-size: 1.2rem;
|
||||
}
|
||||
|
||||
.metric-grid {
|
||||
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||||
}
|
||||
}
|
||||
|
||||
/* Desktop */
|
||||
@media (min-width: 1024px) {
|
||||
.app {
|
||||
padding: 34px 24px 110px;
|
||||
}
|
||||
|
||||
.list-section {
|
||||
padding: 30px 32px 36px;
|
||||
}
|
||||
|
||||
.series-item {
|
||||
grid-template-columns: 96px 1fr;
|
||||
padding: 22px 26px;
|
||||
}
|
||||
|
||||
.series-name {
|
||||
font-size: 1.22rem;
|
||||
}
|
||||
|
||||
.metric-grid {
|
||||
grid-template-columns: repeat(4, minmax(0, 1fr));
|
||||
}
|
||||
}
|
||||
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
* {
|
||||
animation-duration: 0.01ms !important;
|
||||
animation-iteration-count: 1 !important;
|
||||
transition-duration: 0.01ms !important;
|
||||
scroll-behavior: auto !important;
|
||||
}
|
||||
}
|
||||
62
InfoGenie-frontend/public/60sapi/热搜榜单/猫眼网剧实时热度/index.html
Normal file
62
InfoGenie-frontend/public/60sapi/热搜榜单/猫眼网剧实时热度/index.html
Normal file
@@ -0,0 +1,62 @@
|
||||
<!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/background.css">
|
||||
<link rel="stylesheet" href="./css/style.css">
|
||||
</head>
|
||||
<body>
|
||||
<div class="background-canvas">
|
||||
<div class="glow glow-1"></div>
|
||||
<div class="glow glow-2"></div>
|
||||
<div class="glow glow-3"></div>
|
||||
</div>
|
||||
|
||||
<div class="app">
|
||||
<header class="hero">
|
||||
<div class="hero-text">
|
||||
<span class="badge">实时热度</span>
|
||||
<h1>猫眼网剧实时热度</h1>
|
||||
<p class="subtitle">网剧热度榜单即时更新,洞察全网追剧风向</p>
|
||||
</div>
|
||||
<div class="hero-actions">
|
||||
<button type="button" id="refreshButton" class="refresh">手动刷新</button>
|
||||
<span id="updateTime" class="update-time">正在获取最新数据...</span>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<section class="quick-stats" id="quickStats">
|
||||
<div class="stat-card">
|
||||
<p class="stat-label">上榜剧集</p>
|
||||
<p class="stat-value" id="seriesCount">--</p>
|
||||
</div>
|
||||
<div class="stat-card">
|
||||
<p class="stat-label">最高热度值</p>
|
||||
<p class="stat-value"><span id="topHeat">--</span><span class="unit">热度</span></p>
|
||||
</div>
|
||||
<div class="stat-card">
|
||||
<p class="stat-label">平均热度值</p>
|
||||
<p class="stat-value"><span id="avgHeat">--</span><span class="unit">热度</span></p>
|
||||
</div>
|
||||
<div class="stat-card">
|
||||
<p class="stat-label">官方刷新频率</p>
|
||||
<p class="stat-value" id="refreshGap">--</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="list-section">
|
||||
<div class="list-header">
|
||||
<h2>网剧热度排行</h2>
|
||||
<span class="list-tag">数据持续刷新</span>
|
||||
</div>
|
||||
<div id="seriesList" class="series-list">
|
||||
<div class="loading">正在载入网剧热度...</div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<script src="./js/main.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
293
InfoGenie-frontend/public/60sapi/热搜榜单/猫眼网剧实时热度/js/main.js
Normal file
293
InfoGenie-frontend/public/60sapi/热搜榜单/猫眼网剧实时热度/js/main.js
Normal file
@@ -0,0 +1,293 @@
|
||||
const API_ENDPOINTS = [
|
||||
"https://60s.api.shumengya.top/v2/maoyan/realtime/web"
|
||||
];
|
||||
|
||||
const FALLBACK_ENDPOINT = "./返回接口.json";
|
||||
const REFRESH_INTERVAL = 4500;
|
||||
const MAX_ITEMS = 40;
|
||||
|
||||
const refreshButton = document.getElementById("refreshButton");
|
||||
const updateTimeEl = document.getElementById("updateTime");
|
||||
const seriesListEl = document.getElementById("seriesList");
|
||||
const seriesCountEl = document.getElementById("seriesCount");
|
||||
const topHeatEl = document.getElementById("topHeat");
|
||||
const avgHeatEl = document.getElementById("avgHeat");
|
||||
const refreshGapEl = document.getElementById("refreshGap");
|
||||
|
||||
let isLoading = false;
|
||||
let autoTimer = null;
|
||||
|
||||
function escapeHtml(value) {
|
||||
if (value === undefined || value === null) {
|
||||
return "";
|
||||
}
|
||||
return String(value)
|
||||
.replace(/&/g, "&")
|
||||
.replace(/</g, "<")
|
||||
.replace(/>/g, ">")
|
||||
.replace(/"/g, """)
|
||||
.replace(/'/g, "'");
|
||||
}
|
||||
|
||||
function safeText(value, fallback = "--") {
|
||||
if (value === undefined || value === null || value === "") {
|
||||
return fallback;
|
||||
}
|
||||
return escapeHtml(value);
|
||||
}
|
||||
|
||||
function formatNumber(value, fractionDigits = 2) {
|
||||
const numeric = Number(value);
|
||||
if (!Number.isFinite(numeric)) {
|
||||
return "--";
|
||||
}
|
||||
return numeric.toFixed(fractionDigits);
|
||||
}
|
||||
|
||||
function formatGap(seconds) {
|
||||
const numeric = Number(seconds);
|
||||
if (!Number.isFinite(numeric) || numeric <= 0) {
|
||||
return "--";
|
||||
}
|
||||
|
||||
if (numeric < 60) {
|
||||
return `约每 ${Math.round(numeric)} 秒`;
|
||||
}
|
||||
|
||||
const minutes = Math.floor(numeric / 60);
|
||||
const remainder = Math.round(numeric % 60);
|
||||
if (remainder === 0) {
|
||||
return `约每 ${minutes} 分钟`;
|
||||
}
|
||||
return `约每 ${minutes} 分 ${remainder} 秒`;
|
||||
}
|
||||
|
||||
function formatUpdateTime(data) {
|
||||
if (data && typeof data.updated === "string" && data.updated.trim()) {
|
||||
return data.updated.trim();
|
||||
}
|
||||
if (data && typeof data.updated_at === "number" && Number.isFinite(data.updated_at)) {
|
||||
return new Date(data.updated_at).toLocaleString("zh-CN", { hour12: false });
|
||||
}
|
||||
return new Date().toLocaleString("zh-CN", { hour12: false });
|
||||
}
|
||||
|
||||
function renderStats(list, gapSeconds) {
|
||||
const total = Array.isArray(list) ? list.length : 0;
|
||||
seriesCountEl.textContent = total ? total.toString() : "--";
|
||||
|
||||
if (total) {
|
||||
let maxHeat = 0;
|
||||
let sumHeat = 0;
|
||||
list.forEach(item => {
|
||||
const heat = Number(item?.curr_heat);
|
||||
if (Number.isFinite(heat)) {
|
||||
if (heat > maxHeat) {
|
||||
maxHeat = heat;
|
||||
}
|
||||
sumHeat += heat;
|
||||
}
|
||||
});
|
||||
|
||||
topHeatEl.textContent = maxHeat ? maxHeat.toFixed(2) : "--";
|
||||
const average = sumHeat && total ? (sumHeat / total) : 0;
|
||||
avgHeatEl.textContent = average ? average.toFixed(2) : "--";
|
||||
} else {
|
||||
topHeatEl.textContent = "--";
|
||||
avgHeatEl.textContent = "--";
|
||||
}
|
||||
|
||||
refreshGapEl.textContent = formatGap(gapSeconds);
|
||||
}
|
||||
|
||||
function createMetric(label, value) {
|
||||
return `
|
||||
<div class="metric">
|
||||
<span class="metric-label">${label}</span>
|
||||
<span class="metric-value">${safeText(value)}</span>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
function normalizeBarValue(list) {
|
||||
let maxValue = 0;
|
||||
if (Array.isArray(list)) {
|
||||
list.forEach(item => {
|
||||
const bar = Number(item?.bar_value ?? item?.curr_heat);
|
||||
if (Number.isFinite(bar) && bar > maxValue) {
|
||||
maxValue = bar;
|
||||
}
|
||||
});
|
||||
}
|
||||
return maxValue || 1;
|
||||
}
|
||||
|
||||
function createSeriesItem(series, index, maxBar) {
|
||||
const article = document.createElement("article");
|
||||
article.className = "series-item";
|
||||
|
||||
const rankClass = index < 3 ? ` top-${index + 1}` : "";
|
||||
const name = safeText(series?.series_name || "未命名剧集");
|
||||
const releaseInfo = safeText(series?.release_info || "--");
|
||||
const platform = safeText(series?.platform_desc || "--");
|
||||
const heatDesc = safeText(series?.curr_heat_desc || formatNumber(series?.curr_heat));
|
||||
|
||||
const barValue = Number(series?.bar_value ?? series?.curr_heat);
|
||||
const ratio = Number.isFinite(barValue) && maxBar > 0 ? Math.min(100, Math.max(0, (barValue / maxBar) * 100)) : 0;
|
||||
|
||||
article.innerHTML = `
|
||||
<div class="rank-pill${rankClass}">${index + 1}</div>
|
||||
<div class="series-body">
|
||||
<div class="series-head">
|
||||
<div class="series-name">${name}</div>
|
||||
<div class="series-meta">${releaseInfo} · ${platform}</div>
|
||||
</div>
|
||||
<div class="metric-grid">
|
||||
${createMetric("实时热度", heatDesc)}
|
||||
${createMetric("上线信息", releaseInfo)}
|
||||
${createMetric("播出平台", platform)}
|
||||
${createMetric("剧集ID", safeText(series?.series_id))}
|
||||
</div>
|
||||
<div class="progress-wrap">
|
||||
<div class="progress-row">
|
||||
<div class="progress-label">
|
||||
<span>热度走势</span>
|
||||
<span>${heatDesc}</span>
|
||||
</div>
|
||||
<div class="progress-bar"><span style="width: ${ratio}%"></span></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
return article;
|
||||
}
|
||||
|
||||
function renderSeriesList(list) {
|
||||
seriesListEl.innerHTML = "";
|
||||
|
||||
if (!Array.isArray(list) || list.length === 0) {
|
||||
const empty = document.createElement("div");
|
||||
empty.className = "empty-message";
|
||||
empty.textContent = "暂时没有可展示的剧集数据";
|
||||
seriesListEl.appendChild(empty);
|
||||
return;
|
||||
}
|
||||
|
||||
const maxBar = normalizeBarValue(list);
|
||||
list.slice(0, MAX_ITEMS).forEach((series, index) => {
|
||||
seriesListEl.appendChild(createSeriesItem(series, index, maxBar));
|
||||
});
|
||||
}
|
||||
|
||||
async function requestJson(url) {
|
||||
const response = await fetch(url, { cache: "no-store" });
|
||||
if (!response.ok) {
|
||||
throw new Error(`请求失败: ${response.status}`);
|
||||
}
|
||||
return response.json();
|
||||
}
|
||||
|
||||
async function retrieveData() {
|
||||
for (const endpoint of API_ENDPOINTS) {
|
||||
try {
|
||||
const result = await requestJson(endpoint);
|
||||
if (result?.code === 200 && result?.data) {
|
||||
return result.data;
|
||||
}
|
||||
} catch (error) {
|
||||
console.warn("主接口请求失败", error);
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
const fallbackResult = await requestJson(FALLBACK_ENDPOINT);
|
||||
if (fallbackResult?.data) {
|
||||
return fallbackResult.data;
|
||||
}
|
||||
} catch (fallbackError) {
|
||||
console.warn("本地示例数据读取失败", fallbackError);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
async function loadData(isManual = false) {
|
||||
if (isLoading) {
|
||||
return;
|
||||
}
|
||||
|
||||
isLoading = true;
|
||||
|
||||
if (isManual) {
|
||||
refreshButton.disabled = true;
|
||||
refreshButton.textContent = "刷新中...";
|
||||
}
|
||||
|
||||
if (!seriesListEl.children.length) {
|
||||
seriesListEl.innerHTML = '<div class="loading">正在载入网剧热度...</div>';
|
||||
}
|
||||
|
||||
try {
|
||||
const data = await retrieveData();
|
||||
if (!data) {
|
||||
throw new Error("无法获取数据");
|
||||
}
|
||||
|
||||
const list = Array.isArray(data.list) ? data.list : [];
|
||||
renderSeriesList(list);
|
||||
renderStats(list, data.update_gap_second);
|
||||
updateTimeEl.textContent = `最近更新 ${formatUpdateTime(data)}`;
|
||||
} catch (error) {
|
||||
console.error("加载数据失败", error);
|
||||
seriesListEl.innerHTML = "";
|
||||
const errBox = document.createElement("div");
|
||||
errBox.className = "error-message";
|
||||
errBox.textContent = "数据获取暂时不可用,系统稍后会自动重试";
|
||||
seriesListEl.appendChild(errBox);
|
||||
updateTimeEl.textContent = "最近更新 --";
|
||||
renderStats([], 0);
|
||||
} finally {
|
||||
if (isManual) {
|
||||
refreshButton.disabled = false;
|
||||
refreshButton.textContent = "手动刷新";
|
||||
}
|
||||
isLoading = false;
|
||||
}
|
||||
}
|
||||
|
||||
function startAutoRefresh() {
|
||||
if (autoTimer) {
|
||||
clearInterval(autoTimer);
|
||||
}
|
||||
autoTimer = setInterval(() => {
|
||||
loadData(false);
|
||||
}, REFRESH_INTERVAL);
|
||||
}
|
||||
|
||||
refreshButton.addEventListener("click", () => {
|
||||
loadData(true);
|
||||
});
|
||||
|
||||
document.addEventListener("visibilitychange", () => {
|
||||
if (document.hidden) {
|
||||
if (autoTimer) {
|
||||
clearInterval(autoTimer);
|
||||
autoTimer = null;
|
||||
}
|
||||
} else {
|
||||
startAutoRefresh();
|
||||
loadData(false);
|
||||
}
|
||||
});
|
||||
|
||||
function init() {
|
||||
loadData(false);
|
||||
startAutoRefresh();
|
||||
}
|
||||
|
||||
if (document.readyState === "loading") {
|
||||
document.addEventListener("DOMContentLoaded", init);
|
||||
} else {
|
||||
init();
|
||||
}
|
||||
311
InfoGenie-frontend/public/60sapi/热搜榜单/猫眼网剧实时热度/返回接口.json
Normal file
311
InfoGenie-frontend/public/60sapi/热搜榜单/猫眼网剧实时热度/返回接口.json
Normal file
@@ -0,0 +1,311 @@
|
||||
{
|
||||
"code": 200,
|
||||
"message": "获取成功。数据来自官方/权威源头,以确保稳定与实时。开源地址 https://github.com/vikiboss/60s,反馈群 595941841",
|
||||
"data": {
|
||||
"update_gap_second": 3,
|
||||
"updated": "2025-09-26 16:36:56",
|
||||
"updated_at": 1758875816062,
|
||||
"list": [
|
||||
{
|
||||
"series_id": 1517707,
|
||||
"series_name": "赴山海",
|
||||
"release_info": "上线16天",
|
||||
"platform_desc": "多平台播放",
|
||||
"platform_txt": -1,
|
||||
"curr_heat": 6290.29,
|
||||
"curr_heat_desc": "6290.29",
|
||||
"bar_value": 6290.29
|
||||
},
|
||||
{
|
||||
"series_id": 1528168,
|
||||
"series_name": "许我耀眼",
|
||||
"release_info": "上线首日",
|
||||
"platform_desc": "腾讯视频独播",
|
||||
"platform_txt": -1,
|
||||
"curr_heat": 6231.35,
|
||||
"curr_heat_desc": "6231.35",
|
||||
"bar_value": 5749.54721862606
|
||||
},
|
||||
{
|
||||
"series_id": 1528151,
|
||||
"series_name": "欢乐家长群2",
|
||||
"release_info": "上线12天",
|
||||
"platform_desc": "芒果TV独播",
|
||||
"platform_txt": -1,
|
||||
"curr_heat": 6012.95,
|
||||
"curr_heat_desc": "6012.95",
|
||||
"bar_value": 5119.06438712135
|
||||
},
|
||||
{
|
||||
"series_id": 1492955,
|
||||
"series_name": "吴邪私家笔记",
|
||||
"release_info": "上线7天",
|
||||
"platform_desc": "腾讯视频独播",
|
||||
"platform_txt": -1,
|
||||
"curr_heat": 5851.91,
|
||||
"curr_heat_desc": "5851.91",
|
||||
"bar_value": 4596.76326056356
|
||||
},
|
||||
{
|
||||
"series_id": 1538034,
|
||||
"series_name": "不眠日",
|
||||
"release_info": "上线10天",
|
||||
"platform_desc": "多平台播放",
|
||||
"platform_txt": -1,
|
||||
"curr_heat": 5804.09,
|
||||
"curr_heat_desc": "5804.09",
|
||||
"bar_value": 4206.68639815508
|
||||
},
|
||||
{
|
||||
"series_id": 1501684,
|
||||
"series_name": "灼灼韶华",
|
||||
"release_info": "上线16天",
|
||||
"platform_desc": "优酷独播",
|
||||
"platform_txt": 0,
|
||||
"curr_heat": 5799.01,
|
||||
"curr_heat_desc": "5799.01",
|
||||
"bar_value": 3878.03171596132
|
||||
},
|
||||
{
|
||||
"series_id": 1474248,
|
||||
"series_name": "围猎",
|
||||
"release_info": "上线2天",
|
||||
"platform_desc": "多平台播放",
|
||||
"platform_txt": -1,
|
||||
"curr_heat": 5752.05,
|
||||
"curr_heat_desc": "5752.05",
|
||||
"bar_value": 3549.20963005863
|
||||
},
|
||||
{
|
||||
"series_id": 1501687,
|
||||
"series_name": "守护者们",
|
||||
"release_info": "上线4天",
|
||||
"platform_desc": "多平台播放",
|
||||
"platform_txt": -1,
|
||||
"curr_heat": 5730.63,
|
||||
"curr_heat_desc": "5730.63",
|
||||
"bar_value": 3262.59275525736
|
||||
},
|
||||
{
|
||||
"series_id": 1520710,
|
||||
"series_name": "生万物",
|
||||
"release_info": "上线45天",
|
||||
"platform_desc": "爱奇艺独播",
|
||||
"platform_txt": 1,
|
||||
"curr_heat": 5475.27,
|
||||
"curr_heat_desc": "5475.27",
|
||||
"bar_value": 2876.18977832356
|
||||
},
|
||||
{
|
||||
"series_id": 1520734,
|
||||
"series_name": "芬芳喜事",
|
||||
"release_info": "上线5天",
|
||||
"platform_desc": "腾讯视频独播",
|
||||
"platform_txt": -1,
|
||||
"curr_heat": 5462.54,
|
||||
"curr_heat_desc": "5462.54",
|
||||
"bar_value": 2647.63508938203
|
||||
},
|
||||
{
|
||||
"series_id": 1506349,
|
||||
"series_name": "子夜归",
|
||||
"release_info": "上线40天",
|
||||
"platform_desc": "腾讯视频独播",
|
||||
"platform_txt": -1,
|
||||
"curr_heat": 5414.09,
|
||||
"curr_heat_desc": "5414.09",
|
||||
"bar_value": 2421.25465526037
|
||||
},
|
||||
{
|
||||
"series_id": 1568466,
|
||||
"series_name": "照镜辞",
|
||||
"release_info": "上线8天",
|
||||
"platform_desc": "哔哩哔哩独播",
|
||||
"platform_txt": -1,
|
||||
"curr_heat": 5405.94,
|
||||
"curr_heat_desc": "5405.94",
|
||||
"bar_value": 2230.68228745166
|
||||
},
|
||||
{
|
||||
"series_id": 1501665,
|
||||
"series_name": "足迹",
|
||||
"release_info": "上线23天",
|
||||
"platform_desc": "多平台播放",
|
||||
"platform_txt": -1,
|
||||
"curr_heat": 5345.55,
|
||||
"curr_heat_desc": "5345.55",
|
||||
"bar_value": 2035.21546242053
|
||||
},
|
||||
{
|
||||
"series_id": 1481475,
|
||||
"series_name": "与晋长安",
|
||||
"release_info": "上线34天",
|
||||
"platform_desc": "爱奇艺独播",
|
||||
"platform_txt": 1,
|
||||
"curr_heat": 5231.26,
|
||||
"curr_heat_desc": "5231.26",
|
||||
"bar_value": 1837.70502435479
|
||||
},
|
||||
{
|
||||
"series_id": 1500426,
|
||||
"series_name": "归队",
|
||||
"release_info": "上线33天",
|
||||
"platform_desc": "腾讯视频独播",
|
||||
"platform_txt": -1,
|
||||
"curr_heat": 5167.29,
|
||||
"curr_heat_desc": "5167.29",
|
||||
"bar_value": 1674.88052510491
|
||||
},
|
||||
{
|
||||
"series_id": 1513970,
|
||||
"series_name": "阵地",
|
||||
"release_info": "上线11天",
|
||||
"platform_desc": "多平台播放",
|
||||
"platform_txt": -1,
|
||||
"curr_heat": 5155.5,
|
||||
"curr_heat_desc": "5155.50",
|
||||
"bar_value": 1541.8541283172
|
||||
},
|
||||
{
|
||||
"series_id": 1578416,
|
||||
"series_name": "金式森林",
|
||||
"release_info": "上线10天",
|
||||
"platform_desc": "腾讯视频独播",
|
||||
"platform_txt": -1,
|
||||
"curr_heat": 5098.99,
|
||||
"curr_heat_desc": "5098.99",
|
||||
"bar_value": 1407.04554929882
|
||||
},
|
||||
{
|
||||
"series_id": 1500365,
|
||||
"series_name": "锦月如歌",
|
||||
"release_info": "上线52天",
|
||||
"platform_desc": "多平台播放",
|
||||
"platform_txt": -1,
|
||||
"curr_heat": 5082.9,
|
||||
"curr_heat_desc": "5082.90",
|
||||
"bar_value": 1294.15728646218
|
||||
},
|
||||
{
|
||||
"series_id": 1481543,
|
||||
"series_name": "凡人修仙传",
|
||||
"release_info": "上线62天",
|
||||
"platform_desc": "优酷独播",
|
||||
"platform_txt": 0,
|
||||
"curr_heat": 5064.74,
|
||||
"curr_heat_desc": "5064.74",
|
||||
"bar_value": 1189.82790916312
|
||||
},
|
||||
{
|
||||
"series_id": 1521009,
|
||||
"series_name": "十二封信",
|
||||
"release_info": "上线29天",
|
||||
"platform_desc": "腾讯视频独播",
|
||||
"platform_txt": -1,
|
||||
"curr_heat": 5029.58,
|
||||
"curr_heat_desc": "5029.58",
|
||||
"bar_value": 1090.21013799029
|
||||
},
|
||||
{
|
||||
"series_id": 1492917,
|
||||
"series_name": "献鱼",
|
||||
"release_info": "上线42天",
|
||||
"platform_desc": "优酷独播",
|
||||
"platform_txt": 0,
|
||||
"curr_heat": 5010.95,
|
||||
"curr_heat_desc": "5010.95",
|
||||
"bar_value": 1002.19
|
||||
},
|
||||
{
|
||||
"series_id": 1444502,
|
||||
"series_name": "利剑·玫瑰",
|
||||
"release_info": "上线61天",
|
||||
"platform_desc": "多平台播放",
|
||||
"platform_txt": -1,
|
||||
"curr_heat": 4972.54,
|
||||
"curr_heat_desc": "4972.54",
|
||||
"bar_value": 917.613471447017
|
||||
},
|
||||
{
|
||||
"series_id": 1518217,
|
||||
"series_name": "扫毒风暴",
|
||||
"release_info": "上线77天",
|
||||
"platform_desc": "腾讯视频独播",
|
||||
"platform_txt": -1,
|
||||
"curr_heat": 4896.37,
|
||||
"curr_heat_desc": "4896.37",
|
||||
"bar_value": 833.695051286619
|
||||
},
|
||||
{
|
||||
"series_id": 1500364,
|
||||
"series_name": "桃花映江山",
|
||||
"release_info": "上线94天",
|
||||
"platform_desc": "腾讯视频独播",
|
||||
"platform_txt": -1,
|
||||
"curr_heat": 4806.34,
|
||||
"curr_heat_desc": "4806.34",
|
||||
"bar_value": 755.090462080828
|
||||
},
|
||||
{
|
||||
"series_id": 1505465,
|
||||
"series_name": "定风波",
|
||||
"release_info": "上线57天",
|
||||
"platform_desc": "爱奇艺独播",
|
||||
"platform_txt": 1,
|
||||
"curr_heat": 4744.14,
|
||||
"curr_heat_desc": "4744.14",
|
||||
"bar_value": 687.69123872798
|
||||
},
|
||||
{
|
||||
"series_id": 1531702,
|
||||
"series_name": "书卷一梦",
|
||||
"release_info": "上线93天",
|
||||
"platform_desc": "爱奇艺独播",
|
||||
"platform_txt": 1,
|
||||
"curr_heat": 4733.39,
|
||||
"curr_heat_desc": "4733.39",
|
||||
"bar_value": 633.081734434469
|
||||
},
|
||||
{
|
||||
"series_id": 1500328,
|
||||
"series_name": "蓄意宠爱",
|
||||
"release_info": "上线5天",
|
||||
"platform_desc": "优酷独播",
|
||||
"platform_txt": 0,
|
||||
"curr_heat": 4730.18,
|
||||
"curr_heat_desc": "4730.18",
|
||||
"bar_value": 583.736247352187
|
||||
},
|
||||
{
|
||||
"series_id": 1532221,
|
||||
"series_name": "目之所及",
|
||||
"release_info": "上线30天",
|
||||
"platform_desc": "爱奇艺独播",
|
||||
"platform_txt": 1,
|
||||
"curr_heat": 4712.48,
|
||||
"curr_heat_desc": "4712.48",
|
||||
"bar_value": 536.586836256929
|
||||
},
|
||||
{
|
||||
"series_id": 1524115,
|
||||
"series_name": "白夜宸缘起三生",
|
||||
"release_info": "上线13天",
|
||||
"platform_desc": "腾讯视频独播",
|
||||
"platform_txt": -1,
|
||||
"curr_heat": 4653.77,
|
||||
"curr_heat_desc": "4653.77",
|
||||
"bar_value": 488.930252012005
|
||||
},
|
||||
{
|
||||
"series_id": 1491942,
|
||||
"series_name": "朝雪录",
|
||||
"release_info": "上线76天",
|
||||
"platform_desc": "爱奇艺独播",
|
||||
"platform_txt": 1,
|
||||
"curr_heat": 4623.3,
|
||||
"curr_heat_desc": "4623.30",
|
||||
"bar_value": 448.172875941959
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user