Files
InfoGenie/InfoGenie-frontend/public/60sapi/热搜榜单/懂车帝热搜/app.js
2025-09-16 09:14:04 +08:00

313 lines
9.0 KiB
JavaScript
Executable File
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.
/**
* 懂车帝热搜应用主程序
* 整合API和UI模块管理应用生命周期
*/
class CarHotTopicsApp {
constructor() {
this.api = null;
this.ui = null;
this.autoRefreshInterval = null;
this.autoRefreshDelay = 5 * 60 * 1000; // 5分钟自动刷新
this.isInitialized = false;
this.init();
}
/**
* 初始化应用
*/
async init() {
try {
console.log('[App] 开始初始化懂车帝热搜应用...');
// 等待DOM加载完成
if (document.readyState === 'loading') {
await new Promise(resolve => {
document.addEventListener('DOMContentLoaded', resolve);
});
}
// 检查必需的类是否存在
if (!window.CarHotTopicsAPI || !window.UIManager) {
throw new Error('缺少必需的模块CarHotTopicsAPI 或 UIManager');
}
// 初始化模块
this.api = new window.CarHotTopicsAPI();
this.ui = new window.UIManager();
// 检查必需的DOM元素
this.checkRequiredElements();
// 绑定事件
this.bindEvents();
// 首次加载数据
await this.loadData();
// 设置自动刷新
this.setupAutoRefresh();
// 设置页面可见性监听
this.setupVisibilityListener();
this.isInitialized = true;
console.log('[App] 应用初始化完成');
} catch (error) {
console.error('[App] 初始化失败:', error);
this.handleInitError(error);
}
}
/**
* 检查必需的DOM元素
*/
checkRequiredElements() {
const requiredIds = ['loading', 'error', 'hotList', 'topicsContainer', 'refreshBtn'];
const missingElements = requiredIds.filter(id => !document.getElementById(id));
if (missingElements.length > 0) {
throw new Error(`缺少必需的DOM元素: ${missingElements.join(', ')}`);
}
}
/**
* 绑定事件监听器
*/
bindEvents() {
// 监听UI触发的刷新事件
document.addEventListener('refreshData', () => {
this.handleManualRefresh();
});
// 监听网络状态变化
window.addEventListener('online', () => {
console.log('[App] 网络已连接,尝试刷新数据');
this.ui.showToast('网络已连接');
this.loadData();
});
window.addEventListener('offline', () => {
console.log('[App] 网络已断开');
this.ui.showToast('网络连接已断开');
});
// 监听页面错误
window.addEventListener('error', (event) => {
console.error('[App] 页面错误:', event.error);
});
// 监听未处理的Promise拒绝
window.addEventListener('unhandledrejection', (event) => {
console.error('[App] 未处理的Promise拒绝:', event.reason);
event.preventDefault();
});
}
/**
* 加载热搜数据
* @param {boolean} showLoading - 是否显示加载状态
*/
async loadData(showLoading = true) {
try {
if (showLoading) {
this.ui.showLoading();
}
console.log('[App] 开始加载热搜数据...');
const data = await this.api.fetchHotTopics();
console.log('[App] 数据加载成功:', data);
this.ui.showHotList(data);
// 重置自动刷新计时器
this.resetAutoRefresh();
} catch (error) {
console.error('[App] 数据加载失败:', error);
this.ui.showError(error.message);
// 如果是网络错误,延迟重试
if (this.isNetworkError(error)) {
setTimeout(() => {
if (navigator.onLine) {
this.loadData(false);
}
}, 30000); // 30秒后重试
}
}
}
/**
* 处理手动刷新
*/
async handleManualRefresh() {
console.log('[App] 手动刷新数据');
await this.loadData();
}
/**
* 设置自动刷新
*/
setupAutoRefresh() {
if (this.autoRefreshInterval) {
clearInterval(this.autoRefreshInterval);
}
this.autoRefreshInterval = setInterval(() => {
if (document.visibilityState === 'visible' && navigator.onLine) {
console.log('[App] 自动刷新数据');
this.loadData(false);
}
}, this.autoRefreshDelay);
console.log(`[App] 自动刷新已设置,间隔: ${this.autoRefreshDelay / 1000}`);
}
/**
* 重置自动刷新计时器
*/
resetAutoRefresh() {
this.setupAutoRefresh();
}
/**
* 设置页面可见性监听
*/
setupVisibilityListener() {
document.addEventListener('visibilitychange', () => {
if (document.visibilityState === 'visible') {
console.log('[App] 页面变为可见');
// 检查数据是否需要更新
const currentData = this.ui.getCurrentData();
if (currentData) {
const lastUpdate = new Date(currentData.updateTime);
const now = new Date();
const timeDiff = now - lastUpdate;
// 如果数据超过3分钟自动刷新
if (timeDiff > 3 * 60 * 1000) {
console.log('[App] 数据已过期,自动刷新');
this.loadData(false);
}
}
} else {
console.log('[App] 页面变为隐藏');
}
});
}
/**
* 判断是否为网络错误
* @param {Error} error - 错误对象
* @returns {boolean} 是否为网络错误
*/
isNetworkError(error) {
const networkErrorMessages = [
'fetch',
'network',
'timeout',
'connection',
'offline'
];
return networkErrorMessages.some(msg =>
error.message.toLowerCase().includes(msg)
);
}
/**
* 处理初始化错误
* @param {Error} error - 错误对象
*/
handleInitError(error) {
// 显示基本错误信息
const errorContainer = document.getElementById('error');
if (errorContainer) {
errorContainer.style.display = 'flex';
const errorMessage = errorContainer.querySelector('.error-message');
if (errorMessage) {
errorMessage.textContent = `初始化失败: ${error.message}`;
}
}
// 隐藏加载状态
const loadingContainer = document.getElementById('loading');
if (loadingContainer) {
loadingContainer.style.display = 'none';
}
}
/**
* 获取应用状态
* @returns {Object} 应用状态信息
*/
getStatus() {
return {
isInitialized: this.isInitialized,
hasData: !!this.ui?.getCurrentData(),
autoRefreshEnabled: !!this.autoRefreshInterval,
isOnline: navigator.onLine,
isVisible: document.visibilityState === 'visible'
};
}
/**
* 销毁应用
*/
destroy() {
console.log('[App] 销毁应用');
if (this.autoRefreshInterval) {
clearInterval(this.autoRefreshInterval);
this.autoRefreshInterval = null;
}
if (this.ui) {
this.ui.clearData();
}
this.isInitialized = false;
}
}
// 全局错误处理
window.addEventListener('error', (event) => {
console.error('[Global] JavaScript错误:', {
message: event.message,
filename: event.filename,
lineno: event.lineno,
colno: event.colno,
error: event.error
});
});
window.addEventListener('unhandledrejection', (event) => {
console.error('[Global] 未处理的Promise拒绝:', event.reason);
});
// 应用启动
let app;
// 确保在DOM加载完成后启动应用
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', () => {
app = new CarHotTopicsApp();
});
} else {
app = new CarHotTopicsApp();
}
// 导出应用实例(用于调试)
window.CarHotTopicsApp = CarHotTopicsApp;
window.app = app;
// 调试信息
console.log('[App] 懂车帝热搜应用脚本已加载');
console.log('[Debug] 可用的全局对象:', {
CarHotTopicsAPI: !!window.CarHotTopicsAPI,
UIManager: !!window.UIManager,
CarHotTopicsApp: !!window.CarHotTopicsApp
});