Files
YMhut-box-C-/box-old/src/js/tools/baiduHotTool.js
T
QWQLwToo 46a3674381
build-winui / winui (push) Has been cancelled
Add legacy Electron app
2026-06-26 13:29:02 +08:00

155 lines
6.6 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// src/js/tools/baiduHotTool.js
import BaseTool from '../baseTool.js';
class BaiduHotTool extends BaseTool {
constructor() {
super('baidu-hot', '百度热搜');
this.abortController = null;
// 定义分榜信息
this.boards = [
{ id: 'hot-search', name: '热搜榜' },
{ id: 'hot-meme', name: '热梗榜' },
{ id: 'finance', name: '财经榜' },
{ id: 'livelihood', name: '民生榜' },
];
}
render() {
return `
<div class="page-container" style="display: flex; flex-direction: column; height: 100%;">
<div class="section-header">
<button id="back-to-toolbox-btn" class="back-btn ripple"><i class="fas fa-arrow-left"></i> 返回工具箱</button>
<h1 style="flex-grow: 1; text-align: center;">${this.name}</h1>
</div>
<div class="sys-info-tabs baidu-hot-tabs" id="baidu-hot-tabs">
${this.boards.map(board => `
<button class="sys-info-tab" data-board-name="${board.name}">${board.name}</button>
`).join('')}
</div>
<div id="baidu-hot-results-container" class="content-area" style="padding: 0 20px 10px 10px; flex-grow: 1; overflow-y: auto;">
<div class="loading-container">
<img src="./assets/loading.gif" alt="加载中..." class="loading-gif">
<p class="loading-text">正在加载热搜...</p>
</div>
</div>
</div>`;
}
init() {
this._log('工具已初始化');
document.getElementById('back-to-toolbox-btn')?.addEventListener('click', () => {
window.mainPage.navigateTo('toolbox');
window.mainPage.updateActiveNavButton(document.getElementById('toolbox-btn'));
});
const tabs = document.querySelectorAll('#baidu-hot-tabs .sys-info-tab');
tabs.forEach(tab => {
tab.addEventListener('click', (e) => {
tabs.forEach(t => t.classList.remove('active'));
e.currentTarget.classList.add('active');
const boardName = e.currentTarget.dataset.boardName;
this._fetchAndRenderData(boardName);
});
});
// 默认加载第一个榜单
if (tabs.length > 0) {
tabs[0].click();
}
}
async _fetchAndRenderData(boardName) {
if (this.abortController) this.abortController.abort();
this.abortController = new AbortController();
const resultsContainer = document.getElementById('baidu-hot-results-container');
if (!resultsContainer) return;
resultsContainer.innerHTML = `
<div class="loading-container">
<img src="./assets/loading.gif" alt="加载中..." class="loading-gif">
<p class="loading-text">正在加载 ${boardName}...</p>
</div>`;
try {
const apiUrl = `https://api.suyanw.cn/api/bdrs.php?msg=${encodeURIComponent(boardName)}`;
const response = await fetch(apiUrl, { signal: this.abortController.signal });
if (!response.ok) throw new Error(`网络请求失败: ${response.status}`);
const blob = await response.blob();
await window.electronAPI.addTraffic(blob.size);
const textData = await blob.text();
this._log(`成功获取 ${boardName} 数据`);
this._renderList(textData);
} catch (error) {
if (error.name === 'AbortError') return;
const errorMessage = error.message.includes('API') ? error.message : `解析数据失败或网络异常`;
this._log(`获取 ${boardName} 失败: ${errorMessage}`);
resultsContainer.innerHTML = `<div class="loading-container"><p class="error-message"><i class="fas fa-exclamation-triangle"></i> 获取失败: ${errorMessage}</p></div>`;
}
}
_renderList(textData) {
const resultsContainer = document.getElementById('baidu-hot-results-container');
const lines = textData.split('\n').filter(line => line.trim() !== '' && !line.startsWith('----'));
if (lines.length === 0) {
throw new Error('API返回数据为空或格式无法解析');
}
// [修复] 改为使用 Flex 布局的 div 结构 (灵动岛风格),而非之前的 table
const itemsHtml = lines.map((line, index) => {
const match = line.match(/^(\d+)(.*)/);
if (!match) return '';
const rank = match[1];
const title = match[2].trim();
const searchUrl = `https://www.baidu.com/s?wd=${encodeURIComponent(title)}`;
let rankClass = '';
let iconClass = 'fa-fire';
let iconColor = 'var(--text-secondary)';
if (rank <= 3) {
rankClass = `rank-top-3 rank-${rank}`; // 复用 hotboardTool 的样式
iconClass = 'fa-fire-alt';
iconColor = 'var(--error-color)';
}
// 使用 island-card 样式 (在 style.css 中已定义)
return `
<div class="island-card ripple" style="height: auto; min-height: 60px; margin-bottom: 10px; padding: 15px;" data-link="${searchUrl}">
<div class="island-icon-box" style="width: 40px; height: 40px; border-radius: 10px; background: rgba(var(--bg-color-rgb), 0.5);">
<span class="hotboard-rank ${rankClass}" style="margin: 0; font-size: 16px;">${rank}</span>
</div>
<div class="island-content" style="flex-grow: 1; padding-left: 15px;">
<h3 class="island-title" style="margin: 0; white-space: normal;">${title}</h3>
</div>
<div class="island-action">
<i class="fas fa-chevron-right arrow-icon"></i>
</div>
</div>
`;
}).join('');
resultsContainer.innerHTML = `<div style="animation: contentFadeIn 0.5s;">${itemsHtml}</div>`;
resultsContainer.querySelectorAll('.island-card[data-link]').forEach(card => {
card.addEventListener('click', (e) => {
e.preventDefault();
window.electronAPI.openExternalLink(e.currentTarget.dataset.link);
});
});
}
destroy() {
if (this.abortController) this.abortController.abort();
this._log('工具已销毁');
super.destroy();
}
}
export default BaiduHotTool;