chore: sync local changes (2026-03-12)

This commit is contained in:
2026-03-12 18:58:26 +08:00
parent 04a4cb962a
commit 939442e061
348 changed files with 91638 additions and 92091 deletions

View File

@@ -1,423 +1,423 @@
/* 历史上的今天 - 手机端优先的响应式设计 */
/* 重置样式 */
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
background: linear-gradient(135deg,
#e8f5e8 0%, /* 淡绿色 */
#f0f8e8 25%, /* 浅绿黄 */
#fff8dc 50%, /* 淡黄色 */
#f5f5dc 75%, /* 米色 */
#e8f5e8 100% /* 淡绿色 */
);
background-size: 400% 400%;
animation: freshGradientShift 20s ease infinite;
min-height: 100vh;
color: #2c3e50;
line-height: 1.6;
overflow-x: hidden;
}
@keyframes freshGradientShift {
0% { background-position: 0% 50%; }
25% { background-position: 100% 50%; }
50% { background-position: 100% 100%; }
75% { background-position: 0% 100%; }
100% { background-position: 0% 50%; }
}
.container {
max-width: 100%;
margin: 0 auto;
padding: 10px;
}
/* 头部样式 - 手机端优先 */
.header {
text-align: center;
margin-bottom: 20px;
background: rgba(255, 255, 255, 0.9);
border-radius: 20px;
padding: 25px 20px;
box-shadow: 0 8px 32px rgba(46, 125, 50, 0.15);
backdrop-filter: blur(15px);
border: 1px solid rgba(139, 195, 74, 0.2);
}
.header h1 {
font-size: 1.8rem;
color: #2c3e50;
margin-bottom: 8px;
font-weight: 700;
display: flex;
align-items: center;
justify-content: center;
gap: 10px;
flex-wrap: wrap;
}
.header p {
color: #7f8c8d;
font-size: 0.9rem;
line-height: 1.4;
}
/* 日期显示 */
.date-section {
background: rgba(255, 255, 255, 0.9);
border-radius: 16px;
padding: 20px;
margin-bottom: 20px;
text-align: center;
box-shadow: 0 6px 24px rgba(76, 175, 80, 0.12);
border: 1px solid rgba(139, 195, 74, 0.2);
}
.date-display h2 {
font-size: 1.4rem;
color: #2e7d32;
margin-bottom: 8px;
font-weight: 600;
}
.date-display .date-text {
color: #558b2f;
font-size: 1rem;
font-weight: 500;
}
/* 加载状态 */
.loading {
text-align: center;
padding: 40px 20px;
background: rgba(255, 255, 255, 0.9);
border-radius: 16px;
box-shadow: 0 6px 24px rgba(76, 175, 80, 0.12);
border: 1px solid rgba(139, 195, 74, 0.2);
}
.loading-spinner {
width: 40px;
height: 40px;
border: 3px solid rgba(139, 195, 74, 0.2);
border-top: 3px solid #689f38;
border-radius: 50%;
animation: spin 1.2s linear infinite;
margin: 0 auto 20px;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
/* 历史事件容器 */
.events-container {
background: rgba(255, 255, 255, 0.9);
border-radius: 20px;
padding: 25px;
margin-bottom: 20px;
box-shadow: 0 8px 32px rgba(76, 175, 80, 0.15);
backdrop-filter: blur(15px);
border: 1px solid rgba(139, 195, 74, 0.2);
}
/* 统计信息 */
.stats {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 12px;
margin-bottom: 25px;
}
.stat-item {
background: rgba(139, 195, 74, 0.15);
border-radius: 12px;
padding: 16px 12px;
text-align: center;
border: 1px solid rgba(139, 195, 74, 0.2);
transition: all 0.3s ease;
}
.stat-item:hover {
background: rgba(139, 195, 74, 0.2);
transform: translateY(-2px);
}
.stat-number {
font-size: 1.5rem;
font-weight: 700;
color: #558b2f;
display: block;
}
.stat-label {
color: #689f38;
font-size: 0.85rem;
margin-top: 4px;
font-weight: 500;
}
/* 事件列表 */
.events-list {
display: flex;
flex-direction: column;
gap: 12px;
}
.event-card {
background: rgba(255, 255, 255, 0.95);
border-radius: 16px;
padding: 20px;
box-shadow: 0 4px 16px rgba(76, 175, 80, 0.1);
transition: all 0.3s ease;
border-left: 4px solid #81c784;
position: relative;
border: 1px solid rgba(139, 195, 74, 0.15);
}
.event-card:hover {
transform: translateY(-3px);
box-shadow: 0 8px 24px rgba(76, 175, 80, 0.15);
border-left-color: #66bb6a;
}
/* 事件类型标签 */
.event-type {
position: absolute;
top: 10px;
right: 10px;
padding: 4px 8px;
border-radius: 12px;
font-size: 0.7rem;
font-weight: 600;
text-transform: uppercase;
}
.event-type.birth {
background: #e8f5e8;
color: #2e7d32;
}
.event-type.death {
background: #fff3e0;
color: #f57c00;
}
.event-type.event {
background: #f1f8e9;
color: #558b2f;
}
/* 事件年份 */
.event-year {
font-size: 1.1rem;
font-weight: 700;
color: #558b2f;
margin-bottom: 10px;
display: flex;
align-items: center;
gap: 8px;
}
.event-year::before {
content: "📅";
font-size: 1rem;
}
/* 事件标题 */
.event-title {
font-size: 1rem;
font-weight: 600;
color: #2c3e50;
margin-bottom: 8px;
line-height: 1.4;
}
/* 事件描述 */
.event-description {
color: #7f8c8d;
font-size: 0.85rem;
line-height: 1.5;
margin-bottom: 10px;
}
/* 链接按钮 */
.event-link {
display: inline-flex;
align-items: center;
gap: 6px;
color: #558b2f;
text-decoration: none;
font-size: 0.85rem;
font-weight: 500;
padding: 8px 14px;
background: rgba(139, 195, 74, 0.15);
border-radius: 18px;
transition: all 0.3s ease;
border: 1px solid rgba(139, 195, 74, 0.2);
}
.event-link:hover {
background: rgba(139, 195, 74, 0.25);
transform: translateX(2px);
color: #2e7d32;
}
.event-link::after {
content: "🔗";
font-size: 0.7rem;
}
/* 错误提示 */
.error {
background: #fed7d7;
color: #c53030;
padding: 15px;
border-radius: 12px;
text-align: center;
border: 1px solid #feb2b2;
margin: 15px 0;
font-size: 0.9rem;
}
/* 隐藏类 */
.hidden {
display: none;
}
/* 淡入动画 */
.fade-in {
animation: fadeIn 0.6s ease-in;
}
@keyframes fadeIn {
from {
opacity: 0;
transform: translateY(20px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
/* 平板端适配 (768px+) */
@media (min-width: 768px) {
.container {
max-width: 750px;
padding: 20px;
}
.header {
padding: 30px 25px;
}
.header h1 {
font-size: 2.2rem;
}
.header p {
font-size: 1rem;
}
.date-info {
padding: 20px;
}
.date-info h2 {
font-size: 1.5rem;
}
.events-container {
padding: 25px;
}
.stats {
gap: 15px;
}
.event-card {
padding: 20px;
}
.event-title {
font-size: 1.1rem;
}
.event-description {
font-size: 0.9rem;
}
}
/* 电脑端适配 (1024px+) */
@media (min-width: 1024px) {
.container {
max-width: 1000px;
padding: 30px;
}
.header {
padding: 40px 35px;
}
.header h1 {
font-size: 2.5rem;
}
.events-list {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 20px;
}
.event-card {
padding: 25px;
}
.event-title {
font-size: 1.2rem;
}
.event-description {
font-size: 0.95rem;
}
}
/* 大屏幕优化 (1200px+) */
@media (min-width: 1200px) {
.container {
max-width: 1200px;
padding: 40px;
}
.events-list {
grid-template-columns: repeat(3, 1fr);
gap: 25px;
}
}
/* 滚动条样式 */
::-webkit-scrollbar {
width: 8px;
}
::-webkit-scrollbar-track {
background: rgba(139, 195, 74, 0.1);
border-radius: 4px;
}
::-webkit-scrollbar-thumb {
background: rgba(139, 195, 74, 0.5);
border-radius: 4px;
}
::-webkit-scrollbar-thumb:hover {
background: rgba(139, 195, 74, 0.7);
/* 历史上的今天 - 手机端优先的响应式设计 */
/* 重置样式 */
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
background: linear-gradient(135deg,
#e8f5e8 0%, /* 淡绿色 */
#f0f8e8 25%, /* 浅绿黄 */
#fff8dc 50%, /* 淡黄色 */
#f5f5dc 75%, /* 米色 */
#e8f5e8 100% /* 淡绿色 */
);
background-size: 400% 400%;
animation: freshGradientShift 20s ease infinite;
min-height: 100vh;
color: #2c3e50;
line-height: 1.6;
overflow-x: hidden;
}
@keyframes freshGradientShift {
0% { background-position: 0% 50%; }
25% { background-position: 100% 50%; }
50% { background-position: 100% 100%; }
75% { background-position: 0% 100%; }
100% { background-position: 0% 50%; }
}
.container {
max-width: 100%;
margin: 0 auto;
padding: 10px;
}
/* 头部样式 - 手机端优先 */
.header {
text-align: center;
margin-bottom: 20px;
background: rgba(255, 255, 255, 0.9);
border-radius: 20px;
padding: 25px 20px;
box-shadow: 0 8px 32px rgba(46, 125, 50, 0.15);
backdrop-filter: blur(15px);
border: 1px solid rgba(139, 195, 74, 0.2);
}
.header h1 {
font-size: 1.8rem;
color: #2c3e50;
margin-bottom: 8px;
font-weight: 700;
display: flex;
align-items: center;
justify-content: center;
gap: 10px;
flex-wrap: wrap;
}
.header p {
color: #7f8c8d;
font-size: 0.9rem;
line-height: 1.4;
}
/* 日期显示 */
.date-section {
background: rgba(255, 255, 255, 0.9);
border-radius: 16px;
padding: 20px;
margin-bottom: 20px;
text-align: center;
box-shadow: 0 6px 24px rgba(76, 175, 80, 0.12);
border: 1px solid rgba(139, 195, 74, 0.2);
}
.date-display h2 {
font-size: 1.4rem;
color: #2e7d32;
margin-bottom: 8px;
font-weight: 600;
}
.date-display .date-text {
color: #558b2f;
font-size: 1rem;
font-weight: 500;
}
/* 加载状态 */
.loading {
text-align: center;
padding: 40px 20px;
background: rgba(255, 255, 255, 0.9);
border-radius: 16px;
box-shadow: 0 6px 24px rgba(76, 175, 80, 0.12);
border: 1px solid rgba(139, 195, 74, 0.2);
}
.loading-spinner {
width: 40px;
height: 40px;
border: 3px solid rgba(139, 195, 74, 0.2);
border-top: 3px solid #689f38;
border-radius: 50%;
animation: spin 1.2s linear infinite;
margin: 0 auto 20px;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
/* 历史事件容器 */
.events-container {
background: rgba(255, 255, 255, 0.9);
border-radius: 20px;
padding: 25px;
margin-bottom: 20px;
box-shadow: 0 8px 32px rgba(76, 175, 80, 0.15);
backdrop-filter: blur(15px);
border: 1px solid rgba(139, 195, 74, 0.2);
}
/* 统计信息 */
.stats {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 12px;
margin-bottom: 25px;
}
.stat-item {
background: rgba(139, 195, 74, 0.15);
border-radius: 12px;
padding: 16px 12px;
text-align: center;
border: 1px solid rgba(139, 195, 74, 0.2);
transition: all 0.3s ease;
}
.stat-item:hover {
background: rgba(139, 195, 74, 0.2);
transform: translateY(-2px);
}
.stat-number {
font-size: 1.5rem;
font-weight: 700;
color: #558b2f;
display: block;
}
.stat-label {
color: #689f38;
font-size: 0.85rem;
margin-top: 4px;
font-weight: 500;
}
/* 事件列表 */
.events-list {
display: flex;
flex-direction: column;
gap: 12px;
}
.event-card {
background: rgba(255, 255, 255, 0.95);
border-radius: 16px;
padding: 20px;
box-shadow: 0 4px 16px rgba(76, 175, 80, 0.1);
transition: all 0.3s ease;
border-left: 4px solid #81c784;
position: relative;
border: 1px solid rgba(139, 195, 74, 0.15);
}
.event-card:hover {
transform: translateY(-3px);
box-shadow: 0 8px 24px rgba(76, 175, 80, 0.15);
border-left-color: #66bb6a;
}
/* 事件类型标签 */
.event-type {
position: absolute;
top: 10px;
right: 10px;
padding: 4px 8px;
border-radius: 12px;
font-size: 0.7rem;
font-weight: 600;
text-transform: uppercase;
}
.event-type.birth {
background: #e8f5e8;
color: #2e7d32;
}
.event-type.death {
background: #fff3e0;
color: #f57c00;
}
.event-type.event {
background: #f1f8e9;
color: #558b2f;
}
/* 事件年份 */
.event-year {
font-size: 1.1rem;
font-weight: 700;
color: #558b2f;
margin-bottom: 10px;
display: flex;
align-items: center;
gap: 8px;
}
.event-year::before {
content: "📅";
font-size: 1rem;
}
/* 事件标题 */
.event-title {
font-size: 1rem;
font-weight: 600;
color: #2c3e50;
margin-bottom: 8px;
line-height: 1.4;
}
/* 事件描述 */
.event-description {
color: #7f8c8d;
font-size: 0.85rem;
line-height: 1.5;
margin-bottom: 10px;
}
/* 链接按钮 */
.event-link {
display: inline-flex;
align-items: center;
gap: 6px;
color: #558b2f;
text-decoration: none;
font-size: 0.85rem;
font-weight: 500;
padding: 8px 14px;
background: rgba(139, 195, 74, 0.15);
border-radius: 18px;
transition: all 0.3s ease;
border: 1px solid rgba(139, 195, 74, 0.2);
}
.event-link:hover {
background: rgba(139, 195, 74, 0.25);
transform: translateX(2px);
color: #2e7d32;
}
.event-link::after {
content: "🔗";
font-size: 0.7rem;
}
/* 错误提示 */
.error {
background: #fed7d7;
color: #c53030;
padding: 15px;
border-radius: 12px;
text-align: center;
border: 1px solid #feb2b2;
margin: 15px 0;
font-size: 0.9rem;
}
/* 隐藏类 */
.hidden {
display: none;
}
/* 淡入动画 */
.fade-in {
animation: fadeIn 0.6s ease-in;
}
@keyframes fadeIn {
from {
opacity: 0;
transform: translateY(20px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
/* 平板端适配 (768px+) */
@media (min-width: 768px) {
.container {
max-width: 750px;
padding: 20px;
}
.header {
padding: 30px 25px;
}
.header h1 {
font-size: 2.2rem;
}
.header p {
font-size: 1rem;
}
.date-info {
padding: 20px;
}
.date-info h2 {
font-size: 1.5rem;
}
.events-container {
padding: 25px;
}
.stats {
gap: 15px;
}
.event-card {
padding: 20px;
}
.event-title {
font-size: 1.1rem;
}
.event-description {
font-size: 0.9rem;
}
}
/* 电脑端适配 (1024px+) */
@media (min-width: 1024px) {
.container {
max-width: 1000px;
padding: 30px;
}
.header {
padding: 40px 35px;
}
.header h1 {
font-size: 2.5rem;
}
.events-list {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 20px;
}
.event-card {
padding: 25px;
}
.event-title {
font-size: 1.2rem;
}
.event-description {
font-size: 0.95rem;
}
}
/* 大屏幕优化 (1200px+) */
@media (min-width: 1200px) {
.container {
max-width: 1200px;
padding: 40px;
}
.events-list {
grid-template-columns: repeat(3, 1fr);
gap: 25px;
}
}
/* 滚动条样式 */
::-webkit-scrollbar {
width: 8px;
}
::-webkit-scrollbar-track {
background: rgba(139, 195, 74, 0.1);
border-radius: 4px;
}
::-webkit-scrollbar-thumb {
background: rgba(139, 195, 74, 0.5);
border-radius: 4px;
}
::-webkit-scrollbar-thumb:hover {
background: rgba(139, 195, 74, 0.7);
}

View File

@@ -1,83 +1,83 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="历史上的今天 - 了解今天在历史上发生的重要事件">
<meta name="keywords" content="历史上的今天,历史事件,百度百科,今日历史">
<title>历史上的今天 - 60s API集合</title>
<!-- 预加载关键资源 -->
<link rel="preconnect" href="https://60s.viki.moe">
<link rel="dns-prefetch" href="https://60s.viki.moe">
<!-- 样式文件 -->
<link rel="stylesheet" href="css/style.css">
<!-- 图标 -->
<link rel="icon" type="image/svg+xml" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'><text y='.9em' font-size='90'>📚</text></svg>">
</head>
<body>
<!-- 页面容器 -->
<div class="container">
<!-- 页面头部 -->
<header class="header">
<h1 class="title">📚 历史上的今天</h1>
<p class="subtitle">探索历史,了解今天在历史上发生的重要事件</p>
</header>
<!-- 日期信息 -->
<section class="date-section" id="date-info">
<div class="date-display">
<span class="date-text" id="date-text">加载中...</span>
</div>
</section>
<!-- 加载状态 -->
<div class="loading" id="loading">
<div class="loading-spinner"></div>
<p>正在加载历史数据...</p>
</div>
<!-- 主要内容 -->
<main class="main-content" id="history-content" style="display: none;">
<!-- 历史事件列表 -->
<section class="events-section">
<h2 class="section-title">历史事件</h2>
<div class="events-container">
<div class="events-list" id="events-list">
<!-- 事件卡片将通过 JavaScript 动态生成 -->
</div>
</div>
</section>
</main>
</div>
<!-- JavaScript 文件 -->
<script src="js/script.js"></script>
<!-- 页面性能监控 -->
<script>
// 页面加载性能监控
window.addEventListener('load', function() {
if ('performance' in window) {
const loadTime = performance.timing.loadEventEnd - performance.timing.navigationStart;
console.log(`页面加载时间: ${loadTime}ms`);
}
});
// 错误监控
window.addEventListener('error', function(event) {
console.error('页面错误:', event.error);
});
// 未处理的 Promise 错误
window.addEventListener('unhandledrejection', function(event) {
console.error('未处理的 Promise 错误:', event.reason);
});
</script>
</body>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="历史上的今天 - 了解今天在历史上发生的重要事件">
<meta name="keywords" content="历史上的今天,历史事件,百度百科,今日历史">
<title>历史上的今天 - 60s API集合</title>
<!-- 预加载关键资源 -->
<link rel="preconnect" href="https://60s.viki.moe">
<link rel="dns-prefetch" href="https://60s.viki.moe">
<!-- 样式文件 -->
<link rel="stylesheet" href="css/style.css">
<!-- 图标 -->
<link rel="icon" type="image/svg+xml" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'><text y='.9em' font-size='90'>📚</text></svg>">
</head>
<body>
<!-- 页面容器 -->
<div class="container">
<!-- 页面头部 -->
<header class="header">
<h1 class="title">📚 历史上的今天</h1>
<p class="subtitle">探索历史,了解今天在历史上发生的重要事件</p>
</header>
<!-- 日期信息 -->
<section class="date-section" id="date-info">
<div class="date-display">
<span class="date-text" id="date-text">加载中...</span>
</div>
</section>
<!-- 加载状态 -->
<div class="loading" id="loading">
<div class="loading-spinner"></div>
<p>正在加载历史数据...</p>
</div>
<!-- 主要内容 -->
<main class="main-content" id="history-content" style="display: none;">
<!-- 历史事件列表 -->
<section class="events-section">
<h2 class="section-title">历史事件</h2>
<div class="events-container">
<div class="events-list" id="events-list">
<!-- 事件卡片将通过 JavaScript 动态生成 -->
</div>
</div>
</section>
</main>
</div>
<!-- JavaScript 文件 -->
<script src="js/script.js"></script>
<!-- 页面性能监控 -->
<script>
// 页面加载性能监控
window.addEventListener('load', function() {
if ('performance' in window) {
const loadTime = performance.timing.loadEventEnd - performance.timing.navigationStart;
console.log(`页面加载时间: ${loadTime}ms`);
}
});
// 错误监控
window.addEventListener('error', function(event) {
console.error('页面错误:', event.error);
});
// 未处理的 Promise 错误
window.addEventListener('unhandledrejection', function(event) {
console.error('未处理的 Promise 错误:', event.reason);
});
</script>
</body>
</html>

View File

@@ -1,295 +1,295 @@
// 历史上的今天 - JavaScript 功能实现
// API 配置
const API = {
endpoints: [],
currentIndex: 0,
encoding: 'utf-8',
// 初始化API接口列表
async init() {
try {
const res = await fetch('./接口集合.json');
const endpoints = await res.json();
this.endpoints = endpoints.map(endpoint => `${endpoint}/v2/today_in_history`);
} catch (e) {
// 如果无法加载接口集合,使用默认接口
this.endpoints = ['https://60s.api.shumengya.top/v2/today_in_history'];
}
},
// 获取当前接口URL
getCurrentUrl() {
if (this.endpoints.length === 0) return null;
const url = new URL(this.endpoints[this.currentIndex]);
url.searchParams.append('encoding', this.encoding);
return url.toString();
},
// 切换到下一个接口
switchToNext() {
this.currentIndex = (this.currentIndex + 1) % this.endpoints.length;
return this.currentIndex < this.endpoints.length;
},
// 重置到第一个接口
reset() {
this.currentIndex = 0;
}
};
// 事件类型映射
const EVENT_TYPE_MAP = {
'birth': { name: '诞生', icon: '🎂', color: '#27ae60' },
'death': { name: '逝世', icon: '🕊️', color: '#e67e22' },
'event': { name: '事件', icon: '📰', color: '#3498db' }
};
// DOM 元素
let elements = {};
let currentData = null;
// 页面加载完成后初始化
document.addEventListener('DOMContentLoaded', function() {
initElements();
loadTodayInHistory();
});
// 初始化 DOM 元素
function initElements() {
elements = {
loading: document.getElementById('loading'),
content: document.getElementById('history-content'),
dateInfo: document.getElementById('date-info'),
dateText: document.getElementById('date-text'),
totalEvents: document.getElementById('total-events'),
birthEvents: document.getElementById('birth-events'),
deathEvents: document.getElementById('death-events'),
otherEvents: document.getElementById('other-events'),
eventsList: document.getElementById('events-list')
};
}
// 加载历史上的今天数据
async function loadTodayInHistory() {
try {
showLoading(true);
// 初始化API接口列表
await API.init();
// 重置API索引到第一个接口
API.reset();
// 尝试所有API接口
for (let i = 0; i < API.endpoints.length; i++) {
try {
const url = API.getCurrentUrl();
console.log(`尝试接口 ${i + 1}/${API.endpoints.length}: ${url}`);
const response = await fetch(url, {
cache: 'no-store',
timeout: 10000 // 10秒超时
});
if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
}
const data = await response.json();
console.log('API响应数据:', data);
if (data.code === 200 && data.data) {
console.log(`接口 ${i + 1} 请求成功`);
currentData = data.data;
displayHistoryData(data.data);
return;
} else {
throw new Error(data.message || '获取数据失败');
}
} catch (error) {
console.warn(`接口 ${i + 1} 失败:`, error.message);
// 如果不是最后一个接口,切换到下一个
if (i < API.endpoints.length - 1) {
API.switchToNext();
continue;
}
// 所有接口都失败了,抛出错误
throw new Error('所有接口都无法访问');
}
}
} catch (error) {
console.error('加载历史数据失败:', error);
showError(`加载失败: ${error.message}`);
} finally {
showLoading(false);
}
}
// 显示历史数据
function displayHistoryData(data) {
if (!data || !data.items) {
showError('没有获取到历史数据');
return;
}
// 更新日期信息
updateDateInfo(data);
// 更新统计信息
updateStats(data.items);
// 显示事件列表
renderEventsList(data.items);
// 显示内容区域
if (elements.content) {
elements.content.classList.add('fade-in');
elements.content.style.display = 'block';
}
}
// 更新日期信息
function updateDateInfo(data) {
if (elements.dateText && data.date) {
const today = new Date();
const year = today.getFullYear();
elements.dateText.textContent = `${year}${data.month}${data.day}`;
}
}
// 更新统计信息
function updateStats(items) {
const stats = {
total: items.length,
birth: items.filter(item => item.event_type === 'birth').length,
death: items.filter(item => item.event_type === 'death').length,
event: items.filter(item => item.event_type === 'event').length
};
if (elements.totalEvents) {
elements.totalEvents.textContent = stats.total;
}
if (elements.birthEvents) {
elements.birthEvents.textContent = stats.birth;
}
if (elements.deathEvents) {
elements.deathEvents.textContent = stats.death;
}
if (elements.otherEvents) {
elements.otherEvents.textContent = stats.event;
}
}
// 渲染事件列表
function renderEventsList(items) {
if (!elements.eventsList || !items) return;
// 按年份排序(从今到古)
const sortedItems = [...items].sort((a, b) => {
return parseInt(b.year) - parseInt(a.year);
});
elements.eventsList.innerHTML = '';
sortedItems.forEach(item => {
const eventCard = createEventCard(item);
elements.eventsList.appendChild(eventCard);
});
}
// 创建事件卡片
function createEventCard(item) {
const card = document.createElement('div');
card.className = 'event-card';
const eventType = EVENT_TYPE_MAP[item.event_type] || EVENT_TYPE_MAP['event'];
card.innerHTML = `
<div class="event-type ${item.event_type}">${eventType.name}</div>
<div class="event-year">${formatYear(item.year)}</div>
<div class="event-title">${escapeHtml(item.title)}</div>
<div class="event-description">${escapeHtml(item.description)}</div>
${item.link ? `<a href="${escapeHtml(item.link)}" target="_blank" rel="noopener noreferrer" class="event-link">了解更多</a>` : ''}
`;
return card;
}
// 格式化年份显示
function formatYear(year) {
const yearNum = parseInt(year);
if (yearNum < 0) {
return `公元前${Math.abs(yearNum)}`;
} else if (yearNum < 1000) {
return `公元${yearNum}`;
} else {
return `${yearNum}`;
}
}
// 显示加载状态
function showLoading(show) {
if (elements.loading) {
elements.loading.style.display = show ? 'block' : 'none';
}
if (elements.content) {
elements.content.style.display = show ? 'none' : 'block';
}
}
// 显示错误信息
function showError(message) {
if (elements.content) {
elements.content.innerHTML = `
<div class="error">
<h3>😔 加载失败</h3>
<p>${escapeHtml(message)}</p>
<button onclick="loadTodayInHistory()" style="
margin-top: 10px;
padding: 8px 16px;
background: #667eea;
color: white;
border: none;
border-radius: 6px;
cursor: pointer;
font-size: 0.9rem;
">重新加载</button>
</div>
`;
elements.content.style.display = 'block';
}
}
// HTML 转义
function escapeHtml(text) {
const div = document.createElement('div');
div.textContent = text;
return div.innerHTML;
}
// 错误处理
window.addEventListener('error', function(event) {
console.error('页面错误:', event.error);
});
// 网络状态监听
window.addEventListener('online', function() {
console.log('网络已连接');
});
window.addEventListener('offline', function() {
console.log('网络已断开');
showError('网络连接已断开,请检查网络设置');
});
// 导出全局方法
window.TodayInHistory = {
loadTodayInHistory,
showError,
showLoading
// 历史上的今天 - JavaScript 功能实现
// API 配置
const API = {
endpoints: [],
currentIndex: 0,
encoding: 'utf-8',
// 初始化API接口列表
async init() {
try {
const res = await fetch('./接口集合.json');
const endpoints = await res.json();
this.endpoints = endpoints.map(endpoint => `${endpoint}/v2/today_in_history`);
} catch (e) {
// 如果无法加载接口集合,使用默认接口
this.endpoints = ['https://60s.api.shumengya.top/v2/today_in_history'];
}
},
// 获取当前接口URL
getCurrentUrl() {
if (this.endpoints.length === 0) return null;
const url = new URL(this.endpoints[this.currentIndex]);
url.searchParams.append('encoding', this.encoding);
return url.toString();
},
// 切换到下一个接口
switchToNext() {
this.currentIndex = (this.currentIndex + 1) % this.endpoints.length;
return this.currentIndex < this.endpoints.length;
},
// 重置到第一个接口
reset() {
this.currentIndex = 0;
}
};
// 事件类型映射
const EVENT_TYPE_MAP = {
'birth': { name: '诞生', icon: '🎂', color: '#27ae60' },
'death': { name: '逝世', icon: '🕊️', color: '#e67e22' },
'event': { name: '事件', icon: '📰', color: '#3498db' }
};
// DOM 元素
let elements = {};
let currentData = null;
// 页面加载完成后初始化
document.addEventListener('DOMContentLoaded', function() {
initElements();
loadTodayInHistory();
});
// 初始化 DOM 元素
function initElements() {
elements = {
loading: document.getElementById('loading'),
content: document.getElementById('history-content'),
dateInfo: document.getElementById('date-info'),
dateText: document.getElementById('date-text'),
totalEvents: document.getElementById('total-events'),
birthEvents: document.getElementById('birth-events'),
deathEvents: document.getElementById('death-events'),
otherEvents: document.getElementById('other-events'),
eventsList: document.getElementById('events-list')
};
}
// 加载历史上的今天数据
async function loadTodayInHistory() {
try {
showLoading(true);
// 初始化API接口列表
await API.init();
// 重置API索引到第一个接口
API.reset();
// 尝试所有API接口
for (let i = 0; i < API.endpoints.length; i++) {
try {
const url = API.getCurrentUrl();
console.log(`尝试接口 ${i + 1}/${API.endpoints.length}: ${url}`);
const response = await fetch(url, {
cache: 'no-store',
timeout: 10000 // 10秒超时
});
if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
}
const data = await response.json();
console.log('API响应数据:', data);
if (data.code === 200 && data.data) {
console.log(`接口 ${i + 1} 请求成功`);
currentData = data.data;
displayHistoryData(data.data);
return;
} else {
throw new Error(data.message || '获取数据失败');
}
} catch (error) {
console.warn(`接口 ${i + 1} 失败:`, error.message);
// 如果不是最后一个接口,切换到下一个
if (i < API.endpoints.length - 1) {
API.switchToNext();
continue;
}
// 所有接口都失败了,抛出错误
throw new Error('所有接口都无法访问');
}
}
} catch (error) {
console.error('加载历史数据失败:', error);
showError(`加载失败: ${error.message}`);
} finally {
showLoading(false);
}
}
// 显示历史数据
function displayHistoryData(data) {
if (!data || !data.items) {
showError('没有获取到历史数据');
return;
}
// 更新日期信息
updateDateInfo(data);
// 更新统计信息
updateStats(data.items);
// 显示事件列表
renderEventsList(data.items);
// 显示内容区域
if (elements.content) {
elements.content.classList.add('fade-in');
elements.content.style.display = 'block';
}
}
// 更新日期信息
function updateDateInfo(data) {
if (elements.dateText && data.date) {
const today = new Date();
const year = today.getFullYear();
elements.dateText.textContent = `${year}${data.month}${data.day}`;
}
}
// 更新统计信息
function updateStats(items) {
const stats = {
total: items.length,
birth: items.filter(item => item.event_type === 'birth').length,
death: items.filter(item => item.event_type === 'death').length,
event: items.filter(item => item.event_type === 'event').length
};
if (elements.totalEvents) {
elements.totalEvents.textContent = stats.total;
}
if (elements.birthEvents) {
elements.birthEvents.textContent = stats.birth;
}
if (elements.deathEvents) {
elements.deathEvents.textContent = stats.death;
}
if (elements.otherEvents) {
elements.otherEvents.textContent = stats.event;
}
}
// 渲染事件列表
function renderEventsList(items) {
if (!elements.eventsList || !items) return;
// 按年份排序(从今到古)
const sortedItems = [...items].sort((a, b) => {
return parseInt(b.year) - parseInt(a.year);
});
elements.eventsList.innerHTML = '';
sortedItems.forEach(item => {
const eventCard = createEventCard(item);
elements.eventsList.appendChild(eventCard);
});
}
// 创建事件卡片
function createEventCard(item) {
const card = document.createElement('div');
card.className = 'event-card';
const eventType = EVENT_TYPE_MAP[item.event_type] || EVENT_TYPE_MAP['event'];
card.innerHTML = `
<div class="event-type ${item.event_type}">${eventType.name}</div>
<div class="event-year">${formatYear(item.year)}</div>
<div class="event-title">${escapeHtml(item.title)}</div>
<div class="event-description">${escapeHtml(item.description)}</div>
${item.link ? `<a href="${escapeHtml(item.link)}" target="_blank" rel="noopener noreferrer" class="event-link">了解更多</a>` : ''}
`;
return card;
}
// 格式化年份显示
function formatYear(year) {
const yearNum = parseInt(year);
if (yearNum < 0) {
return `公元前${Math.abs(yearNum)}`;
} else if (yearNum < 1000) {
return `公元${yearNum}`;
} else {
return `${yearNum}`;
}
}
// 显示加载状态
function showLoading(show) {
if (elements.loading) {
elements.loading.style.display = show ? 'block' : 'none';
}
if (elements.content) {
elements.content.style.display = show ? 'none' : 'block';
}
}
// 显示错误信息
function showError(message) {
if (elements.content) {
elements.content.innerHTML = `
<div class="error">
<h3>😔 加载失败</h3>
<p>${escapeHtml(message)}</p>
<button onclick="loadTodayInHistory()" style="
margin-top: 10px;
padding: 8px 16px;
background: #667eea;
color: white;
border: none;
border-radius: 6px;
cursor: pointer;
font-size: 0.9rem;
">重新加载</button>
</div>
`;
elements.content.style.display = 'block';
}
}
// HTML 转义
function escapeHtml(text) {
const div = document.createElement('div');
div.textContent = text;
return div.innerHTML;
}
// 错误处理
window.addEventListener('error', function(event) {
console.error('页面错误:', event.error);
});
// 网络状态监听
window.addEventListener('online', function() {
console.log('网络已连接');
});
window.addEventListener('offline', function() {
console.log('网络已断开');
showError('网络连接已断开,请检查网络设置');
});
// 导出全局方法
window.TodayInHistory = {
loadTodayInHistory,
showError,
showLoading
};

View File

@@ -1,3 +1,3 @@
[
"https://60s.api.shumengya.top"
]
[
"https://60s.api.shumengya.top"
]

View File

@@ -1,102 +1,102 @@
{
"code": 200,
"message": "获取成功。数据来自官方/权威源头,以确保稳定与实时。开源地址 https://github.com/vikiboss/60s反馈群 595941841",
"data": {
"date": "8-19",
"month": 8,
"day": 19,
"items": [
{
"title": "罗马帝国开国皇帝奥古斯都逝世",
"year": "14",
"description": "奥古斯都(拉丁文 Augustus的中译复数型 Augusti的原意为“神圣的”、“高贵的”带有宗教与神学式的意味。",
"event_type": "death",
"link": "https://baike.baidu.com/item/%E5%A5%A5%E5%8F%A4%E6%96%AF%E9%83%BD/14291"
},
{
"title": "近代概率论的奠基者帕斯卡逝世",
"year": "1662",
"description": "布莱士·帕斯卡Blaise Pascal 16231662是法国数学家、物理学家、哲学家、散文家。",
"event_type": "death",
"link": "https://baike.baidu.com/item/%E5%B8%83%E8%8E%B1%E5%A3%AB%C2%B7%E5%B8%95%E6%96%AF%E5%8D%A1"
},
{
"title": "瑞典国王古斯塔夫三世发动政变夺取权力",
"year": "1772",
"description": "古斯塔夫三世Gustavus III17461792是瑞典历史上褒贬最多的国王17711792。阿道夫·弗里德里克国王的儿子和继承者。",
"event_type": "event",
"link": "https://baike.baidu.com/item/%E5%8F%A4%E6%96%AF%E5%A1%94%E5%A4%AB%E4%B8%89%E4%B8%96"
},
{
"title": "美国飞机设计师奥维尔·莱特诞生",
"year": "1871",
"description": "奥威尔莱特公元1871公元1948。 奥维尔·莱特1871年生于美国俄亥俄州代顿市。上过中学但实际上未获得毕业文凭。",
"event_type": "birth",
"link": "https://baike.baidu.com/item/%E5%A5%A5%E7%BB%B4%E5%B0%94%C2%B7%E8%8E%B1%E7%89%B9"
},
{
"title": "法国著名时装设计师、香奈儿品牌创始人加布里埃·香奈儿出生",
"year": "1883",
"description": "香奈儿儿时入读修女院学校学得一手针线活。后来她与许多上流社会男士有过交往。1910年毅然放弃嫁入豪门做阔太太的她在巴黎开设了一家女装帽子店从此开创了香奈儿时尚帝国。",
"event_type": "birth",
"link": "https://baike.baidu.com/item/%E5%8A%A0%E5%B8%83%E9%87%8C%E5%9F%83%C2%B7%E9%A6%99%E5%A5%88%E5%84%BF/9480318"
},
{
"title": "美国宇航员斯托里·马斯格雷夫出生",
"year": "1935",
"description": "斯托里·马斯格雷夫Franklin Story Musgrave1935年8月19日美国宇航员拥有医学、数学、文学等六个学位入选美国国家航空航天局NASA科学家宇航员。",
"event_type": "birth",
"link": "https://baike.baidu.com/item/%E6%96%AF%E6%89%98%E9%87%8C%C2%B7%E9%A9%AC%E6%96%AF%E6%A0%BC%E9%9B%B7%E5%A4%AB"
},
{
"title": "纳粹德国陆军元帅京特·冯·克鲁格畏罪自杀",
"year": "1944",
"description": "汉斯·京特·冯·克卢格Günther·von·Kluge 1882年10月30日1944年8月19日纳粹德国陆军元帅1940.7.19),著名军事家、统帅。",
"event_type": "death",
"link": "https://baike.baidu.com/item/%E4%BA%AC%E7%89%B9%C2%B7%E5%86%AF%C2%B7%E5%85%8B%E9%B2%81%E6%A0%BC"
},
{
"title": "美国第42任总统克林顿出生",
"year": "1946",
"description": "威廉·杰斐逊·克林顿美国律师、政治家美国民主党成员曾任阿肯色州州长和第42任美国总统。克林顿基金会主席 。",
"event_type": "birth",
"link": "https://baike.baidu.com/item/%E5%A8%81%E5%BB%89%C2%B7%E6%9D%B0%E6%96%90%E9%80%8A%C2%B7%E5%85%8B%E6%9E%97%E9%A1%BF"
},
{
"title": "美国演员马修·派瑞出生",
"year": "1969",
"description": "马修·派瑞Matthew Perry1969年8月19日—2023年10月28日出生于美国马萨诸塞州普利茅斯美国、加拿大籍男演员、编剧。",
"event_type": "birth",
"link": "https://baike.baidu.com/item/%E9%A9%AC%E4%BF%AE%C2%B7%E6%B4%BE%E7%91%9E"
},
{
"title": "北回归线标志塔在广州落成",
"year": "1985",
"description": "北回归线标志塔,是标志地理学上北回归线经过地方的建筑物。",
"event_type": "event",
"link": "https://baike.baidu.com/item/%E5%8C%97%E5%9B%9E%E5%BD%92%E7%BA%BF%E6%A0%87%E5%BF%97%E5%A1%94"
},
{
"title": "“八一九事件”,苏联八月政变",
"year": "1991",
"description": "八一九事件又称“苏联政变”、“八月政变”指1991年8月19日-8月21日在苏联发生的一次政变。",
"event_type": "event",
"link": "https://baike.baidu.com/item/%E5%85%AB%E4%B8%80%E4%B9%9D%E4%BA%8B%E4%BB%B6"
},
{
"title": "量子化学家莱纳斯·卡尔·鲍林逝世",
"year": "1994",
"description": "莱纳斯·卡尔·鲍林Linus Carl Pauling1901年2月28日—1994年8月19日出生于美国俄勒冈州波特兰化学家、美国国家科学院院士、美国艺术与科学院院士1954年诺贝尔化学奖获得者。",
"event_type": "death",
"link": "https://baike.baidu.com/item/%E8%8E%B1%E7%BA%B3%E6%96%AF%C2%B7%E5%8D%A1%E5%B0%94%C2%B7%E9%B2%8D%E6%9E%97"
},
{
"title": "中国三江源自然保护区成立",
"year": "2000",
"description": "青海三江源国家级自然保护区位于青藏高原腹地青海省南部地理位置介于东经89°24102°23北纬31°3936°16之间青海三江源国家级自然保护区属湿地类型的自然保护区。",
"event_type": "event",
"link": "https://baike.baidu.com/item/%E4%B8%89%E6%B1%9F%E6%BA%90%E8%87%AA%E7%84%B6%E4%BF%9D%E6%8A%A4%E5%8C%BA"
}
]
}
{
"code": 200,
"message": "获取成功。数据来自官方/权威源头,以确保稳定与实时。开源地址 https://github.com/vikiboss/60s反馈群 595941841",
"data": {
"date": "8-19",
"month": 8,
"day": 19,
"items": [
{
"title": "罗马帝国开国皇帝奥古斯都逝世",
"year": "14",
"description": "奥古斯都(拉丁文 Augustus的中译复数型 Augusti的原意为“神圣的”、“高贵的”带有宗教与神学式的意味。",
"event_type": "death",
"link": "https://baike.baidu.com/item/%E5%A5%A5%E5%8F%A4%E6%96%AF%E9%83%BD/14291"
},
{
"title": "近代概率论的奠基者帕斯卡逝世",
"year": "1662",
"description": "布莱士·帕斯卡Blaise Pascal 16231662是法国数学家、物理学家、哲学家、散文家。",
"event_type": "death",
"link": "https://baike.baidu.com/item/%E5%B8%83%E8%8E%B1%E5%A3%AB%C2%B7%E5%B8%95%E6%96%AF%E5%8D%A1"
},
{
"title": "瑞典国王古斯塔夫三世发动政变夺取权力",
"year": "1772",
"description": "古斯塔夫三世Gustavus III17461792是瑞典历史上褒贬最多的国王17711792。阿道夫·弗里德里克国王的儿子和继承者。",
"event_type": "event",
"link": "https://baike.baidu.com/item/%E5%8F%A4%E6%96%AF%E5%A1%94%E5%A4%AB%E4%B8%89%E4%B8%96"
},
{
"title": "美国飞机设计师奥维尔·莱特诞生",
"year": "1871",
"description": "奥威尔莱特公元1871公元1948。 奥维尔·莱特1871年生于美国俄亥俄州代顿市。上过中学但实际上未获得毕业文凭。",
"event_type": "birth",
"link": "https://baike.baidu.com/item/%E5%A5%A5%E7%BB%B4%E5%B0%94%C2%B7%E8%8E%B1%E7%89%B9"
},
{
"title": "法国著名时装设计师、香奈儿品牌创始人加布里埃·香奈儿出生",
"year": "1883",
"description": "香奈儿儿时入读修女院学校学得一手针线活。后来她与许多上流社会男士有过交往。1910年毅然放弃嫁入豪门做阔太太的她在巴黎开设了一家女装帽子店从此开创了香奈儿时尚帝国。",
"event_type": "birth",
"link": "https://baike.baidu.com/item/%E5%8A%A0%E5%B8%83%E9%87%8C%E5%9F%83%C2%B7%E9%A6%99%E5%A5%88%E5%84%BF/9480318"
},
{
"title": "美国宇航员斯托里·马斯格雷夫出生",
"year": "1935",
"description": "斯托里·马斯格雷夫Franklin Story Musgrave1935年8月19日美国宇航员拥有医学、数学、文学等六个学位入选美国国家航空航天局NASA科学家宇航员。",
"event_type": "birth",
"link": "https://baike.baidu.com/item/%E6%96%AF%E6%89%98%E9%87%8C%C2%B7%E9%A9%AC%E6%96%AF%E6%A0%BC%E9%9B%B7%E5%A4%AB"
},
{
"title": "纳粹德国陆军元帅京特·冯·克鲁格畏罪自杀",
"year": "1944",
"description": "汉斯·京特·冯·克卢格Günther·von·Kluge 1882年10月30日1944年8月19日纳粹德国陆军元帅1940.7.19),著名军事家、统帅。",
"event_type": "death",
"link": "https://baike.baidu.com/item/%E4%BA%AC%E7%89%B9%C2%B7%E5%86%AF%C2%B7%E5%85%8B%E9%B2%81%E6%A0%BC"
},
{
"title": "美国第42任总统克林顿出生",
"year": "1946",
"description": "威廉·杰斐逊·克林顿美国律师、政治家美国民主党成员曾任阿肯色州州长和第42任美国总统。克林顿基金会主席 。",
"event_type": "birth",
"link": "https://baike.baidu.com/item/%E5%A8%81%E5%BB%89%C2%B7%E6%9D%B0%E6%96%90%E9%80%8A%C2%B7%E5%85%8B%E6%9E%97%E9%A1%BF"
},
{
"title": "美国演员马修·派瑞出生",
"year": "1969",
"description": "马修·派瑞Matthew Perry1969年8月19日—2023年10月28日出生于美国马萨诸塞州普利茅斯美国、加拿大籍男演员、编剧。",
"event_type": "birth",
"link": "https://baike.baidu.com/item/%E9%A9%AC%E4%BF%AE%C2%B7%E6%B4%BE%E7%91%9E"
},
{
"title": "北回归线标志塔在广州落成",
"year": "1985",
"description": "北回归线标志塔,是标志地理学上北回归线经过地方的建筑物。",
"event_type": "event",
"link": "https://baike.baidu.com/item/%E5%8C%97%E5%9B%9E%E5%BD%92%E7%BA%BF%E6%A0%87%E5%BF%97%E5%A1%94"
},
{
"title": "“八一九事件”,苏联八月政变",
"year": "1991",
"description": "八一九事件又称“苏联政变”、“八月政变”指1991年8月19日-8月21日在苏联发生的一次政变。",
"event_type": "event",
"link": "https://baike.baidu.com/item/%E5%85%AB%E4%B8%80%E4%B9%9D%E4%BA%8B%E4%BB%B6"
},
{
"title": "量子化学家莱纳斯·卡尔·鲍林逝世",
"year": "1994",
"description": "莱纳斯·卡尔·鲍林Linus Carl Pauling1901年2月28日—1994年8月19日出生于美国俄勒冈州波特兰化学家、美国国家科学院院士、美国艺术与科学院院士1954年诺贝尔化学奖获得者。",
"event_type": "death",
"link": "https://baike.baidu.com/item/%E8%8E%B1%E7%BA%B3%E6%96%AF%C2%B7%E5%8D%A1%E5%B0%94%C2%B7%E9%B2%8D%E6%9E%97"
},
{
"title": "中国三江源自然保护区成立",
"year": "2000",
"description": "青海三江源国家级自然保护区位于青藏高原腹地青海省南部地理位置介于东经89°24102°23北纬31°3936°16之间青海三江源国家级自然保护区属湿地类型的自然保护区。",
"event_type": "event",
"link": "https://baike.baidu.com/item/%E4%B8%89%E6%B1%9F%E6%BA%90%E8%87%AA%E7%84%B6%E4%BF%9D%E6%8A%A4%E5%8C%BA"
}
]
}
}

View File

@@ -1,326 +1,326 @@
/* 必应每日壁纸 - 淡绿色清新风格样式 */
/* 重置样式 */
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
background: linear-gradient(135deg, #a8e6cf 0%, #dcedc1 50%, #ffd3a5 100%);
min-height: 100vh;
color: #2d5016;
line-height: 1.6;
overflow-x: hidden;
}
.container {
max-width: 1200px;
margin: 0 auto;
padding: 20px;
}
/* 头部样式 */
.header {
text-align: center;
margin-bottom: 30px;
background: rgba(255, 255, 255, 0.85);
border-radius: 20px;
padding: 30px;
box-shadow: 0 8px 25px rgba(45, 80, 22, 0.08);
backdrop-filter: blur(10px);
}
.header h1 {
font-size: 2.5rem;
color: #2d5016;
margin-bottom: 10px;
font-weight: 700;
display: flex;
align-items: center;
justify-content: center;
gap: 15px;
}
.header p {
color: #5a7c65;
font-size: 1.1rem;
}
/* 加载状态 */
.loading {
text-align: center;
padding: 40px;
background: rgba(255, 255, 255, 0.85);
border-radius: 15px;
box-shadow: 0 5px 20px rgba(45, 80, 22, 0.08);
}
.spinner {
width: 40px;
height: 40px;
border: 4px solid #e8f5e8;
border-top: 4px solid #81c784;
border-radius: 50%;
animation: spin 1s linear infinite;
margin: 0 auto 20px;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
/* 壁纸容器 */
.wallpaper-container {
background: rgba(255, 255, 255, 0.85);
border-radius: 20px;
padding: 30px;
box-shadow: 0 8px 25px rgba(45, 80, 22, 0.08);
backdrop-filter: blur(10px);
margin-bottom: 20px;
}
/* 壁纸信息 */
.wallpaper-info {
text-align: center;
margin-bottom: 25px;
}
.wallpaper-title {
font-size: 1.8rem;
font-weight: 700;
color: #2d5016;
margin-bottom: 10px;
}
.wallpaper-date {
color: #5a7c65;
font-size: 1rem;
margin-bottom: 15px;
}
.wallpaper-description {
color: #2d5016;
font-size: 1.1rem;
line-height: 1.6;
max-width: 800px;
margin: 0 auto;
}
/* 壁纸图片 */
.wallpaper-image {
position: relative;
border-radius: 15px;
overflow: hidden;
box-shadow: 0 10px 30px rgba(45, 80, 22, 0.15);
margin: 20px 0;
}
.wallpaper-image img {
width: 100%;
height: auto;
display: block;
transition: transform 0.3s ease;
}
.wallpaper-image:hover img {
transform: scale(1.02);
}
/* 下载按钮 */
.download-section {
text-align: center;
margin-top: 25px;
}
.download-btn {
background: linear-gradient(135deg, #81c784 0%, #66bb6a 100%);
color: white;
border: none;
padding: 15px 30px;
border-radius: 25px;
font-size: 1.1rem;
font-weight: 600;
cursor: pointer;
transition: all 0.3s ease;
box-shadow: 0 4px 15px rgba(129, 199, 132, 0.3);
text-decoration: none;
display: inline-flex;
align-items: center;
gap: 10px;
}
.download-btn:hover {
transform: translateY(-2px);
box-shadow: 0 6px 20px rgba(129, 199, 132, 0.4);
}
.download-btn:active {
transform: translateY(0);
}
/* 错误提示 */
.error {
background: #fed7d7;
color: #c53030;
padding: 20px;
border-radius: 15px;
text-align: center;
border: 1px solid #feb2b2;
margin: 20px 0;
}
/* 版权信息 */
.copyright {
background: rgba(255, 255, 255, 0.7);
border-radius: 15px;
padding: 20px;
text-align: center;
color: #5a7c65;
font-size: 0.9rem;
margin-top: 20px;
}
/* 响应式设计 */
/* 平板端 */
@media (max-width: 768px) {
.container {
padding: 15px;
}
.header h1 {
font-size: 2rem;
flex-direction: column;
gap: 10px;
}
.header {
padding: 20px;
}
.wallpaper-container {
padding: 20px;
}
.wallpaper-title {
font-size: 1.5rem;
}
.wallpaper-description {
font-size: 1rem;
}
}
/* 手机端 */
@media (max-width: 480px) {
.container {
padding: 10px;
}
.header {
padding: 15px;
margin-bottom: 20px;
}
.header h1 {
font-size: 1.8rem;
}
.wallpaper-container {
padding: 15px;
}
.wallpaper-title {
font-size: 1.3rem;
}
.wallpaper-description {
font-size: 0.95rem;
}
.download-btn {
padding: 12px 25px;
font-size: 1rem;
width: 100%;
justify-content: center;
}
.copyright {
padding: 15px;
font-size: 0.8rem;
}
}
/* 大屏幕优化 */
@media (min-width: 1200px) {
.container {
padding: 40px;
}
.header {
padding: 40px;
}
.wallpaper-container {
padding: 40px;
}
.wallpaper-image {
max-height: 70vh;
overflow: hidden;
}
.wallpaper-image img {
width: 100%;
height: 100%;
object-fit: cover;
}
}
/* 特殊效果 */
.fade-in {
animation: fadeIn 0.6s ease-in;
}
@keyframes fadeIn {
from {
opacity: 0;
transform: translateY(20px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
/* 图片加载效果 */
.wallpaper-image img {
opacity: 0;
transition: opacity 0.3s ease;
}
.wallpaper-image img.loaded {
opacity: 1;
}
/* 滚动条样式 */
::-webkit-scrollbar {
width: 8px;
}
::-webkit-scrollbar-track {
background: rgba(255, 255, 255, 0.1);
}
::-webkit-scrollbar-thumb {
background: rgba(129, 199, 132, 0.5);
border-radius: 4px;
}
::-webkit-scrollbar-thumb:hover {
background: rgba(129, 199, 132, 0.7);
/* 必应每日壁纸 - 淡绿色清新风格样式 */
/* 重置样式 */
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
background: linear-gradient(135deg, #a8e6cf 0%, #dcedc1 50%, #ffd3a5 100%);
min-height: 100vh;
color: #2d5016;
line-height: 1.6;
overflow-x: hidden;
}
.container {
max-width: 1200px;
margin: 0 auto;
padding: 20px;
}
/* 头部样式 */
.header {
text-align: center;
margin-bottom: 30px;
background: rgba(255, 255, 255, 0.85);
border-radius: 20px;
padding: 30px;
box-shadow: 0 8px 25px rgba(45, 80, 22, 0.08);
backdrop-filter: blur(10px);
}
.header h1 {
font-size: 2.5rem;
color: #2d5016;
margin-bottom: 10px;
font-weight: 700;
display: flex;
align-items: center;
justify-content: center;
gap: 15px;
}
.header p {
color: #5a7c65;
font-size: 1.1rem;
}
/* 加载状态 */
.loading {
text-align: center;
padding: 40px;
background: rgba(255, 255, 255, 0.85);
border-radius: 15px;
box-shadow: 0 5px 20px rgba(45, 80, 22, 0.08);
}
.spinner {
width: 40px;
height: 40px;
border: 4px solid #e8f5e8;
border-top: 4px solid #81c784;
border-radius: 50%;
animation: spin 1s linear infinite;
margin: 0 auto 20px;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
/* 壁纸容器 */
.wallpaper-container {
background: rgba(255, 255, 255, 0.85);
border-radius: 20px;
padding: 30px;
box-shadow: 0 8px 25px rgba(45, 80, 22, 0.08);
backdrop-filter: blur(10px);
margin-bottom: 20px;
}
/* 壁纸信息 */
.wallpaper-info {
text-align: center;
margin-bottom: 25px;
}
.wallpaper-title {
font-size: 1.8rem;
font-weight: 700;
color: #2d5016;
margin-bottom: 10px;
}
.wallpaper-date {
color: #5a7c65;
font-size: 1rem;
margin-bottom: 15px;
}
.wallpaper-description {
color: #2d5016;
font-size: 1.1rem;
line-height: 1.6;
max-width: 800px;
margin: 0 auto;
}
/* 壁纸图片 */
.wallpaper-image {
position: relative;
border-radius: 15px;
overflow: hidden;
box-shadow: 0 10px 30px rgba(45, 80, 22, 0.15);
margin: 20px 0;
}
.wallpaper-image img {
width: 100%;
height: auto;
display: block;
transition: transform 0.3s ease;
}
.wallpaper-image:hover img {
transform: scale(1.02);
}
/* 下载按钮 */
.download-section {
text-align: center;
margin-top: 25px;
}
.download-btn {
background: linear-gradient(135deg, #81c784 0%, #66bb6a 100%);
color: white;
border: none;
padding: 15px 30px;
border-radius: 25px;
font-size: 1.1rem;
font-weight: 600;
cursor: pointer;
transition: all 0.3s ease;
box-shadow: 0 4px 15px rgba(129, 199, 132, 0.3);
text-decoration: none;
display: inline-flex;
align-items: center;
gap: 10px;
}
.download-btn:hover {
transform: translateY(-2px);
box-shadow: 0 6px 20px rgba(129, 199, 132, 0.4);
}
.download-btn:active {
transform: translateY(0);
}
/* 错误提示 */
.error {
background: #fed7d7;
color: #c53030;
padding: 20px;
border-radius: 15px;
text-align: center;
border: 1px solid #feb2b2;
margin: 20px 0;
}
/* 版权信息 */
.copyright {
background: rgba(255, 255, 255, 0.7);
border-radius: 15px;
padding: 20px;
text-align: center;
color: #5a7c65;
font-size: 0.9rem;
margin-top: 20px;
}
/* 响应式设计 */
/* 平板端 */
@media (max-width: 768px) {
.container {
padding: 15px;
}
.header h1 {
font-size: 2rem;
flex-direction: column;
gap: 10px;
}
.header {
padding: 20px;
}
.wallpaper-container {
padding: 20px;
}
.wallpaper-title {
font-size: 1.5rem;
}
.wallpaper-description {
font-size: 1rem;
}
}
/* 手机端 */
@media (max-width: 480px) {
.container {
padding: 10px;
}
.header {
padding: 15px;
margin-bottom: 20px;
}
.header h1 {
font-size: 1.8rem;
}
.wallpaper-container {
padding: 15px;
}
.wallpaper-title {
font-size: 1.3rem;
}
.wallpaper-description {
font-size: 0.95rem;
}
.download-btn {
padding: 12px 25px;
font-size: 1rem;
width: 100%;
justify-content: center;
}
.copyright {
padding: 15px;
font-size: 0.8rem;
}
}
/* 大屏幕优化 */
@media (min-width: 1200px) {
.container {
padding: 40px;
}
.header {
padding: 40px;
}
.wallpaper-container {
padding: 40px;
}
.wallpaper-image {
max-height: 70vh;
overflow: hidden;
}
.wallpaper-image img {
width: 100%;
height: 100%;
object-fit: cover;
}
}
/* 特殊效果 */
.fade-in {
animation: fadeIn 0.6s ease-in;
}
@keyframes fadeIn {
from {
opacity: 0;
transform: translateY(20px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
/* 图片加载效果 */
.wallpaper-image img {
opacity: 0;
transition: opacity 0.3s ease;
}
.wallpaper-image img.loaded {
opacity: 1;
}
/* 滚动条样式 */
::-webkit-scrollbar {
width: 8px;
}
::-webkit-scrollbar-track {
background: rgba(255, 255, 255, 0.1);
}
::-webkit-scrollbar-thumb {
background: rgba(129, 199, 132, 0.5);
border-radius: 4px;
}
::-webkit-scrollbar-thumb:hover {
background: rgba(129, 199, 132, 0.7);
}

View File

@@ -1,42 +1,42 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="必应每日壁纸 - 每天为您呈现精美的必应壁纸">
<meta name="keywords" content="必应壁纸,每日壁纸,高清壁纸,桌面壁纸">
<title>必应每日壁纸</title>
<!-- 引入样式文件 -->
<link rel="stylesheet" href="css/style.css">
<!-- 网站图标 -->
<link rel="icon" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'><text y='.9em' font-size='90'>🖼️</text></svg>">
</head>
<body>
<div class="container">
<!-- 页面头部 -->
<header class="header">
<h1>
<span>🖼️</span>
必应每日壁纸
</h1>
<p>每天为您呈现精美的必应壁纸,发现世界之美</p>
</header>
<!-- 加载状态 -->
<div id="loading" class="loading">
<div class="spinner"></div>
<p>正在加载今日壁纸...</p>
</div>
<!-- 壁纸内容区域 -->
<main id="wallpaper-content" class="content" style="display: none;">
<!-- 壁纸内容将通过JavaScript动态加载 -->
</main>
</div>
<!-- 引入脚本文件 -->
<script src="js/script.js"></script>
</body>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="必应每日壁纸 - 每天为您呈现精美的必应壁纸">
<meta name="keywords" content="必应壁纸,每日壁纸,高清壁纸,桌面壁纸">
<title>必应每日壁纸</title>
<!-- 引入样式文件 -->
<link rel="stylesheet" href="css/style.css">
<!-- 网站图标 -->
<link rel="icon" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'><text y='.9em' font-size='90'>🖼️</text></svg>">
</head>
<body>
<div class="container">
<!-- 页面头部 -->
<header class="header">
<h1>
<span>🖼️</span>
必应每日壁纸
</h1>
<p>每天为您呈现精美的必应壁纸,发现世界之美</p>
</header>
<!-- 加载状态 -->
<div id="loading" class="loading">
<div class="spinner"></div>
<p>正在加载今日壁纸...</p>
</div>
<!-- 壁纸内容区域 -->
<main id="wallpaper-content" class="content" style="display: none;">
<!-- 壁纸内容将通过JavaScript动态加载 -->
</main>
</div>
<!-- 引入脚本文件 -->
<script src="js/script.js"></script>
</body>
</html>

View File

@@ -1,315 +1,315 @@
// 必应每日壁纸 JavaScript 功能
// API配置
const API = {
endpoints: [],
currentIndex: 0,
params: {
encoding: 'json'
},
// 初始化API接口列表
async init() {
try {
const res = await fetch('./接口集合.json');
const endpoints = await res.json();
this.endpoints = endpoints.map(endpoint => `${endpoint}/v2/bing`);
} catch (e) {
// 如果无法加载接口集合,使用默认接口
this.endpoints = ['https://60s.api.shumengya.top/v2/bing'];
}
},
// 获取当前接口URL
getCurrentUrl() {
if (this.endpoints.length === 0) return null;
const url = new URL(this.endpoints[this.currentIndex]);
Object.keys(this.params).forEach(key => {
url.searchParams.append(key, this.params[key]);
});
return url.toString();
},
// 切换到下一个接口
switchToNext() {
this.currentIndex = (this.currentIndex + 1) % this.endpoints.length;
return this.currentIndex < this.endpoints.length;
},
// 重置到第一个接口
reset() {
this.currentIndex = 0;
}
};
// DOM元素
let elements = {};
// 初始化
document.addEventListener('DOMContentLoaded', function() {
initElements();
loadWallpaper();
});
// 初始化DOM元素
function initElements() {
elements = {
container: document.getElementById('wallpaper-content'),
loading: document.getElementById('loading')
};
}
// 加载壁纸数据
async function loadWallpaper() {
try {
showLoading(true);
// 初始化API接口列表
await API.init();
// 重置API索引到第一个接口
API.reset();
// 尝试所有API接口
for (let i = 0; i < API.endpoints.length; i++) {
try {
const url = API.getCurrentUrl();
console.log(`尝试接口 ${i + 1}/${API.endpoints.length}: ${url}`);
const response = await fetch(url, {
cache: 'no-store',
timeout: 10000 // 10秒超时
});
if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
}
const data = await response.json();
console.log('API响应数据:', data);
// 检查数据有效性
if (data && (data.code === 200 || data.data)) {
console.log(`接口 ${i + 1} 请求成功`);
displayWallpaper(data);
return;
}
throw new Error(data && data.message ? data.message : '接口返回异常');
} catch (error) {
console.warn(`接口 ${i + 1} 失败:`, error.message);
// 如果不是最后一个接口,切换到下一个
if (i < API.endpoints.length - 1) {
API.switchToNext();
continue;
}
// 所有接口都失败了,抛出错误
throw new Error('所有接口都无法访问');
}
}
} catch (error) {
console.error('加载壁纸失败:', error);
showError('加载壁纸失败,请稍后重试');
} finally {
showLoading(false);
}
}
// 显示壁纸
function displayWallpaper(data) {
if (!data) {
showError('没有获取到壁纸数据');
return;
}
// 提取壁纸信息
const wallpaperInfo = extractWallpaperInfo(data);
if (!wallpaperInfo || !wallpaperInfo.imageUrl) {
showError('壁纸图片链接无效');
return;
}
// 生成HTML内容
const html = generateWallpaperHTML(wallpaperInfo);
// 显示内容
elements.container.innerHTML = html;
elements.container.classList.add('fade-in');
// 绑定图片加载事件
bindImageEvents();
}
// 提取壁纸信息
function extractWallpaperInfo(data) {
// 根据API响应结构提取信息
let imageUrl = '';
let title = '必应每日壁纸';
let description = '';
let date = new Date().toLocaleDateString('zh-CN');
let copyright = '';
// 处理新的API响应格式
if (data.data) {
const wallpaperData = data.data;
title = wallpaperData.title || title;
description = wallpaperData.description || wallpaperData.main_text || '';
copyright = wallpaperData.copyright || '';
date = wallpaperData.update_date || date;
// 提取图片URL去除反引号
if (wallpaperData.cover) {
imageUrl = wallpaperData.cover.replace(/`/g, '').trim();
}
}
// 处理其他可能的API响应格式
else if (data.url) {
imageUrl = data.url;
} else if (data.image_url) {
imageUrl = data.image_url;
} else if (data.images && data.images.length > 0) {
imageUrl = data.images[0].url || data.images[0].image_url;
title = data.images[0].title || title;
description = data.images[0].description || data.images[0].copyright || '';
copyright = data.images[0].copyright || '';
}
// 如果是相对路径转换为完整URL
if (imageUrl && imageUrl.startsWith('/')) {
imageUrl = 'https://www.bing.com' + imageUrl;
}
// 确保图片URL有效
if (!imageUrl || imageUrl === '') {
console.error('无法提取图片URL原始数据:', data);
return null;
}
return {
imageUrl,
title,
description: description || copyright,
date,
copyright
};
}
// 生成壁纸HTML
function generateWallpaperHTML(info) {
return `
<div class="wallpaper-container">
<div class="wallpaper-info">
<h2 class="wallpaper-title">${escapeHtml(info.title)}</h2>
<div class="wallpaper-date">${info.date}</div>
${info.description ? `<div class="wallpaper-description">${escapeHtml(info.description)}</div>` : ''}
</div>
<div class="wallpaper-image">
<img src="${info.imageUrl}" alt="${escapeHtml(info.title)}" loading="lazy">
</div>
<div class="download-section">
<a href="${info.imageUrl}" class="download-btn" download="bing-wallpaper-${info.date}.jpg" target="_blank">
<span>📥</span>
下载壁纸
</a>
</div>
</div>
${info.copyright ? `
<div class="copyright">
<p>${escapeHtml(info.copyright)}</p>
</div>
` : ''}
`;
}
// 绑定图片事件
function bindImageEvents() {
const images = elements.container.querySelectorAll('img');
images.forEach(img => {
img.addEventListener('load', function() {
this.classList.add('loaded');
});
img.addEventListener('error', function() {
console.error('图片加载失败:', this.src);
this.parentElement.innerHTML = `
<div class="error">
<p>🖼️ 图片加载失败</p>
<p>请检查网络连接或稍后重试</p>
</div>
`;
});
});
}
// 显示/隐藏加载状态
function showLoading(show) {
if (elements.loading) {
elements.loading.style.display = show ? 'block' : 'none';
}
if (elements.container) {
elements.container.style.display = show ? 'none' : 'block';
}
}
// 显示错误信息
function showError(message) {
if (elements.container) {
elements.container.innerHTML = `
<div class="error">
<h3>⚠️ 加载失败</h3>
<p>${escapeHtml(message)}</p>
<p>请检查网络连接或稍后重试</p>
</div>
`;
elements.container.style.display = 'block';
}
}
// HTML转义
function escapeHtml(text) {
if (!text) return '';
const div = document.createElement('div');
div.textContent = text;
return div.innerHTML;
}
// 格式化日期
function formatDate(dateString) {
try {
const date = new Date(dateString);
return date.toLocaleDateString('zh-CN', {
year: 'numeric',
month: 'long',
day: 'numeric'
});
} catch (error) {
return dateString;
}
}
// 错误处理
window.addEventListener('error', function(event) {
console.error('页面错误:', event.error);
});
// 网络状态监听
window.addEventListener('online', function() {
console.log('网络已连接');
});
window.addEventListener('offline', function() {
console.log('网络已断开');
showError('网络连接已断开,请检查网络设置');
});
// 导出函数供外部调用
window.BingWallpaper = {
loadWallpaper,
showError,
showLoading
// 必应每日壁纸 JavaScript 功能
// API配置
const API = {
endpoints: [],
currentIndex: 0,
params: {
encoding: 'json'
},
// 初始化API接口列表
async init() {
try {
const res = await fetch('./接口集合.json');
const endpoints = await res.json();
this.endpoints = endpoints.map(endpoint => `${endpoint}/v2/bing`);
} catch (e) {
// 如果无法加载接口集合,使用默认接口
this.endpoints = ['https://60s.api.shumengya.top/v2/bing'];
}
},
// 获取当前接口URL
getCurrentUrl() {
if (this.endpoints.length === 0) return null;
const url = new URL(this.endpoints[this.currentIndex]);
Object.keys(this.params).forEach(key => {
url.searchParams.append(key, this.params[key]);
});
return url.toString();
},
// 切换到下一个接口
switchToNext() {
this.currentIndex = (this.currentIndex + 1) % this.endpoints.length;
return this.currentIndex < this.endpoints.length;
},
// 重置到第一个接口
reset() {
this.currentIndex = 0;
}
};
// DOM元素
let elements = {};
// 初始化
document.addEventListener('DOMContentLoaded', function() {
initElements();
loadWallpaper();
});
// 初始化DOM元素
function initElements() {
elements = {
container: document.getElementById('wallpaper-content'),
loading: document.getElementById('loading')
};
}
// 加载壁纸数据
async function loadWallpaper() {
try {
showLoading(true);
// 初始化API接口列表
await API.init();
// 重置API索引到第一个接口
API.reset();
// 尝试所有API接口
for (let i = 0; i < API.endpoints.length; i++) {
try {
const url = API.getCurrentUrl();
console.log(`尝试接口 ${i + 1}/${API.endpoints.length}: ${url}`);
const response = await fetch(url, {
cache: 'no-store',
timeout: 10000 // 10秒超时
});
if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
}
const data = await response.json();
console.log('API响应数据:', data);
// 检查数据有效性
if (data && (data.code === 200 || data.data)) {
console.log(`接口 ${i + 1} 请求成功`);
displayWallpaper(data);
return;
}
throw new Error(data && data.message ? data.message : '接口返回异常');
} catch (error) {
console.warn(`接口 ${i + 1} 失败:`, error.message);
// 如果不是最后一个接口,切换到下一个
if (i < API.endpoints.length - 1) {
API.switchToNext();
continue;
}
// 所有接口都失败了,抛出错误
throw new Error('所有接口都无法访问');
}
}
} catch (error) {
console.error('加载壁纸失败:', error);
showError('加载壁纸失败,请稍后重试');
} finally {
showLoading(false);
}
}
// 显示壁纸
function displayWallpaper(data) {
if (!data) {
showError('没有获取到壁纸数据');
return;
}
// 提取壁纸信息
const wallpaperInfo = extractWallpaperInfo(data);
if (!wallpaperInfo || !wallpaperInfo.imageUrl) {
showError('壁纸图片链接无效');
return;
}
// 生成HTML内容
const html = generateWallpaperHTML(wallpaperInfo);
// 显示内容
elements.container.innerHTML = html;
elements.container.classList.add('fade-in');
// 绑定图片加载事件
bindImageEvents();
}
// 提取壁纸信息
function extractWallpaperInfo(data) {
// 根据API响应结构提取信息
let imageUrl = '';
let title = '必应每日壁纸';
let description = '';
let date = new Date().toLocaleDateString('zh-CN');
let copyright = '';
// 处理新的API响应格式
if (data.data) {
const wallpaperData = data.data;
title = wallpaperData.title || title;
description = wallpaperData.description || wallpaperData.main_text || '';
copyright = wallpaperData.copyright || '';
date = wallpaperData.update_date || date;
// 提取图片URL去除反引号
if (wallpaperData.cover) {
imageUrl = wallpaperData.cover.replace(/`/g, '').trim();
}
}
// 处理其他可能的API响应格式
else if (data.url) {
imageUrl = data.url;
} else if (data.image_url) {
imageUrl = data.image_url;
} else if (data.images && data.images.length > 0) {
imageUrl = data.images[0].url || data.images[0].image_url;
title = data.images[0].title || title;
description = data.images[0].description || data.images[0].copyright || '';
copyright = data.images[0].copyright || '';
}
// 如果是相对路径转换为完整URL
if (imageUrl && imageUrl.startsWith('/')) {
imageUrl = 'https://www.bing.com' + imageUrl;
}
// 确保图片URL有效
if (!imageUrl || imageUrl === '') {
console.error('无法提取图片URL原始数据:', data);
return null;
}
return {
imageUrl,
title,
description: description || copyright,
date,
copyright
};
}
// 生成壁纸HTML
function generateWallpaperHTML(info) {
return `
<div class="wallpaper-container">
<div class="wallpaper-info">
<h2 class="wallpaper-title">${escapeHtml(info.title)}</h2>
<div class="wallpaper-date">${info.date}</div>
${info.description ? `<div class="wallpaper-description">${escapeHtml(info.description)}</div>` : ''}
</div>
<div class="wallpaper-image">
<img src="${info.imageUrl}" alt="${escapeHtml(info.title)}" loading="lazy">
</div>
<div class="download-section">
<a href="${info.imageUrl}" class="download-btn" download="bing-wallpaper-${info.date}.jpg" target="_blank">
<span>📥</span>
下载壁纸
</a>
</div>
</div>
${info.copyright ? `
<div class="copyright">
<p>${escapeHtml(info.copyright)}</p>
</div>
` : ''}
`;
}
// 绑定图片事件
function bindImageEvents() {
const images = elements.container.querySelectorAll('img');
images.forEach(img => {
img.addEventListener('load', function() {
this.classList.add('loaded');
});
img.addEventListener('error', function() {
console.error('图片加载失败:', this.src);
this.parentElement.innerHTML = `
<div class="error">
<p>🖼️ 图片加载失败</p>
<p>请检查网络连接或稍后重试</p>
</div>
`;
});
});
}
// 显示/隐藏加载状态
function showLoading(show) {
if (elements.loading) {
elements.loading.style.display = show ? 'block' : 'none';
}
if (elements.container) {
elements.container.style.display = show ? 'none' : 'block';
}
}
// 显示错误信息
function showError(message) {
if (elements.container) {
elements.container.innerHTML = `
<div class="error">
<h3>⚠️ 加载失败</h3>
<p>${escapeHtml(message)}</p>
<p>请检查网络连接或稍后重试</p>
</div>
`;
elements.container.style.display = 'block';
}
}
// HTML转义
function escapeHtml(text) {
if (!text) return '';
const div = document.createElement('div');
div.textContent = text;
return div.innerHTML;
}
// 格式化日期
function formatDate(dateString) {
try {
const date = new Date(dateString);
return date.toLocaleDateString('zh-CN', {
year: 'numeric',
month: 'long',
day: 'numeric'
});
} catch (error) {
return dateString;
}
}
// 错误处理
window.addEventListener('error', function(event) {
console.error('页面错误:', event.error);
});
// 网络状态监听
window.addEventListener('online', function() {
console.log('网络已连接');
});
window.addEventListener('offline', function() {
console.log('网络已断开');
showError('网络连接已断开,请检查网络设置');
});
// 导出函数供外部调用
window.BingWallpaper = {
loadWallpaper,
showError,
showLoading
};

View File

@@ -1,3 +1,3 @@
[
"https://60s.api.shumengya.top"
]
[
"https://60s.api.shumengya.top"
]

View File

@@ -1,15 +1,15 @@
{
"code": 200,
"message": "获取成功。数据来自官方/权威源头,以确保稳定与实时。开源地址 https://github.com/vikiboss/60s反馈群 595941841",
"data": {
"title": "瑟沃格湖,瓦加尔岛,法罗群岛",
"headline": "海洋上方的湖泊",
"description": "大自然自有其奇妙之处瑟沃格湖Sørvágsvatn便是其中最精彩的之一。世界湖泊日是探索法罗群岛丹麦王国的一个自治行政区这片视错觉的绝佳时机。这座位于沃格岛上的湖泊也被称为莱蒂斯湖Leitisvatn看似漂浮在海平面之上。实际上它的海拔不到100英尺。索尔瓦格斯湖是法罗群岛最大的湖泊面积约1.3平方英里为Bøsdalafossur瀑布Bøsdalafossur提供水源瀑布的湖水在那里奔腾而下最终倾泻而入大海。",
"main_text": "该湖位于瓦加尔岛南部通过Bøsdalafossur瀑布与大西洋相连形成了壮丽的“悬湖”景观。",
"cover": "https://bing.com/th?id=OHR.FaroeLake_ZH-CN3977660997_1920x1080.jpg",
"cover_4k": "https://bing.com/th?id=OHR.FaroeLake_ZH-CN3977660997_UHD.jpg",
"copyright": "© Anton Petrus/Getty Images",
"update_date": "2025-08-27 13:24:37",
"update_date_at": 1756301077809
}
{
"code": 200,
"message": "获取成功。数据来自官方/权威源头,以确保稳定与实时。开源地址 https://github.com/vikiboss/60s反馈群 595941841",
"data": {
"title": "瑟沃格湖,瓦加尔岛,法罗群岛",
"headline": "海洋上方的湖泊",
"description": "大自然自有其奇妙之处瑟沃格湖Sørvágsvatn便是其中最精彩的之一。世界湖泊日是探索法罗群岛丹麦王国的一个自治行政区这片视错觉的绝佳时机。这座位于沃格岛上的湖泊也被称为莱蒂斯湖Leitisvatn看似漂浮在海平面之上。实际上它的海拔不到100英尺。索尔瓦格斯湖是法罗群岛最大的湖泊面积约1.3平方英里为Bøsdalafossur瀑布Bøsdalafossur提供水源瀑布的湖水在那里奔腾而下最终倾泻而入大海。",
"main_text": "该湖位于瓦加尔岛南部通过Bøsdalafossur瀑布与大西洋相连形成了壮丽的“悬湖”景观。",
"cover": "https://bing.com/th?id=OHR.FaroeLake_ZH-CN3977660997_1920x1080.jpg",
"cover_4k": "https://bing.com/th?id=OHR.FaroeLake_ZH-CN3977660997_UHD.jpg",
"copyright": "© Anton Petrus/Getty Images",
"update_date": "2025-08-27 13:24:37",
"update_date_at": 1756301077809
}
}

View File

@@ -1,327 +1,327 @@
/* 每天60s读懂世界 - 清新风格样式 */
/* 重置样式 */
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
background: linear-gradient(135deg, #a8e6cf 0%, #dcedc1 50%, #ffd3a5 100%);
min-height: 100vh;
color: #2d5016;
line-height: 1.6;
}
.container {
max-width: 1200px;
margin: 0 auto;
padding: 20px;
}
/* 头部样式 */
.header {
text-align: center;
margin-bottom: 30px;
background: rgba(255, 255, 255, 0.85);
border-radius: 20px;
padding: 30px;
box-shadow: 0 8px 25px rgba(45, 80, 22, 0.08);
backdrop-filter: blur(10px);
}
.header h1 {
font-size: 2.5rem;
color: #2d5016;
margin-bottom: 10px;
font-weight: 700;
}
.header p {
color: #5a7c65;
font-size: 1.1rem;
}
/* 控制面板 */
.controls {
background: rgba(255, 255, 255, 0.85);
border-radius: 15px;
padding: 20px;
margin-bottom: 30px;
box-shadow: 0 5px 20px rgba(45, 80, 22, 0.08);
backdrop-filter: blur(10px);
}
.date-selector {
display: flex;
align-items: center;
gap: 15px;
margin-bottom: 20px;
flex-wrap: wrap;
}
.date-selector label {
font-weight: 600;
color: #4a5568;
}
.date-selector input {
padding: 10px 15px;
border: 2px solid #e2e8f0;
border-radius: 10px;
font-size: 1rem;
transition: all 0.3s ease;
}
.date-selector input:focus {
outline: none;
border-color: #81c784;
box-shadow: 0 0 0 3px rgba(129, 199, 132, 0.1);
}
.btn {
background: linear-gradient(135deg, #81c784 0%, #66bb6a 100%);
color: white;
border: none;
padding: 12px 25px;
border-radius: 10px;
font-size: 1rem;
font-weight: 600;
cursor: pointer;
transition: all 0.3s ease;
box-shadow: 0 4px 15px rgba(129, 199, 132, 0.3);
}
.btn:hover {
transform: translateY(-2px);
box-shadow: 0 6px 20px rgba(129, 199, 132, 0.4);
}
.btn:active {
transform: translateY(0);
}
/* 加载状态 */
.loading {
text-align: center;
padding: 40px;
background: rgba(255, 255, 255, 0.85);
border-radius: 15px;
box-shadow: 0 5px 20px rgba(45, 80, 22, 0.08);
}
.spinner {
width: 40px;
height: 40px;
border: 4px solid #e8f5e8;
border-top: 4px solid #81c784;
border-radius: 50%;
animation: spin 1s linear infinite;
margin: 0 auto 20px;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
/* 内容区域 */
.content {
background: rgba(255, 255, 255, 0.85);
border-radius: 20px;
padding: 30px;
box-shadow: 0 8px 25px rgba(45, 80, 22, 0.08);
backdrop-filter: blur(10px);
}
.news-header {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 25px;
flex-wrap: wrap;
gap: 15px;
}
.news-date {
font-size: 1.5rem;
font-weight: 700;
color: #2d5016;
}
.lunar-date {
color: #5a7c65;
font-size: 1rem;
}
/* 新闻图片 */
.news-image {
width: 100%;
max-width: 600px;
height: auto;
border-radius: 15px;
margin: 20px auto;
display: block;
box-shadow: 0 8px 25px rgba(0, 0, 0, 0.15);
}
/* 新闻列表 */
.news-list {
margin: 25px 0;
}
.news-item {
background: #f1f8e9;
border-left: 4px solid #81c784;
padding: 15px 20px;
margin-bottom: 15px;
border-radius: 0 10px 10px 0;
transition: all 0.3s ease;
position: relative;
}
.news-item:hover {
background: #e8f5e8;
transform: translateX(5px);
box-shadow: 0 4px 15px rgba(45, 80, 22, 0.1);
}
.news-item::before {
content: counter(news-counter);
counter-increment: news-counter;
position: absolute;
left: -15px;
top: 50%;
transform: translateY(-50%);
background: #81c784;
color: white;
width: 25px;
height: 25px;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
font-size: 0.8rem;
font-weight: bold;
}
.news-list {
counter-reset: news-counter;
}
/* 每日一句 */
.daily-tip {
background: linear-gradient(135deg, #ffecd2 0%, #fcb69f 100%);
padding: 20px;
border-radius: 15px;
margin: 25px 0;
text-align: center;
font-style: italic;
font-size: 1.1rem;
color: #744210;
box-shadow: 0 5px 20px rgba(252, 182, 159, 0.3);
}
/* 错误提示 */
.error {
background: #fed7d7;
color: #c53030;
padding: 20px;
border-radius: 10px;
text-align: center;
border: 1px solid #feb2b2;
}
/* 响应式设计 */
/* 平板端 */
@media (max-width: 768px) {
.container {
padding: 15px;
}
.header h1 {
font-size: 2rem;
}
.header {
padding: 20px;
}
.content {
padding: 20px;
}
.date-selector {
flex-direction: column;
align-items: stretch;
}
.news-header {
flex-direction: column;
align-items: flex-start;
}
}
/* 手机端 */
@media (max-width: 480px) {
.container {
padding: 10px;
}
.header {
padding: 15px;
margin-bottom: 20px;
}
.header h1 {
font-size: 1.8rem;
}
.controls {
padding: 15px;
}
.content {
padding: 15px;
}
.news-item {
padding: 12px 15px;
margin-left: 10px;
}
.news-item::before {
left: -10px;
width: 20px;
height: 20px;
font-size: 0.7rem;
}
.daily-tip {
padding: 15px;
font-size: 1rem;
}
.btn {
width: 100%;
padding: 15px;
}
}
/* 大屏幕优化 */
@media (min-width: 1200px) {
.container {
padding: 40px;
}
.header {
padding: 40px;
}
.content {
padding: 40px;
}
/* 每天60s读懂世界 - 清新风格样式 */
/* 重置样式 */
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
background: linear-gradient(135deg, #a8e6cf 0%, #dcedc1 50%, #ffd3a5 100%);
min-height: 100vh;
color: #2d5016;
line-height: 1.6;
}
.container {
max-width: 1200px;
margin: 0 auto;
padding: 20px;
}
/* 头部样式 */
.header {
text-align: center;
margin-bottom: 30px;
background: rgba(255, 255, 255, 0.85);
border-radius: 20px;
padding: 30px;
box-shadow: 0 8px 25px rgba(45, 80, 22, 0.08);
backdrop-filter: blur(10px);
}
.header h1 {
font-size: 2.5rem;
color: #2d5016;
margin-bottom: 10px;
font-weight: 700;
}
.header p {
color: #5a7c65;
font-size: 1.1rem;
}
/* 控制面板 */
.controls {
background: rgba(255, 255, 255, 0.85);
border-radius: 15px;
padding: 20px;
margin-bottom: 30px;
box-shadow: 0 5px 20px rgba(45, 80, 22, 0.08);
backdrop-filter: blur(10px);
}
.date-selector {
display: flex;
align-items: center;
gap: 15px;
margin-bottom: 20px;
flex-wrap: wrap;
}
.date-selector label {
font-weight: 600;
color: #4a5568;
}
.date-selector input {
padding: 10px 15px;
border: 2px solid #e2e8f0;
border-radius: 10px;
font-size: 1rem;
transition: all 0.3s ease;
}
.date-selector input:focus {
outline: none;
border-color: #81c784;
box-shadow: 0 0 0 3px rgba(129, 199, 132, 0.1);
}
.btn {
background: linear-gradient(135deg, #81c784 0%, #66bb6a 100%);
color: white;
border: none;
padding: 12px 25px;
border-radius: 10px;
font-size: 1rem;
font-weight: 600;
cursor: pointer;
transition: all 0.3s ease;
box-shadow: 0 4px 15px rgba(129, 199, 132, 0.3);
}
.btn:hover {
transform: translateY(-2px);
box-shadow: 0 6px 20px rgba(129, 199, 132, 0.4);
}
.btn:active {
transform: translateY(0);
}
/* 加载状态 */
.loading {
text-align: center;
padding: 40px;
background: rgba(255, 255, 255, 0.85);
border-radius: 15px;
box-shadow: 0 5px 20px rgba(45, 80, 22, 0.08);
}
.spinner {
width: 40px;
height: 40px;
border: 4px solid #e8f5e8;
border-top: 4px solid #81c784;
border-radius: 50%;
animation: spin 1s linear infinite;
margin: 0 auto 20px;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
/* 内容区域 */
.content {
background: rgba(255, 255, 255, 0.85);
border-radius: 20px;
padding: 30px;
box-shadow: 0 8px 25px rgba(45, 80, 22, 0.08);
backdrop-filter: blur(10px);
}
.news-header {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 25px;
flex-wrap: wrap;
gap: 15px;
}
.news-date {
font-size: 1.5rem;
font-weight: 700;
color: #2d5016;
}
.lunar-date {
color: #5a7c65;
font-size: 1rem;
}
/* 新闻图片 */
.news-image {
width: 100%;
max-width: 600px;
height: auto;
border-radius: 15px;
margin: 20px auto;
display: block;
box-shadow: 0 8px 25px rgba(0, 0, 0, 0.15);
}
/* 新闻列表 */
.news-list {
margin: 25px 0;
}
.news-item {
background: #f1f8e9;
border-left: 4px solid #81c784;
padding: 15px 20px;
margin-bottom: 15px;
border-radius: 0 10px 10px 0;
transition: all 0.3s ease;
position: relative;
}
.news-item:hover {
background: #e8f5e8;
transform: translateX(5px);
box-shadow: 0 4px 15px rgba(45, 80, 22, 0.1);
}
.news-item::before {
content: counter(news-counter);
counter-increment: news-counter;
position: absolute;
left: -15px;
top: 50%;
transform: translateY(-50%);
background: #81c784;
color: white;
width: 25px;
height: 25px;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
font-size: 0.8rem;
font-weight: bold;
}
.news-list {
counter-reset: news-counter;
}
/* 每日一句 */
.daily-tip {
background: linear-gradient(135deg, #ffecd2 0%, #fcb69f 100%);
padding: 20px;
border-radius: 15px;
margin: 25px 0;
text-align: center;
font-style: italic;
font-size: 1.1rem;
color: #744210;
box-shadow: 0 5px 20px rgba(252, 182, 159, 0.3);
}
/* 错误提示 */
.error {
background: #fed7d7;
color: #c53030;
padding: 20px;
border-radius: 10px;
text-align: center;
border: 1px solid #feb2b2;
}
/* 响应式设计 */
/* 平板端 */
@media (max-width: 768px) {
.container {
padding: 15px;
}
.header h1 {
font-size: 2rem;
}
.header {
padding: 20px;
}
.content {
padding: 20px;
}
.date-selector {
flex-direction: column;
align-items: stretch;
}
.news-header {
flex-direction: column;
align-items: flex-start;
}
}
/* 手机端 */
@media (max-width: 480px) {
.container {
padding: 10px;
}
.header {
padding: 15px;
margin-bottom: 20px;
}
.header h1 {
font-size: 1.8rem;
}
.controls {
padding: 15px;
}
.content {
padding: 15px;
}
.news-item {
padding: 12px 15px;
margin-left: 10px;
}
.news-item::before {
left: -10px;
width: 20px;
height: 20px;
font-size: 0.7rem;
}
.daily-tip {
padding: 15px;
font-size: 1rem;
}
.btn {
width: 100%;
padding: 15px;
}
}
/* 大屏幕优化 */
@media (min-width: 1200px) {
.container {
padding: 40px;
}
.header {
padding: 40px;
}
.content {
padding: 40px;
}
}

View File

@@ -1,49 +1,49 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="每天60秒读懂世界 - 获取最新资讯,了解天下大事">
<meta name="keywords" content="新闻,资讯,每日新闻,60秒读懂世界">
<title>每天60秒读懂世界 | 最新资讯</title>
<!-- 引入CSS样式 -->
<link rel="stylesheet" href="css/style.css">
<!-- 网站图标 -->
<link rel="icon" href="data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 100 100%22><text y=%22.9em%22 font-size=%2290%22>📰</text></svg>">
<!-- Open Graph 元数据 -->
<meta property="og:title" content="每天60秒读懂世界">
<meta property="og:description" content="获取最新资讯,了解天下大事">
<meta property="og:type" content="website">
</head>
<body>
<div class="container">
<!-- 页面头部 -->
<header class="header">
<h1>📰 每天60秒读懂世界</h1>
<p>获取最新资讯,了解天下大事</p>
</header>
<!-- 主要内容区域 -->
<main id="content" class="content">
<!-- 内容将通过JavaScript动态加载 -->
<div class="loading">
<div class="spinner"></div>
<p>正在加载今日资讯...</p>
</div>
</main>
</div>
<!-- 页面底部 -->
<footer style="text-align: center; padding: 20px; color: rgba(255,255,255,0.8); font-size: 0.9rem;">
<p>Made with ❤️ | 数据来源每天60秒读懂世界API</p>
</footer>
<!-- 引入JavaScript -->
<script src="js/script.js"></script>
</body>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="每天60秒读懂世界 - 获取最新资讯,了解天下大事">
<meta name="keywords" content="新闻,资讯,每日新闻,60秒读懂世界">
<title>每天60秒读懂世界 | 最新资讯</title>
<!-- 引入CSS样式 -->
<link rel="stylesheet" href="css/style.css">
<!-- 网站图标 -->
<link rel="icon" href="data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 100 100%22><text y=%22.9em%22 font-size=%2290%22>📰</text></svg>">
<!-- Open Graph 元数据 -->
<meta property="og:title" content="每天60秒读懂世界">
<meta property="og:description" content="获取最新资讯,了解天下大事">
<meta property="og:type" content="website">
</head>
<body>
<div class="container">
<!-- 页面头部 -->
<header class="header">
<h1>📰 每天60秒读懂世界</h1>
<p>获取最新资讯,了解天下大事</p>
</header>
<!-- 主要内容区域 -->
<main id="content" class="content">
<!-- 内容将通过JavaScript动态加载 -->
<div class="loading">
<div class="spinner"></div>
<p>正在加载今日资讯...</p>
</div>
</main>
</div>
<!-- 页面底部 -->
<footer style="text-align: center; padding: 20px; color: rgba(255,255,255,0.8); font-size: 0.9rem;">
<p>Made with ❤️ | 数据来源每天60秒读懂世界API</p>
</footer>
<!-- 引入JavaScript -->
<script src="js/script.js"></script>
</body>
</html>

View File

@@ -1,305 +1,305 @@
// 每天60s读懂世界 - JavaScript功能实现
const API = {
endpoints: [],
currentIndex: 0,
params: {
encoding: 'json'
},
localFallback: '返回接口.json',
// 初始化API接口列表
async init() {
try {
const res = await fetch('./接口集合.json');
const endpoints = await res.json();
this.endpoints = endpoints.map(endpoint => `${endpoint}/v2/60s`);
} catch (e) {
// 如果无法加载接口集合,使用默认接口
this.endpoints = ['https://60s.api.shumengya.top/v2/60s'];
}
},
// 获取当前接口URL
getCurrentUrl() {
if (this.endpoints.length === 0) return null;
const url = new URL(this.endpoints[this.currentIndex]);
Object.entries(this.params).forEach(([k, v]) => url.searchParams.append(k, v));
return url.toString();
},
// 切换到下一个接口
switchToNext() {
this.currentIndex = (this.currentIndex + 1) % this.endpoints.length;
return this.currentIndex < this.endpoints.length;
},
// 重置到第一个接口
reset() {
this.currentIndex = 0;
}
};
class NewsApp {
constructor() {
this.apiUrl = 'https://60s.viki.moe/v2/60s';
this.init();
}
init() {
this.bindEvents();
this.loadTodayNews();
}
bindEvents() {
// 移除了刷新按钮,不需要绑定事件
}
formatDate(date) {
const year = date.getFullYear();
const month = String(date.getMonth() + 1).padStart(2, '0');
const day = String(date.getDate()).padStart(2, '0');
return `${year}-${month}-${day}`;
}
showLoading() {
const contentDiv = document.getElementById('content');
if (contentDiv) {
contentDiv.innerHTML = `
<div class="loading">
<div class="spinner"></div>
<p>正在获取最新资讯...</p>
</div>
`;
}
}
showError(message) {
const contentDiv = document.getElementById('content');
if (contentDiv) {
contentDiv.innerHTML = `
<div class="error">
<h3>😔 获取失败</h3>
<p>${message}</p>
</div>
`;
}
}
async loadNews() {
try {
this.showLoading();
// 尝试从API获取数据
let data = await this.fetchFromAPI();
// 如果API失败尝试本地数据
if (!data) {
data = await this.fetchFromLocal();
}
if (!data) {
throw new Error('无法获取数据,请检查网络连接或稍后重试');
}
if (data.code !== 200) {
throw new Error(data.message || '获取数据失败');
}
this.renderNews(data.data);
} catch (error) {
console.error('获取新闻失败:', error);
this.showError(error.message || '网络连接失败,请检查网络后重试');
}
}
async fetchFromAPI() {
// 初始化API接口列表
await API.init();
// 重置API索引到第一个接口
API.reset();
// 尝试所有API接口
for (let i = 0; i < API.endpoints.length; i++) {
try {
const url = API.getCurrentUrl();
console.log(`尝试接口 ${i + 1}/${API.endpoints.length}: ${url}`);
const resp = await fetch(url, {
cache: 'no-store'
});
if (!resp.ok) {
throw new Error(`HTTP ${resp.status}: ${resp.statusText}`);
}
const data = await resp.json();
if (data && data.code === 200) {
console.log(`接口 ${i + 1} 请求成功`);
return data;
}
throw new Error(data && data.message ? data.message : '接口返回异常');
} catch (e) {
console.warn(`接口 ${i + 1} 失败:`, e.message);
// 如果不是最后一个接口,切换到下一个
if (i < API.endpoints.length - 1) {
API.switchToNext();
continue;
}
// 所有接口都失败了
console.warn('所有远程接口都失败,尝试本地数据');
return null;
}
}
}
async fetchFromLocal() {
try {
const resp = await fetch(API.localFallback + `?t=${Date.now()}`);
if (!resp.ok) throw new Error(`本地文件HTTP ${resp.status}`);
const data = await resp.json();
return data;
} catch (e) {
console.error('读取本地返回接口.json失败:', e);
return null;
}
}
loadTodayNews() {
this.loadNews();
}
renderNews(newsData) {
const contentDiv = document.getElementById('content');
if (!contentDiv || !newsData) return;
const {
date,
day_of_week,
lunar_date,
news,
tip,
link
} = newsData;
let newsListHtml = '';
if (news && news.length > 0) {
newsListHtml = news.map(item => `
<div class="news-item">
${this.escapeHtml(item)}
</div>
`).join('');
}
// 移除图片显示功能
const tipHtml = tip ? `
<div class="daily-tip">
💡 ${this.escapeHtml(tip)}
</div>
` : '';
const linkHtml = link ? `
<div style="text-align: center; margin-top: 20px;">
<a href="${this.escapeHtml(link)}" target="_blank" class="btn" style="text-decoration: none; display: inline-block;">
📖 查看原文
</a>
</div>
` : '';
contentDiv.innerHTML = `
<div class="news-header">
<div>
<div class="news-date">${this.escapeHtml(date)} ${this.escapeHtml(day_of_week || '')}</div>
${lunar_date ? `<div class="lunar-date">${this.escapeHtml(lunar_date)}</div>` : ''}
</div>
</div>
${tipHtml}
<div class="news-list">
<h3 style="margin-bottom: 20px; color: #2d5016; font-size: 1.3rem;">📰 今日要闻</h3>
${newsListHtml}
</div>
${linkHtml}
<div style="text-align: center; margin-top: 30px; color: #5a7c65; font-size: 0.9rem;">
<p>数据来源每天60秒读懂世界</p>
<p>更新时间:${newsData.api_updated || '未知'}</p>
</div>
`;
}
escapeHtml(text) {
if (typeof text !== 'string') return text;
const div = document.createElement('div');
div.textContent = text;
return div.innerHTML;
}
}
// 页面加载完成后初始化应用
document.addEventListener('DOMContentLoaded', function() {
window.newsApp = new NewsApp();
});
// 添加一些实用功能
function copyToClipboard(text) {
navigator.clipboard.writeText(text).then(() => {
showToast('已复制到剪贴板');
}).catch(() => {
showToast('复制失败,请手动复制');
});
}
function showToast(message) {
// 创建提示框
const toast = document.createElement('div');
toast.style.cssText = `
position: fixed;
top: 20px;
right: 20px;
background: #4a5568;
color: white;
padding: 12px 20px;
border-radius: 8px;
z-index: 1000;
font-size: 14px;
box-shadow: 0 4px 12px rgba(0,0,0,0.3);
animation: slideIn 0.3s ease;
`;
toast.textContent = message;
// 添加动画样式
const style = document.createElement('style');
style.textContent = `
@keyframes slideIn {
from { transform: translateX(100%); opacity: 0; }
to { transform: translateX(0); opacity: 1; }
}
`;
document.head.appendChild(style);
document.body.appendChild(toast);
// 3秒后自动移除
setTimeout(() => {
toast.remove();
style.remove();
}, 3000);
}
// 添加键盘快捷键支持
document.addEventListener('keydown', function(e) {
// Ctrl/Cmd + R 刷新数据
if ((e.ctrlKey || e.metaKey) && e.key === 'r') {
e.preventDefault();
if (window.newsApp) {
window.newsApp.loadNews();
}
}
// 每天60s读懂世界 - JavaScript功能实现
const API = {
endpoints: [],
currentIndex: 0,
params: {
encoding: 'json'
},
localFallback: '返回接口.json',
// 初始化API接口列表
async init() {
try {
const res = await fetch('./接口集合.json');
const endpoints = await res.json();
this.endpoints = endpoints.map(endpoint => `${endpoint}/v2/60s`);
} catch (e) {
// 如果无法加载接口集合,使用默认接口
this.endpoints = ['https://60s.api.shumengya.top/v2/60s'];
}
},
// 获取当前接口URL
getCurrentUrl() {
if (this.endpoints.length === 0) return null;
const url = new URL(this.endpoints[this.currentIndex]);
Object.entries(this.params).forEach(([k, v]) => url.searchParams.append(k, v));
return url.toString();
},
// 切换到下一个接口
switchToNext() {
this.currentIndex = (this.currentIndex + 1) % this.endpoints.length;
return this.currentIndex < this.endpoints.length;
},
// 重置到第一个接口
reset() {
this.currentIndex = 0;
}
};
class NewsApp {
constructor() {
this.apiUrl = 'https://60s.viki.moe/v2/60s';
this.init();
}
init() {
this.bindEvents();
this.loadTodayNews();
}
bindEvents() {
// 移除了刷新按钮,不需要绑定事件
}
formatDate(date) {
const year = date.getFullYear();
const month = String(date.getMonth() + 1).padStart(2, '0');
const day = String(date.getDate()).padStart(2, '0');
return `${year}-${month}-${day}`;
}
showLoading() {
const contentDiv = document.getElementById('content');
if (contentDiv) {
contentDiv.innerHTML = `
<div class="loading">
<div class="spinner"></div>
<p>正在获取最新资讯...</p>
</div>
`;
}
}
showError(message) {
const contentDiv = document.getElementById('content');
if (contentDiv) {
contentDiv.innerHTML = `
<div class="error">
<h3>😔 获取失败</h3>
<p>${message}</p>
</div>
`;
}
}
async loadNews() {
try {
this.showLoading();
// 尝试从API获取数据
let data = await this.fetchFromAPI();
// 如果API失败尝试本地数据
if (!data) {
data = await this.fetchFromLocal();
}
if (!data) {
throw new Error('无法获取数据,请检查网络连接或稍后重试');
}
if (data.code !== 200) {
throw new Error(data.message || '获取数据失败');
}
this.renderNews(data.data);
} catch (error) {
console.error('获取新闻失败:', error);
this.showError(error.message || '网络连接失败,请检查网络后重试');
}
}
async fetchFromAPI() {
// 初始化API接口列表
await API.init();
// 重置API索引到第一个接口
API.reset();
// 尝试所有API接口
for (let i = 0; i < API.endpoints.length; i++) {
try {
const url = API.getCurrentUrl();
console.log(`尝试接口 ${i + 1}/${API.endpoints.length}: ${url}`);
const resp = await fetch(url, {
cache: 'no-store'
});
if (!resp.ok) {
throw new Error(`HTTP ${resp.status}: ${resp.statusText}`);
}
const data = await resp.json();
if (data && data.code === 200) {
console.log(`接口 ${i + 1} 请求成功`);
return data;
}
throw new Error(data && data.message ? data.message : '接口返回异常');
} catch (e) {
console.warn(`接口 ${i + 1} 失败:`, e.message);
// 如果不是最后一个接口,切换到下一个
if (i < API.endpoints.length - 1) {
API.switchToNext();
continue;
}
// 所有接口都失败了
console.warn('所有远程接口都失败,尝试本地数据');
return null;
}
}
}
async fetchFromLocal() {
try {
const resp = await fetch(API.localFallback + `?t=${Date.now()}`);
if (!resp.ok) throw new Error(`本地文件HTTP ${resp.status}`);
const data = await resp.json();
return data;
} catch (e) {
console.error('读取本地返回接口.json失败:', e);
return null;
}
}
loadTodayNews() {
this.loadNews();
}
renderNews(newsData) {
const contentDiv = document.getElementById('content');
if (!contentDiv || !newsData) return;
const {
date,
day_of_week,
lunar_date,
news,
tip,
link
} = newsData;
let newsListHtml = '';
if (news && news.length > 0) {
newsListHtml = news.map(item => `
<div class="news-item">
${this.escapeHtml(item)}
</div>
`).join('');
}
// 移除图片显示功能
const tipHtml = tip ? `
<div class="daily-tip">
💡 ${this.escapeHtml(tip)}
</div>
` : '';
const linkHtml = link ? `
<div style="text-align: center; margin-top: 20px;">
<a href="${this.escapeHtml(link)}" target="_blank" class="btn" style="text-decoration: none; display: inline-block;">
📖 查看原文
</a>
</div>
` : '';
contentDiv.innerHTML = `
<div class="news-header">
<div>
<div class="news-date">${this.escapeHtml(date)} ${this.escapeHtml(day_of_week || '')}</div>
${lunar_date ? `<div class="lunar-date">${this.escapeHtml(lunar_date)}</div>` : ''}
</div>
</div>
${tipHtml}
<div class="news-list">
<h3 style="margin-bottom: 20px; color: #2d5016; font-size: 1.3rem;">📰 今日要闻</h3>
${newsListHtml}
</div>
${linkHtml}
<div style="text-align: center; margin-top: 30px; color: #5a7c65; font-size: 0.9rem;">
<p>数据来源每天60秒读懂世界</p>
<p>更新时间:${newsData.api_updated || '未知'}</p>
</div>
`;
}
escapeHtml(text) {
if (typeof text !== 'string') return text;
const div = document.createElement('div');
div.textContent = text;
return div.innerHTML;
}
}
// 页面加载完成后初始化应用
document.addEventListener('DOMContentLoaded', function() {
window.newsApp = new NewsApp();
});
// 添加一些实用功能
function copyToClipboard(text) {
navigator.clipboard.writeText(text).then(() => {
showToast('已复制到剪贴板');
}).catch(() => {
showToast('复制失败,请手动复制');
});
}
function showToast(message) {
// 创建提示框
const toast = document.createElement('div');
toast.style.cssText = `
position: fixed;
top: 20px;
right: 20px;
background: #4a5568;
color: white;
padding: 12px 20px;
border-radius: 8px;
z-index: 1000;
font-size: 14px;
box-shadow: 0 4px 12px rgba(0,0,0,0.3);
animation: slideIn 0.3s ease;
`;
toast.textContent = message;
// 添加动画样式
const style = document.createElement('style');
style.textContent = `
@keyframes slideIn {
from { transform: translateX(100%); opacity: 0; }
to { transform: translateX(0); opacity: 1; }
}
`;
document.head.appendChild(style);
document.body.appendChild(toast);
// 3秒后自动移除
setTimeout(() => {
toast.remove();
style.remove();
}, 3000);
}
// 添加键盘快捷键支持
document.addEventListener('keydown', function(e) {
// Ctrl/Cmd + R 刷新数据
if ((e.ctrlKey || e.metaKey) && e.key === 'r') {
e.preventDefault();
if (window.newsApp) {
window.newsApp.loadNews();
}
}
});

View File

@@ -1,3 +1,3 @@
[
"https://60s.api.shumengya.top"
]
[
"https://60s.api.shumengya.top"
]

View File

@@ -1,66 +1,66 @@
{
"code": 200,
"message": "获取成功。数据来自官方/权威源头,以确保稳定与实时。开源地址 https://github.com/vikiboss/60s反馈群 595941841",
"data": [
{
"id": "9aa227e2ba294bb1a95c95fde892eb31",
"title": "《Totally Reliable Delivery Service》 Standard Edition",
"cover": "https://cdn1.epicgames.com/52b90f9a982a404781b189f6a7903226/offer/EGS_TotallyReliableDeliveryService_WereFiveGames_S1-2560x1440-47e6e9562d62705a75ea7b7096d0b8dc.jpg",
"original_price": 52,
"original_price_desc": "¥52.00",
"description": "穿好护腰护具发动货车送货的时间到啦在一个高度互动的沙盒世界中与最多三位好友一起随意地完成送货。货物已试投这就是我们靠谱快递Totally Reliable Delivery Service的品质保证",
"seller": "Infogrames LLC",
"is_free_now": true,
"free_start": "2025/08/14 23:00:00",
"free_start_at": 1755183600000,
"free_end": "2025/08/21 23:00:00",
"free_end_at": 1755788400000,
"link": "https://store.epicgames.com/store/zh-CN/p/totally-reliable-delivery-service/home"
},
{
"id": "8ea3500dc38e4f429702bf889c172d3d",
"title": "Hidden Folks",
"cover": "https://cdn1.epicgames.com/spt-assets/7bfd56b0586348dcb139945d9e59f988/hidden-folks-1b7hh.png",
"original_price": 47,
"original_price_desc": "¥47.00",
"description": "Search for hidden folks in hand-drawn, interactive, miniature landscapes. Unfurl tent flaps, cut through bushes, slam doors, and poke some crocodiles! Rooooaaaarrrr!!!!!",
"seller": "Adriaan de Jongh",
"is_free_now": true,
"free_start": "2025/08/14 23:00:00",
"free_start_at": 1755183600000,
"free_end": "2025/08/21 23:00:00",
"free_end_at": 1755788400000,
"link": "https://store.epicgames.com/store/zh-CN/p/hidden-folks-239d16"
},
{
"id": "4cbb6c3704d240f19c3dd5f5cb2b0cb4",
"title": "Kamaeru",
"cover": "https://cdn1.epicgames.com/spt-assets/44313cfbb62b4df5801d0c8d541c2624/kamaeru-40asc.png",
"original_price": 62,
"original_price_desc": "¥62.00",
"description": "Foster a sanctuary for frogs and restore the biodiversity of the wetlands in Kamaeru, a cozy frog collecting game, where you take pictures of frogs, play mini-games and decorate your habitat. Hop right to it!",
"seller": "Armor Games Studios",
"is_free_now": false,
"free_start": "2025/08/21 23:00:00",
"free_start_at": 1755788400000,
"free_end": "2025/08/28 23:00:00",
"free_end_at": 1756393200000,
"link": "https://store.epicgames.com/store/zh-CN/p/kamaeru-0c301e"
},
{
"id": "0d9a533f0e684cc18620a8f408e8e72c",
"title": "Strange Horticulture",
"cover": "https://cdn1.epicgames.com/spt-assets/15e8e3eba65a4763a815d6eae1d763b2/strange-horticulture-offer-2wghv.png",
"original_price": 45,
"original_price_desc": "¥45.00",
"description": "款神秘学解谜游戏,你将扮演当地植物商店的店主,寻找并识别新的植物,悠闲撸猫,与女巫团体交谈,或加入异教。收集各种强大的植物,用它们来影响故事走向,揭开昂德米尔镇的黑暗谜团。",
"seller": "Iceberg Interactive",
"is_free_now": false,
"free_start": "2025/08/21 23:00:00",
"free_start_at": 1755788400000,
"free_end": "2025/08/28 23:00:00",
"free_end_at": 1756393200000,
"link": "https://store.epicgames.com/store/zh-CN/p/strange-horticulture-360e80"
}
]
{
"code": 200,
"message": "获取成功。数据来自官方/权威源头,以确保稳定与实时。开源地址 https://github.com/vikiboss/60s反馈群 595941841",
"data": [
{
"id": "9aa227e2ba294bb1a95c95fde892eb31",
"title": "《Totally Reliable Delivery Service》 Standard Edition",
"cover": "https://cdn1.epicgames.com/52b90f9a982a404781b189f6a7903226/offer/EGS_TotallyReliableDeliveryService_WereFiveGames_S1-2560x1440-47e6e9562d62705a75ea7b7096d0b8dc.jpg",
"original_price": 52,
"original_price_desc": "¥52.00",
"description": "穿好护腰护具发动货车送货的时间到啦在一个高度互动的沙盒世界中与最多三位好友一起随意地完成送货。货物已试投这就是我们靠谱快递Totally Reliable Delivery Service的品质保证",
"seller": "Infogrames LLC",
"is_free_now": true,
"free_start": "2025/08/14 23:00:00",
"free_start_at": 1755183600000,
"free_end": "2025/08/21 23:00:00",
"free_end_at": 1755788400000,
"link": "https://store.epicgames.com/store/zh-CN/p/totally-reliable-delivery-service/home"
},
{
"id": "8ea3500dc38e4f429702bf889c172d3d",
"title": "Hidden Folks",
"cover": "https://cdn1.epicgames.com/spt-assets/7bfd56b0586348dcb139945d9e59f988/hidden-folks-1b7hh.png",
"original_price": 47,
"original_price_desc": "¥47.00",
"description": "Search for hidden folks in hand-drawn, interactive, miniature landscapes. Unfurl tent flaps, cut through bushes, slam doors, and poke some crocodiles! Rooooaaaarrrr!!!!!",
"seller": "Adriaan de Jongh",
"is_free_now": true,
"free_start": "2025/08/14 23:00:00",
"free_start_at": 1755183600000,
"free_end": "2025/08/21 23:00:00",
"free_end_at": 1755788400000,
"link": "https://store.epicgames.com/store/zh-CN/p/hidden-folks-239d16"
},
{
"id": "4cbb6c3704d240f19c3dd5f5cb2b0cb4",
"title": "Kamaeru",
"cover": "https://cdn1.epicgames.com/spt-assets/44313cfbb62b4df5801d0c8d541c2624/kamaeru-40asc.png",
"original_price": 62,
"original_price_desc": "¥62.00",
"description": "Foster a sanctuary for frogs and restore the biodiversity of the wetlands in Kamaeru, a cozy frog collecting game, where you take pictures of frogs, play mini-games and decorate your habitat. Hop right to it!",
"seller": "Armor Games Studios",
"is_free_now": false,
"free_start": "2025/08/21 23:00:00",
"free_start_at": 1755788400000,
"free_end": "2025/08/28 23:00:00",
"free_end_at": 1756393200000,
"link": "https://store.epicgames.com/store/zh-CN/p/kamaeru-0c301e"
},
{
"id": "0d9a533f0e684cc18620a8f408e8e72c",
"title": "Strange Horticulture",
"cover": "https://cdn1.epicgames.com/spt-assets/15e8e3eba65a4763a815d6eae1d763b2/strange-horticulture-offer-2wghv.png",
"original_price": 45,
"original_price_desc": "¥45.00",
"description": "款神秘学解谜游戏,你将扮演当地植物商店的店主,寻找并识别新的植物,悠闲撸猫,与女巫团体交谈,或加入异教。收集各种强大的植物,用它们来影响故事走向,揭开昂德米尔镇的黑暗谜团。",
"seller": "Iceberg Interactive",
"is_free_now": false,
"free_start": "2025/08/21 23:00:00",
"free_start_at": 1755788400000,
"free_end": "2025/08/28 23:00:00",
"free_end_at": 1756393200000,
"link": "https://store.epicgames.com/store/zh-CN/p/strange-horticulture-360e80"
}
]
}

View File

@@ -1,474 +1,474 @@
/* 每日国际汇率 - 淡绿色清新风格样式 */
/* 重置样式 */
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
background: linear-gradient(135deg, #a8e6cf 0%, #dcedc1 50%, #ffd3a5 100%);
min-height: 100vh;
color: #2d5016;
line-height: 1.6;
overflow-x: hidden;
}
.container {
max-width: 1200px;
margin: 0 auto;
padding: 20px;
}
/* 头部样式 */
.header {
text-align: center;
margin-bottom: 30px;
background: rgba(255, 255, 255, 0.85);
border-radius: 20px;
padding: 30px;
box-shadow: 0 8px 25px rgba(45, 80, 22, 0.08);
backdrop-filter: blur(10px);
}
.header h1 {
font-size: 2.5rem;
color: #2d5016;
margin-bottom: 10px;
font-weight: 700;
display: flex;
align-items: center;
justify-content: center;
gap: 15px;
}
.header p {
color: #5a7c65;
font-size: 1.1rem;
}
/* 货币选择器 */
.currency-selector {
background: rgba(255, 255, 255, 0.85);
border-radius: 15px;
padding: 20px;
margin-bottom: 20px;
box-shadow: 0 5px 20px rgba(45, 80, 22, 0.08);
text-align: center;
}
.currency-selector label {
display: block;
margin-bottom: 10px;
font-weight: 600;
color: #2d5016;
}
.currency-selector select {
padding: 12px 20px;
border: 2px solid #c8e6c9;
border-radius: 25px;
background: white;
color: #2d5016;
font-size: 1rem;
min-width: 200px;
cursor: pointer;
transition: all 0.3s ease;
}
.currency-selector select:focus {
outline: none;
border-color: #81c784;
box-shadow: 0 0 0 3px rgba(129, 199, 132, 0.2);
}
/* 加载状态 */
.loading {
text-align: center;
padding: 40px;
background: rgba(255, 255, 255, 0.85);
border-radius: 15px;
box-shadow: 0 5px 20px rgba(45, 80, 22, 0.08);
}
.spinner {
width: 40px;
height: 40px;
border: 4px solid #e8f5e8;
border-top: 4px solid #81c784;
border-radius: 50%;
animation: spin 1s linear infinite;
margin: 0 auto 20px;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
/* 汇率信息容器 */
.exchange-info {
background: rgba(255, 255, 255, 0.85);
border-radius: 20px;
padding: 25px;
margin-bottom: 20px;
box-shadow: 0 8px 25px rgba(45, 80, 22, 0.08);
backdrop-filter: blur(10px);
}
.base-currency {
text-align: center;
margin-bottom: 20px;
}
.base-currency h2 {
font-size: 1.8rem;
color: #2d5016;
margin-bottom: 10px;
}
.update-time {
color: #5a7c65;
font-size: 0.9rem;
}
/* 汇率网格 */
.rates-grid {
display: grid;
grid-template-columns: repeat(8, 1fr);
gap: 10px;
margin-top: 20px;
}
.rate-card {
background: rgba(255, 255, 255, 0.9);
border-radius: 10px;
padding: 12px;
box-shadow: 0 3px 10px rgba(45, 80, 22, 0.06);
transition: all 0.3s ease;
border: 1px solid rgba(200, 230, 201, 0.5);
text-align: center;
}
.rate-card:hover {
transform: translateY(-1px);
box-shadow: 0 4px 15px rgba(45, 80, 22, 0.1);
border-color: #81c784;
}
.currency-code {
font-size: 1rem;
font-weight: 700;
color: #2d5016;
margin-bottom: 6px;
display: flex;
align-items: center;
justify-content: center;
gap: 6px;
}
.currency-flag {
font-size: 1.2rem;
}
.exchange-rate {
font-size: 1.1rem;
font-weight: 600;
color: #388e3c;
margin-bottom: 4px;
}
.currency-name {
color: #5a7c65;
font-size: 0.8rem;
line-height: 1.2;
}
/* 搜索框 */
.search-container {
background: rgba(255, 255, 255, 0.85);
border-radius: 15px;
padding: 20px;
margin-bottom: 20px;
box-shadow: 0 5px 20px rgba(45, 80, 22, 0.08);
}
.search-input {
width: 100%;
padding: 12px 20px;
border: 2px solid #c8e6c9;
border-radius: 25px;
background: white;
color: #2d5016;
font-size: 1rem;
transition: all 0.3s ease;
}
.search-input:focus {
outline: none;
border-color: #81c784;
box-shadow: 0 0 0 3px rgba(129, 199, 132, 0.2);
}
.search-input::placeholder {
color: #81c784;
}
/* 错误提示 */
.error {
background: #fed7d7;
color: #c53030;
padding: 20px;
border-radius: 15px;
text-align: center;
border: 1px solid #feb2b2;
margin: 20px 0;
}
/* 统计信息 */
.stats {
background: rgba(255, 255, 255, 0.85);
border-radius: 15px;
padding: 20px;
margin-bottom: 20px;
box-shadow: 0 5px 20px rgba(45, 80, 22, 0.08);
text-align: center;
}
.stats-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
gap: 20px;
margin-top: 15px;
}
.stat-item {
padding: 15px;
background: rgba(129, 199, 132, 0.1);
border-radius: 10px;
}
.stat-number {
font-size: 1.5rem;
font-weight: 700;
color: #2d5016;
}
.stat-label {
color: #5a7c65;
font-size: 0.9rem;
margin-top: 5px;
}
/* 响应式设计 */
/* 平板端 */
@media (max-width: 768px) and (min-width: 481px) {
.container {
padding: 15px;
}
.header h1 {
font-size: 2rem;
flex-direction: column;
gap: 10px;
}
.header {
padding: 20px;
}
.rates-grid {
grid-template-columns: repeat(6, 1fr);
gap: 8px;
}
.rate-card {
padding: 10px;
}
.currency-selector select {
min-width: 180px;
}
}
/* 手机端 */
@media (max-width: 480px) {
body {
overflow-x: hidden;
}
.container {
padding: 8px;
margin: 8px;
max-width: calc(100vw - 16px);
width: calc(100vw - 16px);
}
.header {
padding: 12px;
margin-bottom: 16px;
}
.header h1 {
font-size: 1.6rem;
flex-direction: column;
gap: 8px;
}
.header p {
font-size: 0.9rem;
}
.rates-grid {
grid-template-columns: repeat(2, 1fr);
gap: 8px;
width: 100%;
overflow: hidden;
}
.rate-card {
padding: 10px 6px;
border-radius: 8px;
min-width: 0;
width: 100%;
}
.currency-code {
font-size: 0.8rem;
margin-bottom: 4px;
gap: 3px;
word-break: break-all;
}
.currency-flag {
font-size: 0.9rem;
}
.exchange-rate {
font-size: 0.85rem;
margin-bottom: 3px;
word-break: break-all;
}
.currency-name {
font-size: 0.65rem;
line-height: 1.1;
word-break: break-all;
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
}
.currency-selector {
padding: 12px;
margin-bottom: 16px;
}
.currency-selector select {
width: 100%;
max-width: 100%;
padding: 10px 15px;
font-size: 0.9rem;
}
.search-container {
padding: 12px;
margin-bottom: 16px;
}
.search-input {
padding: 10px 15px;
font-size: 0.9rem;
width: 100%;
}
.stats {
padding: 15px;
margin-bottom: 16px;
}
.stats-grid {
grid-template-columns: repeat(2, 1fr);
gap: 10px;
}
.stat-item {
padding: 12px;
}
.stat-number {
font-size: 1.3rem;
}
.stat-label {
font-size: 0.8rem;
}
.exchange-info {
padding: 15px;
margin-bottom: 16px;
}
.base-currency h2 {
font-size: 1.5rem;
}
.update-time {
font-size: 0.8rem;
}
}
/* 大屏幕优化 */
@media (min-width: 1200px) {
.container {
padding: 40px;
}
.header {
padding: 40px;
}
}
/* 特殊效果 */
.fade-in {
animation: fadeIn 0.6s ease-in;
}
@keyframes fadeIn {
from {
opacity: 0;
transform: translateY(20px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
/* 滚动条样式 */
::-webkit-scrollbar {
width: 8px;
}
::-webkit-scrollbar-track {
background: rgba(255, 255, 255, 0.1);
}
::-webkit-scrollbar-thumb {
background: rgba(129, 199, 132, 0.5);
border-radius: 4px;
}
::-webkit-scrollbar-thumb:hover {
background: rgba(129, 199, 132, 0.7);
}
/* 隐藏类 */
.hidden {
display: none;
/* 每日国际汇率 - 淡绿色清新风格样式 */
/* 重置样式 */
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
background: linear-gradient(135deg, #a8e6cf 0%, #dcedc1 50%, #ffd3a5 100%);
min-height: 100vh;
color: #2d5016;
line-height: 1.6;
overflow-x: hidden;
}
.container {
max-width: 1200px;
margin: 0 auto;
padding: 20px;
}
/* 头部样式 */
.header {
text-align: center;
margin-bottom: 30px;
background: rgba(255, 255, 255, 0.85);
border-radius: 20px;
padding: 30px;
box-shadow: 0 8px 25px rgba(45, 80, 22, 0.08);
backdrop-filter: blur(10px);
}
.header h1 {
font-size: 2.5rem;
color: #2d5016;
margin-bottom: 10px;
font-weight: 700;
display: flex;
align-items: center;
justify-content: center;
gap: 15px;
}
.header p {
color: #5a7c65;
font-size: 1.1rem;
}
/* 货币选择器 */
.currency-selector {
background: rgba(255, 255, 255, 0.85);
border-radius: 15px;
padding: 20px;
margin-bottom: 20px;
box-shadow: 0 5px 20px rgba(45, 80, 22, 0.08);
text-align: center;
}
.currency-selector label {
display: block;
margin-bottom: 10px;
font-weight: 600;
color: #2d5016;
}
.currency-selector select {
padding: 12px 20px;
border: 2px solid #c8e6c9;
border-radius: 25px;
background: white;
color: #2d5016;
font-size: 1rem;
min-width: 200px;
cursor: pointer;
transition: all 0.3s ease;
}
.currency-selector select:focus {
outline: none;
border-color: #81c784;
box-shadow: 0 0 0 3px rgba(129, 199, 132, 0.2);
}
/* 加载状态 */
.loading {
text-align: center;
padding: 40px;
background: rgba(255, 255, 255, 0.85);
border-radius: 15px;
box-shadow: 0 5px 20px rgba(45, 80, 22, 0.08);
}
.spinner {
width: 40px;
height: 40px;
border: 4px solid #e8f5e8;
border-top: 4px solid #81c784;
border-radius: 50%;
animation: spin 1s linear infinite;
margin: 0 auto 20px;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
/* 汇率信息容器 */
.exchange-info {
background: rgba(255, 255, 255, 0.85);
border-radius: 20px;
padding: 25px;
margin-bottom: 20px;
box-shadow: 0 8px 25px rgba(45, 80, 22, 0.08);
backdrop-filter: blur(10px);
}
.base-currency {
text-align: center;
margin-bottom: 20px;
}
.base-currency h2 {
font-size: 1.8rem;
color: #2d5016;
margin-bottom: 10px;
}
.update-time {
color: #5a7c65;
font-size: 0.9rem;
}
/* 汇率网格 */
.rates-grid {
display: grid;
grid-template-columns: repeat(8, 1fr);
gap: 10px;
margin-top: 20px;
}
.rate-card {
background: rgba(255, 255, 255, 0.9);
border-radius: 10px;
padding: 12px;
box-shadow: 0 3px 10px rgba(45, 80, 22, 0.06);
transition: all 0.3s ease;
border: 1px solid rgba(200, 230, 201, 0.5);
text-align: center;
}
.rate-card:hover {
transform: translateY(-1px);
box-shadow: 0 4px 15px rgba(45, 80, 22, 0.1);
border-color: #81c784;
}
.currency-code {
font-size: 1rem;
font-weight: 700;
color: #2d5016;
margin-bottom: 6px;
display: flex;
align-items: center;
justify-content: center;
gap: 6px;
}
.currency-flag {
font-size: 1.2rem;
}
.exchange-rate {
font-size: 1.1rem;
font-weight: 600;
color: #388e3c;
margin-bottom: 4px;
}
.currency-name {
color: #5a7c65;
font-size: 0.8rem;
line-height: 1.2;
}
/* 搜索框 */
.search-container {
background: rgba(255, 255, 255, 0.85);
border-radius: 15px;
padding: 20px;
margin-bottom: 20px;
box-shadow: 0 5px 20px rgba(45, 80, 22, 0.08);
}
.search-input {
width: 100%;
padding: 12px 20px;
border: 2px solid #c8e6c9;
border-radius: 25px;
background: white;
color: #2d5016;
font-size: 1rem;
transition: all 0.3s ease;
}
.search-input:focus {
outline: none;
border-color: #81c784;
box-shadow: 0 0 0 3px rgba(129, 199, 132, 0.2);
}
.search-input::placeholder {
color: #81c784;
}
/* 错误提示 */
.error {
background: #fed7d7;
color: #c53030;
padding: 20px;
border-radius: 15px;
text-align: center;
border: 1px solid #feb2b2;
margin: 20px 0;
}
/* 统计信息 */
.stats {
background: rgba(255, 255, 255, 0.85);
border-radius: 15px;
padding: 20px;
margin-bottom: 20px;
box-shadow: 0 5px 20px rgba(45, 80, 22, 0.08);
text-align: center;
}
.stats-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
gap: 20px;
margin-top: 15px;
}
.stat-item {
padding: 15px;
background: rgba(129, 199, 132, 0.1);
border-radius: 10px;
}
.stat-number {
font-size: 1.5rem;
font-weight: 700;
color: #2d5016;
}
.stat-label {
color: #5a7c65;
font-size: 0.9rem;
margin-top: 5px;
}
/* 响应式设计 */
/* 平板端 */
@media (max-width: 768px) and (min-width: 481px) {
.container {
padding: 15px;
}
.header h1 {
font-size: 2rem;
flex-direction: column;
gap: 10px;
}
.header {
padding: 20px;
}
.rates-grid {
grid-template-columns: repeat(6, 1fr);
gap: 8px;
}
.rate-card {
padding: 10px;
}
.currency-selector select {
min-width: 180px;
}
}
/* 手机端 */
@media (max-width: 480px) {
body {
overflow-x: hidden;
}
.container {
padding: 8px;
margin: 8px;
max-width: calc(100vw - 16px);
width: calc(100vw - 16px);
}
.header {
padding: 12px;
margin-bottom: 16px;
}
.header h1 {
font-size: 1.6rem;
flex-direction: column;
gap: 8px;
}
.header p {
font-size: 0.9rem;
}
.rates-grid {
grid-template-columns: repeat(2, 1fr);
gap: 8px;
width: 100%;
overflow: hidden;
}
.rate-card {
padding: 10px 6px;
border-radius: 8px;
min-width: 0;
width: 100%;
}
.currency-code {
font-size: 0.8rem;
margin-bottom: 4px;
gap: 3px;
word-break: break-all;
}
.currency-flag {
font-size: 0.9rem;
}
.exchange-rate {
font-size: 0.85rem;
margin-bottom: 3px;
word-break: break-all;
}
.currency-name {
font-size: 0.65rem;
line-height: 1.1;
word-break: break-all;
overflow: hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
}
.currency-selector {
padding: 12px;
margin-bottom: 16px;
}
.currency-selector select {
width: 100%;
max-width: 100%;
padding: 10px 15px;
font-size: 0.9rem;
}
.search-container {
padding: 12px;
margin-bottom: 16px;
}
.search-input {
padding: 10px 15px;
font-size: 0.9rem;
width: 100%;
}
.stats {
padding: 15px;
margin-bottom: 16px;
}
.stats-grid {
grid-template-columns: repeat(2, 1fr);
gap: 10px;
}
.stat-item {
padding: 12px;
}
.stat-number {
font-size: 1.3rem;
}
.stat-label {
font-size: 0.8rem;
}
.exchange-info {
padding: 15px;
margin-bottom: 16px;
}
.base-currency h2 {
font-size: 1.5rem;
}
.update-time {
font-size: 0.8rem;
}
}
/* 大屏幕优化 */
@media (min-width: 1200px) {
.container {
padding: 40px;
}
.header {
padding: 40px;
}
}
/* 特殊效果 */
.fade-in {
animation: fadeIn 0.6s ease-in;
}
@keyframes fadeIn {
from {
opacity: 0;
transform: translateY(20px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
/* 滚动条样式 */
::-webkit-scrollbar {
width: 8px;
}
::-webkit-scrollbar-track {
background: rgba(255, 255, 255, 0.1);
}
::-webkit-scrollbar-thumb {
background: rgba(129, 199, 132, 0.5);
border-radius: 4px;
}
::-webkit-scrollbar-thumb:hover {
background: rgba(129, 199, 132, 0.7);
}
/* 隐藏类 */
.hidden {
display: none;
}

View File

@@ -1,86 +1,86 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="每日国际汇率 - 实时获取全球货币汇率信息">
<meta name="keywords" content="汇率,外汇,货币,汇率查询,实时汇率">
<title>每日国际汇率</title>
<!-- 引入样式文件 -->
<link rel="stylesheet" href="css/style.css">
<!-- 网站图标 -->
<link rel="icon" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'><text y='.9em' font-size='90'>💱</text></svg>">
</head>
<body>
<div class="container">
<!-- 页面头部 -->
<header class="header">
<h1>
<span>💱</span>
每日国际汇率
</h1>
<p>实时获取全球货币汇率信息,助您掌握汇率动态</p>
</header>
<!-- 货币选择器 -->
<div class="currency-selector">
<label for="currency-select">选择基础货币:</label>
<select id="currency-select">
<!-- 货币选项将通过JavaScript动态生成 -->
</select>
</div>
<!-- 搜索框 -->
<div class="search-container">
<input
type="text"
id="search-input"
class="search-input"
placeholder="🔍 搜索货币代码或名称..."
>
</div>
<!-- 加载状态 -->
<div id="loading" class="loading">
<div class="spinner"></div>
<p>正在加载汇率数据...</p>
</div>
<!-- 汇率内容区域 -->
<main id="exchange-content" class="content" style="display: none;">
<!-- 汇率信息 -->
<div class="exchange-info">
<div class="base-currency">
<h2 id="base-currency">基础货币</h2>
<div id="update-time" class="update-time">更新时间: --</div>
</div>
<!-- 统计信息 -->
<div class="stats">
<h3>汇率统计</h3>
<div class="stats-grid">
<div class="stat-item">
<div id="total-currencies" class="stat-number">--</div>
<div class="stat-label">货币总数</div>
</div>
<div class="stat-item">
<div id="last-update" class="stat-number">--</div>
<div class="stat-label">最后更新</div>
</div>
</div>
</div>
<!-- 汇率网格 -->
<div id="rates-grid" class="rates-grid">
<!-- 汇率卡片将通过JavaScript动态生成 -->
</div>
</div>
</main>
</div>
<!-- 引入脚本文件 -->
<script src="js/script.js"></script>
</body>
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="每日国际汇率 - 实时获取全球货币汇率信息">
<meta name="keywords" content="汇率,外汇,货币,汇率查询,实时汇率">
<title>每日国际汇率</title>
<!-- 引入样式文件 -->
<link rel="stylesheet" href="css/style.css">
<!-- 网站图标 -->
<link rel="icon" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'><text y='.9em' font-size='90'>💱</text></svg>">
</head>
<body>
<div class="container">
<!-- 页面头部 -->
<header class="header">
<h1>
<span>💱</span>
每日国际汇率
</h1>
<p>实时获取全球货币汇率信息,助您掌握汇率动态</p>
</header>
<!-- 货币选择器 -->
<div class="currency-selector">
<label for="currency-select">选择基础货币:</label>
<select id="currency-select">
<!-- 货币选项将通过JavaScript动态生成 -->
</select>
</div>
<!-- 搜索框 -->
<div class="search-container">
<input
type="text"
id="search-input"
class="search-input"
placeholder="🔍 搜索货币代码或名称..."
>
</div>
<!-- 加载状态 -->
<div id="loading" class="loading">
<div class="spinner"></div>
<p>正在加载汇率数据...</p>
</div>
<!-- 汇率内容区域 -->
<main id="exchange-content" class="content" style="display: none;">
<!-- 汇率信息 -->
<div class="exchange-info">
<div class="base-currency">
<h2 id="base-currency">基础货币</h2>
<div id="update-time" class="update-time">更新时间: --</div>
</div>
<!-- 统计信息 -->
<div class="stats">
<h3>汇率统计</h3>
<div class="stats-grid">
<div class="stat-item">
<div id="total-currencies" class="stat-number">--</div>
<div class="stat-label">货币总数</div>
</div>
<div class="stat-item">
<div id="last-update" class="stat-number">--</div>
<div class="stat-label">最后更新</div>
</div>
</div>
</div>
<!-- 汇率网格 -->
<div id="rates-grid" class="rates-grid">
<!-- 汇率卡片将通过JavaScript动态生成 -->
</div>
</div>
</main>
</div>
<!-- 引入脚本文件 -->
<script src="js/script.js"></script>
</body>
</html>

View File

@@ -1,3 +1,3 @@
[
"https://60s.api.shumengya.top"
]
[
"https://60s.api.shumengya.top"
]