/** * App Store 应用内评分服务 * * 功能: * 1. 调用 iOS 原生模块请求应用内评分 * 2. 管理评分请求时间间隔(至少 14 天) * 3. 提供便捷的业务场景触发方法 * * iOS 限制说明: * - iOS 系统会自动限制评分请求的频率(每年最多 3 次) * - 本服务额外实现 14 天间隔限制,确保不会过于频繁打扰用户 */ import * as kvStore from '@/utils/kvStore'; import { NativeModules, Platform } from 'react-native'; // 原生模块 const { AppStoreReviewManager } = NativeModules; // 存储键 const LAST_REVIEW_REQUEST_DATE_KEY = 'app_store_review_last_request_date'; const MIN_DAYS_BETWEEN_REQUESTS = 14; // 最少间隔天数 /** * 检查是否可以请求评分 * @returns Promise 是否可以请求 */ async function canRequestReview(): Promise { // 只在 iOS 平台支持 if (Platform.OS !== 'ios') { console.log('⚠️ App Store 评分仅支持 iOS 平台'); return false; } // 检查原生模块是否可用 if (!AppStoreReviewManager) { console.error('❌ AppStoreReviewManager 原生模块不可用'); return false; } try { // 检查系统是否支持(iOS 14.0+) const systemCheck = await AppStoreReviewManager.canRequestReview(); if (!systemCheck.canRequest) { console.log('⚠️ 系统不支持应用内评分:', systemCheck.reason); return false; } // 检查上次请求时间 const lastRequestDate = await kvStore.getItem(LAST_REVIEW_REQUEST_DATE_KEY); if (lastRequestDate) { const daysSinceLastRequest = Math.floor( (Date.now() - parseInt(lastRequestDate, 10)) / (1000 * 60 * 60 * 24) ); if (daysSinceLastRequest < MIN_DAYS_BETWEEN_REQUESTS) { console.log( `⚠️ 距离上次评分请求仅 ${daysSinceLastRequest} 天,需要至少 ${MIN_DAYS_BETWEEN_REQUESTS} 天` ); return false; } } return true; } catch (error) { console.error('❌ 检查评分请求条件失败:', error); return false; } } /** * 请求应用内评分 * @returns Promise 是否成功发起请求 */ async function requestReview(): Promise { try { // 检查是否可以请求 const canRequest = await canRequestReview(); if (!canRequest) { return false; } // 调用原生模块请求评分 const result = await AppStoreReviewManager.requestReview(); if (result.success) { // 记录本次请求时间 await kvStore.setItem(LAST_REVIEW_REQUEST_DATE_KEY, Date.now().toString()); console.log('✅ 应用内评分请求已发送'); return true; } else { console.error('❌ 应用内评分请求失败:', result); return false; } } catch (error) { console.error('❌ 请求应用内评分时出错:', error); return false; } } /** * 获取上次请求评分的时间 * @returns Promise 上次请求时间,如果从未请求过则返回 null */ async function getLastRequestDate(): Promise { try { const lastRequestDate = await kvStore.getItem(LAST_REVIEW_REQUEST_DATE_KEY); if (lastRequestDate) { return new Date(parseInt(lastRequestDate, 10)); } return null; } catch (error) { console.error('❌ 获取上次评分请求时间失败:', error); return null; } } /** * 获取距离下次可以请求评分的剩余天数 * @returns Promise 剩余天数,0 表示可以立即请求 */ async function getDaysUntilNextRequest(): Promise { try { const lastRequestDate = await getLastRequestDate(); if (!lastRequestDate) { return 0; // 从未请求过,可以立即请求 } const daysSinceLastRequest = Math.floor( (Date.now() - lastRequestDate.getTime()) / (1000 * 60 * 60 * 24) ); const daysRemaining = MIN_DAYS_BETWEEN_REQUESTS - daysSinceLastRequest; return Math.max(0, daysRemaining); } catch (error) { console.error('❌ 计算剩余天数失败:', error); return MIN_DAYS_BETWEEN_REQUESTS; } } /** * 重置评分请求记录(仅用于测试) * ⚠️ 警告:不应在生产环境中调用此方法 */ async function resetRequestHistory(): Promise { try { await kvStore.removeItem(LAST_REVIEW_REQUEST_DATE_KEY); console.log('✅ 评分请求历史已重置'); } catch (error) { console.error('❌ 重置评分请求历史失败:', error); } } // 导出服务 export const appStoreReviewService = { // 核心方法 canRequestReview, requestReview, getLastRequestDate, getDaysUntilNextRequest, resetRequestHistory, }; // 常量导出 export { MIN_DAYS_BETWEEN_REQUESTS };