pb-sxp-ui 1.20.26 → 1.20.27

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.
Files changed (42) hide show
  1. package/dist/index.cjs +292 -395
  2. package/dist/index.cjs.map +1 -1
  3. package/dist/index.css +355 -291
  4. package/dist/index.js +292 -395
  5. package/dist/index.js.map +1 -1
  6. package/dist/index.min.cjs +6 -6
  7. package/dist/index.min.cjs.map +1 -1
  8. package/dist/index.min.js +6 -6
  9. package/dist/index.min.js.map +1 -1
  10. package/dist/pb-ui.js +292 -395
  11. package/dist/pb-ui.js.map +1 -1
  12. package/dist/pb-ui.min.js +6 -6
  13. package/dist/pb-ui.min.js.map +1 -1
  14. package/es/core/components/StructurePage/index.d.ts +4 -0
  15. package/es/core/components/StructurePage/index.js +8 -1
  16. package/es/core/components/SxpPageRender/Modal/index.d.ts +1 -0
  17. package/es/core/components/SxpPageRender/Modal/index.js +3 -3
  18. package/es/core/components/SxpPageRender/index.d.ts +1 -0
  19. package/es/core/components/SxpPageRender/typing.d.ts +1 -0
  20. package/es/materials/sxp/popup/AddToCart/index.d.ts +1 -27
  21. package/es/materials/sxp/popup/AddToCart/index.js +117 -173
  22. package/es/materials/sxp/popup/AddToCart/index.new.d.ts +8 -0
  23. package/es/materials/sxp/popup/AddToCart/index.new.js +174 -0
  24. package/es/materials/sxp/popup/AddToCart/index.old.d.ts +33 -0
  25. package/es/materials/sxp/popup/AddToCart/index.old.js +299 -0
  26. package/es/materials/sxp/popup/AddToCart/material.js +1 -54
  27. package/es/materials/sxp/popup/CommodityDetailDiroNew/index.js +48 -53
  28. package/lib/core/components/StructurePage/index.d.ts +4 -0
  29. package/lib/core/components/StructurePage/index.js +8 -1
  30. package/lib/core/components/SxpPageRender/Modal/index.d.ts +1 -0
  31. package/lib/core/components/SxpPageRender/Modal/index.js +3 -3
  32. package/lib/core/components/SxpPageRender/index.d.ts +1 -0
  33. package/lib/core/components/SxpPageRender/typing.d.ts +1 -0
  34. package/lib/materials/sxp/popup/AddToCart/index.d.ts +1 -27
  35. package/lib/materials/sxp/popup/AddToCart/index.js +115 -171
  36. package/lib/materials/sxp/popup/AddToCart/index.new.d.ts +8 -0
  37. package/lib/materials/sxp/popup/AddToCart/index.new.js +176 -0
  38. package/lib/materials/sxp/popup/AddToCart/index.old.d.ts +33 -0
  39. package/lib/materials/sxp/popup/AddToCart/index.old.js +301 -0
  40. package/lib/materials/sxp/popup/AddToCart/material.js +1 -54
  41. package/lib/materials/sxp/popup/CommodityDetailDiroNew/index.js +48 -53
  42. package/package.json +1 -1
package/dist/index.cjs CHANGED
@@ -10545,7 +10545,7 @@ function useVisibleHeight() {
10545
10545
  *
10546
10546
  */
10547
10547
  const closeIcon$1 = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAAXNSR0IArs4c6QAAAjhJREFUWEfFlztOw0AQhmeWiJ4CCmpQ5DiRQsIJyAWg5A0lR0AIChDiCJS8ER0cADgBeRSxt4CCDgkaKiq8i+zYeWx2413HEWmiJJv9v535Z2aN8M8vFPT9z3zETD0aAUChUJjwvPFHAJhBhB3Hqd6OAsK2yyucwykAvP38eJX398Z3AJDLlVYR8ToU9Rhj25TWr9KEsKy5dULIGQCMtfZly45TvwsAstm56UwG6wA4FUFwzrdctxZBDcWSy5XWEPG8I84/GcMipdWPtgcsaz5PCHtKG0IuTiqUvjT9U/WYMG2IOPE+AP+LtCB0xKUAAyA2Xbd2o2OG0NQXvTnvhL17D7EPtH9TRCIWwkRcGYGIQgYBABuqPuHXOQBc6pw80lBGwBQiiXhsBHQhkoprA6iM6acjhDQKu5YJZW6XeOI3XJdpvfsdTu52VfXEekD8owQiXGIubpSCbhDbLu8DwKEAd+A41SOdPpE4BS0viFOtvV2iKWqUgn5x/tmS70xR01GuDSCKc86/OCcLgTyyZ0ScDGNhFAktAJV4NFJ9YyaFiAWIE+9uVkkgBgLoig8DMWAa9ro9ynkUdlW5maZDCmB6clmz0k1HH4Cs1Ezbq2p2yEpUuBOKTSZZex00RUWIrltxuuK6EOGDSbGIOPZicpMx6fny650377qNRgBgWeVFQuA+6UjVgREhGIMlSqsPUQqIbZdOOIdZQmCv2axRnU1N1+TzJYsxOEaEV8ep7frPZ7Gd0FTEdP0ft0/kMNdg0eoAAAAASUVORK5CYII=';
10548
- const Modal = ({ visible, onClose, children, modalStyle, padding, popup, schema, fullHeight, isFullScreen = false, openState }) => {
10548
+ const Modal = ({ visible, onClose, children, modalStyle, padding, popup, schema, fullHeight, isFullScreen = false, openState, showCloseButton = true }) => {
10549
10549
  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;
10550
10550
  const { visibleHeight, bottomHeight } = useVisibleHeight();
10551
10551
  const touchRef = React.useRef(null);
@@ -10725,8 +10725,8 @@ const Modal = ({ visible, onClose, children, modalStyle, padding, popup, schema,
10725
10725
  setScrollTop(15 - ((_a = e === null || e === void 0 ? void 0 : e.target) === null || _a === void 0 ? void 0 : _a.scrollTop));
10726
10726
  }
10727
10727
  })), child()),
10728
- React.createElement("button", { className: 'modal-icon-wrapper', role: 'button', "aria-label": 'close button', onClick: onClose, style: { top: scrollTop } },
10729
- React.createElement("img", { src: (globalConfig === null || globalConfig === void 0 ? void 0 : globalConfig.popupCloseIcon) || closeIcon$1, alt: 'close button', className: 'modal-icon' }))))))), modalEleRef.current);
10728
+ showCloseButton && (React.createElement("button", { className: 'modal-icon-wrapper', role: 'button', "aria-label": 'close button', onClick: onClose, style: { top: scrollTop } },
10729
+ React.createElement("img", { src: (globalConfig === null || globalConfig === void 0 ? void 0 : globalConfig.popupCloseIcon) || closeIcon$1, alt: 'close button', className: 'modal-icon' })))))))), modalEleRef.current);
10730
10730
  };
