pb-sxp-ui 1.20.60 → 1.20.62
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 +215 -216
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +215 -216
- 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 +215 -216
- package/dist/pb-ui.js.map +1 -1
- package/dist/pb-ui.min.js +7 -7
- package/dist/pb-ui.min.js.map +1 -1
- package/es/core/components/StructurePage/index.js +138 -161
- package/es/core/hooks/useAdvancedOnScreen.d.ts +2 -1
- package/es/core/hooks/useAdvancedOnScreen.js +2 -2
- package/es/materials/sxp/popup/CommodityDetail/index.js +14 -13
- package/es/materials/sxp/popup/CommodityDetailDiroNew/index.js +24 -24
- package/lib/core/components/StructurePage/index.js +138 -161
- package/lib/core/hooks/useAdvancedOnScreen.d.ts +2 -1
- package/lib/core/hooks/useAdvancedOnScreen.js +2 -2
- package/lib/materials/sxp/popup/CommodityDetail/index.js +14 -13
- package/lib/materials/sxp/popup/CommodityDetailDiroNew/index.js +24 -24
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -2318,7 +2318,7 @@ function useEventReport() {
|
|
|
2318
2318
|
* @returns { isVisible, reset } isVisible 是否可见;reset 重置可见状态(用于页面从后台恢复时重新触发检测)
|
|
2319
2319
|
*/
|
|
2320
2320
|
function useAdvancedOnScreen(ref, options = {}) {
|
|
2321
|
-
const { threshold = 0, delay = 0, onVisible, onHidden, name = 'unknown' } = options;
|
|
2321
|
+
const { threshold = 0, delay = 0, onVisible, onHidden, name = 'unknown', deps = [] } = options;
|
|
2322
2322
|
const observerRef = React.useRef(null);
|
|
2323
2323
|
const [isVisible, setIsVisible] = React.useState(false);
|
|
2324
2324
|
const timerRef = React.useRef(null);
|
|
@@ -2408,7 +2408,8 @@ function useAdvancedOnScreen(ref, options = {}) {
|
|
|
2408
2408
|
observerRef.current.disconnect();
|
|
2409
2409
|
}
|
|
2410
2410
|
};
|
|
2411
|
-
|
|
2411
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
2412
|
+
}, [ref, threshold, delay, name, ...deps]);
|
|
2412
2413
|
/**
|
|
2413
2414
|
* 仅重置内部可见状态为"不可见",不重新触发 Observer 回调。
|
|
2414
2415
|
* 用于页面从后台恢复时,让 Observer 能重新感知后续的离开事件。
|
|
@@ -11299,7 +11300,7 @@ const getPriceText = ({ product, enableFormattedPrice, globalConfig, isHiddenDef
|
|
|
11299
11300
|
};
|
|
11300
11301
|
|
|
11301
11302
|
const CommodityDetail$1 = (_a) => {
|
|
11302
|
-
var _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _0;
|
|
11303
|
+
var _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _0, _1, _2, _3;
|
|
11303
11304
|
var { content, style, bgImg, onClick, schema, isDefault, bottom_image, tipText, isPost, viewTime, rec, swiper, commodityStyles, buttonStyle, index, commodityGroup, popupBg, iframeIcon, commodityImgRatio, isTel, iframeBgColor, isActive = true, enableAddToCart = false, addToCartPopupId = '' } = _a, props = __rest(_a, ["content", "style", "bgImg", "onClick", "schema", "isDefault", "bottom_image", "tipText", "isPost", "viewTime", "rec", "swiper", "commodityStyles", "buttonStyle", "index", "commodityGroup", "popupBg", "iframeIcon", "commodityImgRatio", "isTel", "iframeBgColor", "isActive", "enableAddToCart", "addToCartPopupId"]);
|
|
11304
11305
|
console.log('[CommodityDetail] 组件已加载 - 版本 v1.20.23', { enableAddToCart, addToCartPopupId, isPost });
|
|
11305
11306
|
const { sxpParameter, popupDetailData, isPreview, bffFbReport, popupCurTimeRef, checkCommodityIndexRef, globalConfig, ctaEvent, setPopupDetailData } = useSxpDataSource();
|
|
@@ -11311,14 +11312,14 @@ const CommodityDetail$1 = (_a) => {
|
|
|
11311
11312
|
const swiperRef = React.useRef();
|
|
11312
11313
|
const [swiperActiveIndex, setSwiperActiveIndex] = React.useState(0);
|
|
11313
11314
|
const data = isPost ? rec : popupDetailData;
|
|
11314
|
-
let product = isPost ? data === null || data === void 0 ? void 0 : data.product : (_d = (_c = data === null || data === void 0 ? void 0 : data.video) === null || _c === void 0 ? void 0 : _c.bindProduct) !== null && _d !== void 0 ? _d : (_f = (_e = data === null || data === void 0 ? void 0 : data.video) === null || _e === void 0 ? void 0 : _e.bindProducts) === null || _f === void 0 ? void 0 : _f[0];
|
|
11315
|
+
let product = isPost ? data === null || data === void 0 ? void 0 : data.product : (_g = (_d = (_c = data === null || data === void 0 ? void 0 : data.video) === null || _c === void 0 ? void 0 : _c.bindProduct) !== null && _d !== void 0 ? _d : (_f = (_e = data === null || data === void 0 ? void 0 : data.video) === null || _e === void 0 ? void 0 : _e.bindProducts) === null || _f === void 0 ? void 0 : _f[0]) !== null && _g !== void 0 ? _g : data === null || data === void 0 ? void 0 : data.product;
|
|
11315
11316
|
let cta = isPost
|
|
11316
|
-
? (
|
|
11317
|
-
: (
|
|
11317
|
+
? (_h = data === null || data === void 0 ? void 0 : data.product) === null || _h === void 0 ? void 0 : _h.bindCta
|
|
11318
|
+
: (_q = (_l = (_k = (_j = data === null || data === void 0 ? void 0 : data.video) === null || _j === void 0 ? void 0 : _j.bindProduct) === null || _k === void 0 ? void 0 : _k.bindCta) !== null && _l !== void 0 ? _l : (_p = (_o = (_m = data === null || data === void 0 ? void 0 : data.video) === null || _m === void 0 ? void 0 : _m.bindProducts) === null || _o === void 0 ? void 0 : _o[0]) === null || _p === void 0 ? void 0 : _p.bindCta) !== null && _q !== void 0 ? _q : (_r = data === null || data === void 0 ? void 0 : data.product) === null || _r === void 0 ? void 0 : _r.bindCta;
|
|
11318
11319
|
const position = isPost ? index : 0;
|
|
11319
|
-
if (!isPost && (commodityGroup === null || commodityGroup === void 0 ? void 0 : commodityGroup.open) && ((
|
|
11320
|
+
if (!isPost && (commodityGroup === null || commodityGroup === void 0 ? void 0 : commodityGroup.open) && ((_s = data === null || data === void 0 ? void 0 : data.video) === null || _s === void 0 ? void 0 : _s.bindProducts) && ((_u = (_t = data === null || data === void 0 ? void 0 : data.video) === null || _t === void 0 ? void 0 : _t.bindProducts) === null || _u === void 0 ? void 0 : _u.length) > 0) {
|
|
11320
11321
|
checkCommodityIndexRef.current = checkCommodityIndex;
|
|
11321
|
-
const p = (
|
|
11322
|
+
const p = (_v = data === null || data === void 0 ? void 0 : data.video) === null || _v === void 0 ? void 0 : _v.bindProducts[checkCommodityIndex];
|
|
11322
11323
|
product = p;
|
|
11323
11324
|
cta = p === null || p === void 0 ? void 0 : p.bindCta;
|
|
11324
11325
|
}
|
|
@@ -11382,6 +11383,8 @@ const CommodityDetail$1 = (_a) => {
|
|
|
11382
11383
|
target_content_id: product === null || product === void 0 ? void 0 : product.itemId,
|
|
11383
11384
|
target_url: product.link
|
|
11384
11385
|
});
|
|
11386
|
+
// feed 流 post 跳转外链时也需要上报 productView
|
|
11387
|
+
productView(data, product, cta, viewTime || curTimeRef.current, position);
|
|
11385
11388
|
}
|
|
11386
11389
|
window.location.href = window.getJointUtmLink(product.link);
|
|
11387
11390
|
}
|
|
@@ -11463,11 +11466,11 @@ const CommodityDetail$1 = (_a) => {
|
|
|
11463
11466
|
}, []);
|
|
11464
11467
|
const priceText = getPriceText({
|
|
11465
11468
|
product,
|
|
11466
|
-
enableFormattedPrice: (
|
|
11469
|
+
enableFormattedPrice: (_w = commodityStyles === null || commodityStyles === void 0 ? void 0 : commodityStyles.price) === null || _w === void 0 ? void 0 : _w.enableFormattedPrice,
|
|
11467
11470
|
globalConfig,
|
|
11468
11471
|
style: commodityStyles === null || commodityStyles === void 0 ? void 0 : commodityStyles.price
|
|
11469
11472
|
});
|
|
11470
|
-
const width = (isPreview ? 375 : (
|
|
11473
|
+
const width = (isPreview ? 375 : (_x = style === null || style === void 0 ? void 0 : style.width) !== null && _x !== void 0 ? _x : window.innerWidth) - ((_y = popupBg === null || popupBg === void 0 ? void 0 : popupBg.horizontalMargin) !== null && _y !== void 0 ? _y : 0) * 2;
|
|
11471
11474
|
const height = commodityImgRatio ? width * (commodityImgRatio.h / commodityImgRatio.w) : width;
|
|
11472
11475
|
const renderContent = ({ isPost }) => {
|
|
11473
11476
|
var _a, _b, _c, _d;
|
|
@@ -11567,7 +11570,7 @@ const CommodityDetail$1 = (_a) => {
|
|
|
11567
11570
|
return (React.createElement(React.Fragment, null,
|
|
11568
11571
|
React.createElement("div", Object.assign({ className: css.css(Object.assign(Object.assign({}, style), { position: 'relative' })) }, props),
|
|
11569
11572
|
React.createElement("div", { style: { position: 'relative' }, onMouseEnter: handleMouseEnter, onMouseLeave: handleMouseLeave },
|
|
11570
|
-
product && ((
|
|
11573
|
+
product && ((_z = product === null || product === void 0 ? void 0 : product.homePage) === null || _z === void 0 ? void 0 : _z.length) > 0 && (React.createElement(Swiper, Object.assign({ height: height, modules: [Pagination, Autoplay, ...(isAlly ? [Navigation, A11y, Mousewheel, Keyboard] : [])], pagination: {
|
|
11571
11574
|
clickable: true,
|
|
11572
11575
|
bulletActiveClass: 'swipe-item-active-bullet',
|
|
11573
11576
|
clickableClass: getDotsAlign,
|
|
@@ -11583,7 +11586,7 @@ const CommodityDetail$1 = (_a) => {
|
|
|
11583
11586
|
}
|
|
11584
11587
|
: {}), { loop: true, autoplay: {
|
|
11585
11588
|
delay: (swiper === null || swiper === void 0 ? void 0 : swiper.delay) * 1000
|
|
11586
|
-
}, ref: swiperRef, onSlideChange: handleSlideChange, className: css.css(Object.assign(Object.assign({ '.swiper-pagination': { bottom: (
|
|
11589
|
+
}, ref: swiperRef, onSlideChange: handleSlideChange, className: css.css(Object.assign(Object.assign({ '.swiper-pagination': { bottom: (_0 = swiper === null || swiper === void 0 ? void 0 : swiper.dotsMarginBottom) !== null && _0 !== void 0 ? _0 : 0, fontSize: '14px' } }, ((swiper === null || swiper === void 0 ? void 0 : swiper.dotsBgColor) && {
|
|
11587
11590
|
'.swiper-pagination-bullet': {
|
|
11588
11591
|
backgroundColor: swiper === null || swiper === void 0 ? void 0 : swiper.dotsBgColor,
|
|
11589
11592
|
opacity: 1
|
|
@@ -11594,7 +11597,7 @@ const CommodityDetail$1 = (_a) => {
|
|
|
11594
11597
|
opacity: 1
|
|
11595
11598
|
}
|
|
11596
11599
|
}))) }),
|
|
11597
|
-
React.createElement(React.Fragment, null, (
|
|
11600
|
+
React.createElement(React.Fragment, null, (_1 = product === null || product === void 0 ? void 0 : product.homePage) === null || _1 === void 0 ? void 0 : _1.map((src, srcKey) => {
|
|
11598
11601
|
var _a;
|
|
11599
11602
|
return (React.createElement(SwiperSlide, { key: srcKey, "aria-hidden": srcKey !== swiperActiveIndex },
|
|
11600
11603
|
React.createElement("div", { style: {
|
|
@@ -11610,7 +11613,7 @@ const CommodityDetail$1 = (_a) => {
|
|
|
11610
11613
|
objectPosition: `50% ${(swiper === null || swiper === void 0 ? void 0 : swiper.translateY) ? (swiper === null || swiper === void 0 ? void 0 : swiper.translateY) + 50 : 50}%`
|
|
11611
11614
|
}, src: (_a = src !== null && src !== void 0 ? src : sxpParameter === null || sxpParameter === void 0 ? void 0 : sxpParameter.bottom_image) !== null && _a !== void 0 ? _a : bottom_image }))));
|
|
11612
11615
|
})))),
|
|
11613
|
-
!((
|
|
11616
|
+
!((_2 = product === null || product === void 0 ? void 0 : product.homePage) === null || _2 === void 0 ? void 0 : _2.length) && (React.createElement("div", { className: css.css({
|
|
11614
11617
|
height,
|
|
11615
11618
|
width
|
|
11616
11619
|
}) },
|
|
@@ -11618,7 +11621,7 @@ const CommodityDetail$1 = (_a) => {
|
|
|
11618
11621
|
objectFit: 'cover',
|
|
11619
11622
|
width: '100%',
|
|
11620
11623
|
height: '100%'
|
|
11621
|
-
}), src: (
|
|
11624
|
+
}), src: (_3 = sxpParameter === null || sxpParameter === void 0 ? void 0 : sxpParameter.bottom_image) !== null && _3 !== void 0 ? _3 : bottom_image, alt: 'pdp image' }))),
|
|
11622
11625
|
(iframeUrl || !product) && iframeIcon && (React.createElement("div", { style: {
|
|
11623
11626
|
display: 'flex',
|
|
11624
11627
|
alignItems: 'center',
|
|
@@ -12685,7 +12688,7 @@ const AddToCartPopup$1 = ({ isActive = true }) => {
|
|
|
12685
12688
|
};
|
|
12686
12689
|
|
|
12687
12690
|
const CommodityDetailDiroNew$1 = (_a) => {
|
|
12688
|
-
var _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _0, _1, _2, _3, _4, _5;
|
|
12691
|
+
var _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _0, _1, _2, _3, _4, _5, _6, _7, _8;
|
|
12689
12692
|
var { style, rec, viewTime, isPost, bottom_image, tipText, swiper, commodityStyles, buttonStyle, index, commodityGroup, popupBg, iframeIcon, commodityImgRatio, iframeBgColor, isActive = true } = _a, props = __rest(_a, ["style", "rec", "viewTime", "isPost", "bottom_image", "tipText", "swiper", "commodityStyles", "buttonStyle", "index", "commodityGroup", "popupBg", "iframeIcon", "commodityImgRatio", "iframeBgColor", "isActive"]);
|
|
12690
12693
|
const { sxpParameter, popupCurTimeRef, popupDetailData, setPopupDetailData, isPreview, bffFbReport, checkCommodityIndexRef, globalConfig, ctaEvent } = useSxpDataSource();
|
|
12691
12694
|
useEditor();
|
|
@@ -12698,14 +12701,14 @@ const CommodityDetailDiroNew$1 = (_a) => {
|
|
|
12698
12701
|
const swiperRef = React.useRef();
|
|
12699
12702
|
const [swiperActiveIndex, setSwiperActiveIndex] = React.useState(0);
|
|
12700
12703
|
const data = isPost ? rec : popupDetailData;
|
|
12701
|
-
let product = isPost ? data === null || data === void 0 ? void 0 : data.product : (_d = (_c = data === null || data === void 0 ? void 0 : data.video) === null || _c === void 0 ? void 0 : _c.bindProduct) !== null && _d !== void 0 ? _d : (_f = (_e = data === null || data === void 0 ? void 0 : data.video) === null || _e === void 0 ? void 0 : _e.bindProducts) === null || _f === void 0 ? void 0 : _f[0];
|
|
12704
|
+
let product = isPost ? data === null || data === void 0 ? void 0 : data.product : (_g = (_d = (_c = data === null || data === void 0 ? void 0 : data.video) === null || _c === void 0 ? void 0 : _c.bindProduct) !== null && _d !== void 0 ? _d : (_f = (_e = data === null || data === void 0 ? void 0 : data.video) === null || _e === void 0 ? void 0 : _e.bindProducts) === null || _f === void 0 ? void 0 : _f[0]) !== null && _g !== void 0 ? _g : data === null || data === void 0 ? void 0 : data.product;
|
|
12702
12705
|
let cta = isPost
|
|
12703
|
-
? (
|
|
12704
|
-
: (
|
|
12706
|
+
? (_h = data === null || data === void 0 ? void 0 : data.product) === null || _h === void 0 ? void 0 : _h.bindCta
|
|
12707
|
+
: (_q = (_l = (_k = (_j = data === null || data === void 0 ? void 0 : data.video) === null || _j === void 0 ? void 0 : _j.bindProduct) === null || _k === void 0 ? void 0 : _k.bindCta) !== null && _l !== void 0 ? _l : (_p = (_o = (_m = data === null || data === void 0 ? void 0 : data.video) === null || _m === void 0 ? void 0 : _m.bindProducts) === null || _o === void 0 ? void 0 : _o[0]) === null || _p === void 0 ? void 0 : _p.bindCta) !== null && _q !== void 0 ? _q : (_r = data === null || data === void 0 ? void 0 : data.product) === null || _r === void 0 ? void 0 : _r.bindCta;
|
|
12705
12708
|
const position = isPost ? index : 0;
|
|
12706
|
-
if (!isPost && (commodityGroup === null || commodityGroup === void 0 ? void 0 : commodityGroup.open) && ((
|
|
12709
|
+
if (!isPost && (commodityGroup === null || commodityGroup === void 0 ? void 0 : commodityGroup.open) && ((_s = data === null || data === void 0 ? void 0 : data.video) === null || _s === void 0 ? void 0 : _s.bindProducts) && ((_u = (_t = data === null || data === void 0 ? void 0 : data.video) === null || _t === void 0 ? void 0 : _t.bindProducts) === null || _u === void 0 ? void 0 : _u.length) > 0) {
|
|
12707
12710
|
checkCommodityIndexRef.current = checkCommodityIndex;
|
|
12708
|
-
const p = (
|
|
12711
|
+
const p = (_v = data === null || data === void 0 ? void 0 : data.video) === null || _v === void 0 ? void 0 : _v.bindProducts[checkCommodityIndex];
|
|
12709
12712
|
product = p;
|
|
12710
12713
|
cta = p === null || p === void 0 ? void 0 : p.bindCta;
|
|
12711
12714
|
}
|
|
@@ -12730,9 +12733,8 @@ const CommodityDetailDiroNew$1 = (_a) => {
|
|
|
12730
12733
|
target_content_id: product === null || product === void 0 ? void 0 : product.itemId,
|
|
12731
12734
|
target_url: product === null || product === void 0 ? void 0 : product.link
|
|
12732
12735
|
});
|
|
12733
|
-
|
|
12734
|
-
|
|
12735
|
-
}
|
|
12736
|
+
// 跳转外链时无论 isPost 是否为 true 都需要上报 productView
|
|
12737
|
+
productView(data, product, cta, viewTime || curTimeRef.current, position);
|
|
12736
12738
|
// 跳转到商品链接
|
|
12737
12739
|
if (product === null || product === void 0 ? void 0 : product.link) {
|
|
12738
12740
|
window.location.href = window.getJointUtmLink(product.link);
|
|
@@ -12755,9 +12757,13 @@ const CommodityDetailDiroNew$1 = (_a) => {
|
|
|
12755
12757
|
target_content_id: product === null || product === void 0 ? void 0 : product.itemId,
|
|
12756
12758
|
target_url: product === null || product === void 0 ? void 0 : product.link
|
|
12757
12759
|
});
|
|
12758
|
-
|
|
12759
|
-
|
|
12760
|
-
|
|
12760
|
+
// 打开加购弹窗时无论 isPost 是否为 true 都需要上报 productView
|
|
12761
|
+
productView(data, product, cta, viewTime || curTimeRef.current, position);
|
|
12762
|
+
// 上报 clickShopifyPopup 事件(打开购物车弹窗时上报,无论是 feed 流 post 还是商品详情弹窗内)
|
|
12763
|
+
ctaEvent === null || ctaEvent === void 0 ? void 0 : ctaEvent({
|
|
12764
|
+
eventSubject: 'clickShopifyPopup',
|
|
12765
|
+
eventDescription: 'User clicked to open Shopify popup'
|
|
12766
|
+
}, data, product, position);
|
|
12761
12767
|
// 更新 popupDetailData,确保 AddToCart 组件能获取到商品数据
|
|
12762
12768
|
setPopupDetailData === null || setPopupDetailData === void 0 ? void 0 : setPopupDetailData(Object.assign(Object.assign({}, data), { video: Object.assign(Object.assign({}, data === null || data === void 0 ? void 0 : data.video), { bindProduct: product }), index: position }));
|
|
12763
12769
|
// 打开 AddToCart 弹窗
|
|
@@ -12834,11 +12840,11 @@ const CommodityDetailDiroNew$1 = (_a) => {
|
|
|
12834
12840
|
}, [isActive]);
|
|
12835
12841
|
const priceText = getPriceText({
|
|
12836
12842
|
product,
|
|
12837
|
-
enableFormattedPrice: (
|
|
12843
|
+
enableFormattedPrice: (_w = commodityStyles === null || commodityStyles === void 0 ? void 0 : commodityStyles.price) === null || _w === void 0 ? void 0 : _w.enableFormattedPrice,
|
|
12838
12844
|
globalConfig,
|
|
12839
12845
|
style: commodityStyles === null || commodityStyles === void 0 ? void 0 : commodityStyles.price
|
|
12840
12846
|
});
|
|
12841
|
-
const width = (isPreview ? 375 : (
|
|
12847
|
+
const width = (isPreview ? 375 : (_x = style === null || style === void 0 ? void 0 : style.width) !== null && _x !== void 0 ? _x : window.innerWidth) - ((_y = popupBg === null || popupBg === void 0 ? void 0 : popupBg.horizontalMargin) !== null && _y !== void 0 ? _y : 0) * 2;
|
|
12842
12848
|
const height = commodityImgRatio ? width * (commodityImgRatio.h / commodityImgRatio.w) : width;
|
|
12843
12849
|
// useEffect(() => {
|
|
12844
12850
|
// console.log(scrollRef?.current?.scrollHeight, window.innerHeight);
|
|
@@ -12916,7 +12922,7 @@ Made in Italy` })));
|
|
|
12916
12922
|
if (isPost)
|
|
12917
12923
|
return;
|
|
12918
12924
|
return (React.createElement(CommodityGroup$1, { products: (_a = data === null || data === void 0 ? void 0 : data.video) === null || _a === void 0 ? void 0 : _a.bindProducts, data: commodityGroup, defImg: (_c = (_b = sxpParameter === null || sxpParameter === void 0 ? void 0 : sxpParameter.bottom_image) !== null && _b !== void 0 ? _b : bottom_image) !== null && _c !== void 0 ? _c : '', style: { padding: '0 19px' }, onCLick: handleClick, popupDetailData: popupDetailData, check: checkCommodityIndex }));
|
|
12919
|
-
}, [checkCommodityIndex, isPost, (
|
|
12925
|
+
}, [checkCommodityIndex, isPost, (_z = data === null || data === void 0 ? void 0 : data.video) === null || _z === void 0 ? void 0 : _z.bindProducts, commodityGroup, sxpParameter === null || sxpParameter === void 0 ? void 0 : sxpParameter.bottom_image, bottom_image, handleClick, popupDetailData]);
|
|
12920
12926
|
const getDotsAlign = React.useMemo(() => {
|
|
12921
12927
|
const dotsAlignClass = {
|
|
12922
12928
|
left: 'commondityDetail-swiper-clickable-left',
|
|
@@ -12943,7 +12949,7 @@ Made in Italy` })));
|
|
|
12943
12949
|
return (React.createElement("div", { className: 'pb-commondityDiroNew' },
|
|
12944
12950
|
React.createElement("div", Object.assign({ className: css.css(Object.assign(Object.assign({}, style), { transform: 'translate3d(0px, 0px, 0px)' })) }, props),
|
|
12945
12951
|
React.createElement("div", { style: { position: 'relative' }, onMouseEnter: handleMouseEnter, onMouseLeave: handleMouseLeave },
|
|
12946
|
-
product && ((
|
|
12952
|
+
product && ((_0 = product === null || product === void 0 ? void 0 : product.homePage) === null || _0 === void 0 ? void 0 : _0.length) > 0 && (React.createElement(Swiper, Object.assign({ height: height, modules: [Pagination, Autoplay, ...(isAlly ? [Navigation, A11y, Mousewheel, Keyboard] : [])], pagination: {
|
|
12947
12953
|
clickable: true,
|
|
12948
12954
|
bulletActiveClass: 'swipe-item-active-bullet',
|
|
12949
12955
|
clickableClass: getDotsAlign,
|
|
@@ -12960,7 +12966,7 @@ Made in Italy` })));
|
|
|
12960
12966
|
: {}), { loop: true, ref: swiperRef, onSlideChange: handleSlideChange, autoplay: {
|
|
12961
12967
|
delay: (swiper === null || swiper === void 0 ? void 0 : swiper.delay) * 1000
|
|
12962
12968
|
}, className: css.css(Object.assign(Object.assign({ '.swiper-pagination': {
|
|
12963
|
-
bottom: (
|
|
12969
|
+
bottom: (_1 = swiper === null || swiper === void 0 ? void 0 : swiper.dotsMarginBottom) !== null && _1 !== void 0 ? _1 : 0,
|
|
12964
12970
|
fontSize: '14px'
|
|
12965
12971
|
} }, ((swiper === null || swiper === void 0 ? void 0 : swiper.dotsBgColor) && {
|
|
12966
12972
|
'.swiper-pagination-bullet': {
|
|
@@ -12972,7 +12978,7 @@ Made in Italy` })));
|
|
|
12972
12978
|
backgroundColor: `${swiper === null || swiper === void 0 ? void 0 : swiper.dotsActiveColor}!important`,
|
|
12973
12979
|
opacity: 1
|
|
12974
12980
|
}
|
|
12975
|
-
}))) }), (
|
|
12981
|
+
}))) }), (_2 = product === null || product === void 0 ? void 0 : product.homePage) === null || _2 === void 0 ? void 0 : _2.map((src, srcKey) => {
|
|
12976
12982
|
var _a;
|
|
12977
12983
|
return (React.createElement(SwiperSlide, { key: srcKey, "aria-hidden": srcKey !== swiperActiveIndex },
|
|
12978
12984
|
React.createElement("div", { style: {
|
|
@@ -12988,7 +12994,7 @@ Made in Italy` })));
|
|
|
12988
12994
|
objectPosition: `50% ${(swiper === null || swiper === void 0 ? void 0 : swiper.translateY) ? (swiper === null || swiper === void 0 ? void 0 : swiper.translateY) + 50 : 50}%`
|
|
12989
12995
|
}, src: (_a = src !== null && src !== void 0 ? src : sxpParameter === null || sxpParameter === void 0 ? void 0 : sxpParameter.bottom_image) !== null && _a !== void 0 ? _a : bottom_image }))));
|
|
12990
12996
|
}))),
|
|
12991
|
-
!((
|
|
12997
|
+
!((_3 = product === null || product === void 0 ? void 0 : product.homePage) === null || _3 === void 0 ? void 0 : _3.length) && (React.createElement("div", { className: css.css({
|
|
12992
12998
|
height,
|
|
12993
12999
|
width
|
|
12994
13000
|
}) },
|
|
@@ -12996,7 +13002,7 @@ Made in Italy` })));
|
|
|
12996
13002
|
objectFit: 'cover',
|
|
12997
13003
|
width: '100%',
|
|
12998
13004
|
height: '100%'
|
|
12999
|
-
}), src: (
|
|
13005
|
+
}), src: (_4 = sxpParameter === null || sxpParameter === void 0 ? void 0 : sxpParameter.bottom_image) !== null && _4 !== void 0 ? _4 : bottom_image, alt: 'pdp image' }))),
|
|
13000
13006
|
(iframeUrl || !product) && iframeIcon && (React.createElement("div", { style: {
|
|
13001
13007
|
display: 'flex',
|
|
13002
13008
|
alignItems: 'center',
|
|
@@ -13013,7 +13019,7 @@ Made in Italy` })));
|
|
|
13013
13019
|
React.createElement("div", { className: 'pb-commondityDiroNew-content-top' },
|
|
13014
13020
|
React.createElement("div", { className: 'pb-commondityDiroNew-content-top-left' },
|
|
13015
13021
|
React.createElement("div", { className: 'pb-commondityDiroNew-content-top-left-title', style: getStyle(commodityStyles === null || commodityStyles === void 0 ? void 0 : commodityStyles.title), dangerouslySetInnerHTML: {
|
|
13016
|
-
__html: setFontForText((
|
|
13022
|
+
__html: setFontForText((_5 = product === null || product === void 0 ? void 0 : product.title) !== null && _5 !== void 0 ? _5 : 'Large Dior Toujours BagLarge', commodityStyles === null || commodityStyles === void 0 ? void 0 : commodityStyles.title)
|
|
13017
13023
|
} }),
|
|
13018
13024
|
React.createElement("div", { className: 'pb-commondityDiroNew-content-collection', hidden: !!product && (!(product === null || product === void 0 ? void 0 : product.collection) || (product === null || product === void 0 ? void 0 : product.collection) === ''), style: getStyle(commodityStyles === null || commodityStyles === void 0 ? void 0 : commodityStyles.collection), dangerouslySetInnerHTML: {
|
|
13019
13025
|
__html: setFontForText((product === null || product === void 0 ? void 0 : product.collection) || 'Black Macrocannage CalfskinLarge', commodityStyles === null || commodityStyles === void 0 ? void 0 : commodityStyles.collection)
|
|
@@ -13023,11 +13029,11 @@ Made in Italy` })));
|
|
|
13023
13029
|
__html: priceText !== null && priceText !== void 0 ? priceText : ''
|
|
13024
13030
|
} }),
|
|
13025
13031
|
React.createElement("div", { className: 'pb-commondityDiroNew-content-top-right-price', hidden: !!product && !(product === null || product === void 0 ? void 0 : product.taxInfo), style: getStyle(commodityStyles === null || commodityStyles === void 0 ? void 0 : commodityStyles.taxInfo), dangerouslySetInnerHTML: {
|
|
13026
|
-
__html: setFontForText((
|
|
13032
|
+
__html: setFontForText((_6 = product === null || product === void 0 ? void 0 : product.taxInfo) !== null && _6 !== void 0 ? _6 : '税费', commodityStyles === null || commodityStyles === void 0 ? void 0 : commodityStyles.taxInfo)
|
|
13027
13033
|
} }))),
|
|
13028
|
-
React.createElement("a", { "aria-label": (
|
|
13034
|
+
React.createElement("a", { "aria-label": (_7 = cta === null || cta === void 0 ? void 0 : cta.enTitle) !== null && _7 !== void 0 ? _7 : 'Shop now', role: 'button', tabIndex: 0, onClick: handleLink, className: 'pb-commondityDiroNew-btn', style: buttonStyle },
|
|
13029
13035
|
React.createElement("span", { dangerouslySetInnerHTML: {
|
|
13030
|
-
__html: setFontForText((
|
|
13036
|
+
__html: setFontForText((_8 = cta === null || cta === void 0 ? void 0 : cta.enTitle) !== null && _8 !== void 0 ? _8 : 'Shop now', buttonStyle)
|
|
13031
13037
|
} })),
|
|
13032
13038
|
productInfoText({ isPost }))),
|
|
13033
13039
|
React.createElement(Modal$1, { visible: showModal, onClose: () => setShowModal(false) },
|
|
@@ -20063,6 +20069,8 @@ const StructurePage = (_a) => {
|
|
|
20063
20069
|
var { containerStyle, containerHeight = 664, containerWidth = 375, className = '', apiUrl = 'https://bff-be-dev.chatlabs.net/api/v1/recommend/list', requestBody, editorMode = false, multiCTAConfig: propMultiCTAConfig, videoPlayIcon: propVideoPlayIcon, isCmsMode = false, storyId, customHeaders, preloadImages = true } = _a, // 默认预加载图片,提升用户体验
|
|
20064
20070
|
rest = __rest(_a, ["containerStyle", "containerHeight", "containerWidth", "className", "apiUrl", "requestBody", "editorMode", "multiCTAConfig", "videoPlayIcon", "isCmsMode", "storyId", "customHeaders", "preloadImages"]);
|
|
20065
20071
|
const [data, setData] = React.useState(null);
|
|
20072
|
+
// 用 ref 保存最新的 data,供 visibilitychange 等事件回调中访问,避免闭包陈旧值
|
|
20073
|
+
const dataRef = React.useRef(null);
|
|
20066
20074
|
const [loading, setLoading] = React.useState(true);
|
|
20067
20075
|
const [error, setError] = React.useState(null);
|
|
20068
20076
|
const [carouselIndex, setCarouselIndex] = React.useState(0);
|
|
@@ -20160,9 +20168,16 @@ const StructurePage = (_a) => {
|
|
|
20160
20168
|
}, [data, isHeroVideoLoaded, sxpParameter]);
|
|
20161
20169
|
// 防止重复上报的标记
|
|
20162
20170
|
const h5EnterReportedRef = React.useRef(false);
|
|
20171
|
+
// 标记页面是否已完成首次加载(挂载时的 h5LinkEnterFeed 已上报)
|
|
20172
|
+
// visibilitychange 的 visible 分支只在此标记为 true 后才响应,避免刷新时重复上报
|
|
20173
|
+
const pageInitializedRef = React.useRef(false);
|
|
20174
|
+
// 标记页面是否正在卸载(刷新/关闭),防止刷新时旧页面的 visibilitychange visible 误触发
|
|
20175
|
+
const pageUnloadingRef = React.useRef(false);
|
|
20163
20176
|
// 全局事件管理:用于追踪弹窗打开时间和状态
|
|
20164
20177
|
const popupCurTimeRef = React.useRef(new Date());
|
|
20165
20178
|
const currentPopupDataRef = React.useRef(null);
|
|
20179
|
+
// 标记弹窗是否处于打开状态,用于防止弹窗导致的 window blur/focus 误触发 h5LinkEnterFeed
|
|
20180
|
+
const isPopupOpenRef = React.useRef(false);
|
|
20166
20181
|
// CTA 曝光时间追踪(允许重复上报)
|
|
20167
20182
|
const ctaExposureTime = React.useRef({});
|
|
20168
20183
|
// Carousel 图片浏览时间追踪
|
|
@@ -20233,6 +20248,7 @@ const StructurePage = (_a) => {
|
|
|
20233
20248
|
}, [propVideoPlayIcon, (_e = (_d = schema === null || schema === void 0 ? void 0 : schema.sxpPageConf) === null || _d === void 0 ? void 0 : _d.globalConfig) === null || _e === void 0 ? void 0 : _e.videoPlayIcon]);
|
|
20234
20249
|
// 处理 CTA 点击
|
|
20235
20250
|
const handleCtaClick = React.useCallback((link, interaction, productData, ctaData, viewPosition, sectionIndex) => {
|
|
20251
|
+
var _a, _b, _c;
|
|
20236
20252
|
// 判断是否为外部链接
|
|
20237
20253
|
const isExternalLink = (interaction === null || interaction === void 0 ? void 0 : interaction.linkType) !== 'popup' && !!link;
|
|
20238
20254
|
// ========== 1. BFF 事件上报 (ctaEvent) ==========
|
|
@@ -20263,7 +20279,9 @@ const StructurePage = (_a) => {
|
|
|
20263
20279
|
product: null
|
|
20264
20280
|
};
|
|
20265
20281
|
// 上报 clickCta 事件
|
|
20266
|
-
|
|
20282
|
+
// productGridSection 区域的商品 position 统一传 0(与 ctaExposure 保持一致)
|
|
20283
|
+
const clickCtaPosition = viewPosition === 'productGridSection' ? 0 : (sectionIndex !== undefined ? sectionIndex : 0);
|
|
20284
|
+
ctaEvent === null || ctaEvent === void 0 ? void 0 : ctaEvent(Object.assign({ eventSubject: 'clickCta', eventDescription: 'User clicked the CTA' }, (viewPosition && { viewPosition })), rec, productData, clickCtaPosition);
|
|
20267
20285
|
// ========== 2. Facebook Pixel 和第三方像素上报 ==========
|
|
20268
20286
|
bffFbReport === null || bffFbReport === void 0 ? void 0 : bffFbReport({
|
|
20269
20287
|
eventName: 'ClickCTA',
|
|
@@ -20281,13 +20299,19 @@ const StructurePage = (_a) => {
|
|
|
20281
20299
|
if (interaction) {
|
|
20282
20300
|
const { linkType, popupType, popupAni } = interaction;
|
|
20283
20301
|
if (linkType === 'popup' && popupType) {
|
|
20284
|
-
// 上报 clickShopifyPopup
|
|
20285
|
-
|
|
20302
|
+
// 上报 clickShopifyPopup 事件(仅当弹窗是 AddToCart 购物车弹窗时才上报)
|
|
20303
|
+
// 商品详情弹窗(CommodityDetail 等)打开时不应上报此事件
|
|
20304
|
+
const popupList = ((_b = (_a = schema === null || schema === void 0 ? void 0 : schema.sxpPageConf) === null || _a === void 0 ? void 0 : _a.globalConfig) === null || _b === void 0 ? void 0 : _b.popupList) || [];
|
|
20305
|
+
const popupNode = popupList.find((p) => p.id === popupType);
|
|
20306
|
+
const isAddToCartPopup = ((_c = popupNode === null || popupNode === void 0 ? void 0 : popupNode.item) === null || _c === void 0 ? void 0 : _c.type) === 'AddToCartPopup';
|
|
20307
|
+
if ((productData === null || productData === void 0 ? void 0 : productData.shopifyId) && isAddToCartPopup) {
|
|
20286
20308
|
ctaEvent === null || ctaEvent === void 0 ? void 0 : ctaEvent(Object.assign({ eventSubject: 'clickShopifyPopup', eventDescription: 'User clicked to open Shopify popup' }, (viewPosition && { viewPosition })), rec, productData, sectionIndex !== undefined ? sectionIndex : 0);
|
|
20287
20309
|
}
|
|
20288
20310
|
// ========== 打开弹窗前:记录弹窗数据和时间 ==========
|
|
20289
20311
|
// 重置弹窗时间
|
|
20290
20312
|
popupCurTimeRef.current = new Date();
|
|
20313
|
+
// 标记弹窗已打开,防止弹窗导致的 window blur 被误判为用户离开页面
|
|
20314
|
+
isPopupOpenRef.current = true;
|
|
20291
20315
|
// 保存当前弹窗的产品数据,用于全局事件监听
|
|
20292
20316
|
currentPopupDataRef.current = {
|
|
20293
20317
|
productData,
|
|
@@ -20354,7 +20378,7 @@ const StructurePage = (_a) => {
|
|
|
20354
20378
|
if (link) {
|
|
20355
20379
|
window.open(link, '_blank');
|
|
20356
20380
|
}
|
|
20357
|
-
}, [ctaEvent, bffFbReport, data]);
|
|
20381
|
+
}, [ctaEvent, bffFbReport, data, schema]);
|
|
20358
20382
|
// 合并基础样式和编辑器配置的样式
|
|
20359
20383
|
const mergeStyles = React.useCallback((baseStyle, configKey, options) => {
|
|
20360
20384
|
if (!multiCTAConfig || !multiCTAConfig[configKey]) {
|
|
@@ -20757,6 +20781,18 @@ const StructurePage = (_a) => {
|
|
|
20757
20781
|
// 默认渲染按钮(包装一个 CTAButton 组件来处理曝光事件)
|
|
20758
20782
|
return (React.createElement(CTAButton, { ctaData: ctaData, style: mergeStyles(fallbackStyle || baseStyles.heroButton, buttonKey), onClick: () => handleCtaClick(ctaData === null || ctaData === void 0 ? void 0 : ctaData.link, interaction, productData, ctaData, viewPosition, sectionIndex), onExposure: () => handleCtaExposure(ctaData, productData, viewPosition, sectionIndex, buttonKey) }));
|
|
20759
20783
|
}, [multiCTAConfig, handleCtaClick, handleCtaExposure, mergeStyles, rest, carouselIndex]);
|
|
20784
|
+
// 监听页面卸载事件(刷新/关闭),设置 pageUnloadingRef 防止旧页面监听器误触发
|
|
20785
|
+
React.useEffect(() => {
|
|
20786
|
+
const handlePageUnload = () => {
|
|
20787
|
+
pageUnloadingRef.current = true;
|
|
20788
|
+
};
|
|
20789
|
+
window.addEventListener('beforeunload', handlePageUnload);
|
|
20790
|
+
window.addEventListener('pagehide', handlePageUnload);
|
|
20791
|
+
return () => {
|
|
20792
|
+
window.removeEventListener('beforeunload', handlePageUnload);
|
|
20793
|
+
window.removeEventListener('pagehide', handlePageUnload);
|
|
20794
|
+
};
|
|
20795
|
+
}, []);
|
|
20760
20796
|
// 页面进入事件上报 - 只在组件挂载时执行一次
|
|
20761
20797
|
React.useEffect(() => {
|
|
20762
20798
|
var _a, _b;
|
|
@@ -20793,6 +20829,11 @@ const StructurePage = (_a) => {
|
|
|
20793
20829
|
clSource: getUrlParam('cl_source')
|
|
20794
20830
|
}
|
|
20795
20831
|
});
|
|
20832
|
+
// 标记首次加载已完成,后续 visibilitychange 的 visible 分支才可以响应
|
|
20833
|
+
// 使用 setTimeout 确保在当前 tick 结束后再设置,避免与 visibilitychange 竞争
|
|
20834
|
+
setTimeout(() => {
|
|
20835
|
+
pageInitializedRef.current = true;
|
|
20836
|
+
}, 0);
|
|
20796
20837
|
}, [bffEventReport]); // 只在挂载时执行一次
|
|
20797
20838
|
// 获取数据 - 只在组件挂载时执行一次
|
|
20798
20839
|
React.useEffect(() => {
|
|
@@ -20808,6 +20849,7 @@ const StructurePage = (_a) => {
|
|
|
20808
20849
|
setLoading(false);
|
|
20809
20850
|
setError(null);
|
|
20810
20851
|
// 使用传入的 multiCTAConfig 作为数据源
|
|
20852
|
+
dataRef.current = propMultiCTAConfig;
|
|
20811
20853
|
setData(propMultiCTAConfig);
|
|
20812
20854
|
return;
|
|
20813
20855
|
}
|
|
@@ -20893,6 +20935,7 @@ const StructurePage = (_a) => {
|
|
|
20893
20935
|
multiCtaData = (_d = (_c = (_b = result.data) === null || _b === void 0 ? void 0 : _b.recList) === null || _c === void 0 ? void 0 : _c[0]) === null || _d === void 0 ? void 0 : _d.multiCta;
|
|
20894
20936
|
}
|
|
20895
20937
|
if (multiCtaData) {
|
|
20938
|
+
dataRef.current = multiCtaData;
|
|
20896
20939
|
setData(multiCtaData);
|
|
20897
20940
|
// 保存 requestId 到 curReqInfo(用于后续事件上报)
|
|
20898
20941
|
if (((_e = result.data) === null || _e === void 0 ? void 0 : _e.requestId) && setCurReqInfo) {
|
|
@@ -21518,12 +21561,14 @@ const StructurePage = (_a) => {
|
|
|
21518
21561
|
delay: 1000, // 停留 1 秒后触发
|
|
21519
21562
|
onVisible: handleHeroVisible,
|
|
21520
21563
|
onHidden: handleHeroHidden,
|
|
21521
|
-
name: 'Hero'
|
|
21564
|
+
name: 'Hero',
|
|
21565
|
+
// data 加载完成后 heroSectionRef 才会挂载到 DOM,需要将 data 作为额外依赖
|
|
21566
|
+
// 确保 data 就绪后 IntersectionObserver 能重新初始化并正确观察元素
|
|
21567
|
+
deps: [data]
|
|
21522
21568
|
});
|
|
21523
21569
|
// Carousel Section 的曝光检测 ref
|
|
21524
21570
|
const carouselSectionRef = React.useRef(null);
|
|
21525
21571
|
const carouselIsVisible = React.useRef(false); // 记录 carousel section 是否在可视区域内
|
|
21526
|
-
const windowWasBlurred = React.useRef(false); // 记录 window 是否曾经 blur,防止 focus 误触发
|
|
21527
21572
|
// 调试:检查 carouselSectionRef 是否正确挂载
|
|
21528
21573
|
React.useEffect(() => {
|
|
21529
21574
|
var _a;
|
|
@@ -21818,36 +21863,76 @@ const StructurePage = (_a) => {
|
|
|
21818
21863
|
// ==================== 全局事件监听:visibilitychange ====================
|
|
21819
21864
|
// 监听页面可见性变化(最小化、切换标签页、返回等)
|
|
21820
21865
|
// 参考 SxpPageRender 的实现
|
|
21866
|
+
//
|
|
21867
|
+
// ⚠️ 重要:以下 ref 用于在事件回调中访问最新值,避免 useEffect 依赖变化导致监听器重新注册
|
|
21868
|
+
// 每次渲染时同步更新,确保回调中始终拿到最新值
|
|
21869
|
+
const bffEventReportRef = React.useRef(bffEventReport);
|
|
21870
|
+
const bffFbReportRef = React.useRef(bffFbReport);
|
|
21871
|
+
const refreshFeSessionRef = React.useRef(refreshFeSession);
|
|
21872
|
+
const globalConfigRef = React.useRef(globalConfig);
|
|
21873
|
+
const selectTagRef = React.useRef(selectTag);
|
|
21874
|
+
const backMainFeedRef = React.useRef(backMainFeed);
|
|
21875
|
+
const handleHeroImageStartEventRef = React.useRef(handleHeroImageStartEvent);
|
|
21876
|
+
const handleHeroImageEndEventRef = React.useRef(handleHeroImageEndEvent);
|
|
21877
|
+
const handleCarouselImageStartEventRef = React.useRef(handleCarouselImageStartEvent);
|
|
21878
|
+
const handleCarouselImageEndEventRef = React.useRef(handleCarouselImageEndEvent);
|
|
21879
|
+
const handleVideoPlayOverRef = React.useRef(handleVideoPlayOver);
|
|
21880
|
+
bffEventReportRef.current = bffEventReport;
|
|
21881
|
+
bffFbReportRef.current = bffFbReport;
|
|
21882
|
+
refreshFeSessionRef.current = refreshFeSession;
|
|
21883
|
+
globalConfigRef.current = globalConfig;
|
|
21884
|
+
selectTagRef.current = selectTag;
|
|
21885
|
+
backMainFeedRef.current = backMainFeed;
|
|
21886
|
+
handleHeroImageStartEventRef.current = handleHeroImageStartEvent;
|
|
21887
|
+
handleHeroImageEndEventRef.current = handleHeroImageEndEvent;
|
|
21888
|
+
handleCarouselImageStartEventRef.current = handleCarouselImageStartEvent;
|
|
21889
|
+
handleCarouselImageEndEventRef.current = handleCarouselImageEndEvent;
|
|
21890
|
+
handleVideoPlayOverRef.current = handleVideoPlayOver;
|
|
21821
21891
|
React.useEffect(() => {
|
|
21822
21892
|
const handleVisibilityChange = () => {
|
|
21823
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s;
|
|
21893
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _0, _1, _2, _3, _4, _5, _6;
|
|
21824
21894
|
if (document.visibilityState === 'hidden') {
|
|
21825
21895
|
// ========== 页面隐藏时 ==========
|
|
21826
21896
|
console.log('[StructurePage] Page hidden - 触发全局事件');
|
|
21827
21897
|
// 0. 上报当前可见的 post/product 的离开事件
|
|
21828
21898
|
console.log('[visibilitychange] 页面隐藏,当前可见的 products 数量:', visibleProducts.current.length);
|
|
21829
|
-
// Hero Section:
|
|
21830
|
-
if (heroIsVisible.current && (
|
|
21831
|
-
const item =
|
|
21832
|
-
if (!item.url && ((
|
|
21899
|
+
// Hero Section: 上报离开事件
|
|
21900
|
+
if (heroIsVisible.current && ((_a = dataRef.current) === null || _a === void 0 ? void 0 : _a.heroSection)) {
|
|
21901
|
+
const item = dataRef.current.heroSection;
|
|
21902
|
+
if (!item.url && ((_b = item.imgUrls) === null || _b === void 0 ? void 0 : _b[0])) {
|
|
21903
|
+
// 图片:上报图片离开事件
|
|
21833
21904
|
console.log('[visibilitychange] 页面隐藏,上报 Hero 图片离开事件');
|
|
21834
|
-
|
|
21905
|
+
handleHeroImageEndEventRef.current();
|
|
21906
|
+
}
|
|
21907
|
+
else if (item.url && heroVideoRef.current && !heroVideoRef.current.paused) {
|
|
21908
|
+
// 视频:正在播放时上报视频结束事件
|
|
21909
|
+
console.log('[visibilitychange] 页面隐藏,上报 Hero 视频结束事件');
|
|
21910
|
+
handleVideoPlayOverRef.current(item, 'heroSection', 0, heroVideoRef.current);
|
|
21835
21911
|
}
|
|
21836
21912
|
}
|
|
21837
|
-
// Carousel Section:
|
|
21838
|
-
if (carouselIsVisible.current && (
|
|
21913
|
+
// Carousel Section: 上报离开事件
|
|
21914
|
+
if (carouselIsVisible.current && ((_c = dataRef.current) === null || _c === void 0 ? void 0 : _c.carouselSection)) {
|
|
21839
21915
|
const currentIndex = currentCarouselIndexRef.current;
|
|
21840
|
-
const currentItem =
|
|
21916
|
+
const currentItem = dataRef.current.carouselSection[currentIndex];
|
|
21841
21917
|
if (currentItem && !currentItem.url) {
|
|
21918
|
+
// 图片:上报图片离开事件
|
|
21842
21919
|
console.log('[visibilitychange] 页面隐藏,上报 Carousel 图片离开事件, index:', currentIndex);
|
|
21843
|
-
|
|
21920
|
+
handleCarouselImageEndEventRef.current(currentIndex);
|
|
21921
|
+
}
|
|
21922
|
+
else if (currentItem === null || currentItem === void 0 ? void 0 : currentItem.url) {
|
|
21923
|
+
// 视频:正在播放时上报视频结束事件
|
|
21924
|
+
const carouselVideoRef = carouselVideoRefs.current[currentIndex];
|
|
21925
|
+
if (carouselVideoRef && !carouselVideoRef.paused) {
|
|
21926
|
+
console.log('[visibilitychange] 页面隐藏,上报 Carousel 视频结束事件, index:', currentIndex);
|
|
21927
|
+
handleVideoPlayOverRef.current(currentItem, 'carouselSection', currentIndex, carouselVideoRef);
|
|
21928
|
+
}
|
|
21844
21929
|
}
|
|
21845
21930
|
}
|
|
21846
21931
|
// Products: 上报所有当前可见的 product 的离开事件
|
|
21847
21932
|
// 注意:只上报,不从 visibleProducts 移除,也不删除 productViewStartTime
|
|
21848
21933
|
// 这样页面恢复可见时可以重新记录 startTime,后续滑走/再次最小化能正常上报
|
|
21849
21934
|
visibleProducts.current.forEach((product) => {
|
|
21850
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _j;
|
|
21935
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
|
|
21851
21936
|
const productId = `${(_a = product.productData) === null || _a === void 0 ? void 0 : _a.itemId}-${product.viewPosition}-${product.sectionIndex}`;
|
|
21852
21937
|
const startTime = productViewStartTime.current[productId];
|
|
21853
21938
|
if (!startTime)
|
|
@@ -21860,71 +21945,38 @@ const StructurePage = (_a) => {
|
|
|
21860
21945
|
fromKName = 'recommend page';
|
|
21861
21946
|
else if (product.viewPosition === 'footerSection')
|
|
21862
21947
|
fromKName = 'pdpPage';
|
|
21863
|
-
|
|
21948
|
+
(_b = bffEventReportRef.current) === null || _b === void 0 ? void 0 : _b.call(bffEventReportRef, {
|
|
21864
21949
|
eventInfo: {
|
|
21865
21950
|
eventSubject: 'productView',
|
|
21866
21951
|
eventDescription: 'User browsed the product',
|
|
21867
|
-
productId: ((
|
|
21868
|
-
productName: ((
|
|
21869
|
-
price: ((
|
|
21870
|
-
productCollection: ((
|
|
21952
|
+
productId: ((_c = product.productData) === null || _c === void 0 ? void 0 : _c.itemId) || '',
|
|
21953
|
+
productName: ((_d = product.productData) === null || _d === void 0 ? void 0 : _d.title) || '',
|
|
21954
|
+
price: ((_e = product.productData) === null || _e === void 0 ? void 0 : _e.price) ? `${product.productData.price}` : '0',
|
|
21955
|
+
productCollection: ((_f = product.productData) === null || _f === void 0 ? void 0 : _f.collection) || '',
|
|
21871
21956
|
fromKName,
|
|
21872
21957
|
fromKPage: (location === null || location === void 0 ? void 0 : location.href) || '',
|
|
21873
|
-
contentTags: ((
|
|
21958
|
+
contentTags: ((_g = product.productData) === null || _g === void 0 ? void 0 : _g.tags) ? JSON.stringify(product.productData.tags) : '[]',
|
|
21874
21959
|
position: `${product.sectionIndex || 0}`,
|
|
21875
21960
|
contentId: '',
|
|
21876
21961
|
sceneId: '',
|
|
21877
|
-
ctatId: ((
|
|
21878
|
-
traceInfo: ((
|
|
21962
|
+
ctatId: ((_j = (_h = product.productData) === null || _h === void 0 ? void 0 : _h.bindCta) === null || _j === void 0 ? void 0 : _j.itemId) || '',
|
|
21963
|
+
traceInfo: ((_k = product.productData) === null || _k === void 0 ? void 0 : _k.traceInfo) || '',
|
|
21879
21964
|
timeOnSite: `${timeOnSite}`
|
|
21880
21965
|
}
|
|
21881
21966
|
});
|
|
21882
21967
|
});
|
|
21883
21968
|
// 不清空 visibleProducts,保留快照供页面恢复时使用
|
|
21884
21969
|
// 1. 发送 PAGE_DID_HIDE 事件到事件总线
|
|
21885
|
-
|
|
21886
|
-
|
|
21887
|
-
|
|
21888
|
-
const { productData, viewPosition, sectionIndex } = currentPopupDataRef.current;
|
|
21889
|
-
// 获取当前 section 的 post 数据
|
|
21890
|
-
let postData = null;
|
|
21891
|
-
if (viewPosition === 'heroSection' && (data === null || data === void 0 ? void 0 : data.heroSection)) {
|
|
21892
|
-
postData = data.heroSection;
|
|
21893
|
-
}
|
|
21894
|
-
else if (viewPosition === 'carouselSection' && (data === null || data === void 0 ? void 0 : data.carouselSection) && sectionIndex !== undefined) {
|
|
21895
|
-
postData = data.carouselSection[sectionIndex];
|
|
21896
|
-
}
|
|
21897
|
-
const rec = {
|
|
21898
|
-
video: {
|
|
21899
|
-
bindProduct: productData,
|
|
21900
|
-
bindProducts: productData ? [productData] : [],
|
|
21901
|
-
itemId: (postData === null || postData === void 0 ? void 0 : postData.itemId) || '',
|
|
21902
|
-
tags: (postData === null || postData === void 0 ? void 0 : postData.tags) || null,
|
|
21903
|
-
scene: (postData === null || postData === void 0 ? void 0 : postData.scene) || null,
|
|
21904
|
-
url: (postData === null || postData === void 0 ? void 0 : postData.url) || null,
|
|
21905
|
-
imgUrls: (postData === null || postData === void 0 ? void 0 : postData.imgUrls) || null
|
|
21906
|
-
},
|
|
21907
|
-
product: null
|
|
21908
|
-
};
|
|
21909
|
-
const viewTime = new Date() - popupCurTimeRef.current;
|
|
21910
|
-
bffFbReport === null || bffFbReport === void 0 ? void 0 : bffFbReport({
|
|
21911
|
-
eventName: 'ExitFeed',
|
|
21912
|
-
product: productData ? [productData] : undefined,
|
|
21913
|
-
contentType: 'product',
|
|
21914
|
-
rec: rec,
|
|
21915
|
-
position: sectionIndex !== undefined ? sectionIndex : 0,
|
|
21916
|
-
view_time: viewTime,
|
|
21917
|
-
content_id: (productData === null || productData === void 0 ? void 0 : productData.itemId) || ''
|
|
21918
|
-
});
|
|
21919
|
-
console.log('[StructurePage] 上报 ExitFeed 事件', { viewTime, productId: productData === null || productData === void 0 ? void 0 : productData.itemId });
|
|
21920
|
-
}
|
|
21921
|
-
// 3. 刷新 Session(处理 Session 过期)
|
|
21970
|
+
// ExitFeed 事件由 PAGE_DID_HIDE 监听器统一处理,避免重复上报
|
|
21971
|
+
SXP_EVENT_BUS.emit(SXP_EVENT_TYPE.PAGE_DID_HIDE, dataRef.current);
|
|
21972
|
+
// 2. 刷新 Session(处理 Session 过期)
|
|
21922
21973
|
// 只有在非 organic menu 模式下才刷新 Session(与非 multi-cta 逻辑一致)
|
|
21923
|
-
if ((
|
|
21924
|
-
const isExpire =
|
|
21974
|
+
if (((_d = globalConfigRef.current) === null || _d === void 0 ? void 0 : _d.playbook) !== 'organic menu' && refreshFeSessionRef.current && curTime) {
|
|
21975
|
+
const isExpire = refreshFeSessionRef.current(false, (reason) => {
|
|
21976
|
+
var _a;
|
|
21925
21977
|
console.log('[StructurePage] Session expired:', reason);
|
|
21926
21978
|
// Session 过期时的回调处理
|
|
21927
|
-
|
|
21979
|
+
(_a = bffEventReportRef.current) === null || _a === void 0 ? void 0 : _a.call(bffEventReportRef, {
|
|
21928
21980
|
eventInfo: {
|
|
21929
21981
|
eventSubject: 'sessionExpired',
|
|
21930
21982
|
eventDescription: 'User session has expired',
|
|
@@ -21945,16 +21997,16 @@ const StructurePage = (_a) => {
|
|
|
21945
21997
|
if (currentPopupDataRef.current) {
|
|
21946
21998
|
const { productData, viewPosition, sectionIndex } = currentPopupDataRef.current;
|
|
21947
21999
|
// 获取 contentId 和 sceneId(从对应的 post/image 数据中)
|
|
21948
|
-
if (viewPosition === 'heroSection' && (
|
|
21949
|
-
contentId =
|
|
21950
|
-
sceneId = ((
|
|
21951
|
-
ctatId = ((
|
|
22000
|
+
if (viewPosition === 'heroSection' && ((_e = dataRef.current) === null || _e === void 0 ? void 0 : _e.heroSection)) {
|
|
22001
|
+
contentId = dataRef.current.heroSection.itemId || '';
|
|
22002
|
+
sceneId = ((_f = dataRef.current.heroSection.scene) === null || _f === void 0 ? void 0 : _f.sceneId) || '';
|
|
22003
|
+
ctatId = ((_g = dataRef.current.heroSection.bindCta) === null || _g === void 0 ? void 0 : _g.itemId) || '';
|
|
21952
22004
|
}
|
|
21953
|
-
else if (viewPosition === 'carouselSection' && (
|
|
21954
|
-
const carouselItem =
|
|
22005
|
+
else if (viewPosition === 'carouselSection' && ((_h = dataRef.current) === null || _h === void 0 ? void 0 : _h.carouselSection) && sectionIndex !== undefined) {
|
|
22006
|
+
const carouselItem = dataRef.current.carouselSection[sectionIndex];
|
|
21955
22007
|
contentId = (carouselItem === null || carouselItem === void 0 ? void 0 : carouselItem.itemId) || '';
|
|
21956
|
-
sceneId = ((
|
|
21957
|
-
ctatId = ((
|
|
22008
|
+
sceneId = ((_j = carouselItem === null || carouselItem === void 0 ? void 0 : carouselItem.scene) === null || _j === void 0 ? void 0 : _j.sceneId) || '';
|
|
22009
|
+
ctatId = ((_k = carouselItem === null || carouselItem === void 0 ? void 0 : carouselItem.bindCta) === null || _k === void 0 ? void 0 : _k.itemId) || '';
|
|
21958
22010
|
}
|
|
21959
22011
|
// 获取 productId
|
|
21960
22012
|
productId = (productData === null || productData === void 0 ? void 0 : productData.itemId) || '';
|
|
@@ -21962,23 +22014,23 @@ const StructurePage = (_a) => {
|
|
|
21962
22014
|
// 2. 如果没有弹窗,从当前可见的内容中获取
|
|
21963
22015
|
else {
|
|
21964
22016
|
// 优先从 Hero Section 获取(如果可见)
|
|
21965
|
-
if (heroIsVisible.current && (
|
|
21966
|
-
contentId =
|
|
21967
|
-
sceneId = ((
|
|
21968
|
-
ctatId = ((
|
|
22017
|
+
if (heroIsVisible.current && ((_l = dataRef.current) === null || _l === void 0 ? void 0 : _l.heroSection)) {
|
|
22018
|
+
contentId = dataRef.current.heroSection.itemId || '';
|
|
22019
|
+
sceneId = ((_m = dataRef.current.heroSection.scene) === null || _m === void 0 ? void 0 : _m.sceneId) || '';
|
|
22020
|
+
ctatId = ((_o = dataRef.current.heroSection.bindCta) === null || _o === void 0 ? void 0 : _o.itemId) || '';
|
|
21969
22021
|
// 如果 Hero 有绑定的产品,获取第一个产品的 ID
|
|
21970
|
-
if (
|
|
21971
|
-
productId =
|
|
22022
|
+
if (dataRef.current.heroSection.bindProducts && dataRef.current.heroSection.bindProducts.length > 0) {
|
|
22023
|
+
productId = dataRef.current.heroSection.bindProducts[0].itemId || '';
|
|
21972
22024
|
}
|
|
21973
22025
|
}
|
|
21974
22026
|
// 其次从 Carousel Section 获取(如果可见)
|
|
21975
|
-
else if (carouselIsVisible.current && (
|
|
22027
|
+
else if (carouselIsVisible.current && ((_p = dataRef.current) === null || _p === void 0 ? void 0 : _p.carouselSection)) {
|
|
21976
22028
|
const currentIndex = currentCarouselIndexRef.current;
|
|
21977
|
-
const currentItem =
|
|
22029
|
+
const currentItem = dataRef.current.carouselSection[currentIndex];
|
|
21978
22030
|
if (currentItem) {
|
|
21979
22031
|
contentId = currentItem.itemId || '';
|
|
21980
|
-
sceneId = ((
|
|
21981
|
-
ctatId = ((
|
|
22032
|
+
sceneId = ((_q = currentItem.scene) === null || _q === void 0 ? void 0 : _q.sceneId) || '';
|
|
22033
|
+
ctatId = ((_r = currentItem.bindCta) === null || _r === void 0 ? void 0 : _r.itemId) || '';
|
|
21982
22034
|
// 如果 Carousel 有绑定的产品,获取第一个产品的 ID
|
|
21983
22035
|
if (currentItem.bindProducts && currentItem.bindProducts.length > 0) {
|
|
21984
22036
|
productId = currentItem.bindProducts[0].itemId || '';
|
|
@@ -21988,24 +22040,24 @@ const StructurePage = (_a) => {
|
|
|
21988
22040
|
// 最后从当前可见的产品列表中获取(如果有)
|
|
21989
22041
|
else if (visibleProducts.current.length > 0) {
|
|
21990
22042
|
const firstVisibleProduct = visibleProducts.current[0];
|
|
21991
|
-
productId = ((
|
|
22043
|
+
productId = ((_s = firstVisibleProduct.productData) === null || _s === void 0 ? void 0 : _s.itemId) || '';
|
|
21992
22044
|
// 尝试获取对应的 contentId
|
|
21993
|
-
if (firstVisibleProduct.viewPosition === 'heroSection' && (
|
|
21994
|
-
contentId =
|
|
21995
|
-
sceneId = ((
|
|
21996
|
-
ctatId = ((
|
|
22045
|
+
if (firstVisibleProduct.viewPosition === 'heroSection' && ((_t = dataRef.current) === null || _t === void 0 ? void 0 : _t.heroSection)) {
|
|
22046
|
+
contentId = dataRef.current.heroSection.itemId || '';
|
|
22047
|
+
sceneId = ((_u = dataRef.current.heroSection.scene) === null || _u === void 0 ? void 0 : _u.sceneId) || '';
|
|
22048
|
+
ctatId = ((_v = dataRef.current.heroSection.bindCta) === null || _v === void 0 ? void 0 : _v.itemId) || '';
|
|
21997
22049
|
}
|
|
21998
|
-
else if (firstVisibleProduct.viewPosition === 'carouselSection' && (
|
|
21999
|
-
const carouselItem =
|
|
22050
|
+
else if (firstVisibleProduct.viewPosition === 'carouselSection' && ((_w = dataRef.current) === null || _w === void 0 ? void 0 : _w.carouselSection)) {
|
|
22051
|
+
const carouselItem = dataRef.current.carouselSection[firstVisibleProduct.sectionIndex];
|
|
22000
22052
|
if (carouselItem) {
|
|
22001
22053
|
contentId = carouselItem.itemId || '';
|
|
22002
|
-
sceneId = ((
|
|
22003
|
-
ctatId = ((
|
|
22054
|
+
sceneId = ((_x = carouselItem.scene) === null || _x === void 0 ? void 0 : _x.sceneId) || '';
|
|
22055
|
+
ctatId = ((_y = carouselItem.bindCta) === null || _y === void 0 ? void 0 : _y.itemId) || '';
|
|
22004
22056
|
}
|
|
22005
22057
|
}
|
|
22006
22058
|
}
|
|
22007
22059
|
}
|
|
22008
|
-
|
|
22060
|
+
(_z = bffEventReportRef.current) === null || _z === void 0 ? void 0 : _z.call(bffEventReportRef, {
|
|
22009
22061
|
eventInfo: {
|
|
22010
22062
|
eventSubject: 'sessionCompleted',
|
|
22011
22063
|
eventDescription: 'User session completed normally',
|
|
@@ -22022,14 +22074,25 @@ const StructurePage = (_a) => {
|
|
|
22022
22074
|
else if (document.visibilityState === 'visible') {
|
|
22023
22075
|
// ========== 页面可见时 ==========
|
|
22024
22076
|
console.log('[StructurePage] Page visible - 触发全局事件');
|
|
22077
|
+
// 如果页面尚未完成首次加载(挂载时的 h5LinkEnterFeed 还未上报),
|
|
22078
|
+
// 则跳过此次 visibilitychange visible 处理,避免刷新时重复上报
|
|
22079
|
+
if (!pageInitializedRef.current) {
|
|
22080
|
+
console.log('[StructurePage] 页面尚未初始化完成,跳过 visibilitychange visible 处理');
|
|
22081
|
+
return;
|
|
22082
|
+
}
|
|
22083
|
+
// 如果页面正在卸载(刷新/关闭),跳过处理,避免旧页面监听器误触发
|
|
22084
|
+
if (pageUnloadingRef.current) {
|
|
22085
|
+
console.log('[StructurePage] 页面正在卸载,跳过 visibilitychange visible 处理');
|
|
22086
|
+
return;
|
|
22087
|
+
}
|
|
22025
22088
|
// ⚠️ 重要:必须先刷新 Session,再上报事件(使用最新的 Session ID)
|
|
22026
22089
|
// 1. 刷新 Session(根据配置决定)
|
|
22027
|
-
if (
|
|
22028
|
-
|
|
22090
|
+
if (refreshFeSessionRef.current) {
|
|
22091
|
+
refreshFeSessionRef.current(false);
|
|
22029
22092
|
}
|
|
22030
22093
|
// 2. 如果未启用 session 配置,则强制刷新 Session ID(与非 multi-cta 逻辑一致)
|
|
22031
22094
|
// ⚠️ 必须在上报事件之前刷新,这样上报的事件才会使用最新的 Session ID
|
|
22032
|
-
if (!((
|
|
22095
|
+
if (!((_1 = (_0 = globalConfigRef.current) === null || _0 === void 0 ? void 0 : _0.session) === null || _1 === void 0 ? void 0 : _1.enable)) {
|
|
22033
22096
|
refreshFeSessionId();
|
|
22034
22097
|
console.log('[StructurePage] Session 未启用,强制刷新 Session ID');
|
|
22035
22098
|
}
|
|
@@ -22042,7 +22105,7 @@ const StructurePage = (_a) => {
|
|
|
22042
22105
|
if (curTime) {
|
|
22043
22106
|
curTime.current = time;
|
|
22044
22107
|
}
|
|
22045
|
-
|
|
22108
|
+
(_2 = bffEventReportRef.current) === null || _2 === void 0 ? void 0 : _2.call(bffEventReportRef, {
|
|
22046
22109
|
eventInfo: {
|
|
22047
22110
|
eventSubject: 'h5LinkEnterFeed',
|
|
22048
22111
|
eventDescription: 'User enter h5 link',
|
|
@@ -22052,15 +22115,15 @@ const StructurePage = (_a) => {
|
|
|
22052
22115
|
utmId: getUrlParamByKey('utm_id'),
|
|
22053
22116
|
utmContent: getUrlParamByKey('utm_content'),
|
|
22054
22117
|
enterTime: Math.floor(time / 1000) + '',
|
|
22055
|
-
enterUrl: ((
|
|
22118
|
+
enterUrl: ((_3 = window === null || window === void 0 ? void 0 : window.location) === null || _3 === void 0 ? void 0 : _3.href) || ''
|
|
22056
22119
|
},
|
|
22057
22120
|
reportLayId: false
|
|
22058
22121
|
});
|
|
22059
22122
|
// 3. 上报 backMainFeed 事件(从外部返回)
|
|
22060
|
-
|
|
22123
|
+
backMainFeedRef.current('external', selectTagRef.current);
|
|
22061
22124
|
// 4. 发送 PAGE_DID_SHOW 事件到事件总线(延迟 100ms,与 SxpPageRender 保持一致)
|
|
22062
22125
|
setTimeout(() => {
|
|
22063
|
-
SXP_EVENT_BUS.emit(SXP_EVENT_TYPE.PAGE_DID_SHOW,
|
|
22126
|
+
SXP_EVENT_BUS.emit(SXP_EVENT_TYPE.PAGE_DID_SHOW, dataRef.current);
|
|
22064
22127
|
}, 100);
|
|
22065
22128
|
// 4. 如果有打开的弹窗,重置弹窗时间
|
|
22066
22129
|
if (currentPopupDataRef.current) {
|
|
@@ -22070,24 +22133,24 @@ const StructurePage = (_a) => {
|
|
|
22070
22133
|
// 5. 上报当前可见的 post/product 的进入事件
|
|
22071
22134
|
console.log('[visibilitychange] 页面可见,需要重新上报的 products 数量:', visibleProducts.current.length);
|
|
22072
22135
|
// Hero Section: 如果是图片且可见,上报图片进入事件
|
|
22073
|
-
if (heroIsVisible.current && (
|
|
22074
|
-
const item =
|
|
22075
|
-
if (!item.url && ((
|
|
22136
|
+
if (heroIsVisible.current && ((_4 = dataRef.current) === null || _4 === void 0 ? void 0 : _4.heroSection)) {
|
|
22137
|
+
const item = dataRef.current.heroSection;
|
|
22138
|
+
if (!item.url && ((_5 = item.imgUrls) === null || _5 === void 0 ? void 0 : _5[0])) {
|
|
22076
22139
|
console.log('[visibilitychange] 页面可见,上报 Hero 图片进入事件');
|
|
22077
|
-
|
|
22140
|
+
handleHeroImageStartEventRef.current();
|
|
22078
22141
|
}
|
|
22079
22142
|
}
|
|
22080
22143
|
// Carousel Section: 如果是图片且可见,上报图片进入事件
|
|
22081
|
-
if (carouselIsVisible.current && (
|
|
22144
|
+
if (carouselIsVisible.current && ((_6 = dataRef.current) === null || _6 === void 0 ? void 0 : _6.carouselSection)) {
|
|
22082
22145
|
const currentIndex = currentCarouselIndexRef.current;
|
|
22083
|
-
const currentItem =
|
|
22146
|
+
const currentItem = dataRef.current.carouselSection[currentIndex];
|
|
22084
22147
|
if (currentItem && !currentItem.url) {
|
|
22085
22148
|
console.log('[visibilitychange] 页面可见,当前是图片, index:', currentIndex);
|
|
22086
22149
|
// 检查图片是否已加载
|
|
22087
22150
|
if (carouselImageLoadStartTime.current[currentIndex] > 0) {
|
|
22088
22151
|
// 图片已加载,立即上报
|
|
22089
22152
|
console.log('[visibilitychange] 图片已加载,上报 Carousel 图片进入事件');
|
|
22090
|
-
|
|
22153
|
+
handleCarouselImageStartEventRef.current(currentIndex, carouselImageLoadTime.current[currentIndex]);
|
|
22091
22154
|
}
|
|
22092
22155
|
else {
|
|
22093
22156
|
// 图片未加载,标记为待上报,等图片加载完成后触发
|
|
@@ -22106,80 +22169,15 @@ const StructurePage = (_a) => {
|
|
|
22106
22169
|
});
|
|
22107
22170
|
}
|
|
22108
22171
|
};
|
|
22109
|
-
//
|
|
22110
|
-
//
|
|
22111
|
-
// 注意:只有在经历过 blur(真正离开)之后 focus 才上报,防止页面内交互误触发
|
|
22112
|
-
const handleWindowBlur = () => {
|
|
22113
|
-
// 窗口失去焦点(缩小到 Dock / 切换到其他 App)
|
|
22114
|
-
windowWasBlurred.current = true;
|
|
22115
|
-
// 与 visibilitychange hidden 分支对齐:刷新 Session
|
|
22116
|
-
if ((globalConfig === null || globalConfig === void 0 ? void 0 : globalConfig.playbook) !== 'organic menu' && refreshFeSession && curTime) {
|
|
22117
|
-
refreshFeSession(false);
|
|
22118
|
-
}
|
|
22119
|
-
};
|
|
22120
|
-
const handleWindowFocus = () => {
|
|
22121
|
-
var _a, _b;
|
|
22122
|
-
// 仅在经历过真实 blur 之后才处理(防止页面内点击/滑动误触发)
|
|
22123
|
-
if (!windowWasBlurred.current)
|
|
22124
|
-
return;
|
|
22125
|
-
windowWasBlurred.current = false;
|
|
22126
|
-
// 窗口重新获得焦点(从 Dock 还原 / 切回浏览器)
|
|
22127
|
-
// 与 visibilitychange visible 分支对齐:刷新 Session ID 并上报进入事件
|
|
22128
|
-
if (refreshFeSession) {
|
|
22129
|
-
refreshFeSession(false);
|
|
22130
|
-
}
|
|
22131
|
-
if (!((_a = globalConfig === null || globalConfig === void 0 ? void 0 : globalConfig.session) === null || _a === void 0 ? void 0 : _a.enable)) {
|
|
22132
|
-
refreshFeSessionId();
|
|
22133
|
-
}
|
|
22134
|
-
const getUrlParamByKey = (key) => {
|
|
22135
|
-
const urlParams = new URLSearchParams(window.location.search);
|
|
22136
|
-
return urlParams.get(key) || '';
|
|
22137
|
-
};
|
|
22138
|
-
const time = new Date();
|
|
22139
|
-
if (curTime)
|
|
22140
|
-
curTime.current = time;
|
|
22141
|
-
bffEventReport === null || bffEventReport === void 0 ? void 0 : bffEventReport({
|
|
22142
|
-
eventInfo: {
|
|
22143
|
-
eventSubject: 'h5LinkEnterFeed',
|
|
22144
|
-
eventDescription: 'User enter h5 link',
|
|
22145
|
-
utmSource: getUrlParamByKey('utm_source'),
|
|
22146
|
-
utmMedium: getUrlParamByKey('utm_medium'),
|
|
22147
|
-
utmCampaign: getUrlParamByKey('utm_campaign'),
|
|
22148
|
-
utmId: getUrlParamByKey('utm_id'),
|
|
22149
|
-
utmContent: getUrlParamByKey('utm_content'),
|
|
22150
|
-
enterTime: Math.floor(time / 1000) + '',
|
|
22151
|
-
enterUrl: ((_b = window === null || window === void 0 ? void 0 : window.location) === null || _b === void 0 ? void 0 : _b.href) || ''
|
|
22152
|
-
},
|
|
22153
|
-
reportLayId: false
|
|
22154
|
-
});
|
|
22155
|
-
setTimeout(() => {
|
|
22156
|
-
SXP_EVENT_BUS.emit(SXP_EVENT_TYPE.PAGE_DID_SHOW, data);
|
|
22157
|
-
}, 100);
|
|
22158
|
-
};
|
|
22159
|
-
// 添加事件监听
|
|
22172
|
+
// 添加事件监听(只使用 visibilitychange,不使用 window blur/focus)
|
|
22173
|
+
// window blur/focus 会被页面内点击、刷新等操作误触发,难以可靠区分,已移除
|
|
22160
22174
|
document.addEventListener('visibilitychange', handleVisibilityChange);
|
|
22161
|
-
window.addEventListener('blur', handleWindowBlur);
|
|
22162
|
-
window.addEventListener('focus', handleWindowFocus);
|
|
22163
22175
|
// 清理函数
|
|
22164
22176
|
return () => {
|
|
22165
22177
|
document.removeEventListener('visibilitychange', handleVisibilityChange);
|
|
22166
|
-
window.removeEventListener('blur', handleWindowBlur);
|
|
22167
|
-
window.removeEventListener('focus', handleWindowFocus);
|
|
22168
22178
|
};
|
|
22169
|
-
|
|
22170
|
-
|
|
22171
|
-
bffFbReport,
|
|
22172
|
-
bffEventReport,
|
|
22173
|
-
refreshFeSession,
|
|
22174
|
-
curTime,
|
|
22175
|
-
globalConfig,
|
|
22176
|
-
handleHeroImageStartEvent,
|
|
22177
|
-
handleHeroImageEndEvent,
|
|
22178
|
-
handleCarouselImageStartEvent,
|
|
22179
|
-
handleCarouselImageEndEvent,
|
|
22180
|
-
backMainFeed,
|
|
22181
|
-
selectTag
|
|
22182
|
-
]);
|
|
22179
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
22180
|
+
}, []); // 只在挂载时注册一次,所有依赖通过 ref 访问最新值,避免重新注册导致重复上报
|
|
22183
22181
|
// ==================== 初始化弹窗时间记录 ====================
|
|
22184
22182
|
React.useEffect(() => {
|
|
22185
22183
|
const initTime = () => {
|
|
@@ -22243,8 +22241,9 @@ const StructurePage = (_a) => {
|
|
|
22243
22241
|
productId: productData === null || productData === void 0 ? void 0 : productData.itemId,
|
|
22244
22242
|
engagement_type: 'close_popup'
|
|
22245
22243
|
});
|
|
22246
|
-
//
|
|
22244
|
+
// 清空弹窗数据引用,并重置弹窗打开标记
|
|
22247
22245
|
currentPopupDataRef.current = null;
|
|
22246
|
+
isPopupOpenRef.current = false;
|
|
22248
22247
|
}
|
|
22249
22248
|
wasPopupOpen = isPopupOpen;
|
|
22250
22249
|
};
|