feat: add global error indicator

This commit is contained in:
shinya
2025-08-04 23:19:33 +08:00
parent 0bbf2b0a5b
commit c0bba763d1
7 changed files with 193 additions and 2 deletions

View File

@@ -17,6 +17,17 @@
import { getAuthInfoFromBrowserCookie } from './auth';
import { SkipConfig } from './types';
// 全局错误触发函数
function triggerGlobalError(message: string) {
if (typeof window !== 'undefined') {
window.dispatchEvent(
new CustomEvent('globalError', {
detail: { message },
})
);
}
}
// ---- 类型 ----
export interface PlayRecord {
title: string;
@@ -346,6 +357,7 @@ async function handleDatabaseOperationFailure(
error: any
): Promise<void> {
console.error(`数据库操作失败 (${dataType}):`, error);
triggerGlobalError(`数据库操作失败`);
try {
let freshData: any;
@@ -381,6 +393,7 @@ async function handleDatabaseOperationFailure(
);
} catch (refreshErr) {
console.error(`刷新${dataType}缓存失败:`, refreshErr);
triggerGlobalError(`刷新${dataType}缓存失败`);
}
}
@@ -458,6 +471,7 @@ export async function getAllPlayRecords(): Promise<Record<string, PlayRecord>> {
})
.catch((err) => {
console.warn('后台同步播放记录失败:', err);
triggerGlobalError('后台同步播放记录失败');
});
return cachedData;
@@ -471,6 +485,7 @@ export async function getAllPlayRecords(): Promise<Record<string, PlayRecord>> {
return freshData;
} catch (err) {
console.error('获取播放记录失败:', err);
triggerGlobalError('获取播放记录失败');
return {};
}
}
@@ -483,6 +498,7 @@ export async function getAllPlayRecords(): Promise<Record<string, PlayRecord>> {
return JSON.parse(raw) as Record<string, PlayRecord>;
} catch (err) {
console.error('读取播放记录失败:', err);
triggerGlobalError('读取播放记录失败');
return {};
}
}
@@ -523,6 +539,7 @@ export async function savePlayRecord(
});
} catch (err) {
await handleDatabaseOperationFailure('playRecords', err);
triggerGlobalError('保存播放记录失败');
throw err;
}
return;
@@ -545,6 +562,7 @@ export async function savePlayRecord(
);
} catch (err) {
console.error('保存播放记录失败:', err);
triggerGlobalError('保存播放记录失败');
throw err;
}
}
@@ -580,6 +598,7 @@ export async function deletePlayRecord(
});
} catch (err) {
await handleDatabaseOperationFailure('playRecords', err);
triggerGlobalError('删除播放记录失败');
throw err;
}
return;
@@ -602,6 +621,7 @@ export async function deletePlayRecord(
);
} catch (err) {
console.error('删除播放记录失败:', err);
triggerGlobalError('删除播放记录失败');
throw err;
}
}
@@ -640,6 +660,7 @@ export async function getSearchHistory(): Promise<string[]> {
})
.catch((err) => {
console.warn('后台同步搜索历史失败:', err);
triggerGlobalError('后台同步搜索历史失败');
});
return cachedData;
@@ -651,6 +672,7 @@ export async function getSearchHistory(): Promise<string[]> {
return freshData;
} catch (err) {
console.error('获取搜索历史失败:', err);
triggerGlobalError('获取搜索历史失败');
return [];
}
}
@@ -665,6 +687,7 @@ export async function getSearchHistory(): Promise<string[]> {
return Array.isArray(arr) ? arr : [];
} catch (err) {
console.error('读取搜索历史失败:', err);
triggerGlobalError('读取搜索历史失败');
return [];
}
}
@@ -728,6 +751,7 @@ export async function addSearchHistory(keyword: string): Promise<void> {
);
} catch (err) {
console.error('保存搜索历史失败:', err);
triggerGlobalError('保存搜索历史失败');
}
}
@@ -819,6 +843,7 @@ export async function deleteSearchHistory(keyword: string): Promise<void> {
);
} catch (err) {
console.error('删除搜索历史失败:', err);
triggerGlobalError('删除搜索历史失败');
}
}
@@ -856,6 +881,7 @@ export async function getAllFavorites(): Promise<Record<string, Favorite>> {
})
.catch((err) => {
console.warn('后台同步收藏失败:', err);
triggerGlobalError('后台同步收藏失败');
});
return cachedData;
@@ -869,6 +895,7 @@ export async function getAllFavorites(): Promise<Record<string, Favorite>> {
return freshData;
} catch (err) {
console.error('获取收藏失败:', err);
triggerGlobalError('获取收藏失败');
return {};
}
}
@@ -881,6 +908,7 @@ export async function getAllFavorites(): Promise<Record<string, Favorite>> {
return JSON.parse(raw) as Record<string, Favorite>;
} catch (err) {
console.error('读取收藏失败:', err);
triggerGlobalError('读取收藏失败');
return {};
}
}
@@ -921,6 +949,7 @@ export async function saveFavorite(
});
} catch (err) {
await handleDatabaseOperationFailure('favorites', err);
triggerGlobalError('保存收藏失败');
throw err;
}
return;
@@ -943,6 +972,7 @@ export async function saveFavorite(
);
} catch (err) {
console.error('保存收藏失败:', err);
triggerGlobalError('保存收藏失败');
throw err;
}
}
@@ -978,6 +1008,7 @@ export async function deleteFavorite(
});
} catch (err) {
await handleDatabaseOperationFailure('favorites', err);
triggerGlobalError('删除收藏失败');
throw err;
}
return;
@@ -1000,6 +1031,7 @@ export async function deleteFavorite(
);
} catch (err) {
console.error('删除收藏失败:', err);
triggerGlobalError('删除收藏失败');
throw err;
}
}
@@ -1035,6 +1067,7 @@ export async function isFavorited(
})
.catch((err) => {
console.warn('后台同步收藏失败:', err);
triggerGlobalError('后台同步收藏失败');
});
return !!cachedFavorites[key];
@@ -1048,6 +1081,7 @@ export async function isFavorited(
return !!freshData[key];
} catch (err) {
console.error('检查收藏状态失败:', err);
triggerGlobalError('检查收藏状态失败');
return false;
}
}
@@ -1083,6 +1117,7 @@ export async function clearAllPlayRecords(): Promise<void> {
});
} catch (err) {
await handleDatabaseOperationFailure('playRecords', err);
triggerGlobalError('清空播放记录失败');
throw err;
}
return;
@@ -1123,6 +1158,7 @@ export async function clearAllFavorites(): Promise<void> {
});
} catch (err) {
await handleDatabaseOperationFailure('favorites', err);
triggerGlobalError('清空收藏失败');
throw err;
}
return;
@@ -1204,6 +1240,7 @@ export async function refreshAllCache(): Promise<void> {
}
} catch (err) {
console.error('刷新缓存失败:', err);
triggerGlobalError('刷新缓存失败');
}
}
@@ -1297,6 +1334,7 @@ export async function preloadUserData(): Promise<void> {
// 后台静默预加载,不阻塞界面
refreshAllCache().catch((err) => {
console.warn('预加载用户数据失败:', err);
triggerGlobalError('预加载用户数据失败');
});
}
@@ -1352,6 +1390,7 @@ export async function getSkipConfig(
return freshData[key] || null;
} catch (err) {
console.error('获取跳过片头片尾配置失败:', err);
triggerGlobalError('获取跳过片头片尾配置失败');
return null;
}
}
@@ -1365,6 +1404,7 @@ export async function getSkipConfig(
return configs[key] || null;
} catch (err) {
console.error('读取跳过片头片尾配置失败:', err);
triggerGlobalError('读取跳过片头片尾配置失败');
return null;
}
}
@@ -1405,6 +1445,7 @@ export async function saveSkipConfig(
});
} catch (err) {
console.error('保存跳过片头片尾配置失败:', err);
triggerGlobalError('保存跳过片头片尾配置失败');
}
return;
}
@@ -1427,6 +1468,7 @@ export async function saveSkipConfig(
);
} catch (err) {
console.error('保存跳过片头片尾配置失败:', err);
triggerGlobalError('保存跳过片头片尾配置失败');
throw err;
}
}
@@ -1463,6 +1505,7 @@ export async function getAllSkipConfigs(): Promise<Record<string, SkipConfig>> {
})
.catch((err) => {
console.warn('后台同步跳过片头片尾配置失败:', err);
triggerGlobalError('后台同步跳过片头片尾配置失败');
});
return cachedData;
@@ -1476,6 +1519,7 @@ export async function getAllSkipConfigs(): Promise<Record<string, SkipConfig>> {
return freshData;
} catch (err) {
console.error('获取跳过片头片尾配置失败:', err);
triggerGlobalError('获取跳过片头片尾配置失败');
return {};
}
}
@@ -1488,6 +1532,7 @@ export async function getAllSkipConfigs(): Promise<Record<string, SkipConfig>> {
return JSON.parse(raw) as Record<string, SkipConfig>;
} catch (err) {
console.error('读取跳过片头片尾配置失败:', err);
triggerGlobalError('读取跳过片头片尾配置失败');
return {};
}
}
@@ -1523,6 +1568,7 @@ export async function deleteSkipConfig(
});
} catch (err) {
console.error('删除跳过片头片尾配置失败:', err);
triggerGlobalError('删除跳过片头片尾配置失败');
}
return;
}
@@ -1547,6 +1593,7 @@ export async function deleteSkipConfig(
}
} catch (err) {
console.error('删除跳过片头片尾配置失败:', err);
triggerGlobalError('删除跳过片头片尾配置失败');
throw err;
}
}