10731
10731
  var Modal$1 = React.memo(Modal);
10732
10732
 
@@ -11914,18 +11914,248 @@ var settingRender$d = [
11914
11914
  }
11915
11915
  ];
11916
11916
 
11917
+ const AddToCartPopup$1 = ({ isActive = true }) => {
11918
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j;
11919
+ const { popupDetailData, globalConfig } = useSxpDataSource();
11920
+ const [productData, setProductData] = React.useState(null);
11921
+ const [selectedOptions, setSelectedOptions] = React.useState({});
11922
+ const [selectedVariant, setSelectedVariant] = React.useState(null);
11923
+ const [quantity, setQuantity] = React.useState(1);
11924
+ const [loading, setLoading] = React.useState(true);
11925
+ const [error, setError] = React.useState(null);
11926
+ const [showImagePreview, setShowImagePreview] = React.useState(false);
11927
+ const [previewImageUrl, setPreviewImageUrl] = React.useState('');
11928
+ // 获取商品数据
11929
+ const data = popupDetailData;
11930
+ const product = (_e = (_b = (_a = data === null || data === void 0 ? void 0 : data.video) === null || _a === void 0 ? void 0 : _a.bindProduct) !== null && _b !== void 0 ? _b : (_d = (_c = data === null || data === void 0 ? void 0 : data.video) === null || _c === void 0 ? void 0 : _c.bindProducts) === null || _d === void 0 ? void 0 : _d[0]) !== null && _e !== void 0 ? _e : data === null || data === void 0 ? void 0 : data.product;
11931
+ // Shopify 配置
11932
+ const shopifyConfig = window.__SHOPIFY_CONFIG__;
11933
+ const shopifyDomain = ((_f = globalConfig === null || globalConfig === void 0 ? void 0 : globalConfig.shopify) === null || _f === void 0 ? void 0 : _f.domain) || (globalConfig === null || globalConfig === void 0 ? void 0 : globalConfig.shopifyDomain) || (shopifyConfig === null || shopifyConfig === void 0 ? void 0 : shopifyConfig.domain) || 'dev-store-749237498237498636.myshopify.com';
11934
+ const storefrontToken = ((_g = globalConfig === null || globalConfig === void 0 ? void 0 : globalConfig.shopify) === null || _g === void 0 ? void 0 : _g.storefrontAccessToken) || (globalConfig === null || globalConfig === void 0 ? void 0 : globalConfig.storefrontAccessToken) || (shopifyConfig === null || shopifyConfig === void 0 ? void 0 : shopifyConfig.storefrontAccessToken) || '77d894c490f79430ce7bd0a7efdff6b7';
11935
+ const productId = (product === null || product === void 0 ? void 0 : product.shopifyId) || (product === null || product === void 0 ? void 0 : product.itemId) || '';
11936
+ // 查询 Shopify 商品数据
11937
+ const fetchProductData = React.useCallback(() => __awaiter(void 0, void 0, void 0, function* () {
11938
+ var _k;
11939
+ if (!productId || !shopifyDomain || !storefrontToken) {
11940
+ setLoading(false);
11941
+ return;
11942
+ }
11943
+ setLoading(true);
11944
+ setError(null);
11945
+ try {
11946
+ const query = `
11947
+ query getProduct($id: ID!) {
11948
+ product(id: $id) {
11949
+ id
11950
+ title
11951
+ images(first: 10) {
11952
+ edges {
11953
+ node {
11954
+ url
11955
+ }
11956
+ }
11957
+ }
11958
+ options {
11959
+ name
11960
+ values
11961
+ }
11962
+ variants(first: 100) {
11963
+ edges {
11964
+ node {
11965
+ id
11966
+ title
11967
+ availableForSale
11968
+ quantityAvailable
11969
+ price {
11970
+ amount
11971
+ currencyCode
11972
+ }
11973
+ image {
11974
+ url
11975
+ }
11976
+ selectedOptions {
11977
+ name
11978
+ value
11979
+ }
11980
+ }
11981
+ }
11982
+ }
11983
+ }
11984
+ }
11985
+ `;
11986
+ const fullProductId = productId.startsWith('gid://') ? productId : `gid://shopify/Product/${productId}`;
11987
+ const response = yield fetch(`https://${shopifyDomain}/api/2024-01/graphql.json`, {
11988
+ method: 'POST',
11989
+ headers: {
11990
+ 'Content-Type': 'application/json',
11991
+ 'X-Shopify-Storefront-Access-Token': storefrontToken
11992
+ },
11993
+ body: JSON.stringify({
11994
+ query,
11995
+ variables: { id: fullProductId }
11996
+ })
11997
+ });
11998
+ const result = yield response.json();
11999
+ if (result.errors) {
12000
+ throw new Error(result.errors[0].message);
12001
+ }
12002
+ console.log('[AddToCart] Shopify Product Data:', result.data.product);
12003
+ console.log('[AddToCart] Options:', (_k = result.data.product) === null || _k === void 0 ? void 0 : _k.options);
12004
+ setProductData(result.data.product);
12005
+ }
12006
+ catch (err) {
12007
+ setError(err instanceof Error ? err.message : 'Failed to load product');
12008
+ console.error('[AddToCartPopup] 加载失败:', err);
12009
+ }
12010
+ finally {
12011
+ setLoading(false);
12012
+ }
12013
+ }), [productId, shopifyDomain, storefrontToken]);
12014
+ React.useEffect(() => {
12015
+ if (isActive) {
12016
+ fetchProductData();
12017
+ }
12018
+ }, [isActive, fetchProductData]);
12019
+ // 根据选中的规格匹配 variant
12020
+ React.useEffect(() => {
12021
+ if (!productData)
12022
+ return;
12023
+ const variants = productData.variants.edges.map(edge => edge.node);
12024
+ const optionsCount = productData.options.length;
12025
+ const selectedCount = Object.keys(selectedOptions).length;
12026
+ if (selectedCount === 0 || selectedCount < optionsCount) {
12027
+ setSelectedVariant(null);
12028
+ return;
12029
+ }
12030
+ const matchedVariant = variants.find(variant => {
12031
+ return variant.selectedOptions.every(option => {
12032
+ return selectedOptions[option.name] === option.value;
12033
+ });
12034
+ });
12035
+ setSelectedVariant(matchedVariant || null);
12036
+ // 当 variant 改变时,如果有库存数量限制,确保数量不超过库存
12037
+ if ((matchedVariant === null || matchedVariant === void 0 ? void 0 : matchedVariant.quantityAvailable) !== undefined && matchedVariant.quantityAvailable > 0) {
12038
+ setQuantity(prev => Math.min(prev, matchedVariant.quantityAvailable));
12039
+ }
12040
+ }, [selectedOptions, productData]);
12041
+ // 处理规格选择
12042
+ const handleOptionSelect = (optionName, value) => {
12043
+ setSelectedOptions(prev => (Object.assign(Object.assign({}, prev), { [optionName]: value })));
12044
+ };
12045
+ // 处理加购
12046
+ const handleAddToCart = () => {
12047
+ if (!selectedVariant) {
12048
+ alert('Please select all options');
12049
+ return;
12050
+ }
12051
+ // 提取 variant ID(去掉 gid://shopify/ProductVariant/ 前缀)
12052
+ const variantId = selectedVariant.id.replace('gid://shopify/ProductVariant/', '');
12053
+ console.log('[AddToCart] 添加到购物车:', {
12054
+ variantId,
12055
+ quantity,
12056
+ shopifyDomain,
12057
+ selectedVariant
12058
+ });
12059
+ // 使用 Shopify 的 /cart/add 接口,通过查询参数添加商品
12060
+ // 这种方式会跳转到购物车页面而不是结算页面
12061
+ const params = new URLSearchParams({
12062
+ id: variantId,
12063
+ quantity: quantity.toString()
12064
+ });
12065
+ const cartUrl = `https://${shopifyDomain}/cart/add?${params.toString()}`;
12066
+ console.log('[AddToCart] 跳转到购物车 URL:', cartUrl);
12067
+ window.location.href = cartUrl;
12068
+ };
12069
+ // 计算总价
12070
+ const totalPrice = selectedVariant
12071
+ ? (parseFloat(selectedVariant.price.amount) * quantity).toFixed(2)
12072
+ : '0.00';
12073
+ if (loading) {
12074
+ return (React.createElement("div", { className: 'add-to-cart-popup' },
12075
+ React.createElement("div", { className: 'loading' }, "Loading...")));
12076
+ }
12077
+ if (error) {
12078
+ return (React.createElement("div", { className: 'add-to-cart-popup' },
12079
+ React.createElement("div", { className: 'error' }, error)));
12080
+ }
12081
+ if (!productData) {
12082
+ return null;
12083
+ }
12084
+ const mainImage = ((_h = productData.images.edges[0]) === null || _h === void 0 ? void 0 : _h.node.url) || '';
12085
+ const variantImage = ((_j = selectedVariant === null || selectedVariant === void 0 ? void 0 : selectedVariant.image) === null || _j === void 0 ? void 0 : _j.url) || mainImage;
12086
+ const maxQuantity = (selectedVariant === null || selectedVariant === void 0 ? void 0 : selectedVariant.quantityAvailable) || 999; // 如果没有库存数据,默认允许最多 999
12087
+ return (React.createElement("div", { className: 'add-to-cart-popup' },
12088
+ React.createElement("div", { className: 'popup-content' },
12089
+ React.createElement("div", { className: 'product-header' },
12090
+ React.createElement("div", { className: 'product-title' }, productData.title)),
12091
+ React.createElement("div", { className: 'variant-detail' },
12092
+ React.createElement("div", { className: 'variant-image-container', onClick: () => {
12093
+ if (variantImage) {
12094
+ setPreviewImageUrl(variantImage);
12095
+ setShowImagePreview(true);
12096
+ }
12097
+ }, style: { cursor: 'pointer' } },
12098
+ React.createElement("img", { src: variantImage, alt: 'Selected variant', className: 'variant-image' })),
12099
+ React.createElement("div", { className: 'variant-info' },
12100
+ React.createElement("div", { className: 'variant-specs-row' },
12101
+ React.createElement("div", { className: 'variant-specs' }, Object.keys(selectedOptions).length > 0 ? (Object.entries(selectedOptions).map(([key, value]) => (React.createElement("span", { key: key, className: 'spec-item' }, value)))) : (React.createElement("span", { className: 'spec-placeholder' }, "Please select options"))),
12102
+ selectedVariant && selectedVariant.quantityAvailable !== undefined && (React.createElement("div", { className: 'stock-info' },
12103
+ "Available: ",
12104
+ selectedVariant.quantityAvailable))),
12105
+ React.createElement("div", { className: 'variant-price-row' },
12106
+ React.createElement("div", { className: 'price' },
12107
+ "$",
12108
+ totalPrice),
12109
+ React.createElement("div", { className: 'quantity-selector' },
12110
+ React.createElement("button", { className: 'qty-btn', onClick: () => setQuantity(Math.max(1, quantity - 1)), disabled: quantity <= 1 }, "\u2212"),
12111
+ React.createElement("span", { className: 'qty-value' }, quantity),
12112
+ React.createElement("button", { className: 'qty-btn', onClick: () => setQuantity(quantity + 1), disabled: !selectedVariant || quantity >= maxQuantity }, "+"))))),
12113
+ React.createElement("div", { className: 'variant-options' }, productData.options.map(option => (React.createElement("div", { key: option.name, className: 'option-group' },
12114
+ React.createElement("div", { className: 'option-label' }, option.name),
12115
+ React.createElement("div", { className: 'option-values' }, option.values.map(value => {
12116
+ // 检查这个选项是否可选(availableForSale = true,如果有 quantityAvailable 则还需 > 0)
12117
+ const isAvailable = productData.variants.edges.some(({ node: variant }) => {
12118
+ const hasThisOption = variant.selectedOptions.some(opt => opt.name === option.name && opt.value === value);
12119
+ if (!hasThisOption || !variant.availableForSale)
12120
+ return false;
12121
+ // 如果有 quantityAvailable 字段,则需要检查库存
12122
+ if (variant.quantityAvailable !== undefined) {
12123
+ return variant.quantityAvailable > 0;
12124
+ }
12125
+ // 没有 quantityAvailable 字段时,只要 availableForSale 为 true 就可选
12126
+ return true;
12127
+ });
12128
+ const isSelected = selectedOptions[option.name] === value;
12129
+ return (React.createElement("button", { key: value, className: `option-btn ${isSelected ? 'selected' : ''} ${!isAvailable ? 'disabled' : ''}`, onClick: () => isAvailable && handleOptionSelect(option.name, value), disabled: !isAvailable }, value));
12130
+ }))))))),
12131
+ React.createElement("div", { className: 'popup-footer' },
12132
+ React.createElement("button", { className: 'add-to-cart-btn', onClick: handleAddToCart, disabled: !selectedVariant }, "Add To Cart")),
12133
+ showImagePreview && previewImageUrl && (React.createElement(Modal$1, { visible: showImagePreview, padding: 0, isFullScreen: true, onClose: () => setShowImagePreview(false) },
12134
+ React.createElement("div", { style: {
12135
+ width: '100%',
12136
+ height: '100%',
12137
+ display: 'flex',
12138
+ alignItems: 'center',
12139
+ justifyContent: 'center',
12140
+ backgroundColor: 'rgba(0, 0, 0, 0.9)'
12141
+ }, onClick: () => setShowImagePreview(false) },
12142
+ React.createElement("img", { src: previewImageUrl, alt: 'Preview', style: {
12143
+ maxWidth: '100%',
12144
+ maxHeight: '100%',
12145
+ objectFit: 'contain'
12146
+ } }))))));
12147
+ };
12148
+
11917
12149
  const CommodityDetailDiroNew$1 = (_a) => {
11918
- 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;
11919
- var { style, isDefault, rec, viewTime, isPost, bottom_image, tipText, swiper, commodityStyles, buttonStyle, index, commodityGroup, popupBg, iframeIcon, commodityImgRatio, isTel, iframeBgColor, isActive = true } = _a, props = __rest(_a, ["style", "isDefault", "rec", "viewTime", "isPost", "bottom_image", "tipText", "swiper", "commodityStyles", "buttonStyle", "index", "commodityGroup", "popupBg", "iframeIcon", "commodityImgRatio", "isTel", "iframeBgColor", "isActive"]);
11920
- React.useState(true);
11921
- const { sxpParameter, popupCurTimeRef, popupDetailData, isPreview, bffFbReport, checkCommodityIndexRef, globalConfig, ctaEvent } = useSxpDataSource();
11922
- const { jumpToWeb, productView } = useEventReport();
11923
- React.useState(false);
11924
- React.useState(false);
11925
- React.useState(true);
12150
+ 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;
12151
+ 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"]);
12152
+ const { sxpParameter, popupCurTimeRef, popupDetailData, setPopupDetailData, isPreview, bffFbReport, checkCommodityIndexRef, globalConfig, ctaEvent } = useSxpDataSource();
12153
+ useEditor();
12154
+ const { productView } = useEventReport();
11926
12155
  const [showModal, setShowModal] = React.useState(false);
11927
12156
  const curTimeRef = React.useRef(null);
11928
12157
  const [show3DModal, setShow3DModal] = React.useState(false);
12158
+ const [showAddToCart, setShowAddToCart] = React.useState(false);
11929
12159
  const [checkCommodityIndex, setCheckCommodityIndex] = React.useState((_b = popupDetailData === null || popupDetailData === void 0 ? void 0 : popupDetailData.multiCheckIndex) !== null && _b !== void 0 ? _b : 0);
11930
12160
  const swiperRef = React.useRef();
11931
12161
  const [swiperActiveIndex, setSwiperActiveIndex] = React.useState(0);
@@ -11942,30 +12172,30 @@ const CommodityDetailDiroNew$1 = (_a) => {
11942
12172
  cta = p === null || p === void 0 ? void 0 : p.bindCta;
11943
12173
  }
11944
12174
  const handleLink = (e) => {
11945
- if (product === null || product === void 0 ? void 0 : product.link) {
11946
- jumpToWeb(e, data, product, cta, position);
11947
- if (!isPost) {
11948
- productView(data, product, cta, viewTime || curTimeRef.current, position);
11949
- }
11950
- else {
11951
- ctaEvent === null || ctaEvent === void 0 ? void 0 : ctaEvent({
11952
- eventSubject: 'clickCta',
11953
- eventDescription: 'User clicked the CTA'
11954
- }, data, product, position);
11955
- bffFbReport === null || bffFbReport === void 0 ? void 0 : bffFbReport({
11956
- eventName: 'ClickCTA',
11957
- product: product ? [product] : undefined,
11958
- contentType: 'product',
11959
- data,
11960
- position,
11961
- cta_text: cta === null || cta === void 0 ? void 0 : cta.enTitle,
11962
- cta_action_type: 'open_external_link',
11963
- target_content_id: product === null || product === void 0 ? void 0 : product.itemId,
11964
- target_url: product.link
11965
- });
11966
- }
11967
- window.location.href = window.getJointUtmLink(product.link);
12175
+ e.preventDefault();
12176
+ // 上报点击事件
12177
+ ctaEvent === null || ctaEvent === void 0 ? void 0 : ctaEvent({
12178
+ eventSubject: 'clickCta',
12179
+ eventDescription: 'User clicked the CTA'
12180
+ }, data, product, position);
12181
+ bffFbReport === null || bffFbReport === void 0 ? void 0 : bffFbReport({
12182
+ eventName: 'ClickCTA',
12183
+ product: product ? [product] : undefined,
12184
+ contentType: 'product',
12185
+ data,
12186
+ position,
12187
+ cta_text: cta === null || cta === void 0 ? void 0 : cta.enTitle,
12188
+ cta_action_type: 'open_internal_popup',
12189
+ target_content_id: product === null || product === void 0 ? void 0 : product.itemId,
12190
+ target_url: product === null || product === void 0 ? void 0 : product.link
12191
+ });
12192
+ if (!isPost) {
12193
+ productView(data, product, cta, viewTime || curTimeRef.current, position);
11968
12194
  }
12195
+ // 更新 popupDetailData,确保 AddToCart 组件能获取到商品数据
12196
+ 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 }));
12197
+ // 打开 AddToCart 弹窗
12198
+ setShowAddToCart(true);
11969
12199
  };
