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 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
- }, [ref, threshold, delay, name]);
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
- ? (_g = data === null || data === void 0 ? void 0 : data.product) === null || _g === void 0 ? void 0 : _g.bindCta
11317
- : (_k = (_j = (_h = data === null || data === void 0 ? void 0 : data.video) === null || _h === void 0 ? void 0 : _h.bindProduct) === null || _j === void 0 ? void 0 : _j.bindCta) !== null && _k !== void 0 ? _k : (_o = (_m = (_l = data === null || data === void 0 ? void 0 : data.video) === null || _l === void 0 ? void 0 : _l.bindProducts) === null || _m === void 0 ? void 0 : _m[0]) === null || _o === void 0 ? void 0 : _o.bindCta;
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) && ((_p = data === null || data === void 0 ? void 0 : data.video) === null || _p === void 0 ? void 0 : _p.bindProducts) && ((_r = (_q = data === null || data === void 0 ? void 0 : data.video) === null || _q === void 0 ? void 0 : _q.bindProducts) === null || _r === void 0 ? void 0 : _r.length) > 0) {
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 = (_s = data === null || data === void 0 ? void 0 : data.video) === null || _s === void 0 ? void 0 : _s.bindProducts[checkCommodityIndex];
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: (_t = commodityStyles === null || commodityStyles === void 0 ? void 0 : commodityStyles.price) === null || _t === void 0 ? void 0 : _t.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 : (_u = style === null || style === void 0 ? void 0 : style.width) !== null && _u !== void 0 ? _u : window.innerWidth) - ((_v = popupBg === null || popupBg === void 0 ? void 0 : popupBg.horizontalMargin) !== null && _v !== void 0 ? _v : 0) * 2;
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 && ((_w = product === null || product === void 0 ? void 0 : product.homePage) === null || _w === void 0 ? void 0 : _w.length) > 0 && (React.createElement(Swiper, Object.assign({ height: height, modules: [Pagination, Autoplay, ...(isAlly ? [Navigation, A11y, Mousewheel, Keyboard] : [])], pagination: {
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: (_x = swiper === null || swiper === void 0 ? void 0 : swiper.dotsMarginBottom) !== null && _x !== void 0 ? _x : 0, fontSize: '14px' } }, ((swiper === null || swiper === void 0 ? void 0 : swiper.dotsBgColor) && {
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, (_y = product === null || product === void 0 ? void 0 : product.homePage) === null || _y === void 0 ? void 0 : _y.map((src, srcKey) => {
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
- !((_z = product === null || product === void 0 ? void 0 : product.homePage) === null || _z === void 0 ? void 0 : _z.length) && (React.createElement("div", { className: css.css({
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: (_0 = sxpParameter === null || sxpParameter === void 0 ? void 0 : sxpParameter.bottom_image) !== null && _0 !== void 0 ? _0 : bottom_image, alt: 'pdp image' }))),
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
- ? (_g = data === null || data === void 0 ? void 0 : data.product) === null || _g === void 0 ? void 0 : _g.bindCta
12704
- : (_k = (_j = (_h = data === null || data === void 0 ? void 0 : data.video) === null || _h === void 0 ? void 0 : _h.bindProduct) === null || _j === void 0 ? void 0 : _j.bindCta) !== null && _k !== void 0 ? _k : (_o = (_m = (_l = data === null || data === void 0 ? void 0 : data.video) === null || _l === void 0 ? void 0 : _l.bindProducts) === null || _m === void 0 ? void 0 : _m[0]) === null || _o === void 0 ? void 0 : _o.bindCta;
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) && ((_p = data === null || data === void 0 ? void 0 : data.video) === null || _p === void 0 ? void 0 : _p.bindProducts) && ((_r = (_q = data === null || data === void 0 ? void 0 : data.video) === null || _q === void 0 ? void 0 : _q.bindProducts) === null || _r === void 0 ? void 0 : _r.length) > 0) {
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 = (_s = data === null || data === void 0 ? void 0 : data.video) === null || _s === void 0 ? void 0 : _s.bindProducts[checkCommodityIndex];
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: (_t = commodityStyles === null || commodityStyles === void 0 ? void 0 : commodityStyles.price) === null || _t === void 0 ? void 0 : _t.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 : (_u = style === null || style === void 0 ? void 0 : style.width) !== null && _u !== void 0 ? _u : window.innerWidth) - ((_v = popupBg === null || popupBg === void 0 ? void 0 : popupBg.horizontalMargin) !== null && _v !== void 0 ? _v : 0) * 2;
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, (_w = data === null || data === void 0 ? void 0 : data.video) === null || _w === void 0 ? void 0 : _w.bindProducts, commodityGroup, sxpParameter === null || sxpParameter === void 0 ? void 0 : sxpParameter.bottom_image, bottom_image, handleClick, popupDetailData]);
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 && ((_x = product === null || product === void 0 ? void 0 : product.homePage) === null || _x === void 0 ? void 0 : _x.length) > 0 && (React.createElement(Swiper, Object.assign({ height: height, modules: [Pagination, Autoplay, ...(isAlly ? [Navigation, A11y, Mousewheel, Keyboard] : [])], pagination: {
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: (_y = swiper === null || swiper === void 0 ? void 0 : swiper.dotsMarginBottom) !== null && _y !== void 0 ? _y : 0,
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
- }))) }), (_z = product === null || product === void 0 ? void 0 : product.homePage) === null || _z === void 0 ? void 0 : _z.map((src, srcKey) => {
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
- !((_0 = product === null || product === void 0 ? void 0 : product.homePage) === null || _0 === void 0 ? void 0 : _0.length) && (React.createElement("div", { className: css.css({
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: (_1 = sxpParameter === null || sxpParameter === void 0 ? void 0 : sxpParameter.bottom_image) !== null && _1 !== void 0 ? _1 : bottom_image, alt: 'pdp image' }))),
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((_2 = product === null || product === void 0 ? void 0 : product.title) !== null && _2 !== void 0 ? _2 : 'Large Dior Toujours BagLarge', commodityStyles === null || commodityStyles === void 0 ? void 0 : commodityStyles.title)
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((_3 = product === null || product === void 0 ? void 0 : product.taxInfo) !== null && _3 !== void 0 ? _3 : '税费', commodityStyles === null || commodityStyles === void 0 ? void 0 : commodityStyles.taxInfo)
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": (_4 = cta === null || cta === void 0 ? void 0 : cta.enTitle) !== null && _4 !== void 0 ? _4 : 'Shop now', role: 'button', tabIndex: 0, onClick: handleLink, className: 'pb-commondityDiroNew-btn', style: buttonStyle },
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((_5 = cta === null || cta === void 0 ? void 0 : cta.enTitle) !== null && _5 !== void 0 ? _5 : 'Shop now', buttonStyle)
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
- ctaEvent === null || ctaEvent === void 0 ? void 0 : ctaEvent(Object.assign({ eventSubject: 'clickCta', eventDescription: 'User clicked the CTA' }, (viewPosition && { viewPosition })), rec, productData, sectionIndex !== undefined ? sectionIndex : 0);
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 && (data === null || data === void 0 ? void 0 : data.heroSection)) {
21826
- const item = data.heroSection;
21827
- if (!item.url && ((_a = item.imgUrls) === null || _a === void 0 ? void 0 : _a[0])) {
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
- handleHeroImageEndEvent();
21903
+ handleHeroImageEndEventRef.current();
21830
21904
  }
21831
21905
  }
21832
21906
  // Carousel Section: 如果是图片且可见,上报图片离开事件
21833
- if (carouselIsVisible.current && (data === null || data === void 0 ? void 0 : data.carouselSection)) {
21907
+ if (carouselIsVisible.current && ((_c = dataRef.current) === null || _c === void 0 ? void 0 : _c.carouselSection)) {
21834
21908
  const currentIndex = currentCarouselIndexRef.current;
21835
- const currentItem = data.carouselSection[currentIndex];
21909
+ const currentItem = dataRef.current.carouselSection[currentIndex];
21836
21910
  if (currentItem && !currentItem.url) {
21837
21911
  console.log('[visibilitychange] 页面隐藏,上报 Carousel 图片离开事件, index:', currentIndex);
21838
- handleCarouselImageEndEvent(currentIndex);
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
- bffEventReport === null || bffEventReport === void 0 ? void 0 : bffEventReport({
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: ((_b = product.productData) === null || _b === void 0 ? void 0 : _b.itemId) || '',
21863
- productName: ((_c = product.productData) === null || _c === void 0 ? void 0 : _c.title) || '',
21864
- price: ((_d = product.productData) === null || _d === void 0 ? void 0 : _d.price) ? `${product.productData.price}` : '0',
21865
- productCollection: ((_e = product.productData) === null || _e === void 0 ? void 0 : _e.collection) || '',
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: ((_f = product.productData) === null || _f === void 0 ? void 0 : _f.tags) ? JSON.stringify(product.productData.tags) : '[]',
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: ((_h = (_g = product.productData) === null || _g === void 0 ? void 0 : _g.bindCta) === null || _h === void 0 ? void 0 : _h.itemId) || '',
21873
- traceInfo: ((_j = product.productData) === null || _j === void 0 ? void 0 : _j.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, data);
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' && (data === null || data === void 0 ? void 0 : data.heroSection)) {
21887
- postData = data.heroSection;
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' && (data === null || data === void 0 ? void 0 : data.carouselSection) && sectionIndex !== undefined) {
21890
- postData = data.carouselSection[sectionIndex];
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
- bffFbReport === null || bffFbReport === void 0 ? void 0 : bffFbReport({
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 ((globalConfig === null || globalConfig === void 0 ? void 0 : globalConfig.playbook) !== 'organic menu' && refreshFeSession && curTime) {
21919
- const isExpire = refreshFeSession(false, (reason) => {
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
- bffEventReport === null || bffEventReport === void 0 ? void 0 : bffEventReport({
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' && (data === null || data === void 0 ? void 0 : data.heroSection)) {
21944
- contentId = data.heroSection.itemId || '';
21945
- sceneId = ((_b = data.heroSection.scene) === null || _b === void 0 ? void 0 : _b.sceneId) || '';
21946
- ctatId = ((_c = data.heroSection.bindCta) === null || _c === void 0 ? void 0 : _c.itemId) || '';
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' && (data === null || data === void 0 ? void 0 : data.carouselSection) && sectionIndex !== undefined) {
21949
- const carouselItem = data.carouselSection[sectionIndex];
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 = ((_d = carouselItem === null || carouselItem === void 0 ? void 0 : carouselItem.scene) === null || _d === void 0 ? void 0 : _d.sceneId) || '';
21952
- ctatId = ((_e = carouselItem === null || carouselItem === void 0 ? void 0 : carouselItem.bindCta) === null || _e === void 0 ? void 0 : _e.itemId) || '';
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 && (data === null || data === void 0 ? void 0 : data.heroSection)) {
21961
- contentId = data.heroSection.itemId || '';
21962
- sceneId = ((_f = data.heroSection.scene) === null || _f === void 0 ? void 0 : _f.sceneId) || '';
21963
- ctatId = ((_g = data.heroSection.bindCta) === null || _g === void 0 ? void 0 : _g.itemId) || '';
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 (data.heroSection.bindProducts && data.heroSection.bindProducts.length > 0) {
21966
- productId = data.heroSection.bindProducts[0].itemId || '';
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 && (data === null || data === void 0 ? void 0 : data.carouselSection)) {
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 = data.carouselSection[currentIndex];
22047
+ const currentItem = dataRef.current.carouselSection[currentIndex];
21973
22048
  if (currentItem) {
21974
22049
  contentId = currentItem.itemId || '';
21975
- sceneId = ((_h = currentItem.scene) === null || _h === void 0 ? void 0 : _h.sceneId) || '';
21976
- ctatId = ((_j = currentItem.bindCta) === null || _j === void 0 ? void 0 : _j.itemId) || '';
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 = ((_k = firstVisibleProduct.productData) === null || _k === void 0 ? void 0 : _k.itemId) || '';
22061
+ productId = ((_v = firstVisibleProduct.productData) === null || _v === void 0 ? void 0 : _v.itemId) || '';
21987
22062
  // 尝试获取对应的 contentId
21988
- if (firstVisibleProduct.viewPosition === 'heroSection' && (data === null || data === void 0 ? void 0 : data.heroSection)) {
21989
- contentId = data.heroSection.itemId || '';
21990
- sceneId = ((_l = data.heroSection.scene) === null || _l === void 0 ? void 0 : _l.sceneId) || '';
21991
- ctatId = ((_m = data.heroSection.bindCta) === null || _m === void 0 ? void 0 : _m.itemId) || '';
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' && (data === null || data === void 0 ? void 0 : data.carouselSection)) {
21994
- const carouselItem = data.carouselSection[firstVisibleProduct.sectionIndex];
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 = ((_o = carouselItem.scene) === null || _o === void 0 ? void 0 : _o.sceneId) || '';
21998
- ctatId = ((_p = carouselItem.bindCta) === null || _p === void 0 ? void 0 : _p.itemId) || '';
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
- bffEventReport === null || bffEventReport === void 0 ? void 0 : bffEventReport({
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 (refreshFeSession) {
22023
- refreshFeSession(false);
22116
+ if (refreshFeSessionRef.current) {
22117
+ refreshFeSessionRef.current(false);
22024
22118
  }
22025
22119
  // 2. 如果未启用 session 配置,则强制刷新 Session ID(与非 multi-cta 逻辑一致)
22026
22120
  // ⚠️ 必须在上报事件之前刷新,这样上报的事件才会使用最新的 Session ID
22027
- if (!((_q = globalConfig === null || globalConfig === void 0 ? void 0 : globalConfig.session) === null || _q === void 0 ? void 0 : _q.enable)) {
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
- bffEventReport === null || bffEventReport === void 0 ? void 0 : bffEventReport({
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: ((_r = window === null || window === void 0 ? void 0 : window.location) === null || _r === void 0 ? void 0 : _r.href) || ''
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
- backMainFeed('external', selectTag);
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, data);
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 && (data === null || data === void 0 ? void 0 : data.heroSection)) {
22069
- const item = data.heroSection;
22070
- if (!item.url && ((_s = item.imgUrls) === null || _s === void 0 ? void 0 : _s[0])) {
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
- handleHeroImageStartEvent();
22166
+ handleHeroImageStartEventRef.current();
22073
22167
  }
22074
22168
  }
22075
22169
  // Carousel Section: 如果是图片且可见,上报图片进入事件
22076
- if (carouselIsVisible.current && (data === null || data === void 0 ? void 0 : data.carouselSection)) {
22170
+ if (carouselIsVisible.current && ((_9 = dataRef.current) === null || _9 === void 0 ? void 0 : _9.carouselSection)) {
22077
22171
  const currentIndex = currentCarouselIndexRef.current;
22078
- const currentItem = data.carouselSection[currentIndex];
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
- handleCarouselImageStartEvent(currentIndex, carouselImageLoadTime.current[currentIndex]);
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
- // ========== window blur/focus:处理 Mac 缩小窗口到 Dock 的场景 ==========
22105
- // Mac 点击黄色缩小按钮不会触发 visibilitychange,需要额外监听 window blur/focus
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
- data,
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
  };