pb-sxp-ui 1.20.59 → 1.20.61
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 +203 -167
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +203 -167
- 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 +203 -167
- 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 +137 -126
- 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 +13 -13
- package/es/materials/sxp/popup/CommodityDetailDiroNew/index.js +22 -18
- package/lib/core/components/StructurePage/index.js +137 -126
- 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 +13 -13
- package/lib/materials/sxp/popup/CommodityDetailDiroNew/index.js +22 -18
- 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
|
}
|
|
@@ -11463,11 +11464,11 @@ const CommodityDetail$1 = (_a) => {
|
|
|
11463
11464
|
}, []);
|
|
11464
11465
|
const priceText = getPriceText({
|
|
11465
11466
|
product,
|
|
11466
|
-
enableFormattedPrice: (
|
|
11467
|
+
enableFormattedPrice: (_w = commodityStyles === null || commodityStyles === void 0 ? void 0 : commodityStyles.price) === null || _w === void 0 ? void 0 : _w.enableFormattedPrice,
|
|
11467
11468
|
globalConfig,
|
|
11468
11469
|
style: commodityStyles === null || commodityStyles === void 0 ? void 0 : commodityStyles.price
|
|
11469
11470
|
});
|
|
11470
|
-
const width = (isPreview ? 375 : (
|
|
11471
|
+
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
11472
|
const height = commodityImgRatio ? width * (commodityImgRatio.h / commodityImgRatio.w) : width;
|
|
11472
11473
|
const renderContent = ({ isPost }) => {
|
|
11473
11474
|
var _a, _b, _c, _d;
|
|
@@ -11567,7 +11568,7 @@ const CommodityDetail$1 = (_a) => {
|
|
|
11567
11568
|
return (React.createElement(React.Fragment, null,
|
|
11568
11569
|
React.createElement("div", Object.assign({ className: css.css(Object.assign(Object.assign({}, style), { position: 'relative' })) }, props),
|
|
11569
11570
|
React.createElement("div", { style: { position: 'relative' }, onMouseEnter: handleMouseEnter, onMouseLeave: handleMouseLeave },
|
|
11570
|
-
product && ((
|
|
11571
|
+
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
11572
|
clickable: true,
|
|
11572
11573
|
bulletActiveClass: 'swipe-item-active-bullet',
|
|
11573
11574
|
clickableClass: getDotsAlign,
|
|
@@ -11583,7 +11584,7 @@ const CommodityDetail$1 = (_a) => {
|
|
|
11583
11584
|
}
|
|
11584
11585
|
: {}), { loop: true, autoplay: {
|
|
11585
11586
|
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: (
|
|
11587
|
+
}, 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
11588
|
'.swiper-pagination-bullet': {
|
|
11588
11589
|
backgroundColor: swiper === null || swiper === void 0 ? void 0 : swiper.dotsBgColor,
|
|
11589
11590
|
opacity: 1
|
|
@@ -11594,7 +11595,7 @@ const CommodityDetail$1 = (_a) => {
|
|
|
11594
11595
|
opacity: 1
|
|
11595
11596
|
}
|
|
11596
11597
|
}))) }),
|
|
11597
|
-
React.createElement(React.Fragment, null, (
|
|
11598
|
+
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
11599
|
var _a;
|
|
11599
11600
|
return (React.createElement(SwiperSlide, { key: srcKey, "aria-hidden": srcKey !== swiperActiveIndex },
|
|
11600
11601
|
React.createElement("div", { style: {
|
|
@@ -11610,7 +11611,7 @@ const CommodityDetail$1 = (_a) => {
|
|
|
11610
11611
|
objectPosition: `50% ${(swiper === null || swiper === void 0 ? void 0 : swiper.translateY) ? (swiper === null || swiper === void 0 ? void 0 : swiper.translateY) + 50 : 50}%`
|
|
11611
11612
|
}, 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
11613
|
})))),
|
|
11613
|
-
!((
|
|
11614
|
+
!((_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
11615
|
height,
|
|
11615
11616
|
width
|
|
11616
11617
|
}) },
|
|
@@ -11618,7 +11619,7 @@ const CommodityDetail$1 = (_a) => {
|
|
|
11618
11619
|
objectFit: 'cover',
|
|
11619
11620
|
width: '100%',
|
|
11620
11621
|
height: '100%'
|
|
11621
|
-
}), src: (
|
|
11622
|
+
}), src: (_3 = sxpParameter === null || sxpParameter === void 0 ? void 0 : sxpParameter.bottom_image) !== null && _3 !== void 0 ? _3 : bottom_image, alt: 'pdp image' }))),
|
|
11622
11623
|
(iframeUrl || !product) && iframeIcon && (React.createElement("div", { style: {
|
|
11623
11624
|
display: 'flex',
|
|
11624
11625
|
alignItems: 'center',
|
|
@@ -12685,7 +12686,7 @@ const AddToCartPopup$1 = ({ isActive = true }) => {
|
|
|
12685
12686
|
};
|
|
12686
12687
|
|
|
12687
12688
|
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;
|
|
12689
|
+
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
12690
|
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
12691
|
const { sxpParameter, popupCurTimeRef, popupDetailData, setPopupDetailData, isPreview, bffFbReport, checkCommodityIndexRef, globalConfig, ctaEvent } = useSxpDataSource();
|
|
12691
12692
|
useEditor();
|
|
@@ -12698,14 +12699,14 @@ const CommodityDetailDiroNew$1 = (_a) => {
|
|
|
12698
12699
|
const swiperRef = React.useRef();
|
|
12699
12700
|
const [swiperActiveIndex, setSwiperActiveIndex] = React.useState(0);
|
|
12700
12701
|
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];
|
|
12702
|
+
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
12703
|
let cta = isPost
|
|
12703
|
-
? (
|
|
12704
|
-
: (
|
|
12704
|
+
? (_h = data === null || data === void 0 ? void 0 : data.product) === null || _h === void 0 ? void 0 : _h.bindCta
|
|
12705
|
+
: (_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
12706
|
const position = isPost ? index : 0;
|
|
12706
|
-
if (!isPost && (commodityGroup === null || commodityGroup === void 0 ? void 0 : commodityGroup.open) && ((
|
|
12707
|
+
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
12708
|
checkCommodityIndexRef.current = checkCommodityIndex;
|
|
12708
|
-
const p = (
|
|
12709
|
+
const p = (_v = data === null || data === void 0 ? void 0 : data.video) === null || _v === void 0 ? void 0 : _v.bindProducts[checkCommodityIndex];
|
|
12709
12710
|
product = p;
|
|
12710
12711
|
cta = p === null || p === void 0 ? void 0 : p.bindCta;
|
|
12711
12712
|
}
|
|
@@ -12758,6 +12759,11 @@ const CommodityDetailDiroNew$1 = (_a) => {
|
|
|
12758
12759
|
if (!isPost) {
|
|
12759
12760
|
productView(data, product, cta, viewTime || curTimeRef.current, position);
|
|
12760
12761
|
}
|
|
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 图片浏览时间追踪
|
|
@@ -20263,7 +20278,9 @@ const StructurePage = (_a) => {
|
|
|
20263
20278
|
product: null
|
|
20264
20279
|
};
|
|
20265
20280
|
// 上报 clickCta 事件
|
|
20266
|
-
|
|
20281
|
+
// productGridSection 区域的商品 position 统一传 0(与 ctaExposure 保持一致)
|
|
20282
|
+
const clickCtaPosition = viewPosition === 'productGridSection' ? 0 : (sectionIndex !== undefined ? sectionIndex : 0);
|
|
20283
|
+
ctaEvent === null || ctaEvent === void 0 ? void 0 : ctaEvent(Object.assign({ eventSubject: 'clickCta', eventDescription: 'User clicked the CTA' }, (viewPosition && { viewPosition })), rec, productData, clickCtaPosition);
|
|
20267
20284
|
// ========== 2. Facebook Pixel 和第三方像素上报 ==========
|
|
20268
20285
|
bffFbReport === null || bffFbReport === void 0 ? void 0 : bffFbReport({
|
|
20269
20286
|
eventName: 'ClickCTA',
|
|
@@ -20288,6 +20305,8 @@ const StructurePage = (_a) => {
|
|
|
20288
20305
|
// ========== 打开弹窗前:记录弹窗数据和时间 ==========
|
|
20289
20306
|
// 重置弹窗时间
|
|
20290
20307
|
popupCurTimeRef.current = new Date();
|
|
20308
|
+
// 标记弹窗已打开,防止弹窗导致的 window blur 被误判为用户离开页面
|
|
20309
|
+
isPopupOpenRef.current = true;
|
|
20291
20310
|
// 保存当前弹窗的产品数据,用于全局事件监听
|
|
20292
20311
|
currentPopupDataRef.current = {
|
|
20293
20312
|
productData,
|
|
@@ -20757,6 +20776,18 @@ const StructurePage = (_a) => {
|
|
|
20757
20776
|
// 默认渲染按钮(包装一个 CTAButton 组件来处理曝光事件)
|
|
20758
20777
|
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
20778
|
}, [multiCTAConfig, handleCtaClick, handleCtaExposure, mergeStyles, rest, carouselIndex]);
|
|
20779
|
+
// 监听页面卸载事件(刷新/关闭),设置 pageUnloadingRef 防止旧页面监听器误触发
|
|
20780
|
+
React.useEffect(() => {
|
|
20781
|
+
const handlePageUnload = () => {
|
|
20782
|
+
pageUnloadingRef.current = true;
|
|
20783
|
+
};
|
|
20784
|
+
window.addEventListener('beforeunload', handlePageUnload);
|
|
20785
|
+
window.addEventListener('pagehide', handlePageUnload);
|
|
20786
|
+
return () => {
|
|
20787
|
+
window.removeEventListener('beforeunload', handlePageUnload);
|
|
20788
|
+
window.removeEventListener('pagehide', handlePageUnload);
|
|
20789
|
+
};
|
|
20790
|
+
}, []);
|
|
20760
20791
|
// 页面进入事件上报 - 只在组件挂载时执行一次
|
|
20761
20792
|
React.useEffect(() => {
|
|
20762
20793
|
var _a, _b;
|
|
@@ -20771,6 +20802,10 @@ const StructurePage = (_a) => {
|
|
|
20771
20802
|
}
|
|
20772
20803
|
// 上报 h5LinkEnterFeed 事件
|
|
20773
20804
|
const enterTime = Date.now();
|
|
20805
|
+
// 记录进入时间,用于后续 sessionCompleted 的 duration 计算
|
|
20806
|
+
if (curTime) {
|
|
20807
|
+
curTime.current = new Date(enterTime);
|
|
20808
|
+
}
|
|
20774
20809
|
const getUrlParam = (key) => {
|
|
20775
20810
|
const params = new URLSearchParams(window.location.search);
|
|
20776
20811
|
return params.get(key) || '';
|
|
@@ -20789,6 +20824,11 @@ const StructurePage = (_a) => {
|
|
|
20789
20824
|
clSource: getUrlParam('cl_source')
|
|
20790
20825
|
}
|
|
20791
20826
|
});
|
|
20827
|
+
// 标记首次加载已完成,后续 visibilitychange 的 visible 分支才可以响应
|
|
20828
|
+
// 使用 setTimeout 确保在当前 tick 结束后再设置,避免与 visibilitychange 竞争
|
|
20829
|
+
setTimeout(() => {
|
|
20830
|
+
pageInitializedRef.current = true;
|
|
20831
|
+
}, 0);
|
|
20792
20832
|
}, [bffEventReport]); // 只在挂载时执行一次
|
|
20793
20833
|
// 获取数据 - 只在组件挂载时执行一次
|
|
20794
20834
|
React.useEffect(() => {
|
|
@@ -20804,6 +20844,7 @@ const StructurePage = (_a) => {
|
|
|
20804
20844
|
setLoading(false);
|
|
20805
20845
|
setError(null);
|
|
20806
20846
|
// 使用传入的 multiCTAConfig 作为数据源
|
|
20847
|
+
dataRef.current = propMultiCTAConfig;
|
|
20807
20848
|
setData(propMultiCTAConfig);
|
|
20808
20849
|
return;
|
|
20809
20850
|
}
|
|
@@ -20889,6 +20930,7 @@ const StructurePage = (_a) => {
|
|
|
20889
20930
|
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;
|
|
20890
20931
|
}
|
|
20891
20932
|
if (multiCtaData) {
|
|
20933
|
+
dataRef.current = multiCtaData;
|
|
20892
20934
|
setData(multiCtaData);
|
|
20893
20935
|
// 保存 requestId 到 curReqInfo(用于后续事件上报)
|
|
20894
20936
|
if (((_e = result.data) === null || _e === void 0 ? void 0 : _e.requestId) && setCurReqInfo) {
|
|
@@ -21514,7 +21556,10 @@ const StructurePage = (_a) => {
|
|
|
21514
21556
|
delay: 1000, // 停留 1 秒后触发
|
|
21515
21557
|
onVisible: handleHeroVisible,
|
|
21516
21558
|
onHidden: handleHeroHidden,
|
|
21517
|
-
name: 'Hero'
|
|
21559
|
+
name: 'Hero',
|
|
21560
|
+
// data 加载完成后 heroSectionRef 才会挂载到 DOM,需要将 data 作为额外依赖
|
|
21561
|
+
// 确保 data 就绪后 IntersectionObserver 能重新初始化并正确观察元素
|
|
21562
|
+
deps: [data]
|
|
21518
21563
|
});
|
|
21519
21564
|
// Carousel Section 的曝光检测 ref
|
|
21520
21565
|
const carouselSectionRef = React.useRef(null);
|
|
@@ -21813,36 +21858,65 @@ const StructurePage = (_a) => {
|
|
|
21813
21858
|
// ==================== 全局事件监听:visibilitychange ====================
|
|
21814
21859
|
// 监听页面可见性变化(最小化、切换标签页、返回等)
|
|
21815
21860
|
// 参考 SxpPageRender 的实现
|
|
21861
|
+
//
|
|
21862
|
+
// ⚠️ 重要:以下 ref 用于在事件回调中访问最新值,避免 useEffect 依赖变化导致监听器重新注册
|
|
21863
|
+
// 每次渲染时同步更新,确保回调中始终拿到最新值
|
|
21864
|
+
const bffEventReportRef = React.useRef(bffEventReport);
|
|
21865
|
+
const bffFbReportRef = React.useRef(bffFbReport);
|
|
21866
|
+
const refreshFeSessionRef = React.useRef(refreshFeSession);
|
|
21867
|
+
const globalConfigRef = React.useRef(globalConfig);
|
|
21868
|
+
const selectTagRef = React.useRef(selectTag);
|
|
21869
|
+
const backMainFeedRef = React.useRef(backMainFeed);
|
|
21870
|
+
const handleHeroImageStartEventRef = React.useRef(handleHeroImageStartEvent);
|
|
21871
|
+
const handleHeroImageEndEventRef = React.useRef(handleHeroImageEndEvent);
|
|
21872
|
+
const handleCarouselImageStartEventRef = React.useRef(handleCarouselImageStartEvent);
|
|
21873
|
+
const handleCarouselImageEndEventRef = React.useRef(handleCarouselImageEndEvent);
|
|
21874
|
+
bffEventReportRef.current = bffEventReport;
|
|
21875
|
+
bffFbReportRef.current = bffFbReport;
|
|
21876
|
+
refreshFeSessionRef.current = refreshFeSession;
|
|
21877
|
+
globalConfigRef.current = globalConfig;
|
|
21878
|
+
selectTagRef.current = selectTag;
|
|
21879
|
+
backMainFeedRef.current = backMainFeed;
|
|
21880
|
+
handleHeroImageStartEventRef.current = handleHeroImageStartEvent;
|
|
21881
|
+
handleHeroImageEndEventRef.current = handleHeroImageEndEvent;
|
|
21882
|
+
handleCarouselImageStartEventRef.current = handleCarouselImageStartEvent;
|
|
21883
|
+
handleCarouselImageEndEventRef.current = handleCarouselImageEndEvent;
|
|
21816
21884
|
React.useEffect(() => {
|
|
21885
|
+
// 记录 visibilitychange hidden 发生的时间
|
|
21886
|
+
// visible 时检查距离 hidden 的间隔,若太短(< 2000ms)则认为是刷新导致的,忽略
|
|
21887
|
+
const lastHiddenTime = { current: 0 };
|
|
21888
|
+
const MIN_HIDDEN_DURATION_FOR_FOCUS = 2000;
|
|
21817
21889
|
const handleVisibilityChange = () => {
|
|
21818
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s;
|
|
21890
|
+
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, _7, _8, _9;
|
|
21819
21891
|
if (document.visibilityState === 'hidden') {
|
|
21820
21892
|
// ========== 页面隐藏时 ==========
|
|
21821
21893
|
console.log('[StructurePage] Page hidden - 触发全局事件');
|
|
21894
|
+
// 记录隐藏时间,用于 visible 时判断是否是刷新导致的(间隔太短则忽略)
|
|
21895
|
+
lastHiddenTime.current = Date.now();
|
|
21822
21896
|
// 0. 上报当前可见的 post/product 的离开事件
|
|
21823
21897
|
console.log('[visibilitychange] 页面隐藏,当前可见的 products 数量:', visibleProducts.current.length);
|
|
21824
21898
|
// Hero Section: 如果是图片且可见,上报图片离开事件
|
|
21825
|
-
if (heroIsVisible.current && (
|
|
21826
|
-
const item =
|
|
21827
|
-
if (!item.url && ((
|
|
21899
|
+
if (heroIsVisible.current && ((_a = dataRef.current) === null || _a === void 0 ? void 0 : _a.heroSection)) {
|
|
21900
|
+
const item = dataRef.current.heroSection;
|
|
21901
|
+
if (!item.url && ((_b = item.imgUrls) === null || _b === void 0 ? void 0 : _b[0])) {
|
|
21828
21902
|
console.log('[visibilitychange] 页面隐藏,上报 Hero 图片离开事件');
|
|
21829
|
-
|
|
21903
|
+
handleHeroImageEndEventRef.current();
|
|
21830
21904
|
}
|
|
21831
21905
|
}
|
|
21832
21906
|
// Carousel Section: 如果是图片且可见,上报图片离开事件
|
|
21833
|
-
if (carouselIsVisible.current && (
|
|
21907
|
+
if (carouselIsVisible.current && ((_c = dataRef.current) === null || _c === void 0 ? void 0 : _c.carouselSection)) {
|
|
21834
21908
|
const currentIndex = currentCarouselIndexRef.current;
|
|
21835
|
-
const currentItem =
|
|
21909
|
+
const currentItem = dataRef.current.carouselSection[currentIndex];
|
|
21836
21910
|
if (currentItem && !currentItem.url) {
|
|
21837
21911
|
console.log('[visibilitychange] 页面隐藏,上报 Carousel 图片离开事件, index:', currentIndex);
|
|
21838
|
-
|
|
21912
|
+
handleCarouselImageEndEventRef.current(currentIndex);
|
|
21839
21913
|
}
|
|
21840
21914
|
}
|
|
21841
21915
|
// Products: 上报所有当前可见的 product 的离开事件
|
|
21842
21916
|
// 注意:只上报,不从 visibleProducts 移除,也不删除 productViewStartTime
|
|
21843
21917
|
// 这样页面恢复可见时可以重新记录 startTime,后续滑走/再次最小化能正常上报
|
|
21844
21918
|
visibleProducts.current.forEach((product) => {
|
|
21845
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _j;
|
|
21919
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
|
|
21846
21920
|
const productId = `${(_a = product.productData) === null || _a === void 0 ? void 0 : _a.itemId}-${product.viewPosition}-${product.sectionIndex}`;
|
|
21847
21921
|
const startTime = productViewStartTime.current[productId];
|
|
21848
21922
|
if (!startTime)
|
|
@@ -21855,39 +21929,39 @@ const StructurePage = (_a) => {
|
|
|
21855
21929
|
fromKName = 'recommend page';
|
|
21856
21930
|
else if (product.viewPosition === 'footerSection')
|
|
21857
21931
|
fromKName = 'pdpPage';
|
|
21858
|
-
|
|
21932
|
+
(_b = bffEventReportRef.current) === null || _b === void 0 ? void 0 : _b.call(bffEventReportRef, {
|
|
21859
21933
|
eventInfo: {
|
|
21860
21934
|
eventSubject: 'productView',
|
|
21861
21935
|
eventDescription: 'User browsed the product',
|
|
21862
|
-
productId: ((
|
|
21863
|
-
productName: ((
|
|
21864
|
-
price: ((
|
|
21865
|
-
productCollection: ((
|
|
21936
|
+
productId: ((_c = product.productData) === null || _c === void 0 ? void 0 : _c.itemId) || '',
|
|
21937
|
+
productName: ((_d = product.productData) === null || _d === void 0 ? void 0 : _d.title) || '',
|
|
21938
|
+
price: ((_e = product.productData) === null || _e === void 0 ? void 0 : _e.price) ? `${product.productData.price}` : '0',
|
|
21939
|
+
productCollection: ((_f = product.productData) === null || _f === void 0 ? void 0 : _f.collection) || '',
|
|
21866
21940
|
fromKName,
|
|
21867
21941
|
fromKPage: (location === null || location === void 0 ? void 0 : location.href) || '',
|
|
21868
|
-
contentTags: ((
|
|
21942
|
+
contentTags: ((_g = product.productData) === null || _g === void 0 ? void 0 : _g.tags) ? JSON.stringify(product.productData.tags) : '[]',
|
|
21869
21943
|
position: `${product.sectionIndex || 0}`,
|
|
21870
21944
|
contentId: '',
|
|
21871
21945
|
sceneId: '',
|
|
21872
|
-
ctatId: ((
|
|
21873
|
-
traceInfo: ((
|
|
21946
|
+
ctatId: ((_j = (_h = product.productData) === null || _h === void 0 ? void 0 : _h.bindCta) === null || _j === void 0 ? void 0 : _j.itemId) || '',
|
|
21947
|
+
traceInfo: ((_k = product.productData) === null || _k === void 0 ? void 0 : _k.traceInfo) || '',
|
|
21874
21948
|
timeOnSite: `${timeOnSite}`
|
|
21875
21949
|
}
|
|
21876
21950
|
});
|
|
21877
21951
|
});
|
|
21878
21952
|
// 不清空 visibleProducts,保留快照供页面恢复时使用
|
|
21879
21953
|
// 1. 发送 PAGE_DID_HIDE 事件到事件总线
|
|
21880
|
-
SXP_EVENT_BUS.emit(SXP_EVENT_TYPE.PAGE_DID_HIDE,
|
|
21954
|
+
SXP_EVENT_BUS.emit(SXP_EVENT_TYPE.PAGE_DID_HIDE, dataRef.current);
|
|
21881
21955
|
// 2. 如果有打开的弹窗,上报 ExitFeed 事件
|
|
21882
21956
|
if (currentPopupDataRef.current) {
|
|
21883
21957
|
const { productData, viewPosition, sectionIndex } = currentPopupDataRef.current;
|
|
21884
21958
|
// 获取当前 section 的 post 数据
|
|
21885
21959
|
let postData = null;
|
|
21886
|
-
if (viewPosition === 'heroSection' && (
|
|
21887
|
-
postData =
|
|
21960
|
+
if (viewPosition === 'heroSection' && ((_d = dataRef.current) === null || _d === void 0 ? void 0 : _d.heroSection)) {
|
|
21961
|
+
postData = dataRef.current.heroSection;
|
|
21888
21962
|
}
|
|
21889
|
-
else if (viewPosition === 'carouselSection' && (
|
|
21890
|
-
postData =
|
|
21963
|
+
else if (viewPosition === 'carouselSection' && ((_e = dataRef.current) === null || _e === void 0 ? void 0 : _e.carouselSection) && sectionIndex !== undefined) {
|
|
21964
|
+
postData = dataRef.current.carouselSection[sectionIndex];
|
|
21891
21965
|
}
|
|
21892
21966
|
const rec = {
|
|
21893
21967
|
video: {
|
|
@@ -21902,7 +21976,7 @@ const StructurePage = (_a) => {
|
|
|
21902
21976
|
product: null
|
|
21903
21977
|
};
|
|
21904
21978
|
const viewTime = new Date() - popupCurTimeRef.current;
|
|
21905
|
-
|
|
21979
|
+
(_f = bffFbReportRef.current) === null || _f === void 0 ? void 0 : _f.call(bffFbReportRef, {
|
|
21906
21980
|
eventName: 'ExitFeed',
|
|
21907
21981
|
product: productData ? [productData] : undefined,
|
|
21908
21982
|
contentType: 'product',
|
|
@@ -21915,11 +21989,12 @@ const StructurePage = (_a) => {
|
|
|
21915
21989
|
}
|
|
21916
21990
|
// 3. 刷新 Session(处理 Session 过期)
|
|
21917
21991
|
// 只有在非 organic menu 模式下才刷新 Session(与非 multi-cta 逻辑一致)
|
|
21918
|
-
if ((
|
|
21919
|
-
const isExpire =
|
|
21992
|
+
if (((_g = globalConfigRef.current) === null || _g === void 0 ? void 0 : _g.playbook) !== 'organic menu' && refreshFeSessionRef.current && curTime) {
|
|
21993
|
+
const isExpire = refreshFeSessionRef.current(false, (reason) => {
|
|
21994
|
+
var _a;
|
|
21920
21995
|
console.log('[StructurePage] Session expired:', reason);
|
|
21921
21996
|
// Session 过期时的回调处理
|
|
21922
|
-
|
|
21997
|
+
(_a = bffEventReportRef.current) === null || _a === void 0 ? void 0 : _a.call(bffEventReportRef, {
|
|
21923
21998
|
eventInfo: {
|
|
21924
21999
|
eventSubject: 'sessionExpired',
|
|
21925
22000
|
eventDescription: 'User session has expired',
|
|
@@ -21940,16 +22015,16 @@ const StructurePage = (_a) => {
|
|
|
21940
22015
|
if (currentPopupDataRef.current) {
|
|
21941
22016
|
const { productData, viewPosition, sectionIndex } = currentPopupDataRef.current;
|
|
21942
22017
|
// 获取 contentId 和 sceneId(从对应的 post/image 数据中)
|
|
21943
|
-
if (viewPosition === 'heroSection' && (
|
|
21944
|
-
contentId =
|
|
21945
|
-
sceneId = ((
|
|
21946
|
-
ctatId = ((
|
|
22018
|
+
if (viewPosition === 'heroSection' && ((_h = dataRef.current) === null || _h === void 0 ? void 0 : _h.heroSection)) {
|
|
22019
|
+
contentId = dataRef.current.heroSection.itemId || '';
|
|
22020
|
+
sceneId = ((_j = dataRef.current.heroSection.scene) === null || _j === void 0 ? void 0 : _j.sceneId) || '';
|
|
22021
|
+
ctatId = ((_k = dataRef.current.heroSection.bindCta) === null || _k === void 0 ? void 0 : _k.itemId) || '';
|
|
21947
22022
|
}
|
|
21948
|
-
else if (viewPosition === 'carouselSection' && (
|
|
21949
|
-
const carouselItem =
|
|
22023
|
+
else if (viewPosition === 'carouselSection' && ((_l = dataRef.current) === null || _l === void 0 ? void 0 : _l.carouselSection) && sectionIndex !== undefined) {
|
|
22024
|
+
const carouselItem = dataRef.current.carouselSection[sectionIndex];
|
|
21950
22025
|
contentId = (carouselItem === null || carouselItem === void 0 ? void 0 : carouselItem.itemId) || '';
|
|
21951
|
-
sceneId = ((
|
|
21952
|
-
ctatId = ((
|
|
22026
|
+
sceneId = ((_m = carouselItem === null || carouselItem === void 0 ? void 0 : carouselItem.scene) === null || _m === void 0 ? void 0 : _m.sceneId) || '';
|
|
22027
|
+
ctatId = ((_o = carouselItem === null || carouselItem === void 0 ? void 0 : carouselItem.bindCta) === null || _o === void 0 ? void 0 : _o.itemId) || '';
|
|
21953
22028
|
}
|
|
21954
22029
|
// 获取 productId
|
|
21955
22030
|
productId = (productData === null || productData === void 0 ? void 0 : productData.itemId) || '';
|
|
@@ -21957,23 +22032,23 @@ const StructurePage = (_a) => {
|
|
|
21957
22032
|
// 2. 如果没有弹窗,从当前可见的内容中获取
|
|
21958
22033
|
else {
|
|
21959
22034
|
// 优先从 Hero Section 获取(如果可见)
|
|
21960
|
-
if (heroIsVisible.current && (
|
|
21961
|
-
contentId =
|
|
21962
|
-
sceneId = ((
|
|
21963
|
-
ctatId = ((
|
|
22035
|
+
if (heroIsVisible.current && ((_p = dataRef.current) === null || _p === void 0 ? void 0 : _p.heroSection)) {
|
|
22036
|
+
contentId = dataRef.current.heroSection.itemId || '';
|
|
22037
|
+
sceneId = ((_q = dataRef.current.heroSection.scene) === null || _q === void 0 ? void 0 : _q.sceneId) || '';
|
|
22038
|
+
ctatId = ((_r = dataRef.current.heroSection.bindCta) === null || _r === void 0 ? void 0 : _r.itemId) || '';
|
|
21964
22039
|
// 如果 Hero 有绑定的产品,获取第一个产品的 ID
|
|
21965
|
-
if (
|
|
21966
|
-
productId =
|
|
22040
|
+
if (dataRef.current.heroSection.bindProducts && dataRef.current.heroSection.bindProducts.length > 0) {
|
|
22041
|
+
productId = dataRef.current.heroSection.bindProducts[0].itemId || '';
|
|
21967
22042
|
}
|
|
21968
22043
|
}
|
|
21969
22044
|
// 其次从 Carousel Section 获取(如果可见)
|
|
21970
|
-
else if (carouselIsVisible.current && (
|
|
22045
|
+
else if (carouselIsVisible.current && ((_s = dataRef.current) === null || _s === void 0 ? void 0 : _s.carouselSection)) {
|
|
21971
22046
|
const currentIndex = currentCarouselIndexRef.current;
|
|
21972
|
-
const currentItem =
|
|
22047
|
+
const currentItem = dataRef.current.carouselSection[currentIndex];
|
|
21973
22048
|
if (currentItem) {
|
|
21974
22049
|
contentId = currentItem.itemId || '';
|
|
21975
|
-
sceneId = ((
|
|
21976
|
-
ctatId = ((
|
|
22050
|
+
sceneId = ((_t = currentItem.scene) === null || _t === void 0 ? void 0 : _t.sceneId) || '';
|
|
22051
|
+
ctatId = ((_u = currentItem.bindCta) === null || _u === void 0 ? void 0 : _u.itemId) || '';
|
|
21977
22052
|
// 如果 Carousel 有绑定的产品,获取第一个产品的 ID
|
|
21978
22053
|
if (currentItem.bindProducts && currentItem.bindProducts.length > 0) {
|
|
21979
22054
|
productId = currentItem.bindProducts[0].itemId || '';
|
|
@@ -21983,24 +22058,24 @@ const StructurePage = (_a) => {
|
|
|
21983
22058
|
// 最后从当前可见的产品列表中获取(如果有)
|
|
21984
22059
|
else if (visibleProducts.current.length > 0) {
|
|
21985
22060
|
const firstVisibleProduct = visibleProducts.current[0];
|
|
21986
|
-
productId = ((
|
|
22061
|
+
productId = ((_v = firstVisibleProduct.productData) === null || _v === void 0 ? void 0 : _v.itemId) || '';
|
|
21987
22062
|
// 尝试获取对应的 contentId
|
|
21988
|
-
if (firstVisibleProduct.viewPosition === 'heroSection' && (
|
|
21989
|
-
contentId =
|
|
21990
|
-
sceneId = ((
|
|
21991
|
-
ctatId = ((
|
|
22063
|
+
if (firstVisibleProduct.viewPosition === 'heroSection' && ((_w = dataRef.current) === null || _w === void 0 ? void 0 : _w.heroSection)) {
|
|
22064
|
+
contentId = dataRef.current.heroSection.itemId || '';
|
|
22065
|
+
sceneId = ((_x = dataRef.current.heroSection.scene) === null || _x === void 0 ? void 0 : _x.sceneId) || '';
|
|
22066
|
+
ctatId = ((_y = dataRef.current.heroSection.bindCta) === null || _y === void 0 ? void 0 : _y.itemId) || '';
|
|
21992
22067
|
}
|
|
21993
|
-
else if (firstVisibleProduct.viewPosition === 'carouselSection' && (
|
|
21994
|
-
const carouselItem =
|
|
22068
|
+
else if (firstVisibleProduct.viewPosition === 'carouselSection' && ((_z = dataRef.current) === null || _z === void 0 ? void 0 : _z.carouselSection)) {
|
|
22069
|
+
const carouselItem = dataRef.current.carouselSection[firstVisibleProduct.sectionIndex];
|
|
21995
22070
|
if (carouselItem) {
|
|
21996
22071
|
contentId = carouselItem.itemId || '';
|
|
21997
|
-
sceneId = ((
|
|
21998
|
-
ctatId = ((
|
|
22072
|
+
sceneId = ((_0 = carouselItem.scene) === null || _0 === void 0 ? void 0 : _0.sceneId) || '';
|
|
22073
|
+
ctatId = ((_1 = carouselItem.bindCta) === null || _1 === void 0 ? void 0 : _1.itemId) || '';
|
|
21999
22074
|
}
|
|
22000
22075
|
}
|
|
22001
22076
|
}
|
|
22002
22077
|
}
|
|
22003
|
-
|
|
22078
|
+
(_2 = bffEventReportRef.current) === null || _2 === void 0 ? void 0 : _2.call(bffEventReportRef, {
|
|
22004
22079
|
eventInfo: {
|
|
22005
22080
|
eventSubject: 'sessionCompleted',
|
|
22006
22081
|
eventDescription: 'User session completed normally',
|
|
@@ -22017,14 +22092,33 @@ const StructurePage = (_a) => {
|
|
|
22017
22092
|
else if (document.visibilityState === 'visible') {
|
|
22018
22093
|
// ========== 页面可见时 ==========
|
|
22019
22094
|
console.log('[StructurePage] Page visible - 触发全局事件');
|
|
22095
|
+
// 如果页面尚未完成首次加载(挂载时的 h5LinkEnterFeed 还未上报),
|
|
22096
|
+
// 则跳过此次 visibilitychange visible 处理,避免刷新时重复上报
|
|
22097
|
+
if (!pageInitializedRef.current) {
|
|
22098
|
+
console.log('[StructurePage] 页面尚未初始化完成,跳过 visibilitychange visible 处理');
|
|
22099
|
+
return;
|
|
22100
|
+
}
|
|
22101
|
+
// 如果页面正在卸载(刷新/关闭),跳过处理,避免旧页面监听器误触发
|
|
22102
|
+
if (pageUnloadingRef.current) {
|
|
22103
|
+
console.log('[StructurePage] 页面正在卸载,跳过 visibilitychange visible 处理');
|
|
22104
|
+
return;
|
|
22105
|
+
}
|
|
22106
|
+
// 如果距离上次 hidden 的时间太短(< 2000ms),说明是刷新导致的 visible,忽略
|
|
22107
|
+
if (lastHiddenTime.current > 0) {
|
|
22108
|
+
const hiddenDuration = Date.now() - lastHiddenTime.current;
|
|
22109
|
+
if (hiddenDuration < MIN_HIDDEN_DURATION_FOR_FOCUS) {
|
|
22110
|
+
console.log(`[StructurePage] visibilitychange visible 被忽略(距离 hidden 仅 ${hiddenDuration}ms,可能是刷新导致)`);
|
|
22111
|
+
return;
|
|
22112
|
+
}
|
|
22113
|
+
}
|
|
22020
22114
|
// ⚠️ 重要:必须先刷新 Session,再上报事件(使用最新的 Session ID)
|
|
22021
22115
|
// 1. 刷新 Session(根据配置决定)
|
|
22022
|
-
if (
|
|
22023
|
-
|
|
22116
|
+
if (refreshFeSessionRef.current) {
|
|
22117
|
+
refreshFeSessionRef.current(false);
|
|
22024
22118
|
}
|
|
22025
22119
|
// 2. 如果未启用 session 配置,则强制刷新 Session ID(与非 multi-cta 逻辑一致)
|
|
22026
22120
|
// ⚠️ 必须在上报事件之前刷新,这样上报的事件才会使用最新的 Session ID
|
|
22027
|
-
if (!((
|
|
22121
|
+
if (!((_4 = (_3 = globalConfigRef.current) === null || _3 === void 0 ? void 0 : _3.session) === null || _4 === void 0 ? void 0 : _4.enable)) {
|
|
22028
22122
|
refreshFeSessionId();
|
|
22029
22123
|
console.log('[StructurePage] Session 未启用,强制刷新 Session ID');
|
|
22030
22124
|
}
|
|
@@ -22037,7 +22131,7 @@ const StructurePage = (_a) => {
|
|
|
22037
22131
|
if (curTime) {
|
|
22038
22132
|
curTime.current = time;
|
|
22039
22133
|
}
|
|
22040
|
-
|
|
22134
|
+
(_5 = bffEventReportRef.current) === null || _5 === void 0 ? void 0 : _5.call(bffEventReportRef, {
|
|
22041
22135
|
eventInfo: {
|
|
22042
22136
|
eventSubject: 'h5LinkEnterFeed',
|
|
22043
22137
|
eventDescription: 'User enter h5 link',
|
|
@@ -22047,15 +22141,15 @@ const StructurePage = (_a) => {
|
|
|
22047
22141
|
utmId: getUrlParamByKey('utm_id'),
|
|
22048
22142
|
utmContent: getUrlParamByKey('utm_content'),
|
|
22049
22143
|
enterTime: Math.floor(time / 1000) + '',
|
|
22050
|
-
enterUrl: ((
|
|
22144
|
+
enterUrl: ((_6 = window === null || window === void 0 ? void 0 : window.location) === null || _6 === void 0 ? void 0 : _6.href) || ''
|
|
22051
22145
|
},
|
|
22052
22146
|
reportLayId: false
|
|
22053
22147
|
});
|
|
22054
22148
|
// 3. 上报 backMainFeed 事件(从外部返回)
|
|
22055
|
-
|
|
22149
|
+
backMainFeedRef.current('external', selectTagRef.current);
|
|
22056
22150
|
// 4. 发送 PAGE_DID_SHOW 事件到事件总线(延迟 100ms,与 SxpPageRender 保持一致)
|
|
22057
22151
|
setTimeout(() => {
|
|
22058
|
-
SXP_EVENT_BUS.emit(SXP_EVENT_TYPE.PAGE_DID_SHOW,
|
|
22152
|
+
SXP_EVENT_BUS.emit(SXP_EVENT_TYPE.PAGE_DID_SHOW, dataRef.current);
|
|
22059
22153
|
}, 100);
|
|
22060
22154
|
// 4. 如果有打开的弹窗,重置弹窗时间
|
|
22061
22155
|
if (currentPopupDataRef.current) {
|
|
@@ -22065,24 +22159,24 @@ const StructurePage = (_a) => {
|
|
|
22065
22159
|
// 5. 上报当前可见的 post/product 的进入事件
|
|
22066
22160
|
console.log('[visibilitychange] 页面可见,需要重新上报的 products 数量:', visibleProducts.current.length);
|
|
22067
22161
|
// Hero Section: 如果是图片且可见,上报图片进入事件
|
|
22068
|
-
if (heroIsVisible.current && (
|
|
22069
|
-
const item =
|
|
22070
|
-
if (!item.url && ((
|
|
22162
|
+
if (heroIsVisible.current && ((_7 = dataRef.current) === null || _7 === void 0 ? void 0 : _7.heroSection)) {
|
|
22163
|
+
const item = dataRef.current.heroSection;
|
|
22164
|
+
if (!item.url && ((_8 = item.imgUrls) === null || _8 === void 0 ? void 0 : _8[0])) {
|
|
22071
22165
|
console.log('[visibilitychange] 页面可见,上报 Hero 图片进入事件');
|
|
22072
|
-
|
|
22166
|
+
handleHeroImageStartEventRef.current();
|
|
22073
22167
|
}
|
|
22074
22168
|
}
|
|
22075
22169
|
// Carousel Section: 如果是图片且可见,上报图片进入事件
|
|
22076
|
-
if (carouselIsVisible.current && (
|
|
22170
|
+
if (carouselIsVisible.current && ((_9 = dataRef.current) === null || _9 === void 0 ? void 0 : _9.carouselSection)) {
|
|
22077
22171
|
const currentIndex = currentCarouselIndexRef.current;
|
|
22078
|
-
const currentItem =
|
|
22172
|
+
const currentItem = dataRef.current.carouselSection[currentIndex];
|
|
22079
22173
|
if (currentItem && !currentItem.url) {
|
|
22080
22174
|
console.log('[visibilitychange] 页面可见,当前是图片, index:', currentIndex);
|
|
22081
22175
|
// 检查图片是否已加载
|
|
22082
22176
|
if (carouselImageLoadStartTime.current[currentIndex] > 0) {
|
|
22083
22177
|
// 图片已加载,立即上报
|
|
22084
22178
|
console.log('[visibilitychange] 图片已加载,上报 Carousel 图片进入事件');
|
|
22085
|
-
|
|
22179
|
+
handleCarouselImageStartEventRef.current(currentIndex, carouselImageLoadTime.current[currentIndex]);
|
|
22086
22180
|
}
|
|
22087
22181
|
else {
|
|
22088
22182
|
// 图片未加载,标记为待上报,等图片加载完成后触发
|
|
@@ -22101,74 +22195,15 @@ const StructurePage = (_a) => {
|
|
|
22101
22195
|
});
|
|
22102
22196
|
}
|
|
22103
22197
|
};
|
|
22104
|
-
//
|
|
22105
|
-
//
|
|
22106
|
-
const handleWindowBlur = () => {
|
|
22107
|
-
// 窗口失去焦点(缩小到 Dock / 切换到其他 App)
|
|
22108
|
-
// 与 visibilitychange hidden 分支对齐:刷新 Session
|
|
22109
|
-
if ((globalConfig === null || globalConfig === void 0 ? void 0 : globalConfig.playbook) !== 'organic menu' && refreshFeSession && curTime) {
|
|
22110
|
-
refreshFeSession(false);
|
|
22111
|
-
}
|
|
22112
|
-
};
|
|
22113
|
-
const handleWindowFocus = () => {
|
|
22114
|
-
var _a, _b;
|
|
22115
|
-
// 窗口重新获得焦点(从 Dock 还原 / 切回浏览器)
|
|
22116
|
-
// 与 visibilitychange visible 分支对齐:刷新 Session ID 并上报进入事件
|
|
22117
|
-
if (refreshFeSession) {
|
|
22118
|
-
refreshFeSession(false);
|
|
22119
|
-
}
|
|
22120
|
-
if (!((_a = globalConfig === null || globalConfig === void 0 ? void 0 : globalConfig.session) === null || _a === void 0 ? void 0 : _a.enable)) {
|
|
22121
|
-
refreshFeSessionId();
|
|
22122
|
-
}
|
|
22123
|
-
const getUrlParamByKey = (key) => {
|
|
22124
|
-
const urlParams = new URLSearchParams(window.location.search);
|
|
22125
|
-
return urlParams.get(key) || '';
|
|
22126
|
-
};
|
|
22127
|
-
const time = new Date();
|
|
22128
|
-
if (curTime)
|
|
22129
|
-
curTime.current = time;
|
|
22130
|
-
bffEventReport === null || bffEventReport === void 0 ? void 0 : bffEventReport({
|
|
22131
|
-
eventInfo: {
|
|
22132
|
-
eventSubject: 'h5LinkEnterFeed',
|
|
22133
|
-
eventDescription: 'User enter h5 link',
|
|
22134
|
-
utmSource: getUrlParamByKey('utm_source'),
|
|
22135
|
-
utmMedium: getUrlParamByKey('utm_medium'),
|
|
22136
|
-
utmCampaign: getUrlParamByKey('utm_campaign'),
|
|
22137
|
-
utmId: getUrlParamByKey('utm_id'),
|
|
22138
|
-
utmContent: getUrlParamByKey('utm_content'),
|
|
22139
|
-
enterTime: Math.floor(time / 1000) + '',
|
|
22140
|
-
enterUrl: ((_b = window === null || window === void 0 ? void 0 : window.location) === null || _b === void 0 ? void 0 : _b.href) || ''
|
|
22141
|
-
},
|
|
22142
|
-
reportLayId: false
|
|
22143
|
-
});
|
|
22144
|
-
setTimeout(() => {
|
|
22145
|
-
SXP_EVENT_BUS.emit(SXP_EVENT_TYPE.PAGE_DID_SHOW, data);
|
|
22146
|
-
}, 100);
|
|
22147
|
-
};
|
|
22148
|
-
// 添加事件监听
|
|
22198
|
+
// 添加事件监听(只使用 visibilitychange,不使用 window blur/focus)
|
|
22199
|
+
// window blur/focus 会被页面内点击、刷新等操作误触发,难以可靠区分,已移除
|
|
22149
22200
|
document.addEventListener('visibilitychange', handleVisibilityChange);
|
|
22150
|
-
window.addEventListener('blur', handleWindowBlur);
|
|
22151
|
-
window.addEventListener('focus', handleWindowFocus);
|
|
22152
22201
|
// 清理函数
|
|
22153
22202
|
return () => {
|
|
22154
22203
|
document.removeEventListener('visibilitychange', handleVisibilityChange);
|
|
22155
|
-
window.removeEventListener('blur', handleWindowBlur);
|
|
22156
|
-
window.removeEventListener('focus', handleWindowFocus);
|
|
22157
22204
|
};
|
|
22158
|
-
|
|
22159
|
-
|
|
22160
|
-
bffFbReport,
|
|
22161
|
-
bffEventReport,
|
|
22162
|
-
refreshFeSession,
|
|
22163
|
-
curTime,
|
|
22164
|
-
globalConfig,
|
|
22165
|
-
handleHeroImageStartEvent,
|
|
22166
|
-
handleHeroImageEndEvent,
|
|
22167
|
-
handleCarouselImageStartEvent,
|
|
22168
|
-
handleCarouselImageEndEvent,
|
|
22169
|
-
backMainFeed,
|
|
22170
|
-
selectTag
|
|
22171
|
-
]);
|
|
22205
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
22206
|
+
}, []); // 只在挂载时注册一次,所有依赖通过 ref 访问最新值,避免重新注册导致重复上报
|
|
22172
22207
|
// ==================== 初始化弹窗时间记录 ====================
|
|
22173
22208
|
React.useEffect(() => {
|
|
22174
22209
|
const initTime = () => {
|
|
@@ -22232,8 +22267,9 @@ const StructurePage = (_a) => {
|
|
|
22232
22267
|
productId: productData === null || productData === void 0 ? void 0 : productData.itemId,
|
|
22233
22268
|
engagement_type: 'close_popup'
|
|
22234
22269
|
});
|
|
22235
|
-
//
|
|
22270
|
+
// 清空弹窗数据引用,并重置弹窗打开标记
|
|
22236
22271
|
currentPopupDataRef.current = null;
|
|
22272
|
+
isPopupOpenRef.current = false;
|
|
22237
22273
|
}
|
|
22238
22274
|
wasPopupOpen = isPopupOpen;
|
|
22239
22275
|
};
|