创建Hexo博客7×24小时新闻页面

第一步:在 Hexo 中新建一个独立页面

1
hexo new page live

第二步:编辑 index.md 写入前端代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
<!-- 顶部状态栏:显示倒计时 -->
<div style="margin-bottom: 0px; padding: 10px 15px; border-radius: 4px 4px 0 0; font-size: 0.9em; color: #666; border-bottom: 1px solid #eee;">
📊 新浪财经 | <span id="refresh-timer" style="color: #222; font-weight: bold;">正在初始化...</span>
</div>

<!-- 新闻流总包裹容器 -->
<div id="news-stream-wrap" style="position: relative; padding: 20px 5px 20px 20px;">
<!-- 贯穿整条时间轴的独立纵线 -->
<div style="position: absolute; left: 24px; top: 0; bottom: 0; width: 2px; background: #eaeaea; z-index: 1;"></div>

<!-- 新闻列表实际放置容器 -->
<div id="news-stream-container" style="position: relative; z-index: 2;">
<p id="stream-loading" style="color: #999; text-align: center; padding: 20px;">正在直连新浪官方快讯流...</p>
</div>
</div>

<!-- 底部加载更多状态提示 -->
<div id="load-more-status" style="text-align: center; color: #999; font-size: 0.9em; padding: 15px 0;">
滚动到轴底自动加载历史消息...
</div>

<script>
const REFRESH_INTERVAL = 60;
let countdown = REFRESH_INTERVAL;
let timerInterval = null;
let currentPage = 1;
let isLoadingMore = false;
let hasMoreData = true;

// 通过动态创建 script 标签完美解决跨域
function fetchNewsData(page = 1, isAppend = false) {
if (page > 1) {
document.getElementById('load-more-status').innerText = '正在调取历史快讯...';
}

const oldScript = document.getElementById('sina-jsonp-script');
if (oldScript) oldScript.remove();

// 挂载全局全局回调,进行极强的防御性安全解析
window.sinaCallback = function(res) {
const container = document.getElementById('news-stream-container');
const loadingText = document.getElementById('stream-loading');

// 安全地层层向下寻找新闻列表数组
let list = [];
if (res && res.result && res.result.data) {
const data = res.result.data;
if (Array.isArray(data)) {
list = data;
} else if (data.feed && Array.isArray(data.feed.list)) {
list = data.feed.list;
}
}

if (list.length > 0) {
if (!isAppend) {
container.innerHTML = ''; // 顶层刷新,清空旧数据
currentPage = 1;
hasMoreData = true;
} else if (loadingText) {
loadingText.remove();
}

list.forEach(item => {
const rawTime = item.create_time || '';
const displayTime = rawTime.includes(' ') ? rawTime.split(' ')[1] : rawTime;
const content = item.rich_text || item.title || item.content || '无内容';

const newsItemDiv = document.createElement('div');
newsItemDiv.className = 'live-news-item';
newsItemDiv.style.cssText = 'position: relative; padding-left: 20px; margin-bottom: 30px;';

newsItemDiv.innerHTML = `
<div style="position: absolute; left: -2px; top: 5px; width: 8px; height: 8px; background: #222; border: 2px solid #fff; border-radius: 50%; box-shadow: 0 0 0 2px #222;"></div>
<span style="color: #666; font-weight: bold; font-size: 0.88em; font-family: monospace; display: block; margin-bottom: 4px;">${displayTime}</span>
<div style="color: #333; line-height: 1.6; font-size: 0.95em;">${content}</div>
`;

container.appendChild(newsItemDiv);
});

if (!isAppend) {
countdown = REFRESH_INTERVAL;
} else {
document.getElementById('load-more-status').innerText = '滚动到轴底自动加载历史消息...';
}
} else {
if (isAppend) {
hasMoreData = false;
document.getElementById('load-more-status').innerText = '已经到底啦,没有更早的新闻了。';
} else {
container.innerHTML = '<p style="text-align:center;color:#999;">暂无最新消息</p>';
}
}
isLoadingMore = false;
};

// 生成直连脚本
const script = document.createElement('script');
script.id = 'sina-jsonp-script';
// 直接请求你当前在浏览器打开的这个规范接口
script.src = `https://zhibo.sina.com.cn/api/zhibo/feed?page=${page}&page_size=30&zhibo_id=152&callback=sinaCallback&_=${new Date().getTime()}`;

script.onerror = function() {
isLoadingMore = false;
document.getElementById('load-more-status').innerText = '连接超时,正在自动重试...';
};

document.body.appendChild(script);
}

// 倒计时管理器
function startTimer() {
if (timerInterval) clearInterval(timerInterval);
timerInterval = setInterval(() => {
const timerSpan = document.getElementById('refresh-timer');
if (!timerSpan) return;

if (countdown <= 0) {
fetchNewsData(1, false);
} else {
timerSpan.innerText = `${countdown} 秒后刷新`;
countdown--;
}
}, 1000);
}

// 自动触底加载更多
window.addEventListener('scroll', () => {
if (isLoadingMore || !hasMoreData) return;
if ((window.innerHeight + window.scrollY) >= document.documentElement.scrollHeight - 180) {
isLoadingMore = true;
currentPage++;
fetchNewsData(currentPage, true);
}
});

// 初始化启动
fetchNewsData(1, false);
startTimer();
</script>