Compare commits

..

No commits in common. "d6fba57afcdcf8c39be2430d48b0c8898f39c78b" and "be71df2ecd47f1259d43fba22f66b3af0c814c0e" have entirely different histories.

3 changed files with 78 additions and 100 deletions

View File

@ -1,3 +1,8 @@
@tailwind base;
@tailwind components;
@tailwind utilities;
#app{ #app{
width: 100vw; width: 100vw;
height: 100vh; height: 100vh;

View File

@ -17,28 +17,16 @@ interface UseAdOptions {
onReward?: AdRewardCallback; // 观看完整广告后的奖励回调 onReward?: AdRewardCallback; // 观看完整广告后的奖励回调
onClose?: (isEnded: boolean) => void; // 广告关闭回调,传入是否完整观看 onClose?: (isEnded: boolean) => void; // 广告关闭回调,传入是否完整观看
} }
// 创建平台广告实例
const factory = createPlatformFactory()
export function useAd(options?: UseAdOptions): UseAdReturn { export function useAd(options?: UseAdOptions): UseAdReturn {
const [loading, setLoading] = useState(true); const [loading, setLoading] = useState(true);
const [adAvailable, setAdAvailable] = useState(false); const [adAvailable, setAdAvailable] = useState(false);
const adRef = useRef<RewardedVideoAd | null>(null); const adRef = useRef<RewardedVideoAd | null>(null);
const platform = factory.getPlatform()
// 检查当前平台是否支持广告
const isAdSupportedPlatform = platform === 'bytedance';
useEffect(() => { useEffect(() => {
// 如果当前平台不支持广告,直接设置为不可用状态
if (!isAdSupportedPlatform) {
console.log(`当前平台 ${platform} 未开通广告,跳过广告初始化`);
setAdAvailable(false);
setLoading(false);
return;
}
try { try {
// 创建平台广告实例
const factory = createPlatformFactory()
adRef.current = factory.createRewardedVideoAd(); adRef.current = factory.createRewardedVideoAd();
const ad = adRef.current!; const ad = adRef.current!;
@ -47,100 +35,91 @@ export function useAd(options?: UseAdOptions): UseAdReturn {
console.warn('广告功能不可用,可能是流量主未开通'); console.warn('广告功能不可用,可能是流量主未开通');
setAdAvailable(false); setAdAvailable(false);
setLoading(false); setLoading(false);
return () => { }; // 返回空的清理函数 return () => {}; // 返回空的清理函数
} }
setAdAvailable(true); setAdAvailable(true);
// 广告关闭回调处理 // 广告关闭回调处理
const onClose: RewardedVideoCloseCb = (res) => { const onClose: RewardedVideoCloseCb = (res) => {
console.log('广告关闭:', res); console.log('广告关闭:', res);
setLoading(false); setLoading(false);
// 判断用户是否完成播放 // 判断用户是否完成播放
const isEnded = Boolean(res?.isEnded); const isEnded = Boolean(res?.isEnded);
if (isEnded) { if (isEnded) {
// 播放完成的业务逻辑 // 播放完成的业务逻辑
console.log('用户观看完整广告,给予奖励'); console.log('用户观看完整广告,给予奖励');
// 执行奖励回调 // 执行奖励回调
options?.onReward?.(); options?.onReward?.();
// 可以在这里处理以下业务: // 可以在这里处理以下业务:
// 1. 发放奖励(积分、道具等) // 1. 发放奖励(积分、道具等)
// 2. 解锁功能或内容 // 2. 解锁功能或内容
// 3. 统计完成观看数据 // 3. 统计完成观看数据
// 4. 触发下一步操作 // 4. 触发下一步操作
} else { } else {
// 未完成播放的处理 // 未完成播放的处理
console.log('用户未完整观看广告'); console.log('用户未完整观看广告');
// 可以处理以下场景: // 可以处理以下场景:
// 1. 提示用户观看完整广告才能获得奖励 // 1. 提示用户观看完整广告才能获得奖励
// 2. 记录未完成播放的统计 // 2. 记录未完成播放的统计
// 3. 可能的重试提示 // 3. 可能的重试提示
}
// 执行关闭回调,传入是否完整观看
options?.onClose?.(isEnded);
}
// 广告加载错误回调处理
const onError: RewardedVideoErrorCb = (res) => {
console.error('广告错误:', res);
setLoading(false);
// 根据错误类型判断广告是否不可用
const errorCode = res?.errCode;
if (errorCode && ['1004', '1008', '1009', 1004, 1008, 1009].includes(errorCode)) {
console.warn('广告服务不可用,可能是流量主未开通或被暂停');
setAdAvailable(false);
}
} }
// 广告加载成功回调处理 // 执行关闭回调,传入是否完整观看
const onLoad = () => { options?.onClose?.(isEnded);
console.log('广告加载成功'); }
setLoading(false); // 广告加载错误回调处理
} const onError: RewardedVideoErrorCb = (res) => {
// 绑定广告事件监听 console.error('广告错误:', res);
ad.onLoad(onLoad); setLoading(false);
ad.onClose(onClose);
ad.onError(onError);
// 清理函数:组件卸载时移除事件监听和销毁广告实例 // 根据错误类型判断广告是否不可用
return () => { const errorCode = res?.errCode;
if (adRef.current) { if (errorCode && ['1004', '1008', '1009', 1004, 1008, 1009].includes(errorCode)) {
adRef.current.offClose(onClose) console.warn('广告服务不可用,可能是流量主未开通或被暂停');
adRef.current.offError(onError) setAdAvailable(false);
adRef.current.offLoad(onLoad) }
adRef.current.destroy(); }
}
}; // 广告加载成功回调处理
const onLoad = () => {
console.log('广告加载成功');
setLoading(false);
}
// 绑定广告事件监听
ad.onLoad(onLoad);
ad.onClose(onClose);
ad.onError(onError);
// 清理函数:组件卸载时移除事件监听和销毁广告实例
return () => {
if (adRef.current) {
adRef.current.offClose(onClose)
adRef.current.offError(onError)
adRef.current.offLoad(onLoad)
adRef.current.destroy();
}
};
} catch (error) { } catch (error) {
console.error('初始化广告失败:', error); console.error('初始化广告失败:', error);
setAdAvailable(false); setAdAvailable(false);
setLoading(false); setLoading(false);
return () => { }; // 返回空的清理函数 return () => {}; // 返回空的清理函数
} }
}, [options, isAdSupportedPlatform, platform]); }, [options]);
// 显示广告方法 // 显示广告方法
const showAd = useCallback(() => { const showAd = useCallback(() => {
// 如果当前平台不支持广告,直接给予奖励并触发关闭回调
if (!isAdSupportedPlatform) {
console.log(`当前平台 ${platform} 未开通广告,直接给予奖励`);
options?.onReward?.();
options?.onClose?.(true); // 模拟广告播放完成
return;
}
if (!adAvailable) { if (!adAvailable) {
console.warn('广告不可用,跳过广告播放'); console.warn('广告不可用,跳过广告播放');
// 如果广告不可用,直接给予奖励 // 如果广告不可用,直接给予奖励
options?.onReward?.(); options?.onReward?.();
options?.onClose?.(true); // 模拟广告播放完成
return; return;
} }
@ -153,24 +132,17 @@ export function useAd(options?: UseAdOptions): UseAdReturn {
setLoading(false); setLoading(false);
// 如果显示失败,也给予奖励作为降级处理 // 如果显示失败,也给予奖励作为降级处理
options?.onReward?.(); options?.onReward?.();
options?.onClose?.(true); // 模拟广告播放完成
} }
} }
}, [adAvailable, options, isAdSupportedPlatform, platform]); }, [adAvailable, options]);
// 加载广告方法 // 加载广告方法
const loadAd = useCallback(() => { const loadAd = useCallback(() => {
// 如果当前平台不支持广告,直接跳过加载
if (!isAdSupportedPlatform) {
console.log(`当前平台 ${platform} 未开通广告,跳过广告加载`);
return;
}
if (adRef.current) { if (adRef.current) {
setLoading(true); setLoading(true);
adRef.current.load(); adRef.current.load();
} }
}, [isAdSupportedPlatform, platform]); }, []);
return { return {
showAd, showAd,

View File

@ -70,13 +70,14 @@ const ResultPage: React.FC = () => {
} else if (!adAvailable) { } else if (!adAvailable) {
// 广告不可用(如流量主未开通),直接允许下载 // 广告不可用(如流量主未开通),直接允许下载
showToast({ showToast({
title: '已为您跳过广告', title: '已为您跳过广告,直接下载',
icon: 'success', icon: 'success',
duration: 1500 duration: 2000
}) })
setHasWatchedAd(true) // 标记为已"观看",允许下载
setTimeout(() => { setTimeout(() => {
handleDownloadImages(true) // 跳过广告检查,直接下载 handleDownloadImages()
}, 800) }, 500)
} else { } else {
// 还没观看广告,先播放广告 // 还没观看广告,先播放广告
showAd() showAd()
@ -84,8 +85,8 @@ const ResultPage: React.FC = () => {
} }
// 下载图片到本地相册 // 下载图片到本地相册
const handleDownloadImages = async (skipAdCheck: boolean = false) => { const handleDownloadImages = async () => {
if (!skipAdCheck && !hasWatchedAd) { if (!hasWatchedAd) {
showToast({ showToast({
title: '请先观看广告', title: '请先观看广告',
icon: 'none', icon: 'none',