/** * 后台任务调试辅助工具 * * 用于在开发和测试阶段验证后台任务配置和执行情况 */ import { logger } from '@/utils/logger'; import { NativeModules, Platform } from 'react-native'; import { BackgroundTaskManager } from './backgroundTaskManagerV2'; const NativeBackgroundModule = NativeModules.BackgroundTaskBridge; export class BackgroundTaskDebugHelper { private static instance: BackgroundTaskDebugHelper; static getInstance(): BackgroundTaskDebugHelper { if (!BackgroundTaskDebugHelper.instance) { BackgroundTaskDebugHelper.instance = new BackgroundTaskDebugHelper(); } return BackgroundTaskDebugHelper.instance; } /** * 执行完整的后台任务诊断 */ async runFullDiagnostics(): Promise { logger.info('[BackgroundTaskDebug] ====== 开始后台任务诊断 ======'); const report: DiagnosticsReport = { platform: Platform.OS, timestamp: new Date().toISOString(), checks: {}, }; // 1. 检查平台支持 report.checks.platformSupport = this.checkPlatformSupport(); // 2. 检查原生模块 report.checks.nativeModule = await this.checkNativeModule(); // 3. 检查后台刷新权限 report.checks.backgroundRefresh = await this.checkBackgroundRefreshStatus(); // 4. 检查待处理任务 report.checks.pendingTasks = await this.checkPendingTasks(); // 5. 检查配置 report.checks.configuration = this.checkConfiguration(); // 6. 检查最后执行时间 report.checks.lastExecution = await this.checkLastExecution(); logger.info('[BackgroundTaskDebug] ====== 诊断完成 ======'); logger.info('[BackgroundTaskDebug] 报告:', JSON.stringify(report, null, 2)); return report; } /** * 检查平台支持 */ private checkPlatformSupport(): CheckResult { const isIOS = Platform.OS === 'ios'; return { status: isIOS ? 'success' : 'error', message: isIOS ? 'iOS 平台支持后台任务' : `当前平台 (${Platform.OS}) 不支持后台任务`, details: { platform: Platform.OS, version: Platform.Version, }, }; } /** * 检查原生模块 */ private async checkNativeModule(): Promise { if (!NativeBackgroundModule) { return { status: 'error', message: '原生模块 BackgroundTaskBridge 不可用', details: { available: false, }, }; } try { // 尝试调用一个简单的方法来验证模块是否正常工作 const status = await NativeBackgroundModule.backgroundRefreshStatus(); return { status: 'success', message: '原生模块可用且正常工作', details: { available: true, backgroundRefreshStatus: status, }, }; } catch (error) { return { status: 'error', message: '原生模块存在但调用失败', details: { available: true, error: (error as Error).message, }, }; } } /** * 检查后台刷新权限状态 */ private async checkBackgroundRefreshStatus(): Promise { try { const manager = BackgroundTaskManager.getInstance(); const status = await manager.getStatus(); const statusText = await manager.checkStatus(); let resultStatus: 'success' | 'warning' | 'error'; let message: string; switch (status) { case 'available': resultStatus = 'success'; message = '后台刷新权限已启用'; break; case 'denied': resultStatus = 'error'; message = '后台刷新被拒绝,请在设置中启用'; break; case 'restricted': resultStatus = 'error'; message = '后台刷新被限制(可能是家长控制)'; break; default: resultStatus = 'warning'; message = `后台刷新状态未知: ${status}`; } return { status: resultStatus, message, details: { status, statusText, }, }; } catch (error) { return { status: 'error', message: '检查后台刷新状态失败', details: { error: (error as Error).message, }, }; } } /** * 检查待处理的任务 */ private async checkPendingTasks(): Promise { try { const manager = BackgroundTaskManager.getInstance(); const pendingRequests = await manager.getPendingRequests(); return { status: pendingRequests.length > 0 ? 'success' : 'warning', message: pendingRequests.length > 0 ? `有 ${pendingRequests.length} 个待处理任务` : '没有待处理的任务(可能需要调度)', details: { count: pendingRequests.length, tasks: pendingRequests, }, }; } catch (error) { return { status: 'error', message: '检查待处理任务失败', details: { error: (error as Error).message, }, }; } } /** * 检查配置 */ private checkConfiguration(): CheckResult { const config = { identifier: 'com.anonymous.digitalpilates.task', defaultDelay: 15 * 60, // 15分钟 }; return { status: 'info', message: '后台任务配置', details: config, }; } /** * 检查最后执行时间 */ private async checkLastExecution(): Promise { try { const manager = BackgroundTaskManager.getInstance(); const lastCheckTime = await manager.getLastBackgroundCheckTime(); if (!lastCheckTime) { return { status: 'warning', message: '后台任务从未执行过', details: { lastExecution: null, }, }; } const timeSinceLastCheck = Date.now() - lastCheckTime; const hoursSinceLastCheck = timeSinceLastCheck / (1000 * 60 * 60); return { status: hoursSinceLastCheck > 24 ? 'warning' : 'success', message: hoursSinceLastCheck > 24 ? `距离上次执行已超过24小时 (${hoursSinceLastCheck.toFixed(1)}小时)` : `上次执行时间: ${new Date(lastCheckTime).toLocaleString()}`, details: { lastExecution: lastCheckTime, timeSinceLastCheck: `${hoursSinceLastCheck.toFixed(1)} 小时`, }, }; } catch (error) { return { status: 'error', message: '检查最后执行时间失败', details: { error: (error as Error).message, }, }; } } /** * 生成可读的诊断报告 */ generateReadableReport(report: DiagnosticsReport): string { let output = '\n========== 后台任务诊断报告 ==========\n'; output += `时间: ${new Date(report.timestamp).toLocaleString()}\n`; output += `平台: ${report.platform}\n`; output += '\n'; Object.entries(report.checks).forEach(([key, check]) => { const icon = check.status === 'success' ? '✅' : check.status === 'error' ? '❌' : '⚠️'; output += `${icon} ${key}: ${check.message}\n`; if (check.details && Object.keys(check.details).length > 0) { output += ` 详情: ${JSON.stringify(check.details, null, 2)}\n`; } output += '\n'; }); output += '=====================================\n'; return output; } /** * 模拟触发后台任务(仅用于测试) */ async triggerTestTask(): Promise { logger.info('[BackgroundTaskDebug] 触发测试任务...'); try { const manager = BackgroundTaskManager.getInstance(); await manager.triggerTaskForTesting(); logger.info('[BackgroundTaskDebug] ✅ 测试任务执行完成'); } catch (error: any) { const errorCode = error?.code || ''; if (errorCode === 'SIMULATOR_NOT_SUPPORTED') { logger.info('[BackgroundTaskDebug] ℹ️ 在模拟器上执行了后台任务逻辑'); logger.info('[BackgroundTaskDebug] 模拟器不支持完整的后台任务调度'); logger.info('[BackgroundTaskDebug] 这是正常的,请在真机上测试完整功能'); } else { logger.error('[BackgroundTaskDebug] ❌ 测试任务执行失败', error); throw error; } } } } export interface DiagnosticsReport { platform: string; timestamp: string; checks: { [key: string]: CheckResult; }; } export interface CheckResult { status: 'success' | 'warning' | 'error' | 'info'; message: string; details?: Record; }