11970
12200
  React.useEffect(() => {
11971
12201
  var _a, _b;
@@ -11986,7 +12216,7 @@ const CommodityDetailDiroNew$1 = (_a) => {
11986
12216
  rec: recData,
11987
12217
  position
11988
12218
  });
11989
- }, [isActive, bffFbReport, isPost]);
12219
+ }, [isActive, bffFbReport, isPost, data, product, position]);
11990
12220
  React.useEffect(() => {
11991
12221
  if (!isActive || isPost)
11992
12222
  return;
@@ -12114,13 +12344,13 @@ Made in Italy` })));
12114
12344
  swiperRef.current.swiper.slideTo(0);
12115
12345
  swiperRef.current.swiper.autoplay.start();
12116
12346
  }
12117
- }, []);
12347
+ }, [popupCurTimeRef, checkCommodityIndexRef]);
12118
12348
  const renderCommodityGroup = React.useCallback(() => {
12119
12349
  var _a, _b, _c;
12120
12350
  if (isPost)
12121
12351
  return;
12122
12352
  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 }));
12123
- }, [checkCommodityIndex]);
12353
+ }, [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]);
12124
12354
  const getDotsAlign = React.useMemo(() => {
12125
12355
  const dotsAlignClass = {
12126
12356
  left: 'commondityDetail-swiper-clickable-left',
@@ -12130,24 +12360,24 @@ Made in Italy` })));
12130
12360
  return dotsAlignClass === null || dotsAlignClass === void 0 ? void 0 : dotsAlignClass[swiper === null || swiper === void 0 ? void 0 : swiper.dotsAlign];
