From 96e5630b7c6e230178d5de68a5da77033f6c2fa8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B5=B7=E9=BE=99?= Date: Thu, 28 Aug 2025 23:00:24 +0800 Subject: [PATCH] =?UTF-8?q?=E6=80=A7=E8=83=BD=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/pages/home-page2.tsx | 129 ++++++++++++++++++++++++++++++++ 1 file changed, 129 insertions(+) diff --git a/components/pages/home-page2.tsx b/components/pages/home-page2.tsx index 19bad29..010f891 100644 --- a/components/pages/home-page2.tsx +++ b/components/pages/home-page2.tsx @@ -29,8 +29,137 @@ import { TextCanvas } from "../common/TextCanvas"; import { fetchSubscriptionPlans, SubscriptionPlan } from "@/lib/stripe"; import { useCallbackModal } from "@/app/layout"; +/** 视频预加载系统 - 后台静默运行 */ +function useVideoPreloader() { + /** 预加载单个视频 */ + const preloadVideo = (src: string): Promise => { + return new Promise((resolve) => { + const video = document.createElement('video'); + video.muted = true; + video.preload = 'auto'; + + // 设置超时,避免某个视频卡住整个预加载过程 + const timeout = setTimeout(() => { + console.warn(`视频预加载超时: ${src}`); + resolve(); + }, 10000); // 10秒超时 + + video.onloadeddata = () => { + clearTimeout(timeout); + resolve(); + }; + + video.onerror = () => { + clearTimeout(timeout); + console.warn(`视频预加载失败: ${src}`); + resolve(); // 即使失败也继续,不影响其他视频 + }; + + video.src = src; + video.load(); + }); + }; + + /** 预加载所有视频 */ + const preloadAllVideos = async () => { + const allVideos = [ + // HomeModule1 - 首屏视频(最高优先级) + "https://cdn.qikongjian.com/videos/home.mp4", + // HomeModule2 - 核心价值视频(高优先级) + "https://cdn.qikongjian.com/videos/module2 (1).mp4", + "https://cdn.qikongjian.com/videos/module2 (2).mp4", + "https://cdn.qikongjian.com/videos/module2 (3).mp4", + // HomeModule4 - 制作工序视频(中优先级) + "https://cdn.qikongjian.com/videos/module4 (3).mp4", + "https://cdn.qikongjian.com/videos/module4 (1).mp4", + "https://cdn.qikongjian.com/videos/module4 (4).mp4", + "https://cdn.qikongjian.com/videos/module4 (2).mp4", + // HomeModule3 - 案例展示视频(低优先级,数量多) + "https://cdn.qikongjian.com/videos/show (1).mp4", + "https://cdn.qikongjian.com/videos/show (2).mp4", + "https://cdn.qikongjian.com/videos/show (3).mp4", + "https://cdn.qikongjian.com/videos/show (4).mp4", + "https://cdn.qikongjian.com/videos/show (5).mp4", + "https://cdn.qikongjian.com/videos/show (6).mp4", + "https://cdn.qikongjian.com/videos/show (7).mp4", + "https://cdn.qikongjian.com/videos/show (8).mp4", + "https://cdn.qikongjian.com/videos/show (9).mp4", + "https://cdn.qikongjian.com/videos/show (10).mp4", + "https://cdn.qikongjian.com/videos/show (11).mp4", + "https://cdn.qikongjian.com/videos/show (12).mp4", + "https://cdn.qikongjian.com/videos/show (13).mp4", + "https://cdn.qikongjian.com/videos/show (14).mp4", + "https://cdn.qikongjian.com/videos/show (15).mp4", + ]; + + try { + // 分阶段预加载:先加载关键视频,再加载其他视频 + const criticalVideos = allVideos.slice(0, 8); // 前8个是关键视频 + const otherVideos = allVideos.slice(8); + + // 第一阶段:预加载关键视频 + for (let i = 0; i < criticalVideos.length; i += 2) { + const batch = criticalVideos.slice(i, i + 2); + await Promise.all(batch.map(preloadVideo)); + } + + // 第二阶段:后台预加载其他视频 + if (otherVideos.length > 0) { + // 使用 requestIdleCallback 在浏览器空闲时预加载 + const preloadRemaining = () => { + let index = 0; + const processBatch = () => { + if (index >= otherVideos.length) return; + + const batch = otherVideos.slice(index, Math.min(index + 3, otherVideos.length)); + batch.forEach(preloadVideo); + index += batch.length; + + if (index < otherVideos.length) { + requestIdleCallback(processBatch, { timeout: 1000 }); + } + }; + + requestIdleCallback(processBatch, { timeout: 1000 }); + }; + + // 如果浏览器不支持 requestIdleCallback,使用 setTimeout + if (typeof requestIdleCallback !== 'undefined') { + preloadRemaining(); + } else { + setTimeout(() => { + for (let i = 0; i < otherVideos.length; i += 3) { + const batch = otherVideos.slice(i, i + 3); + batch.forEach(preloadVideo); + } + }, 100); + } + } + + } catch (error) { + console.error('视频预加载过程中出现错误:', error); + } + }; + + useEffect(() => { + // 使用 requestIdleCallback 在浏览器空闲时开始预加载 + // 如果浏览器不支持,则使用 setTimeout 延迟执行 + if (typeof requestIdleCallback !== 'undefined') { + requestIdleCallback(() => preloadAllVideos(), { timeout: 2000 }); + } else { + setTimeout(() => preloadAllVideos(), 100); + } + }, []); + + // 这个 hook 不需要返回任何值,它只是后台静默运行 + return; +} + export function HomePage2() { + // 后台静默预加载视频,不显示任何加载界面 + useVideoPreloader(); const [hPading, setHPading] = useState(0); + useEffect(() => { // 获取当前窗口尺寸 const currentWidth = window.innerWidth;