pb-sxp-ui 1.20.28 → 1.20.29

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.js CHANGED
@@ -398,6 +398,54 @@ function getUrlParamByKey(key) {
398
398
  }
399
399
  return (_b = params[key]) !== null && _b !== void 0 ? _b : '';
400
400
  }
401
+ /**
402
+ * 货币代码到货币符号的映射
403
+ * 根据 Shopify 返回的 currencyCode 获取对应的货币符号
404
+ */
405
+ function getCurrencySymbol(currencyCode) {
406
+ const currencySymbolMap = {
407
+ // 主要货币
408
+ USD: '$', // 美元
409
+ EUR: '€', // 欧元
410
+ GBP: '£', // 英镑
411
+ JPY: '¥', // 日元
412
+ CNY: '¥', // 人民币
413
+ KRW: '₩', // 韩元
414
+ INR: '₹', // 印度卢比
415
+ RUB: '₽', // 俄罗斯卢布
416
+ BRL: 'R$', // 巴西雷亚尔
417
+ CAD: 'CA$', // 加拿大元
418
+ AUD: 'A$', // 澳元
419
+ CHF: 'CHF', // 瑞士法郎
420
+ SEK: 'kr', // 瑞典克朗
421
+ NOK: 'kr', // 挪威克朗
422
+ DKK: 'kr', // 丹麦克朗
423
+ PLN: 'zł', // 波兰兹罗提
424
+ THB: '฿', // 泰铢
425
+ IDR: 'Rp', // 印尼盾
426
+ MYR: 'RM', // 马来西亚林吉特
427
+ PHP: '₱', // 菲律宾比索
428
+ SGD: 'S$', // 新加坡元
429
+ HKD: 'HK$', // 港币
430
+ TWD: 'NT$', // 新台币
431
+ NZD: 'NZ$', // 新西兰元
432
+ MXN: 'MX$', // 墨西哥比索
433
+ ZAR: 'R', // 南非兰特
434
+ TRY: '₺', // 土耳其里拉
435
+ AED: 'AED', // 阿联酋迪拉姆
436
+ SAR: 'SAR', // 沙特里亚尔
437
+ ILS: '₪', // 以色列新谢克尔
438
+ ARS: 'AR$', // 阿根廷比索
439
+ CLP: 'CL$', // 智利比索
440
+ COP: 'CO$', // 哥伦比亚比索
441
+ VND: '₫', // 越南盾
442
+ EGP: 'E£', // 埃及镑
443
+ NGN: '₦', // 尼日利亚奈拉
444
+ PKR: '₨', // 巴基斯坦卢比
445
+ BDT: '৳', // 孟加拉塔卡
446
+ };
447
+ return currencySymbolMap[currencyCode.toUpperCase()] || currencyCode;
448
+ }
401
449
 