12131
12361
  }, [swiper === null || swiper === void 0 ? void 0 : swiper.dotsAlign]);
12132
12362
  const iframeUrl = product === null || product === void 0 ? void 0 : product.remark;
12363
+ const isAlly = React.useMemo(() => getScreenReader(), []);
12133
12364
  const handleMouseEnter = React.useCallback(() => {
12134
12365
  if (swiperRef.current && swiperRef.current.swiper && isAlly) {
12135
12366
  swiperRef.current.swiper.autoplay.stop();
12136
12367
  }
12137
- }, []);
12368
+ }, [isAlly]);
12138
12369
  const handleMouseLeave = React.useCallback(() => {
12139
12370
  if (swiperRef.current && swiperRef.current.swiper && isAlly) {
12140
12371
  swiperRef.current.swiper.autoplay.start();
12141
12372
  }
12142
- }, []);
12373
+ }, [isAlly]);
12143
12374
  const handleSlideChange = React.useCallback((swiper) => {
12144
12375
  setSwiperActiveIndex(swiper.activeIndex);
12145
12376
  }, []);
12146
- const isAlly = React.useMemo(() => getScreenReader(), []);
12147
12377
  return (React.createElement("div", { className: 'pb-commondityDiroNew' },
12148
12378
  React.createElement("div", Object.assign({ className: css.css(Object.assign(Object.assign({}, style), { transform: 'translate3d(0px, 0px, 0px)' })) }, props),
12149
12379
  React.createElement("div", { style: { position: 'relative' }, onMouseEnter: handleMouseEnter, onMouseLeave: handleMouseLeave },
12150
- 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: {
12380
+ 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: {
12151
12381
  clickable: true,
12152
12382
  bulletActiveClass: 'swipe-item-active-bullet',
12153
12383
  clickableClass: getDotsAlign,
@@ -12164,7 +12394,7 @@ Made in Italy` })));
12164
12394
  : {}), { loop: true, ref: swiperRef, onSlideChange: handleSlideChange, autoplay: {
12165
12395
  delay: (swiper === null || swiper === void 0 ? void 0 : swiper.delay) * 1000
12166
12396
  }, className: css.css(Object.assign(Object.assign({ '.swiper-pagination': {
12167
- bottom: (_x = swiper === null || swiper === void 0 ? void 0 : swiper.dotsMarginBottom) !== null && _x !== void 0 ? _x : 0,
12397
+ bottom: (_y = swiper === null || swiper === void 0 ? void 0 : swiper.dotsMarginBottom) !== null && _y !== void 0 ? _y : 0,
12168
12398
  fontSize: '14px'
12169
12399
  } }, ((swiper === null || swiper === void 0 ? void 0 : swiper.dotsBgColor) && {
12170
12400
  '.swiper-pagination-bullet': {
@@ -12176,7 +12406,7 @@ Made in Italy` })));
12176
12406
  backgroundColor: `${swiper === null || swiper === void 0 ? void 0 : swiper.dotsActiveColor}!important`,
12177
12407
  opacity: 1
12178
12408
  }
12179
- }))) }), (_y = product === null || product === void 0 ? void 0 : product.homePage) === null || _y === void 0 ? void 0 : _y.map((src, srcKey) => {
12409
+ }))) }), (_z = product === null || product === void 0 ? void 0 : product.homePage) === null || _z === void 0 ? void 0 : _z.map((src, srcKey) => {
12180
12410
  var _a;
12181
12411
  return (React.createElement(SwiperSlide, { key: srcKey, "aria-hidden": srcKey !== swiperActiveIndex },
12182
12412
  React.createElement("div", { style: {
@@ -12192,7 +12422,7 @@ Made in Italy` })));
12192
12422
  objectPosition: `50% ${(swiper === null || swiper === void 0 ? void 0 : swiper.translateY) ? (swiper === null || swiper === void 0 ? void 0 : swiper.translateY) + 50 : 50}%`
12193
12423
  }, 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 }))));
12194
12424
  }))),
12195
- !((_z = product === null || product === void 0 ? void 0 : product.homePage) === null || _z === void 0 ? void 0 : _z.length) && (React.createElement("div", { className: css.css({
12425
+ !((_0 = product === null || product === void 0 ? void 0 : product.homePage) === null || _0 === void 0 ? void 0 : _0.length) && (React.createElement("div", { className: css.css({
12196
12426
  height,
12197
12427
  width
12198
12428
  }) },
@@ -12200,7 +12430,7 @@ Made in Italy` })));
12200
12430
  objectFit: 'cover',
12201
12431
  width: '100%',
12202
12432
  height: '100%'
12203
- }), src: (_0 = sxpParameter === null || sxpParameter === void 0 ? void 0 : sxpParameter.bottom_image) !== null && _0 !== void 0 ? _0 : bottom_image, alt: 'pdp image' }))),
12433
+ }), src: (_1 = sxpParameter === null || sxpParameter === void 0 ? void 0 : sxpParameter.bottom_image) !== null && _1 !== void 0 ? _1 : bottom_image, alt: 'pdp image' }))),
12204
12434
  (iframeUrl || !product) && iframeIcon && (React.createElement("div", { style: {
12205
12435
  display: 'flex',
12206
12436
  alignItems: 'center',
@@ -12217,7 +12447,7 @@ Made in Italy` })));
12217
12447
  React.createElement("div", { className: 'pb-commondityDiroNew-content-top' },
12218
12448
  React.createElement("div", { className: 'pb-commondityDiroNew-content-top-left' },
12219
12449
  React.createElement("div", { className: 'pb-commondityDiroNew-content-top-left-title', style: getStyle(commodityStyles === null || commodityStyles === void 0 ? void 0 : commodityStyles.title), dangerouslySetInnerHTML: {
12220
- __html: setFontForText((_1 = product === null || product === void 0 ? void 0 : product.title) !== null && _1 !== void 0 ? _1 : 'Large Dior Toujours BagLarge', commodityStyles === null || commodityStyles === void 0 ? void 0 : commodityStyles.title)
12450
+ __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)
12221
12451
  } }),
12222
12452
  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: {
12223
12453
  __html: setFontForText((product === null || product === void 0 ? void 0 : product.collection) || 'Black Macrocannage CalfskinLarge', commodityStyles === null || commodityStyles === void 0 ? void 0 : commodityStyles.collection)
@@ -12227,11 +12457,11 @@ Made in Italy` })));
12227
12457
  __html: priceText !== null && priceText !== void 0 ? priceText : ''
