pb-sxp-ui 1.20.43 → 1.20.44
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +206 -65
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +206 -65
- package/dist/index.js.map +1 -1
- package/dist/index.min.cjs +7 -7
- package/dist/index.min.cjs.map +1 -1
- package/dist/index.min.js +7 -7
- package/dist/index.min.js.map +1 -1
- package/dist/pb-ui.js +206 -65
- package/dist/pb-ui.js.map +1 -1
- package/dist/pb-ui.min.js +6 -6
- package/dist/pb-ui.min.js.map +1 -1
- package/es/core/components/StructurePage/index.js +153 -45
- package/es/core/hooks/useAdvancedOnScreen.d.ts +1 -0
- package/es/core/hooks/useAdvancedOnScreen.js +8 -8
- package/lib/core/components/StructurePage/index.js +153 -45
- package/lib/core/hooks/useAdvancedOnScreen.d.ts +1 -0
- package/lib/core/hooks/useAdvancedOnScreen.js +8 -8
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -2224,7 +2224,7 @@ const EditorCore = React.forwardRef(({ children, resolver, isSsr, schema, enable
|
|
|
2224
2224
|
* @returns isVisible 是否可见
|
|
2225
2225
|
*/
|
|
2226
2226
|
function useAdvancedOnScreen(ref, options = {}) {
|
|
2227
|
-
const { threshold = 0, delay = 0, onVisible, onHidden } = options;
|
|
2227
|
+
const { threshold = 0, delay = 0, onVisible, onHidden, name = 'unknown' } = options;
|
|
2228
2228
|
const observerRef = React.useRef(null);
|
|
2229
2229
|
const [isVisible, setIsVisible] = React.useState(false);
|
|
2230
2230
|
const timerRef = React.useRef(null);
|
|
@@ -2250,7 +2250,7 @@ function useAdvancedOnScreen(ref, options = {}) {
|
|
|
2250
2250
|
var _a, _b;
|
|
2251
2251
|
const isIntersecting = entry.isIntersecting;
|
|
2252
2252
|
const intersectionRatio = entry.intersectionRatio;
|
|
2253
|
-
console.log(
|
|
2253
|
+
console.log(`[useAdvancedOnScreen ${name}] IntersectionObserver callback:`, {
|
|
2254
2254
|
isIntersecting,
|
|
2255
2255
|
threshold,
|
|
2256
2256
|
delay,
|
|
@@ -2262,18 +2262,18 @@ function useAdvancedOnScreen(ref, options = {}) {
|
|
|
2262
2262
|
if (isIntersecting && intersectionRatio >= threshold) {
|
|
2263
2263
|
// 元素进入可视区域且达到阈值
|
|
2264
2264
|
setIsVisible(true);
|
|
2265
|
-
//
|
|
2265
|
+
// 如果已经在等待中,清除旧的定时器,重新开始计时
|
|
2266
2266
|
if (isWaitingRef.current) {
|
|
2267
|
-
console.log(
|
|
2268
|
-
|
|
2267
|
+
console.log(`[useAdvancedOnScreen ${name}] 已在等待中,清除旧定时器并重新计时`);
|
|
2268
|
+
clearTimer();
|
|
2269
2269
|
}
|
|
2270
2270
|
// 如果设置了延迟时间
|
|
2271
2271
|
if (delay > 0) {
|
|
2272
|
-
console.log(`[useAdvancedOnScreen] 设置延迟定时器: ${delay}ms`);
|
|
2272
|
+
console.log(`[useAdvancedOnScreen ${name}] 设置延迟定时器: ${delay}ms`);
|
|
2273
2273
|
isWaitingRef.current = true;
|
|
2274
2274
|
timerRef.current = setTimeout(() => {
|
|
2275
2275
|
var _a;
|
|
2276
|
-
console.log(
|
|
2276
|
+
console.log(`[useAdvancedOnScreen ${name}] 延迟时间到,触发 onVisible`);
|
|
2277
2277
|
isWaitingRef.current = false;
|
|
2278
2278
|
timerRef.current = null;
|
|
2279
2279
|
(_a = onVisibleRef.current) === null || _a === void 0 ? void 0 : _a.call(onVisibleRef);
|
|
@@ -2281,13 +2281,13 @@ function useAdvancedOnScreen(ref, options = {}) {
|
|
|
2281
2281
|
}
|
|
2282
2282
|
else {
|
|
2283
2283
|
// 没有延迟,立即触发
|
|
2284
|
-
console.log(
|
|
2284
|
+
console.log(`[useAdvancedOnScreen ${name}] 无延迟,立即触发 onVisible`);
|
|
2285
2285
|
(_a = onVisibleRef.current) === null || _a === void 0 ? void 0 : _a.call(onVisibleRef);
|
|
2286
2286
|
}
|
|
2287
2287
|
}
|
|
2288
2288
|
else if (!isIntersecting || intersectionRatio < threshold) {
|
|
2289
2289
|
// 元素离开可视区域或未达到阈值
|
|
2290
|
-
console.log(
|
|
2290
|
+
console.log(`[useAdvancedOnScreen ${name}] 元素离开可视区域或未达到阈值,清除定时器`);
|
|
2291
2291
|
setIsVisible(false);
|
|
2292
2292
|
clearTimer();
|
|
2293
2293
|
(_b = onHiddenRef.current) === null || _b === void 0 ? void 0 : _b.call(onHiddenRef);
|
|
@@ -19624,32 +19624,54 @@ const ProductView = ({ children, onExposure }) => {
|
|
|
19624
19624
|
});
|
|
19625
19625
|
return (React.createElement("div", { ref: productRef, style: { width: '100%' } }, children));
|
|
19626
19626
|
};
|
|
19627
|
-
const PostView = ({ children, videoRef, isVideo, onExposure,
|
|
19627
|
+
const PostView = ({ children, videoRef, isVideo, onExposure, autoPlayTriggerRef, onVideoPlay, onVideoPause }) => {
|
|
19628
19628
|
const postRef = React.useRef(null);
|
|
19629
19629
|
// 使用高级曝光检测:2/3区域(threshold=0.67)+ 1000ms延迟
|
|
19630
19630
|
useAdvancedOnScreen(postRef, {
|
|
19631
19631
|
threshold: 0.67,
|
|
19632
19632
|
delay: 1000,
|
|
19633
19633
|
onVisible: () => {
|
|
19634
|
+
console.log('[PostView onVisible] 触发,isVideo:', isVideo, 'hasVideoRef:', !!(videoRef === null || videoRef === void 0 ? void 0 : videoRef.current));
|
|
19634
19635
|
// 每次进入2/3区域并停留1秒后都触发曝光上报
|
|
19635
19636
|
if (onExposure) {
|
|
19636
19637
|
onExposure();
|
|
19637
19638
|
}
|
|
19638
19639
|
// 如果是视频,自动播放
|
|
19639
19640
|
if (isVideo && (videoRef === null || videoRef === void 0 ? void 0 : videoRef.current)) {
|
|
19640
|
-
|
|
19641
|
+
console.log('[PostView onVisible] 准备播放视频');
|
|
19642
|
+
// 标记这次播放是自动触发的
|
|
19643
|
+
if (autoPlayTriggerRef) {
|
|
19644
|
+
autoPlayTriggerRef.current = true;
|
|
19645
|
+
console.log('[PostView onVisible] 已设置自动播放标记');
|
|
19646
|
+
}
|
|
19647
|
+
videoRef.current.play().then(() => {
|
|
19648
|
+
console.log('[PostView onVisible] 视频 play() 成功');
|
|
19649
|
+
// 触发播放回调,更新暂停图标状态
|
|
19650
|
+
if (onVideoPlay) {
|
|
19651
|
+
onVideoPlay();
|
|
19652
|
+
}
|
|
19653
|
+
}).catch(err => {
|
|
19641
19654
|
console.warn('[PostView] Video autoplay failed:', err);
|
|
19655
|
+
// 播放失败时重置标记
|
|
19656
|
+
if (autoPlayTriggerRef) {
|
|
19657
|
+
autoPlayTriggerRef.current = false;
|
|
19658
|
+
}
|
|
19642
19659
|
});
|
|
19643
|
-
// 触发自动播放回调(用于上报 playVideo 事件)
|
|
19644
|
-
onVideoAutoPlay === null || onVideoAutoPlay === void 0 ? void 0 : onVideoAutoPlay();
|
|
19645
19660
|
}
|
|
19646
19661
|
},
|
|
19647
19662
|
onHidden: () => {
|
|
19663
|
+
console.log('[PostView onHidden] 触发,isVideo:', isVideo, 'hasVideoRef:', !!(videoRef === null || videoRef === void 0 ? void 0 : videoRef.current));
|
|
19648
19664
|
// 如果是视频,离开2/3区域时自动暂停
|
|
19649
19665
|
if (isVideo && (videoRef === null || videoRef === void 0 ? void 0 : videoRef.current)) {
|
|
19666
|
+
console.log('[PostView onHidden] 暂停视频');
|
|
19650
19667
|
videoRef.current.pause();
|
|
19668
|
+
// 触发暂停回调,更新暂停图标状态
|
|
19669
|
+
if (onVideoPause) {
|
|
19670
|
+
onVideoPause();
|
|
19671
|
+
}
|
|
19651
19672
|
}
|
|
19652
|
-
}
|
|
19673
|
+
},
|
|
19674
|
+
name: 'PostView(Hero)'
|
|
19653
19675
|
});
|
|
19654
19676
|
return (React.createElement("div", { ref: postRef, style: { width: '100%', height: '100%' } }, children));
|
|
19655
19677
|
};
|
|
@@ -20015,6 +20037,11 @@ const StructurePage = (_a) => {
|
|
|
20015
20037
|
const isFirstPlay = React.useRef({});
|
|
20016
20038
|
const videoLoadTime = React.useRef({});
|
|
20017
20039
|
const videoAutoPlayReported = React.useRef(new Set()); // 追踪哪些视频已通过自动播放上报
|
|
20040
|
+
// 自动播放触发标记(用于区分自动播放和用户手动播放)
|
|
20041
|
+
const heroAutoPlayTrigger = React.useRef(false);
|
|
20042
|
+
const carouselAutoPlayTriggers = React.useRef({});
|
|
20043
|
+
// 追踪当前正在播放的 Carousel 视频索引(用于 onHidden 回调)
|
|
20044
|
+
const currentPlayingCarouselIndex = React.useRef(-1);
|
|
20018
20045
|
// 调试日志
|
|
20019
20046
|
console.log('[StructurePage] Props:', {
|
|
20020
20047
|
editorMode,
|
|
@@ -20251,17 +20278,35 @@ const StructurePage = (_a) => {
|
|
|
20251
20278
|
ctaEvent === null || ctaEvent === void 0 ? void 0 : ctaEvent(Object.assign({ eventSubject: 'ctaExposure', eventDescription: 'The cta was shown to the user' }, (viewPosition && { viewPosition })), rec, productData, sectionIndex !== undefined ? sectionIndex : 0);
|
|
20252
20279
|
}, [ctaEvent, data]);
|
|
20253
20280
|
// 视频播放事件处理
|
|
20254
|
-
const handleVideoPlay = React.useCallback((videoData, viewPosition, sectionIndex, videoRef
|
|
20255
|
-
|
|
20281
|
+
const handleVideoPlay = React.useCallback((videoData, viewPosition, sectionIndex, videoRef) => {
|
|
20282
|
+
console.log('[handleVideoPlay] 调用,viewPosition:', viewPosition, 'sectionIndex:', sectionIndex, 'hasDuration:', !!(videoRef === null || videoRef === void 0 ? void 0 : videoRef.duration));
|
|
20283
|
+
if (!videoRef || !videoRef.duration) {
|
|
20284
|
+
console.log('[handleVideoPlay] 返回:没有 videoRef 或 duration');
|
|
20256
20285
|
return;
|
|
20286
|
+
}
|
|
20257
20287
|
const videoId = `${videoData === null || videoData === void 0 ? void 0 : videoData.itemId}-${viewPosition}-${sectionIndex}`;
|
|
20258
|
-
//
|
|
20288
|
+
// 检查是否是自动播放触发的
|
|
20289
|
+
let isAutoPlay = false;
|
|
20290
|
+
if (viewPosition === 'heroSection' && heroAutoPlayTrigger.current) {
|
|
20291
|
+
isAutoPlay = true;
|
|
20292
|
+
console.log('[handleVideoPlay] Hero Section 自动播放标记为 true');
|
|
20293
|
+
heroAutoPlayTrigger.current = false; // 重置标记
|
|
20294
|
+
}
|
|
20295
|
+
else if (viewPosition === 'carouselSection' && sectionIndex !== undefined && carouselAutoPlayTriggers.current[sectionIndex]) {
|
|
20296
|
+
isAutoPlay = true;
|
|
20297
|
+
console.log('[handleVideoPlay] Carousel Section 自动播放标记为 true, index:', sectionIndex);
|
|
20298
|
+
carouselAutoPlayTriggers.current[sectionIndex] = false; // 重置标记
|
|
20299
|
+
}
|
|
20300
|
+
console.log('[handleVideoPlay] isAutoPlay:', isAutoPlay, 'videoId:', videoId);
|
|
20301
|
+
// 如果是自动播放,标记为已上报
|
|
20259
20302
|
if (isAutoPlay) {
|
|
20260
20303
|
videoAutoPlayReported.current.add(videoId);
|
|
20304
|
+
console.log('[handleVideoPlay] 标记为已通过自动播放上报');
|
|
20261
20305
|
}
|
|
20262
20306
|
else {
|
|
20263
20307
|
// 如果不是自动播放,但已经通过自动播放上报过,则跳过
|
|
20264
20308
|
if (videoAutoPlayReported.current.has(videoId)) {
|
|
20309
|
+
console.log('[handleVideoPlay] 跳过上报:已经通过自动播放上报过');
|
|
20265
20310
|
// 只记录播放时间,不上报
|
|
20266
20311
|
videoStartTime.current[videoId] = videoRef.currentTime || 0;
|
|
20267
20312
|
return;
|
|
@@ -20274,6 +20319,14 @@ const StructurePage = (_a) => {
|
|
|
20274
20319
|
isFirstPlay.current[videoId] = false;
|
|
20275
20320
|
const videoDuration = videoRef.duration.toFixed(2);
|
|
20276
20321
|
const startTime = videoRef.currentTime.toFixed(2);
|
|
20322
|
+
console.log('[handleVideoPlay] 准备上报 playVideo 事件:', {
|
|
20323
|
+
videoId,
|
|
20324
|
+
isAutoPlay,
|
|
20325
|
+
playType,
|
|
20326
|
+
viewPosition,
|
|
20327
|
+
sectionIndex,
|
|
20328
|
+
duration: videoDuration
|
|
20329
|
+
});
|
|
20277
20330
|
bffEventReport === null || bffEventReport === void 0 ? void 0 : bffEventReport({
|
|
20278
20331
|
eventInfo: Object.assign({ eventSubject: 'playVideo', eventDescription: 'User played the video', sceneId: '', contentId: (videoData === null || videoData === void 0 ? void 0 : videoData.itemId) || '', contentName: (videoData === null || videoData === void 0 ? void 0 : videoData.title) || '', playType,
|
|
20279
20332
|
startTime,
|
|
@@ -20584,13 +20637,18 @@ const StructurePage = (_a) => {
|
|
|
20584
20637
|
// 2. propMultiCTAConfig 只是样式配置,不是数据源
|
|
20585
20638
|
// 3. 数据获取只应该在组件挂载时执行一次(除非 apiUrl/storyId 等关键参数变化)
|
|
20586
20639
|
// Hero Section 视频自动播放
|
|
20587
|
-
|
|
20588
|
-
|
|
20589
|
-
|
|
20590
|
-
|
|
20591
|
-
|
|
20592
|
-
|
|
20593
|
-
|
|
20640
|
+
// 注意:视频的自动播放逻辑由 PostView 组件处理(进入2/3可视区域并停留1秒后播放)
|
|
20641
|
+
// 移除了初始播放逻辑,避免与 PostView 冲突,确保视频加载完成后再播放
|
|
20642
|
+
// useEffect(() => {
|
|
20643
|
+
// if (heroVideoRef.current && data?.heroSection?.url) {
|
|
20644
|
+
// heroAutoPlayTrigger.current = true;
|
|
20645
|
+
// heroVideoRef.current.play().catch((err) => {
|
|
20646
|
+
// console.log('Video autoplay failed:', err);
|
|
20647
|
+
// heroAutoPlayTrigger.current = false;
|
|
20648
|
+
// });
|
|
20649
|
+
// setIsHeroVideoPaused(false);
|
|
20650
|
+
// }
|
|
20651
|
+
// }, [data?.heroSection]);
|
|
20594
20652
|
// 初始化 carousel 视频暂停状态
|
|
20595
20653
|
React.useEffect(() => {
|
|
20596
20654
|
if (data === null || data === void 0 ? void 0 : data.carouselSection) {
|
|
@@ -20635,7 +20693,7 @@ const StructurePage = (_a) => {
|
|
|
20635
20693
|
}, []);
|
|
20636
20694
|
// Post 图片/视频曝光上报(用于 Hero Section 等非轮播的 Post)
|
|
20637
20695
|
const postExposureReported = React.useRef(new Set());
|
|
20638
|
-
|
|
20696
|
+
React.useCallback((postData, viewPosition, sectionIndex) => {
|
|
20639
20697
|
var _a;
|
|
20640
20698
|
const postId = `${postData === null || postData === void 0 ? void 0 : postData.itemId}-${viewPosition}-${sectionIndex}`;
|
|
20641
20699
|
// 防止重复上报
|
|
@@ -20732,26 +20790,87 @@ const StructurePage = (_a) => {
|
|
|
20732
20790
|
// Carousel Section 的曝光检测 ref
|
|
20733
20791
|
const carouselSectionRef = React.useRef(null);
|
|
20734
20792
|
const hasCarouselReported = React.useRef(false);
|
|
20735
|
-
// Carousel Section
|
|
20793
|
+
// Carousel Section 进入可视区域时的回调
|
|
20794
|
+
const handleCarouselVisible = React.useCallback(() => {
|
|
20795
|
+
if (!(data === null || data === void 0 ? void 0 : data.carouselSection) || data.carouselSection.length === 0)
|
|
20796
|
+
return;
|
|
20797
|
+
const currentItem = data.carouselSection[carouselIndex];
|
|
20798
|
+
console.log('[Carousel onVisible] 当前索引:', carouselIndex, '是否是视频:', !!(currentItem === null || currentItem === void 0 ? void 0 : currentItem.url));
|
|
20799
|
+
// 只在首次进入可视区域时上报第一张图片
|
|
20800
|
+
if (!hasCarouselReported.current) {
|
|
20801
|
+
hasCarouselReported.current = true;
|
|
20802
|
+
// 只对图片类型上报(不包括视频)
|
|
20803
|
+
if (!currentItem.url) {
|
|
20804
|
+
handleCarouselImageStartEvent(carouselIndex);
|
|
20805
|
+
}
|
|
20806
|
+
}
|
|
20807
|
+
// 如果当前项是视频,自动播放
|
|
20808
|
+
if ((currentItem === null || currentItem === void 0 ? void 0 : currentItem.url) && carouselVideoRefs.current[carouselIndex]) {
|
|
20809
|
+
const currentVideo = carouselVideoRefs.current[carouselIndex];
|
|
20810
|
+
if (currentVideo) {
|
|
20811
|
+
console.log('[Carousel onVisible] 开始播放视频,索引:', carouselIndex);
|
|
20812
|
+
// 更新当前正在播放的视频索引
|
|
20813
|
+
currentPlayingCarouselIndex.current = carouselIndex;
|
|
20814
|
+
// 标记这次播放是自动触发的
|
|
20815
|
+
carouselAutoPlayTriggers.current[carouselIndex] = true;
|
|
20816
|
+
currentVideo.play().catch(err => {
|
|
20817
|
+
console.warn('[Carousel] Video autoplay failed (onVisible):', err);
|
|
20818
|
+
// 播放失败时重置标记
|
|
20819
|
+
carouselAutoPlayTriggers.current[carouselIndex] = false;
|
|
20820
|
+
});
|
|
20821
|
+
// 更新播放状态
|
|
20822
|
+
setCarouselVideoPausedStates(prev => {
|
|
20823
|
+
const newStates = [...prev];
|
|
20824
|
+
newStates[carouselIndex] = false;
|
|
20825
|
+
return newStates;
|
|
20826
|
+
});
|
|
20827
|
+
}
|
|
20828
|
+
}
|
|
20829
|
+
}, [data === null || data === void 0 ? void 0 : data.carouselSection, carouselIndex, handleCarouselImageStartEvent]);
|
|
20830
|
+
// Carousel Section 离开可视区域时的回调
|
|
20831
|
+
const handleCarouselHidden = React.useCallback(() => {
|
|
20832
|
+
// Carousel Section 离开可视区域时,暂停当前正在播放的视频
|
|
20833
|
+
// 使用 ref 来获取当前正在播放的视频索引,避免闭包问题
|
|
20834
|
+
const playingIndex = currentPlayingCarouselIndex.current;
|
|
20835
|
+
console.log('[Carousel onHidden] 被调用');
|
|
20836
|
+
console.log('[Carousel onHidden] 正在播放的视频索引:', playingIndex);
|
|
20837
|
+
console.log('[Carousel onHidden] carouselVideoRefs.current 长度:', carouselVideoRefs.current.length);
|
|
20838
|
+
console.log('[Carousel onHidden] carouselVideoRefs.current[playingIndex] 存在:', !!carouselVideoRefs.current[playingIndex]);
|
|
20839
|
+
if (playingIndex >= 0 && carouselVideoRefs.current[playingIndex]) {
|
|
20840
|
+
const currentVideo = carouselVideoRefs.current[playingIndex];
|
|
20841
|
+
if (currentVideo) {
|
|
20842
|
+
console.log('[Carousel onHidden] 准备暂停视频,索引:', playingIndex, '当前播放状态:', !currentVideo.paused);
|
|
20843
|
+
currentVideo.pause();
|
|
20844
|
+
console.log('[Carousel onHidden] 已调用 pause()');
|
|
20845
|
+
// 更新暂停状态
|
|
20846
|
+
setCarouselVideoPausedStates(prev => {
|
|
20847
|
+
const newStates = [...prev];
|
|
20848
|
+
newStates[playingIndex] = true;
|
|
20849
|
+
return newStates;
|
|
20850
|
+
});
|
|
20851
|
+
}
|
|
20852
|
+
else {
|
|
20853
|
+
console.log('[Carousel onHidden] currentVideo 为空');
|
|
20854
|
+
}
|
|
20855
|
+
}
|
|
20856
|
+
else {
|
|
20857
|
+
console.log('[Carousel onHidden] 条件不满足,不暂停视频');
|
|
20858
|
+
}
|
|
20859
|
+
}, []);
|
|
20860
|
+
// Carousel Section 进入可视区域时上报第一张图片的浏览事件,并自动播放视频
|
|
20736
20861
|
useAdvancedOnScreen(carouselSectionRef, {
|
|
20737
20862
|
threshold: 0.67,
|
|
20738
20863
|
delay: 1000,
|
|
20739
|
-
onVisible:
|
|
20740
|
-
|
|
20741
|
-
|
|
20742
|
-
hasCarouselReported.current = true;
|
|
20743
|
-
const currentItem = data.carouselSection[carouselIndex];
|
|
20744
|
-
// 只对图片类型上报(不包括视频)
|
|
20745
|
-
if (!currentItem.url) {
|
|
20746
|
-
handleCarouselImageStartEvent(carouselIndex);
|
|
20747
|
-
}
|
|
20748
|
-
}
|
|
20749
|
-
}
|
|
20864
|
+
onVisible: handleCarouselVisible,
|
|
20865
|
+
onHidden: handleCarouselHidden,
|
|
20866
|
+
name: 'Carousel'
|
|
20750
20867
|
});
|
|
20751
|
-
// Carousel
|
|
20868
|
+
// Carousel 切换时暂停其他视频
|
|
20869
|
+
// 注意:不再在切换时立即播放当前视频,而是由 PostView 组件处理(进入2/3可视区域并停留1秒后播放)
|
|
20752
20870
|
React.useEffect(() => {
|
|
20753
20871
|
if (!(data === null || data === void 0 ? void 0 : data.carouselSection) || data.carouselSection.length === 0)
|
|
20754
20872
|
return;
|
|
20873
|
+
console.log('[Carousel useEffect] 切换到索引:', carouselIndex);
|
|
20755
20874
|
// 暂停所有其他视频
|
|
20756
20875
|
carouselVideoRefs.current.forEach((videoRef, index) => {
|
|
20757
20876
|
if (videoRef && index !== carouselIndex) {
|
|
@@ -20764,22 +20883,6 @@ const StructurePage = (_a) => {
|
|
|
20764
20883
|
});
|
|
20765
20884
|
}
|
|
20766
20885
|
});
|
|
20767
|
-
// 如果当前项是视频,自动播放
|
|
20768
|
-
const currentItem = data.carouselSection[carouselIndex];
|
|
20769
|
-
if ((currentItem === null || currentItem === void 0 ? void 0 : currentItem.url) && carouselVideoRefs.current[carouselIndex]) {
|
|
20770
|
-
const currentVideo = carouselVideoRefs.current[carouselIndex];
|
|
20771
|
-
if (currentVideo) {
|
|
20772
|
-
currentVideo.play().catch(err => {
|
|
20773
|
-
console.warn('[Carousel] Video autoplay failed:', err);
|
|
20774
|
-
});
|
|
20775
|
-
// 更新播放状态
|
|
20776
|
-
setCarouselVideoPausedStates(prev => {
|
|
20777
|
-
const newStates = [...prev];
|
|
20778
|
-
newStates[carouselIndex] = false;
|
|
20779
|
-
return newStates;
|
|
20780
|
-
});
|
|
20781
|
-
}
|
|
20782
|
-
}
|
|
20783
20886
|
}, [carouselIndex, data]);
|
|
20784
20887
|
// 触摸滑动处理
|
|
20785
20888
|
const handleTouchStart = (e) => {
|
|
@@ -20904,15 +21007,7 @@ const StructurePage = (_a) => {
|
|
|
20904
21007
|
return textStyle;
|
|
20905
21008
|
})()) }, data.heroSection.text))),
|
|
20906
21009
|
React.createElement("div", { style: baseStyles.heroImageContainer },
|
|
20907
|
-
React.createElement(PostView, { videoRef: heroVideoRef, isVideo: !!data.heroSection.url,
|
|
20908
|
-
// 图片或视频的曝光上报
|
|
20909
|
-
handlePostExposure(data.heroSection, 'heroSection', 0);
|
|
20910
|
-
}, onVideoAutoPlay: () => {
|
|
20911
|
-
// 视频自动播放时上报 playVideo 事件(2/3区域 + 300ms后)
|
|
20912
|
-
if (heroVideoRef.current) {
|
|
20913
|
-
handleVideoPlay(data.heroSection, 'heroSection', 0, heroVideoRef.current, true);
|
|
20914
|
-
}
|
|
20915
|
-
} }, data.heroSection.url ? (React.createElement("div", { style: { position: 'relative', width: '100%', height: '100%' }, onClick: handleHeroVideoClick },
|
|
21010
|
+
React.createElement(PostView, { videoRef: heroVideoRef, isVideo: !!data.heroSection.url, autoPlayTriggerRef: heroAutoPlayTrigger }, data.heroSection.url ? (React.createElement("div", { style: { position: 'relative', width: '100%', height: '100%' }, onClick: handleHeroVideoClick },
|
|
20916
21011
|
React.createElement("video", { ref: heroVideoRef, src: data.heroSection.url, style: baseStyles.heroVideo, muted: true, loop: true, playsInline: true, controls: false, onLoadedMetadata: () => {
|
|
20917
21012
|
var _a;
|
|
20918
21013
|
const videoId = `${(_a = data.heroSection) === null || _a === void 0 ? void 0 : _a.itemId}-heroSection-0`;
|
|
@@ -20920,6 +21015,7 @@ const StructurePage = (_a) => {
|
|
|
20920
21015
|
const initTime = videoLoadTime.current[videoId] || loadTime;
|
|
20921
21016
|
videoLoadTime.current[videoId] = loadTime - initTime;
|
|
20922
21017
|
}, onPlay: (e) => {
|
|
21018
|
+
// 视频真正开始播放时才上报(考虑网速问题)
|
|
20923
21019
|
handleVideoPlay(data.heroSection, 'heroSection', 0, e.currentTarget);
|
|
20924
21020
|
}, onPause: (e) => {
|
|
20925
21021
|
handleVideoPlayOver(data.heroSection, 'heroSection', 0, e.currentTarget);
|
|
@@ -20932,7 +21028,52 @@ const StructurePage = (_a) => {
|
|
|
20932
21028
|
React.createElement("div", { style: baseStyles.carouselImageContainer, onTouchStart: handleTouchStart, onTouchMove: handleTouchMove, onTouchEnd: handleTouchEnd },
|
|
20933
21029
|
React.createElement("div", { style: Object.assign(Object.assign({}, baseStyles.carouselContainer), { transform: `translateX(-${carouselIndex * 100}%)` }) }, data.carouselSection.map((item, index) => {
|
|
20934
21030
|
var _a;
|
|
20935
|
-
|
|
21031
|
+
// 只有当前显示的 slide 才应用曝光检测
|
|
21032
|
+
const isCurrentSlide = index === carouselIndex;
|
|
21033
|
+
return (React.createElement("div", { key: item.itemId, style: baseStyles.carouselSlide }, item.url ? (
|
|
21034
|
+
// 视频:使用 PostView 包裹,但只在当前显示时生效
|
|
21035
|
+
isCurrentSlide ? (React.createElement(PostView, { videoRef: { current: carouselVideoRefs.current[index] }, isVideo: true, autoPlayTriggerRef: {
|
|
21036
|
+
get current() {
|
|
21037
|
+
return carouselAutoPlayTriggers.current[index] || false;
|
|
21038
|
+
},
|
|
21039
|
+
set current(value) {
|
|
21040
|
+
carouselAutoPlayTriggers.current[index] = value;
|
|
21041
|
+
}
|
|
21042
|
+
}, onVideoPlay: () => {
|
|
21043
|
+
// 视频开始播放,隐藏暂停图标
|
|
21044
|
+
console.log('[Carousel PostView] onVideoPlay 回调,索引:', index);
|
|
21045
|
+
setCarouselVideoPausedStates(prev => {
|
|
21046
|
+
const newStates = [...prev];
|
|
21047
|
+
newStates[index] = false;
|
|
21048
|
+
return newStates;
|
|
21049
|
+
});
|
|
21050
|
+
}, onVideoPause: () => {
|
|
21051
|
+
// 视频暂停,显示暂停图标
|
|
21052
|
+
console.log('[Carousel PostView] onVideoPause 回调,索引:', index);
|
|
21053
|
+
setCarouselVideoPausedStates(prev => {
|
|
21054
|
+
const newStates = [...prev];
|
|
21055
|
+
newStates[index] = true;
|
|
21056
|
+
return newStates;
|
|
21057
|
+
});
|
|
21058
|
+
} },
|
|
21059
|
+
React.createElement("div", { style: { position: 'relative', width: '100%', height: '100%' }, onClick: () => handleCarouselVideoClick(index) },
|
|
21060
|
+
React.createElement("video", { ref: (el) => {
|
|
21061
|
+
carouselVideoRefs.current[index] = el;
|
|
21062
|
+
}, src: item.url, style: baseStyles.carouselVideo, muted: true, loop: true, playsInline: true, controls: false, draggable: false, onDragStart: (e) => e.preventDefault(), onLoadedMetadata: () => {
|
|
21063
|
+
const videoId = `${item.itemId}-carouselSection-${index}`;
|
|
21064
|
+
const loadTime = Date.now();
|
|
21065
|
+
const initTime = videoLoadTime.current[videoId] || loadTime;
|
|
21066
|
+
videoLoadTime.current[videoId] = loadTime - initTime;
|
|
21067
|
+
}, onPlay: (e) => {
|
|
21068
|
+
handleVideoPlay(item, 'carouselSection', index, e.currentTarget);
|
|
21069
|
+
}, onPause: (e) => {
|
|
21070
|
+
handleVideoPlayOver(item, 'carouselSection', index, e.currentTarget);
|
|
21071
|
+
}, onEnded: (e) => {
|
|
21072
|
+
handleVideoPlayOver(item, 'carouselSection', index, e.currentTarget);
|
|
21073
|
+
} }),
|
|
21074
|
+
carouselVideoPausedStates[index] && (React.createElement(FormatImage$1, { className: 'clc-pb-video-pause', src: videoPlayIcon, alt: 'play' }))))) : (
|
|
21075
|
+
// 非当前 slide,不使用 PostView
|
|
21076
|
+
React.createElement("div", { style: { position: 'relative', width: '100%', height: '100%' }, onClick: () => handleCarouselVideoClick(index) },
|
|
20936
21077
|
React.createElement("video", { ref: (el) => {
|
|
20937
21078
|
carouselVideoRefs.current[index] = el;
|
|
20938
21079
|
}, src: item.url, style: baseStyles.carouselVideo, muted: true, loop: true, playsInline: true, controls: false, draggable: false, onDragStart: (e) => e.preventDefault(), onLoadedMetadata: () => {
|
|
@@ -20947,7 +21088,7 @@ const StructurePage = (_a) => {
|
|
|
20947
21088
|
}, onEnded: (e) => {
|
|
20948
21089
|
handleVideoPlayOver(item, 'carouselSection', index, e.currentTarget);
|
|
20949
21090
|
} }),
|
|
20950
|
-
carouselVideoPausedStates[index] && (React.createElement(FormatImage$1, { className: 'clc-pb-video-pause', src: videoPlayIcon, alt: 'play' })))) : ((_a = item.imgUrls) === null || _a === void 0 ? void 0 : _a[0]) ? (React.createElement("img", { src: item.imgUrls[0], alt: item.text || 'Carousel', style: baseStyles.carouselImage, draggable: false, onDragStart: (e) => e.preventDefault(), onLoad: () => {
|
|
21091
|
+
carouselVideoPausedStates[index] && (React.createElement(FormatImage$1, { className: 'clc-pb-video-pause', src: videoPlayIcon, alt: 'play' }))))) : ((_a = item.imgUrls) === null || _a === void 0 ? void 0 : _a[0]) ? (React.createElement("img", { src: item.imgUrls[0], alt: item.text || 'Carousel', style: baseStyles.carouselImage, draggable: false, onDragStart: (e) => e.preventDefault(), onLoad: () => {
|
|
20951
21092
|
// 记录图片加载完成时间
|
|
20952
21093
|
if (!carouselImageLoadTime.current[index]) {
|
|
20953
21094
|
carouselImageLoadTime.current[index] = Date.now();
|