View File

@@ -119,6 +119,14 @@ export async function fetchDoubanCategories(
list: list,
};
} catch (error) {
// 触发全局错误提示
if (typeof window !== 'undefined') {
window.dispatchEvent(
new CustomEvent('globalError', {
detail: { message: '获取豆瓣分类数据失败' },
})
);
}
throw new Error(`获取豆瓣分类数据失败: ${(error as Error).message}`);
}
}
@@ -140,6 +148,14 @@ export async function getDoubanCategories(
);
if (!response.ok) {
// 触发全局错误提示
if (typeof window !== 'undefined') {
window.dispatchEvent(
new CustomEvent('globalError', {
detail: { message: '获取豆瓣分类数据失败' },
})
);
}
throw new Error('获取豆瓣分类数据失败');
}
@@ -167,6 +183,14 @@ export async function getDoubanList(
);
if (!response.ok) {
// 触发全局错误提示
if (typeof window !== 'undefined') {
window.dispatchEvent(
new CustomEvent('globalError', {
detail: { message: '获取豆瓣列表数据失败' },
})
);
}
throw new Error('获取豆瓣列表数据失败');
}
@@ -222,6 +246,14 @@ export async function fetchDoubanList(
list: list,
};
} catch (error) {
// 触发全局错误提示
if (typeof window !== 'undefined') {
window.dispatchEvent(
new CustomEvent('globalError', {
detail: { message: '获取豆瓣列表数据失败' },
})
);
}
throw new Error(`获取豆瓣分类数据失败: ${(error as Error).message}`);
}
}

View File

@@ -2,7 +2,7 @@
'use client';
const CURRENT_VERSION = '20250804223856';
const CURRENT_VERSION = '20250804231933';
// 版本检查结果枚举
export enum UpdateStatus {