-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathapp.js
More file actions
408 lines (360 loc) · 15 KB
/
app.js
File metadata and controls
408 lines (360 loc) · 15 KB
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
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
// UAPI热榜查询工具 - 前端JavaScript
class HotboardApp {
constructor() {
this.platforms = {
// 视频/社区
'bilibili': '哔哩哔哩弹幕网',
'acfun': 'A站弹幕视频网站',
'weibo': '新浪微博热搜',
'zhihu': '知乎热榜',
'zhihu-daily': '知乎日报热榜',
'douyin': '抖音热榜',
'kuaishou': '快手热榜',
'douban-movie': '豆瓣电影榜单',
'douban-group': '豆瓣小组话题',
'tieba': '百度贴吧热帖',
'hupu': '虎扑热帖',
'miyoushe': '米游社话题榜',
'ngabbs': 'NGA游戏论坛热帖',
'v2ex': 'V2EX技术社区热帖',
'52pojie': '吾爱破解热帖',
'hostloc': '全球主机交流论坛',
'coolapk': '酷安热榜',
// 新闻/资讯
'baidu': '百度热搜',
'thepaper': '澎湃新闻热榜',
'toutiao': '今日头条热榜',
'qq-news': '腾讯新闻热榜',
'sina': '新浪热搜',
'sina-news': '新浪新闻热榜',
'netease-news': '网易新闻热榜',
'huxiu': '虎嗅网热榜',
'ifanr': '爱范儿热榜',
// 技术/IT
'sspai': '少数派热榜',
'ithome': 'IT之家热榜',
'ithome-xijiayi': 'IT之家·喜加一栏目',
'juejin': '掘金社区热榜',
'jianshu': '简书热榜',
'guokr': '果壳热榜',
'36kr': '36氪热榜',
'51cto': '51CTO热榜',
'csdn': 'CSDN博客热榜',
'nodeseek': 'NodeSeek 技术社区',
'hellogithub': 'HelloGitHub 项目推荐',
// 游戏
'lol': '英雄联盟热帖',
'genshin': '原神热榜',
'honkai': '崩坏3热榜',
'starrail': '星穹铁道热榜',
// 其他
'weread': '微信读书热门书籍',
'weatheralarm': '天气预警信息',
'earthquake': '地震速报',
'history': '历史上的今天'
};
this.baseUrl = 'https://uapis.cn/api/v1/misc/hotboard';
this.corsProxy = 'https://cors-anywhere.herokuapp.com/'; // 免费CORS代理
this.init();
}
init() {
this.setupEventListeners();
this.populatePlatformSelect();
this.showDefaultContent();
}
setupEventListeners() {
document.getElementById('queryBtn').addEventListener('click', () => this.queryHotboard());
document.getElementById('platform').addEventListener('change', (e) => this.onPlatformChange(e));
document.getElementById('limit').addEventListener('keypress', (e) => {
if (e.key === 'Enter') this.queryHotboard();
});
// 快速查询按钮
document.querySelectorAll('.platform-tab').forEach(tab => {
tab.addEventListener('click', (e) => {
const platform = e.target.dataset.platform;
this.quickQuery(platform);
});
});
// 刷新按钮
document.getElementById('refreshBtn').addEventListener('click', () => {
const platform = document.getElementById('platform').value;
if (platform) this.queryHotboard();
});
}
populatePlatformSelect() {
const select = document.getElementById('platform');
const categories = {
'🎬 视频/社区': ['bilibili', 'acfun', 'weibo', 'zhihu', 'zhihu-daily', 'douyin', 'kuaishou', 'douban-movie', 'douban-group', 'tieba', 'hupu', 'miyoushe', 'ngabbs', 'v2ex', '52pojie', 'hostloc', 'coolapk'],
'📰 新闻/资讯': ['baidu', 'thepaper', 'toutiao', 'qq-news', 'sina', 'sina-news', 'netease-news', 'huxiu', 'ifanr'],
'💻 技术/IT': ['sspai', 'ithome', 'ithome-xijiayi', 'juejin', 'jianshu', 'guokr', '36kr', '51cto', 'csdn', 'nodeseek', 'hellogithub'],
'🎮 游戏': ['lol', 'genshin', 'honkai', 'starrail'],
'📚 其他': ['weread', 'weatheralarm', 'earthquake', 'history']
};
for (const [category, platforms] of Object.entries(categories)) {
const optgroup = document.createElement('optgroup');
optgroup.label = category;
platforms.forEach(platform => {
if (this.platforms[platform]) {
const option = document.createElement('option');
option.value = platform;
option.textContent = `${platform} - ${this.platforms[platform]}`;
optgroup.appendChild(option);
}
});
select.appendChild(optgroup);
}
}
showDefaultContent() {
this.quickQuery('weibo');
}
onPlatformChange(e) {
const platform = e.target.value;
if (platform) {
// 更新快速查询标签状态
document.querySelectorAll('.platform-tab').forEach(tab => {
tab.classList.remove('active');
if (tab.dataset.platform === platform) {
tab.classList.add('active');
}
});
}
}
quickQuery(platform) {
document.getElementById('platform').value = platform;
this.queryHotboard();
// 更新标签状态
document.querySelectorAll('.platform-tab').forEach(tab => {
tab.classList.toggle('active', tab.dataset.platform === platform);
});
}
showLoading() {
document.getElementById('loading').style.display = 'block';
document.getElementById('results').innerHTML = '';
document.getElementById('queryBtn').disabled = true;
document.getElementById('refreshBtn').disabled = true;
}
hideLoading() {
document.getElementById('loading').style.display = 'none';
document.getElementById('queryBtn').disabled = false;
document.getElementById('refreshBtn').disabled = false;
}
formatNumber(num) {
if (typeof num === 'number') {
if (num >= 100000000) {
return (num / 100000000).toFixed(1) + '亿';
} else if (num >= 10000) {
return (num / 10000).toFixed(1) + '万';
}
return num.toString();
}
return num || '0';
}
async queryHotboard() {
const platform = document.getElementById('platform').value;
const limit = parseInt(document.getElementById('limit').value) || 20;
if (!platform) {
this.showError('请选择平台!');
return;
}
this.showLoading();
try {
// 首先尝试直接调用API
let data = await this.fetchFromAPI(platform, limit);
// 如果直接调用失败,尝试使用代理
if (!data) {
data = await this.fetchWithProxy(platform, limit);
}
// 如果仍然失败,显示示例数据
if (!data) {
data = this.getFallbackData(platform, limit);
}
this.displayResults(data, platform, limit);
} catch (error) {
console.error('查询失败:', error);
this.showError('获取数据失败,请稍后重试或检查网络连接');
} finally {
this.hideLoading();
}
}
async fetchFromAPI(platform, limit) {
try {
const url = `${this.baseUrl}/${platform}?type=${platform}`;
const response = await fetch(url, {
method: 'GET',
headers: {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
}
});
if (response.ok) {
const result = await response.json();
if (result.code === 200) {
return result.data;
}
}
} catch (error) {
console.log('直接API调用失败:', error.message);
}
return null;
}
async fetchWithProxy(platform, limit) {
try {
const url = `${this.corsProxy}${this.baseUrl}/${platform}?type=${platform}`;
const response = await fetch(url, {
method: 'GET',
headers: {
'X-Requested-With': 'XMLHttpRequest',
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
}
});
if (response.ok) {
const result = await response.json();
if (result.code === 200) {
return result.data;
}
}
} catch (error) {
console.log('代理API调用失败:', error.message);
}
return null;
}
getFallbackData(platform, limit) {
// 生成示例数据
const mockTopics = {
'weibo': [
'新年新气象,大家有什么新的计划吗?',
'今天天气真不错,适合出门走走',
'分享一下最近看过的好电影',
'推荐一本值得一读的好书',
'聊聊大家的工作心得',
'周末去哪里玩比较好?',
'分享一下可爱的宠物照片',
'讨论一下最近的热播剧',
'聊聊美食,推荐一些好吃的',
'分享一些生活小窍门'
],
'baidu': [
'人工智能最新发展动态',
'2024年科技趋势预测',
'新能源汽车市场分析',
'区块链技术应用前景',
'5G网络建设进展',
'量子计算技术突破',
'元宇宙产业发展现状',
'云计算技术演进',
'物联网安全挑战',
'自动驾驶技术进展'
],
'zhihu': [
'如何提高工作效率?',
'职场新人应该注意什么?',
'有哪些值得学习的新技能?',
'如何平衡工作和生活?',
'推荐一些优质的学习资源',
'聊聊时间管理的经验',
'如何建立良好的人际关系?',
'有什么好的理财建议?',
'如何保持持续学习?',
'分享一些实用的工具'
],
'ithome': [
'iPhone 15系列全面评测',
'Windows 11最新功能介绍',
'最佳编程工具推荐',
'云服务选择指南',
'网络安全防护技巧',
'数据备份最佳实践',
'开发环境配置优化',
'新软件版本更新内容',
'硬件升级建议',
'技术趋势分析'
]
};
const topics = mockTopics[platform] || [
'热门话题讨论',
'行业最新动态',
'技术发展趋势',
'市场分析报告',
'产品评测对比',
'使用经验分享',
'问题解决方案',
'资源推荐分享',
'学习心得总结',
'行业见解分析'
];
const data = [];
const count = Math.min(limit, topics.length);
for (let i = 0; i < count; i++) {
data.push({
title: topics[i],
hot: Math.floor(Math.random() * 1000000) + 10000,
url: `https://example.com/article/${platform}/${i + 1}`,
time: new Date().toLocaleString('zh-CN')
});
}
return { list: data };
}
displayResults(data, platform, limit) {
const platformName = this.platforms[platform] || platform;
if (!data || !data.list || data.list.length === 0) {
this.showError(`${platformName} 暂无热榜数据`);
return;
}
const items = data.list.slice(0, limit);
let html = `
<div class="platform-header">
🔥 ${platformName} 热榜
<small style="opacity: 0.8; font-weight: normal;">数据来源: UAPI | ${new Date().toLocaleString('zh-CN')}</small>
</div>
<div class="hotboard-list">
`;
items.forEach((item, index) => {
const hot = this.formatNumber(item.hot || item.heat || 0);
const title = this.escapeHtml(item.title || '无标题');
const url = item.url || '#';
html += `
<div class="hotboard-item">
<div class="item-rank">${index + 1}</div>
<div class="item-content">
<div class="item-title">${title}</div>
<div class="item-meta">
<span class="item-hot">🔥 ${hot}</span>
${url !== '#' ? `<a href="${url}" class="item-link" target="_blank" rel="noopener">查看详情</a>` : ''}
<span class="item-time">${this.getTimeString()}</span>
</div>
</div>
</div>
`;
});
html += `
</div>
<div style="text-align: center; padding: 20px; color: #666; font-size: 14px;">
💡 数据仅供参考,实时数据请访问各平台官网
</div>
`;
document.getElementById('results').innerHTML = html;
}
showError(message) {
const html = `
<div class="error">
<strong>⚠️ 查询失败</strong><br>
${message}
</div>
`;
document.getElementById('results').innerHTML = html;
}
escapeHtml(text) {
const div = document.createElement('div');
div.textContent = text;
return div.innerHTML;
}
getTimeString() {
const now = new Date();
const hours = now.getHours().toString().padStart(2, '0');
const minutes = now.getMinutes().toString().padStart(2, '0');
return `${hours}:${minutes}`;
}
}
// 页面加载完成后初始化应用
document.addEventListener('DOMContentLoaded', () => {
new HotboardApp();
});