402
450
  var tool = /*#__PURE__*/Object.freeze({
403
451
  __proto__: null,
@@ -405,6 +453,7 @@ var tool = /*#__PURE__*/Object.freeze({
405
453
  generateRandomString: generateRandomString,
406
454
  getBrowserInfo: getBrowserInfo,
407
455
  getCookie: getCookie,
456
+ getCurrencySymbol: getCurrencySymbol,
408
457
  getDevice: getDevice$1,
409
458
  getIndexByblockType: getIndexByblockType,
410
459
  getScreenReader: getScreenReader,
@@ -10982,7 +11031,7 @@ const getBgStyle = (imgSrc) => {
10982
11031
  : '';
10983
11032
  };
10984
11033
  const getPriceText = ({ product, enableFormattedPrice, globalConfig, isHiddenDef, style }) => {
10985
- var _a, _b, _c, _d, _e, _f, _g, _h;
11034
+ var _a, _b, _c, _d, _e;
10986
11035
  let text = '';
10987
11036
  if ((!(product === null || product === void 0 ? void 0 : product.currency) || !(product === null || product === void 0 ? void 0 : product.price)) && isHiddenDef)
10988
11037
  return null;
@@ -10990,18 +11039,51 @@ const getPriceText = ({ product, enableFormattedPrice, globalConfig, isHiddenDef
10990
11039
  if (typeof price !== 'number')
10991
11040
  return text;
10992
11041
  let priceSymbol = globalConfig === null || globalConfig === void 0 ? void 0 : globalConfig.priceSymbol;
10993
- let currency = (product === null || product === void 0 ? void 0 : product.currency) ? (_c = (_b = (_a = product === null || product === void 0 ? void 0 : product.currency) === null || _a === void 0 ? void 0 : _a.split('-')[1]) === null || _b === void 0 ? void 0 : _b.toUpperCase()) !== null && _c !== void 0 ? _c : '' : '$';
11042
+ // product.currency 中提取货币代码
11043
+ // 支持多种格式:
11044
+ // 1. "EUR" - 直接是货币代码
11045
+ // 2. "USD-$" - 货币代码-货币符号
11046
+ // 3. "$-USD" - 货币符号-货币代码 (不常见)
11047
+ let currencyCode = '';
11048
+ if (product === null || product === void 0 ? void 0 : product.currency) {
11049
+ const parts = product.currency.split('-');
11050
+ if (parts.length > 1) {
11051
+ // 判断哪一部分是货币代码(通常是3个大写字母)
11052
+ // 货币代码通常是3个字母,如 USD, EUR, GBP
11053
+ const firstPart = parts[0].toUpperCase();
11054
+ const secondPart = parts[1].toUpperCase();
11055
+ // 如果第一部分是3个字母,则认为是货币代码
11056
+ if (/^[A-Z]{3}$/.test(firstPart)) {
11057
+ currencyCode = firstPart;
11058
+ }
11059
+ else if (/^[A-Z]{3}$/.test(secondPart)) {
11060
+ currencyCode = secondPart;
11061
+ }
11062
+ else {
11063
+ // 都不是标准格式,取第一部分
11064
+ currencyCode = firstPart;
11065
+ }
11066
+ }
11067
+ else {
11068
+ currencyCode = parts[0].toUpperCase();
11069
+ }
11070
+ }
11071
+ else {
11072
+ currencyCode = 'USD'; // 默认美元
11073
+ }
11074
+ // 使用货币代码映射获取货币符号
11075
+ let currency = getCurrencySymbol(currencyCode);
10994
11076
  const isToLocStr = enableFormattedPrice === undefined || enableFormattedPrice;
10995
11077
  let decPic = price === null || price === void 0 ? void 0 : price.toString();
10996
11078
  if (priceSymbol === null || priceSymbol === void 0 ? void 0 : priceSymbol.showTwoDecimalPoint) {
10997
11079
  decPic = price === null || price === void 0 ? void 0 : price.toFixed(2);
10998
11080
  }
10999
- let decInd = (_d = decPic === null || decPic === void 0 ? void 0 : decPic.indexOf('.')) !== null && _d !== void 0 ? _d : -1;
11081
+ let decInd = (_a = decPic === null || decPic === void 0 ? void 0 : decPic.indexOf('.')) !== null && _a !== void 0 ? _a : -1;
11000
11082
  if (isToLocStr) {
11001
11083
  text =
11002
- (_e = price === null || price === void 0 ? void 0 : price.toLocaleString('zh', {
11084
+ (_b = price === null || price === void 0 ? void 0 : price.toLocaleString('zh', {
11003
11085
  minimumFractionDigits: (priceSymbol === null || priceSymbol === void 0 ? void 0 : priceSymbol.showTwoDecimalPoint) ? 2 : 0
11004
- })) !== null && _e !== void 0 ? _e : '';
11086
+ })) !== null && _b !== void 0 ? _b : '';
11005
11087
  let startIndex = 0;
11006
11088
  let endIndex = decInd !== null && decInd !== void 0 ? decInd : text === null || text === void 0 ? void 0 : text.length;
11007
11089
  if ((priceSymbol === null || priceSymbol === void 0 ? void 0 : priceSymbol.millesimalSymbol) === '.') {
@@ -11032,7 +11114,7 @@ const getPriceText = ({ product, enableFormattedPrice, globalConfig, isHiddenDef
11032
11114
  }
11033
11115
  });
11034
11116
  }
11035
- currency = `<span style="font-family:${(_h = (_g = (_f = globalConfig === null || globalConfig === void 0 ? void 0 : globalConfig.priceSymbol) === null || _f === void 0 ? void 0 : _f.fontFamily) !== null && _g !== void 0 ? _g : style === null || style === void 0 ? void 0 : style['fontFamily-en']) !== null && _h !== void 0 ? _h : 'inherit'}">${currency}</span>`;
11117
+ currency = `<span style="font-family:${(_e = (_d = (_c = globalConfig === null || globalConfig === void 0 ? void 0 : globalConfig.priceSymbol) === null || _c === void 0 ? void 0 : _c.fontFamily) !== null && _d !== void 0 ? _d : style === null || style === void 0 ? void 0 : style['fontFamily-en']) !== null && _e !== void 0 ? _e : 'inherit'}">${currency}</span>`;
11036
11118
  text = setFontForText(text, style);
11037
11119
  if ((priceSymbol === null || priceSymbol === void 0 ? void 0 : priceSymbol.currencyPosition) && (priceSymbol === null || priceSymbol === void 0 ? void 0 : priceSymbol.currencyPosition) !== 'none') {
11038
11120
  text = (priceSymbol === null || priceSymbol === void 0 ? void 0 : priceSymbol.currencyPosition) === 'left' ? currency + text : text + currency;
@@ -11068,30 +11150,37 @@ const CommodityDetail$1 = (_a) => {
11068
11150
  cta = p === null || p === void 0 ? void 0 : p.bindCta;
11069
11151
  }
11070
11152
  const handleLink = (e) => {
11071
- // 如果启用了加购功能且配置了加购弹窗ID,则打开加购弹窗
11153
+ // 如果启用了加购功能且配置了加购弹窗ID,检查是否是 Shopify 商品
11072
11154
  if (enableAddToCart && addToCartPopupId) {
11073
- // 设置弹窗数据
11074
- setPopupDetailData === null || setPopupDetailData === void 0 ? void 0 : setPopupDetailData(Object.assign(Object.assign({}, data), { index: position }));
11075
- // 上报点击事件
11076
- bffFbReport === null || bffFbReport === void 0 ? void 0 : bffFbReport({
11077
- eventName: 'ClickCTA',
11078
- product: product ? [product] : undefined,
11079
- contentType: 'product',
11080
- data,
11081
- position,
11082
- cta_text: cta === null || cta === void 0 ? void 0 : cta.enTitle,
11083
- cta_action_type: 'open_internal_popup',
11084
- target_content_id: product === null || product === void 0 ? void 0 : product.itemId
11085
- });
11086
- console.log('[CommodityDetail] 打开加购弹窗:', addToCartPopupId);
11087
- // 打开加购弹窗
11088
- if (typeof window !== 'undefined' && window.sxpPopup) {
11089
- window.sxpPopup(addToCartPopupId);
11155
+ // 问题3:只有 Shopify 商品(有 shopifyId)才打开加购弹窗
11156
+ if (!(product === null || product === void 0 ? void 0 : product.shopifyId)) {
11157
+ console.warn('[CommodityDetail] 非 Shopify 商品,跳过加购弹窗');
11158
+ // 继续执行默认行为(跳转链接)
11090
11159
  }
11091
11160
  else {
11092
- console.warn('[CommodityDetail] sxpPopup 方法不存在');
11161
+ // 设置弹窗数据
11162
+ setPopupDetailData === null || setPopupDetailData === void 0 ? void 0 : setPopupDetailData(Object.assign(Object.assign({}, data), { index: position }));
11163
+ // 上报点击事件
11164
+ bffFbReport === null || bffFbReport === void 0 ? void 0 : bffFbReport({
11165
+ eventName: 'ClickCTA',
11166
+ product: product ? [product] : undefined,
11167
+ contentType: 'product',
11168
+ data,
11169
+ position,
11170
+ cta_text: cta === null || cta === void 0 ? void 0 : cta.enTitle,
11171
+ cta_action_type: 'open_internal_popup',
11172
+ target_content_id: product === null || product === void 0 ? void 0 : product.itemId
11173
+ });
11174
+ console.log('[CommodityDetail] 打开加购弹窗:', addToCartPopupId);
11175
+ // 打开加购弹窗
11176
+ if (typeof window !== 'undefined' && window.sxpPopup) {
11177
+ window.sxpPopup(addToCartPopupId);
11178
+ }
11179
+ else {
11180
+ console.warn('[CommodityDetail] sxpPopup 方法不存在');
11181
+ }
11182
+ return;
11093
11183
  }
11094
- return;
11095
11184
  }
11096
11185
  // 默认行为:跳转到商品链接
11097
11186
  if (product === null || product === void 0 ? void 0 : product.link) {
@@ -12061,7 +12150,7 @@ var settingRender$d = [
12061
12150
 
12062
12151
  const AddToCartPopup$1 = ({ isActive = true }) => {
12063
12152
  var _a, _b, _c, _d, _e, _f, _g, _h, _j;
12064
- const { popupDetailData, globalConfig } = useSxpDataSource();
12153
+ const { popupDetailData, globalConfig, bffFbReport } = useSxpDataSource();
12065
12154
  const [productData, setProductData] = useState(null);
12066
12155
  const [selectedOptions, setSelectedOptions] = useState({});
12067
12156
  const [selectedVariant, setSelectedVariant] = useState(null);
@@ -12201,6 +12290,18 @@ const AddToCartPopup$1 = ({ isActive = true }) => {
12201
12290
  shopifyDomain,
12202
12291
  selectedVariant
12203
12292
  });
12293
+ // 上报 sessionCompleted 事件(问题4)
12294
+ bffFbReport === null || bffFbReport === void 0 ? void 0 : bffFbReport({
12295
+ eventName: 'sessionCompleted',
12296
+ product: product ? [product] : undefined,
12297
+ contentType: 'product',
12298
+ rec: data,
12299
+ position: data === null || data === void 0 ? void 0 : data.index,
12300
+ cta_text: 'Add To Cart',
12301
+ cta_action_type: 'add_to_cart',
12302
+ target_content_id: product === null || product === void 0 ? void 0 : product.itemId,
12303
+ target_url: `https://${shopifyDomain}/cart/add`
12304
+ });
12204
12305
  // 使用 Shopify 的 /cart/add 接口,通过查询参数添加商品
12205
12306
  // 这种方式会跳转到购物车页面而不是结算页面
12206
12307
  const params = new URLSearchParams({
@@ -12215,6 +12316,10 @@ const AddToCartPopup$1 = ({ isActive = true }) => {
12215
12316
  const totalPrice = selectedVariant
12216
12317
  ? (parseFloat(selectedVariant.price.amount) * quantity).toFixed(2)
12217
12318
  : '0.00';
12319
+ // 只有选择了 variant 后才显示货币符号
12320
+ const displayPrice = selectedVariant
12321
+ ? `${getCurrencySymbol(selectedVariant.price.currencyCode)}${totalPrice}`
12322
+ : totalPrice;
12218
12323
  if (loading) {
12219
12324
  return (React.createElement("div", { className: 'add-to-cart-popup' },
12220
12325
  React.createElement("div", { className: 'loading' }, "Loading...")));
@@ -12248,9 +12353,7 @@ const AddToCartPopup$1 = ({ isActive = true }) => {
12248
12353
  "Available: ",
12249
12354
  selectedVariant.quantityAvailable))),
12250
12355
  React.createElement("div", { className: 'variant-price-row' },
12251
- React.createElement("div", { className: 'price' },
12252
- "$",
12253
- totalPrice),
12356
+ React.createElement("div", { className: 'price' }, displayPrice),
12254
12357
  React.createElement("div", { className: 'quantity-selector' },
12255
12358
  React.createElement("button", { className: 'qty-btn', onClick: () => setQuantity(Math.max(1, quantity - 1)), disabled: quantity <= 1 }, "\u2212"),
12256
12359
  React.createElement("span", { className: 'qty-value' }, quantity),
@@ -12258,16 +12361,26 @@ const AddToCartPopup$1 = ({ isActive = true }) => {
12258
12361
  React.createElement("div", { className: 'variant-options' }, productData.options.map(option => (React.createElement("div", { key: option.name, className: 'option-group' },
12259
12362
  React.createElement("div", { className: 'option-label' }, option.name),
12260
12363
  React.createElement("div", { className: 'option-values' }, option.values.map(value => {
12261
- // 检查这个选项是否可选(availableForSale = true,如果有 quantityAvailable 则还需 > 0)
12364
+ // 检查这个选项值与当前已选择的其他选项组合后是否可用
12262
12365
  const isAvailable = productData.variants.edges.some(({ node: variant }) => {
12366
+ // 检查这个variant是否匹配当前选项值
12263
12367
  const hasThisOption = variant.selectedOptions.some(opt => opt.name === option.name && opt.value === value);
12264
- if (!hasThisOption || !variant.availableForSale)
12368
+ if (!hasThisOption)
12265
12369
  return false;
12266
- // 如果有 quantityAvailable 字段,则需要检查库存
12267
- if (variant.quantityAvailable !== undefined) {
12268
- return variant.quantityAvailable > 0;
12269
- }
12270
- // 没有 quantityAvailable 字段时,只要 availableForSale 为 true 就可选
12370
+ // 检查这个variant是否匹配其他已选择的选项
12371
+ const matchesOtherSelections = Object.entries(selectedOptions).every(([key, val]) => {
12372
+ // 跳过当前正在检查的选项
12373
+ if (key === option.name)
12374
+ return true;
12375
+ return variant.selectedOptions.some(opt => opt.name === key && opt.value === val);
12376
+ });
12377
+ if (!matchesOtherSelections)
12378
+ return false;
12379
+ // 检查是否可售
12380
+ if (!variant.availableForSale)
12381
+ return false;
12382
+ // 如果有 quantityAvailable 字段且为0,但 availableForSale 为 true,仍然可选(问题2)
12383
+ // 如果 quantityAvailable 不存在,只要 availableForSale 为 true 就可选
12271
12384
  return true;
12272
12385
  });
12273
12386
  const isSelected = selectedOptions[option.name] === value;
@@ -12318,7 +12431,35 @@ const CommodityDetailDiroNew$1 = (_a) => {
12318
12431
  }
12319
12432
  const handleLink = (e) => {
12320
12433
  e.preventDefault();
12321
- // 上报点击事件
12434
+ // 问题3:只有 Shopify 商品(有 shopifyId)才打开加购弹窗
12435
+ if (!(product === null || product === void 0 ? void 0 : product.shopifyId)) {
12436
+ console.warn('[CommodityDetailDiroNew] 非 Shopify 商品,跳转到外链');
12437
+ // 上报点击事件
12438
+ ctaEvent === null || ctaEvent === void 0 ? void 0 : ctaEvent({
12439
+ eventSubject: 'clickCta',
12440
+ eventDescription: 'User clicked the CTA'
12441
+ }, data, product, position);
12442
+ bffFbReport === null || bffFbReport === void 0 ? void 0 : bffFbReport({
12443
+ eventName: 'ClickCTA',
12444
+ product: product ? [product] : undefined,
12445
+ contentType: 'product',
12446
+ data,
12447
+ position,
12448
+ cta_text: cta === null || cta === void 0 ? void 0 : cta.enTitle,
12449
+ cta_action_type: 'open_external_link',
12450
+ target_content_id: product === null || product === void 0 ? void 0 : product.itemId,
12451
+ target_url: product === null || product === void 0 ? void 0 : product.link
12452
+ });
12453
+ if (!isPost) {
12454
+ productView(data, product, cta, viewTime || curTimeRef.current, position);
12455
+ }
12456
+ // 跳转到商品链接
12457
+ if (product === null || product === void 0 ? void 0 : product.link) {
12458
+ window.location.href = window.getJointUtmLink(product.link);
12459
+ }
12460
+ return;
12461
+ }
12462
+ // Shopify 商品:上报点击事件
12322
12463
  ctaEvent === null || ctaEvent === void 0 ? void 0 : ctaEvent({
12323
12464
  eventSubject: 'clickCta',
12324
12465
  eventDescription: 'User clicked the CTA'