12228
12458
  } }),
12229
12459
  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: {
12230
- __html: setFontForText((_2 = product === null || product === void 0 ? void 0 : product.taxInfo) !== null && _2 !== void 0 ? _2 : '税费', commodityStyles === null || commodityStyles === void 0 ? void 0 : commodityStyles.taxInfo)
12460
+ __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)
12231
12461
  } }))),
12232
- React.createElement("a", { "aria-label": (_3 = cta === null || cta === void 0 ? void 0 : cta.enTitle) !== null && _3 !== void 0 ? _3 : 'Shop now', role: 'button', tabIndex: 0, onClick: handleLink, className: 'pb-commondityDiroNew-btn', style: buttonStyle },
12462
+ 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 },
12233
12463
  React.createElement("span", { dangerouslySetInnerHTML: {
12234
- __html: setFontForText((_4 = cta === null || cta === void 0 ? void 0 : cta.enTitle) !== null && _4 !== void 0 ? _4 : 'Shop now', buttonStyle)
12464
+ __html: setFontForText((_5 = cta === null || cta === void 0 ? void 0 : cta.enTitle) !== null && _5 !== void 0 ? _5 : 'Shop now', buttonStyle)
12235
12465
  } })),
12236
12466
  productInfoText({ isPost }))),
12237
12467
  React.createElement(Modal$1, { visible: showModal, onClose: () => setShowModal(false) },
@@ -12243,7 +12473,9 @@ Made in Italy` })));
12243
12473
  height: 'calc(100% - 50px)',
12244
12474
  marginTop: '50px',
12245
12475
  border: 'none'
12246
- } })))));
12476
+ } }))),
12477
+ showAddToCart && (React.createElement(Modal$1, { visible: showAddToCart, padding: 0, isFullScreen: false, onClose: () => setShowAddToCart(false) },
12478
+ React.createElement(AddToCartPopup$1, { isActive: true })))));
12247
12479
  };
12248
12480
  var CommodityDetailDiroNewComponent = React.memo(CommodityDetailDiroNew$1);
12249
12481
 
@@ -13245,296 +13477,6 @@ var interactionRender$d = () => {
13245
13477
  React.createElement("li", null, "\u65E0\u5E93\u5B58\u6216\u4E0D\u53EF\u552E\u5356\u7684\u89C4\u683C\u81EA\u52A8\u7F6E\u7070\u4E0D\u53EF\u9009"))));
13246
13478
  };
13247
13479
 
13248
- const AddToCartPopup$1 = (_a) => {
13249
- var _b, _c, _d, _e, _f, _g, _h, _j, _k, _l;
13250
- var { style, isActive = true, index, shopifyDomain = '', storefrontAccessToken = '', variantStyles = {}, buttonStyle = {}, quantityStyle = {}, texts = {}, popupBg = {} } = _a, props = __rest(_a, ["style", "isActive", "index", "shopifyDomain", "storefrontAccessToken", "variantStyles", "buttonStyle", "quantityStyle", "texts", "popupBg"]);
13251
- const { sxpParameter, popupDetailData, isPreview, bffFbReport, globalConfig } = useSxpDataSource();
13252
- useEventReport();
13253
- const curTimeRef = React.useRef(null);
13254
- const [productData, setProductData] = React.useState(null);
13255
- const [selectedOptions, setSelectedOptions] = React.useState({});
13256
- const [selectedVariant, setSelectedVariant] = React.useState(null);
13257
- const [quantity, setQuantity] = React.useState(1);
13258
- const [loading, setLoading] = React.useState(true);
13259
- const [error, setError] = React.useState(null);
13260
- // 获取当前弹窗商品数据(自动从 popupDetailData 获取)
13261
- const data = popupDetailData;
13262
- const product = (_c = (_b = data === null || data === void 0 ? void 0 : data.video) === null || _b === void 0 ? void 0 : _b.bindProduct) !== null && _c !== void 0 ? _c : (_e = (_d = data === null || data === void 0 ? void 0 : data.video) === null || _d === void 0 ? void 0 : _d.bindProducts) === null || _e === void 0 ? void 0 : _e[0];
13263
- product === null || product === void 0 ? void 0 : product.bindCta;
13264
- const position = (_g = (_f = popupDetailData === null || popupDetailData === void 0 ? void 0 : popupDetailData.index) !== null && _f !== void 0 ? _f : index) !== null && _g !== void 0 ? _g : 0;
13265
- // Shopify配置 - 优先级:props > globalConfig > 默认值
13266
- const finalShopifyDomain = shopifyDomain || (globalConfig === null || globalConfig === void 0 ? void 0 : globalConfig.shopifyDomain) || 'dev-store-749237498237498636.myshopify.com';
13267
- const finalStorefrontToken = storefrontAccessToken || (globalConfig === null || globalConfig === void 0 ? void 0 : globalConfig.storefrontAccessToken) || '77d894c490f79430ce7bd0a7efdff6b7';
13268
- // 自动从商品数据获取 Shopify Product ID
13269
- const productId = (product === null || product === void 0 ? void 0 : product.itemId) || '';
13270
- // 文案
13271
- const finalTexts = {
13272
- addToCart: texts.addToCart || 'Add to Cart',
13273
- selectOptions: texts.selectOptions || 'Please select options',
13274
- loading: texts.loading || 'Loading...',
13275
- error: texts.error || 'Failed to load product',
13276
- color: texts.color || 'Color',
13277
- size: texts.size || 'Size',
13278
- material: texts.material || 'Material',
13279
- style: texts.style || 'Style'
13280
- };
13281
- // 查询Shopify商品数据
13282
- const fetchProductData = React.useCallback(() => __awaiter(void 0, void 0, void 0, function* () {
13283
- var _m;
13284
- if (!productId || !finalShopifyDomain || !finalStorefrontToken) {
13285
- console.log('[AddToCartPopup] 缺少必要配置:', {
13286
- productId,
13287
- shopifyDomain: finalShopifyDomain,
13288
- hasToken: !!finalStorefrontToken
13289
- });
13290
- setLoading(false);
13291
- return;
13292
- }
13293
- console.log('[AddToCartPopup] 开始加载商品数据:', {
13294
- productId,
13295
- shopifyDomain: finalShopifyDomain
13296
- });
13297
- setLoading(true);
13298
- setError(null);
13299
- try {
13300
- const query = `
13301
- query getProduct($id: ID!) {
13302
- product(id: $id) {
13303
- id
13304
- title
13305
- images(first: 10) {
13306
- edges {
13307
- node {
13308
- url
13309
- }
13310
- }
13311
- }
13312
- options {
13313
- name
13314
- values
13315
- }
13316
- variants(first: 100) {
13317
- edges {
13318
- node {
13319
- id
13320
- title
13321
- availableForSale
13322
- quantityAvailable
13323
- price {
13324
- amount
13325
- currencyCode
13326
- }
13327
- image {
13328
- url
13329
- }
13330
- selectedOptions {
13331
- name
13332
- value
13333
- }
13334
- }
13335
- }
13336
- }
13337
- }
13338
- }
13339
- `;
13340
- // 确保 Product ID 格式正确
13341
- const formattedProductId = productId.startsWith('gid://')
13342
- ? productId
13343
- : `gid://shopify/Product/${productId}`;
13344
- console.log('[AddToCartPopup] 使用的 Product ID:', formattedProductId);
13345
- const response = yield fetch(`https://${finalShopifyDomain}/api/2024-01/graphql.json`, {
13346
- method: 'POST',
13347
- headers: {
13348
- 'Content-Type': 'application/json',
13349
- 'X-Shopify-Storefront-Access-Token': finalStorefrontToken
13350
- },
13351
- body: JSON.stringify({
13352
- query,
13353
- variables: { id: formattedProductId }
13354
- })
13355
- });
13356
- if (!response.ok) {
13357
- throw new Error(`HTTP ${response.status}`);
13358
- }
13359
- const result = yield response.json();
13360
- if (result.errors) {
13361
- console.error('[AddToCartPopup] GraphQL 错误:', result.errors);
13362
- throw new Error(result.errors[0].message);
13363
- }
13364
- if (!((_m = result.data) === null || _m === void 0 ? void 0 : _m.product)) {
13365
- console.error('[AddToCartPopup] 未找到商品');
13366
- throw new Error('Product not found');
13367
- }
13368
- console.log('[AddToCartPopup] 商品数据加载成功:', result.data.product.title);
13369
- setProductData(result.data.product);
13370
- }
13371
- catch (err) {
13372
- const errorMessage = err instanceof Error ? err.message : finalTexts.error;
13373
- setError(errorMessage);
13374
- console.error('[AddToCartPopup] 加载失败:', err);
13375
- }
13376
- finally {
13377
- setLoading(false);
13378
- }
13379
- }), [productId, finalShopifyDomain, finalStorefrontToken, finalTexts.error]);
13380
- React.useEffect(() => {
13381
- if (isActive) {
13382
- fetchProductData();
13383
- }
13384
- }, [isActive, fetchProductData]);
13385
- // 根据选中的规格匹配variant
13386
- React.useEffect(() => {
13387
- if (!productData)
13388
- return;
13389
- const variants = productData.variants.edges.map(edge => edge.node);
13390
- const optionsCount = productData.options.length;
13391
- const selectedCount = Object.keys(selectedOptions).length;
13392
- if (selectedCount === 0 || selectedCount < optionsCount) {
13393
- setSelectedVariant(null);
13394
- return;
13395
- }
13396
- const matchedVariant = variants.find(variant => {
13397
- return variant.selectedOptions.every(option => selectedOptions[option.name] === option.value);
13398
- });
13399
- setSelectedVariant(matchedVariant || null);
13400
- setQuantity(1);
13401
- }, [selectedOptions, productData]);
13402
- // 处理规格选择
13403
- const handleOptionSelect = React.useCallback((optionName, value) => {
13404
- setSelectedOptions(prev => {
13405
- const newOptions = Object.assign({}, prev);
13406
- if (newOptions[optionName] === value) {
13407
- delete newOptions[optionName];
13408
- }
13409
- else {
13410
- newOptions[optionName] = value;
13411
- }
13412
- return newOptions;
13413
- });
13414
- }, []);
13415
- // 处理数量变化
13416
- const handleQuantityChange = React.useCallback((delta) => {
13417
- setQuantity(prev => {
13418
- var _a;
13419
- const newQuantity = prev + delta;
13420
- const maxQuantity = (_a = selectedVariant === null || selectedVariant === void 0 ? void 0 : selectedVariant.quantityAvailable) !== null && _a !== void 0 ? _a : 999;
13421
- return Math.max(1, Math.min(newQuantity, maxQuantity));
13422
- });
13423
- }, [selectedVariant]);
13424
- // 检查某个规格值是否可用
13425
- const isOptionValueAvailable = React.useCallback((optionName, value) => {
13426
- if (!productData)
13427
- return false;
13428
- const variants = productData.variants.edges.map(edge => edge.node);
13429
- const tempOptions = Object.assign(Object.assign({}, selectedOptions), { [optionName]: value });
13430
- return variants.some(variant => {
13431
- const matches = variant.selectedOptions.every(option => !tempOptions[option.name] || tempOptions[option.name] === option.value);
13432
- const hasStock = variant.quantityAvailable === null || variant.quantityAvailable > 0;
13433
- return matches && variant.availableForSale && hasStock;
13434
- });
13435
- }, [productData, selectedOptions]);
13436
- // 处理加购
13437
- const handleAddToCart = React.useCallback(() => {
13438
- var _a;
13439
- if (!selectedVariant || quantity === 0)
13440
- return;
13441
- const variantId = selectedVariant.id.split('/').pop();
13442
- const cartUrl = `https://${finalShopifyDomain}/cart/add?id=${variantId}&quantity=${quantity}`;
13443
- console.log('[AddToCartPopup] 加购:', {
13444
- variantId,
13445
- quantity,
13446
- cartUrl
13447
- });
13448
- // 上报事件
13449
- bffFbReport === null || bffFbReport === void 0 ? void 0 : bffFbReport({
13450
- eventName: 'AddToCart',
13451
- product: product ? [product] : undefined,
13452
- contentType: 'product',
13453
- data,
13454
- position,
13455
- content_id: (_a = product === null || product === void 0 ? void 0 : product.itemId) !== null && _a !== void 0 ? _a : '',
13456
- value: parseFloat(selectedVariant.price.amount) * quantity,
13457
- currency: selectedVariant.price.currencyCode,
13458
- contents: [{
13459
- id: variantId,
13460
- quantity
13461
- }]
13462
- });
13463
- // 跳转到Shopify购物车页面
13464
- window.location.href = cartUrl;
13465
- }, [selectedVariant, quantity, finalShopifyDomain, bffFbReport, product, data, position]);
13466
- // 计算总价
13467
- const totalPrice = React.useMemo(() => {
13468
- if (!selectedVariant)
13469
- return null;
13470
- const price = parseFloat(selectedVariant.price.amount);
13471
- const total = price * quantity;
13472
- return total.toFixed(2);
13473
- }, [selectedVariant, quantity]);
13474
- // 初始化时间
13475
- React.useEffect(() => {
13476
- const initTime = () => {
13477
- curTimeRef.current = new Date();
13478
- };
13479
- initTime();
13480
- window.addEventListener('pageshow', initTime);
13481
- return () => {
13482
- window.removeEventListener('pageshow', initTime);
13483
- };
13484
- }, []);
13485
- // 加载中
13486
- if (loading) {
13487
- return (React.createElement("div", { className: "add-to-cart-popup-loading", style: style },
13488
- React.createElement("div", null, finalTexts.loading)));
13489
- }
13490
- // 错误状态
13491
- if (error || !productData) {
13492
- return (React.createElement("div", { className: "add-to-cart-popup-error", style: style },
13493
- React.createElement("div", null,
13494
- finalTexts.error,
13495
- ": ",
13496
- error || 'Product not found')));
13497
- }
13498
- const mainImage = ((_h = selectedVariant === null || selectedVariant === void 0 ? void 0 : selectedVariant.image) === null || _h === void 0 ? void 0 : _h.url) || ((_j = productData.images.edges[0]) === null || _j === void 0 ? void 0 : _j.node.url) || ((_k = product === null || product === void 0 ? void 0 : product.homePage) === null || _k === void 0 ? void 0 : _k[0]) || '';
13499
- const hasAllOptionsSelected = productData.options.length === Object.keys(selectedOptions).length;
13500
- const isAddToCartDisabled = !selectedVariant || quantity === 0;
13501
- return (React.createElement("div", Object.assign({ className: "add-to-cart-popup-container", style: style }, props),
13502
- React.createElement("div", { className: "variant-detail-section" },
13503
- React.createElement("div", { className: "variant-image-wrapper" },
13504
- React.createElement("img", { src: mainImage, alt: productData.title, className: "variant-image" })),
13505
- React.createElement("div", { className: "variant-info-wrapper" },
13506
- React.createElement("h2", { className: "product-title-text", style: variantStyles.title, dangerouslySetInnerHTML: {
13507
- __html: setFontForText(productData.title, variantStyles.title)
13508
- } }),
13509
- selectedVariant && (React.createElement(React.Fragment, null,
13510
- React.createElement("div", { className: "selected-options-tags" }, selectedVariant.selectedOptions.map(option => (React.createElement("span", { key: option.name, className: "option-tag", style: variantStyles.selectedOption },
13511
- option.name,
13512
- ": ",
13513
- option.value)))),
13514
- React.createElement("div", { className: "price-display" },
13515
- React.createElement("span", { className: "price-value", style: variantStyles.price, dangerouslySetInnerHTML: {
13516
- __html: setFontForText(`${selectedVariant.price.currencyCode} $${totalPrice}`, variantStyles.price)
13517
- } })),
13518
- React.createElement("div", { className: "quantity-selector-wrapper", style: quantityStyle },
13519
- React.createElement("button", { className: "quantity-btn quantity-decrease", onClick: () => handleQuantityChange(-1), disabled: quantity <= 1, "aria-label": "Decrease quantity" }, "-"),
13520
- React.createElement("input", { type: "number", value: quantity, readOnly: true, className: "quantity-input-field", "aria-label": "Quantity" }),
13521
- React.createElement("button", { className: "quantity-btn quantity-increase", onClick: () => handleQuantityChange(1), disabled: quantity >= ((_l = selectedVariant.quantityAvailable) !== null && _l !== void 0 ? _l : 999), "aria-label": "Increase quantity" }, "+")))),
13522
- !hasAllOptionsSelected && (React.createElement("div", { className: "no-selection-hint", style: variantStyles.option }, finalTexts.selectOptions)))),
13523
- React.createElement("div", { className: "variant-options-section" }, productData.options.map(option => (React.createElement("div", { key: option.name, className: "option-group-wrapper" },
13524
- React.createElement("h3", { className: "option-group-name", style: variantStyles.option, dangerouslySetInnerHTML: {
13525
- __html: setFontForText(option.name, variantStyles.option)
13526
- } }),
13527
- React.createElement("div", { className: "option-values-grid" }, option.values.map(value => {
13528
- const isSelected = selectedOptions[option.name] === value;
13529
- const isAvailable = isOptionValueAvailable(option.name, value);
13530
- return (React.createElement("button", { key: value, className: `option-value-button ${isSelected ? 'selected' : ''} ${!isAvailable ? 'disabled' : ''}`, onClick: () => isAvailable && handleOptionSelect(option.name, value), disabled: !isAvailable, "aria-label": `${option.name}: ${value}`, "aria-pressed": isSelected }, value));
13531
- })))))),
13532
- React.createElement("button", { className: `add-to-cart-button ${isAddToCartDisabled ? 'disabled' : ''}`, style: buttonStyle, onClick: handleAddToCart, disabled: isAddToCartDisabled, "aria-label": finalTexts.addToCart },
13533
- React.createElement("span", { dangerouslySetInnerHTML: {
13534
- __html: setFontForText(finalTexts.addToCart, buttonStyle)
13535
- } }))));
13536
- };
13537
-
13538
13480
  /*
13539
13481
  * @Author: tao
13540
13482
  * @Date: 2026-01-12
@@ -13550,60 +13492,7 @@ const AddToCartPopup = createMaterial(AddToCartPopup$1, {
13550
13492
  interactionRender: interactionRender$d
13551
13493
  },
13552
13494
  defaulSetting: {
13553
- props: {
13554
- shopifyDomain: '',
13555
- storefrontAccessToken: '',
13556
- variantStyles: {
13557
- title: {
13558
- color: '#000',
13559
- fontSize: 20,
13560
- fontWeight: 600,
13561
- marginBottom: 12
13562
- },
13563
- price: {
13564
- color: '#000',
13565
- fontSize: 24,
13566
- fontWeight: 700,
13567
- marginBottom: 16
13568
- },
13569
- option: {
13570
- color: '#111',
13571
- fontSize: 16,
13572
- fontWeight: 600,
13573
- marginBottom: 12
13574
- },
13575
- selectedOption: {
13576
- fontSize: 14,
13577
- color: '#374151'
13578
- }
13579
- },
13580
- buttonStyle: {
13581
- backgroundColor: '#000',
13582
- color: '#fff',
13583
- fontSize: 16,
13584
- height: 52,
13585
- fontWeight: 600,
13586
- textAlign: 'center',
13587
- textTransform: 'uppercase'
13588
- },
13589
- quantityStyle: {
13590
- gap: 12
13591
- },
13592
- texts: {
13593
- addToCart: 'Add to Cart',
13594
- selectOptions: 'Please select options',
13595
- loading: 'Loading...',
13596
- error: 'Failed to load product',
13597
- color: 'Color',
13598
- size: 'Size',
13599
- material: 'Material',
13600
- style: 'Style'
13601
- },
13602
- popupBg: {
13603
- horizontalMargin: 0,
13604
- bottomMargin: 0
13605
- }
13606
- },
13495
+ props: {},
13607
13496
  style: {}
13608
13497
  },
13609
13498
  w: 100,
@@ -19699,7 +19588,7 @@ const StructurePage = (_a) => {
19699
19588
  return res.json();
19700
19589
  })
19701
19590
  .then((result) => {
19702
- var _a, _b, _c, _d;
19591
+ var _a, _b, _c, _d, _e;
19703
19592
  if (result.code === '0' || result.code === '00000') {
19704
19593
  // 判断数据结构:CMS 模式和普通模式可能不同
19705
19594
  let multiCtaData = null;
@@ -19718,6 +19607,14 @@ const StructurePage = (_a) => {
19718
19607
  console.error('[StructurePage] No multiCta data found in response:', result);
19719
19608
  setError(result.message || 'No multiCta data found');
19720
19609
  }
19610
+ // 存储 Shopify 配置信息到 window 对象,供 AddToCart 弹窗使用
19611
+ if ((_e = result.data) === null || _e === void 0 ? void 0 : _e.shopify) {
19612
+ window.__SHOPIFY_CONFIG__ = {
19613
+ domain: result.data.shopify.domain,
19614
+ storefrontAccessToken: result.data.shopify.storefrontAccessToken
19615
+ };
19616
+ console.log('[StructurePage] Shopify config stored:', window.__SHOPIFY_CONFIG__);
19617
+ }
19721
19618
  }
19722
19619
  else {
19723
19620
  setError(result.message || 'Failed to load data');