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.cjs +179 -38
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +179 -38
- package/dist/index.js.map +1 -1
- package/dist/index.min.cjs +9 -9
- package/dist/index.min.cjs.map +1 -1
- package/dist/index.min.js +9 -9
- package/dist/index.min.js.map +1 -1
- package/dist/pb-ui.js +179 -38
- package/dist/pb-ui.js.map +1 -1
- package/dist/pb-ui.min.js +9 -9
- package/dist/pb-ui.min.js.map +1 -1
- package/es/core/context/SxpDataSourceProvider.d.ts +1 -1
- package/es/core/utils/materials.js +30 -7
- package/es/core/utils/tool.d.ts +1 -0
- package/es/core/utils/tool.js +43 -0
- package/es/materials/sxp/popup/AddToCart/index.js +27 -8
- package/es/materials/sxp/popup/AddToCart/index.new.js +27 -6
- package/es/materials/sxp/popup/AddToCart/index.old.js +13 -2
- package/es/materials/sxp/popup/CommodityDetail/index.js +21 -16
- package/es/materials/sxp/popup/CommodityDetailDiroNew/index.js +25 -0
- package/lib/core/context/SxpDataSourceProvider.d.ts +1 -1
- package/lib/core/utils/materials.js +29 -6
- package/lib/core/utils/tool.d.ts +1 -0
- package/lib/core/utils/tool.js +45 -1
- package/lib/materials/sxp/popup/AddToCart/index.js +27 -8
- package/lib/materials/sxp/popup/AddToCart/index.new.js +27 -6
- package/lib/materials/sxp/popup/AddToCart/index.old.js +12 -1
- package/lib/materials/sxp/popup/CommodityDetail/index.js +21 -16
- package/lib/materials/sxp/popup/CommodityDetailDiroNew/index.js +25 -0
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -420,6 +420,54 @@ function getUrlParamByKey(key) {
|
|
|
420
420
|
}
|
|
421
421
|
return (_b = params[key]) !== null && _b !== void 0 ? _b : '';
|
|
422
422
|
}
|
|
423
|
+
/**
|
|
424
|
+
* 货币代码到货币符号的映射
|
|
425
|
+
* 根据 Shopify 返回的 currencyCode 获取对应的货币符号
|
|
426
|
+
*/
|
|
427
|
+
function getCurrencySymbol(currencyCode) {
|
|
428
|
+
const currencySymbolMap = {
|
|
429
|
+
// 主要货币
|
|
430
|
+
USD: '$', // 美元
|
|
431
|
+
EUR: '€', // 欧元
|
|
432
|
+
GBP: '£', // 英镑
|
|
433
|
+
JPY: '¥', // 日元
|
|
434
|
+
CNY: '¥', // 人民币
|
|
435
|
+
KRW: '₩', // 韩元
|
|
436
|
+
INR: '₹', // 印度卢比
|
|
437
|
+
RUB: '₽', // 俄罗斯卢布
|
|
438
|
+
BRL: 'R$', // 巴西雷亚尔
|
|
439
|
+
CAD: 'CA$', // 加拿大元
|
|
440
|
+
AUD: 'A$', // 澳元
|
|
441
|
+
CHF: 'CHF', // 瑞士法郎
|
|
442
|
+
SEK: 'kr', // 瑞典克朗
|
|
443
|
+
NOK: 'kr', // 挪威克朗
|
|
444
|
+
DKK: 'kr', // 丹麦克朗
|
|
445
|
+
PLN: 'zł', // 波兰兹罗提
|
|
446
|
+
THB: '฿', // 泰铢
|
|
447
|
+
IDR: 'Rp', // 印尼盾
|
|
448
|
+
MYR: 'RM', // 马来西亚林吉特
|
|
449
|
+
PHP: '₱', // 菲律宾比索
|
|
450
|
+
SGD: 'S$', // 新加坡元
|
|
451
|
+
HKD: 'HK$', // 港币
|
|
452
|
+
TWD: 'NT$', // 新台币
|
|
453
|
+
NZD: 'NZ$', // 新西兰元
|
|
454
|
+
MXN: 'MX$', // 墨西哥比索
|
|
455
|
+
ZAR: 'R', // 南非兰特
|
|
456
|
+
TRY: '₺', // 土耳其里拉
|
|
457
|
+
AED: 'AED', // 阿联酋迪拉姆
|
|
458
|
+
SAR: 'SAR', // 沙特里亚尔
|
|
459
|
+
ILS: '₪', // 以色列新谢克尔
|
|
460
|
+
ARS: 'AR$', // 阿根廷比索
|
|
461
|
+
CLP: 'CL$', // 智利比索
|
|
462
|
+
COP: 'CO$', // 哥伦比亚比索
|
|
463
|
+
VND: '₫', // 越南盾
|
|
464
|
+
EGP: 'E£', // 埃及镑
|
|
465
|
+
NGN: '₦', // 尼日利亚奈拉
|
|
466
|
+
PKR: '₨', // 巴基斯坦卢比
|
|
467
|
+
BDT: '৳', // 孟加拉塔卡
|
|
468
|
+
};
|
|
469
|
+
return currencySymbolMap[currencyCode.toUpperCase()] || currencyCode;
|
|
470
|
+
}
|
|
423
471
|
|
|
424
472
|
var tool = /*#__PURE__*/Object.freeze({
|
|
425
473
|
__proto__: null,
|
|
@@ -427,6 +475,7 @@ var tool = /*#__PURE__*/Object.freeze({
|
|
|
427
475
|
generateRandomString: generateRandomString,
|
|
428
476
|
getBrowserInfo: getBrowserInfo,
|
|
429
477
|
getCookie: getCookie,
|
|
478
|
+
getCurrencySymbol: getCurrencySymbol,
|
|
430
479
|
getDevice: getDevice$1,
|
|
431
480
|
getIndexByblockType: getIndexByblockType,
|
|
432
481
|
getScreenReader: getScreenReader,
|
|
@@ -11004,7 +11053,7 @@ const getBgStyle = (imgSrc) => {
|
|
|
11004
11053
|
: '';
|
|
11005
11054
|
};
|
|
11006
11055
|
const getPriceText = ({ product, enableFormattedPrice, globalConfig, isHiddenDef, style }) => {
|
|
11007
|
-
var _a, _b, _c, _d, _e
|
|
11056
|
+
var _a, _b, _c, _d, _e;
|
|
11008
11057
|
let text = '';
|
|
11009
11058
|
if ((!(product === null || product === void 0 ? void 0 : product.currency) || !(product === null || product === void 0 ? void 0 : product.price)) && isHiddenDef)
|
|
11010
11059
|
return null;
|
|
@@ -11012,18 +11061,51 @@ const getPriceText = ({ product, enableFormattedPrice, globalConfig, isHiddenDef
|
|
|
11012
11061
|
if (typeof price !== 'number')
|
|
11013
11062
|
return text;
|
|
11014
11063
|
let priceSymbol = globalConfig === null || globalConfig === void 0 ? void 0 : globalConfig.priceSymbol;
|
|
11015
|
-
|
|
11064
|
+
// 从 product.currency 中提取货币代码
|
|
11065
|
+
// 支持多种格式:
|
|
11066
|
+
// 1. "EUR" - 直接是货币代码
|
|
11067
|
+
// 2. "USD-$" - 货币代码-货币符号
|
|
11068
|
+
// 3. "$-USD" - 货币符号-货币代码 (不常见)
|
|
11069
|
+
let currencyCode = '';
|
|
11070
|
+
if (product === null || product === void 0 ? void 0 : product.currency) {
|
|
11071
|
+
const parts = product.currency.split('-');
|
|
11072
|
+
if (parts.length > 1) {
|
|
11073
|
+
// 判断哪一部分是货币代码(通常是3个大写字母)
|
|
11074
|
+
// 货币代码通常是3个字母,如 USD, EUR, GBP
|
|
11075
|
+
const firstPart = parts[0].toUpperCase();
|
|
11076
|
+
const secondPart = parts[1].toUpperCase();
|
|
11077
|
+
// 如果第一部分是3个字母,则认为是货币代码
|
|
11078
|
+
if (/^[A-Z]{3}$/.test(firstPart)) {
|
|
11079
|
+
currencyCode = firstPart;
|
|
11080
|
+
}
|
|
11081
|
+
else if (/^[A-Z]{3}$/.test(secondPart)) {
|
|
11082
|
+
currencyCode = secondPart;
|
|
11083
|
+
}
|
|
11084
|
+
else {
|
|
11085
|
+
// 都不是标准格式,取第一部分
|
|
11086
|
+
currencyCode = firstPart;
|
|
11087
|
+
}
|
|
11088
|
+
}
|
|
11089
|
+
else {
|
|
11090
|
+
currencyCode = parts[0].toUpperCase();
|
|
11091
|
+
}
|
|
11092
|
+
}
|
|
11093
|
+
else {
|
|
11094
|
+
currencyCode = 'USD'; // 默认美元
|
|
11095
|
+
}
|
|
11096
|
+
// 使用货币代码映射获取货币符号
|
|
11097
|
+
let currency = getCurrencySymbol(currencyCode);
|
|
11016
11098
|
const isToLocStr = enableFormattedPrice === undefined || enableFormattedPrice;
|
|
11017
11099
|
let decPic = price === null || price === void 0 ? void 0 : price.toString();
|
|
11018
11100
|
if (priceSymbol === null || priceSymbol === void 0 ? void 0 : priceSymbol.showTwoDecimalPoint) {
|
|
11019
11101
|
decPic = price === null || price === void 0 ? void 0 : price.toFixed(2);
|
|
11020
11102
|
}
|
|
11021
|
-
let decInd = (
|
|
11103
|
+
let decInd = (_a = decPic === null || decPic === void 0 ? void 0 : decPic.indexOf('.')) !== null && _a !== void 0 ? _a : -1;
|
|
11022
11104
|
if (isToLocStr) {
|
|
11023
11105
|
text =
|
|
11024
|
-
(
|
|
11106
|
+
(_b = price === null || price === void 0 ? void 0 : price.toLocaleString('zh', {
|
|
11025
11107
|
minimumFractionDigits: (priceSymbol === null || priceSymbol === void 0 ? void 0 : priceSymbol.showTwoDecimalPoint) ? 2 : 0
|
|
11026
|
-
})) !== null &&
|
|
11108
|
+
})) !== null && _b !== void 0 ? _b : '';
|
|
11027
11109
|
let startIndex = 0;
|
|
11028
11110
|
let endIndex = decInd !== null && decInd !== void 0 ? decInd : text === null || text === void 0 ? void 0 : text.length;
|
|
11029
11111
|
if ((priceSymbol === null || priceSymbol === void 0 ? void 0 : priceSymbol.millesimalSymbol) === '.') {
|
|
@@ -11054,7 +11136,7 @@ const getPriceText = ({ product, enableFormattedPrice, globalConfig, isHiddenDef
|
|
|
11054
11136
|
}
|
|
11055
11137
|
});
|
|
11056
11138
|
}
|
|
11057
|
-
currency = `<span style="font-family:${(
|
|
11139
|
+
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>`;
|
|
11058
11140
|
text = setFontForText(text, style);
|
|
11059
11141
|
if ((priceSymbol === null || priceSymbol === void 0 ? void 0 : priceSymbol.currencyPosition) && (priceSymbol === null || priceSymbol === void 0 ? void 0 : priceSymbol.currencyPosition) !== 'none') {
|
|
11060
11142
|
text = (priceSymbol === null || priceSymbol === void 0 ? void 0 : priceSymbol.currencyPosition) === 'left' ? currency + text : text + currency;
|
|
@@ -11090,30 +11172,37 @@ const CommodityDetail$1 = (_a) => {
|
|
|
11090
11172
|
cta = p === null || p === void 0 ? void 0 : p.bindCta;
|
|
11091
11173
|
}
|
|
11092
11174
|
const handleLink = (e) => {
|
|
11093
|
-
// 如果启用了加购功能且配置了加购弹窗ID
|
|
11175
|
+
// 如果启用了加购功能且配置了加购弹窗ID,检查是否是 Shopify 商品
|
|
11094
11176
|
if (enableAddToCart && addToCartPopupId) {
|
|
11095
|
-
//
|
|
11096
|
-
|
|
11097
|
-
|
|
11098
|
-
|
|
11099
|
-
eventName: 'ClickCTA',
|
|
11100
|
-
product: product ? [product] : undefined,
|
|
11101
|
-
contentType: 'product',
|
|
11102
|
-
data,
|
|
11103
|
-
position,
|
|
11104
|
-
cta_text: cta === null || cta === void 0 ? void 0 : cta.enTitle,
|
|
11105
|
-
cta_action_type: 'open_internal_popup',
|
|
11106
|
-
target_content_id: product === null || product === void 0 ? void 0 : product.itemId
|
|
11107
|
-
});
|
|
11108
|
-
console.log('[CommodityDetail] 打开加购弹窗:', addToCartPopupId);
|
|
11109
|
-
// 打开加购弹窗
|
|
11110
|
-
if (typeof window !== 'undefined' && window.sxpPopup) {
|
|
11111
|
-
window.sxpPopup(addToCartPopupId);
|
|
11177
|
+
// 问题3:只有 Shopify 商品(有 shopifyId)才打开加购弹窗
|
|
11178
|
+
if (!(product === null || product === void 0 ? void 0 : product.shopifyId)) {
|
|
11179
|
+
console.warn('[CommodityDetail] 非 Shopify 商品,跳过加购弹窗');
|
|
11180
|
+
// 继续执行默认行为(跳转链接)
|
|
11112
11181
|
}
|
|
11113
11182
|
else {
|
|
11114
|
-
|
|
11183
|
+
// 设置弹窗数据
|
|
11184
|
+
setPopupDetailData === null || setPopupDetailData === void 0 ? void 0 : setPopupDetailData(Object.assign(Object.assign({}, data), { index: position }));
|
|
11185
|
+
// 上报点击事件
|
|
11186
|
+
bffFbReport === null || bffFbReport === void 0 ? void 0 : bffFbReport({
|
|
11187
|
+
eventName: 'ClickCTA',
|
|
11188
|
+
product: product ? [product] : undefined,
|
|
11189
|
+
contentType: 'product',
|
|
11190
|
+
data,
|
|
11191
|
+
position,
|
|
11192
|
+
cta_text: cta === null || cta === void 0 ? void 0 : cta.enTitle,
|
|
11193
|
+
cta_action_type: 'open_internal_popup',
|
|
11194
|
+
target_content_id: product === null || product === void 0 ? void 0 : product.itemId
|
|
11195
|
+
});
|
|
11196
|
+
console.log('[CommodityDetail] 打开加购弹窗:', addToCartPopupId);
|
|
11197
|
+
// 打开加购弹窗
|
|
11198
|
+
if (typeof window !== 'undefined' && window.sxpPopup) {
|
|
11199
|
+
window.sxpPopup(addToCartPopupId);
|
|
11200
|
+
}
|
|
11201
|
+
else {
|
|
11202
|
+
console.warn('[CommodityDetail] sxpPopup 方法不存在');
|
|
11203
|
+
}
|
|
11204
|
+
return;
|
|
11115
11205
|
}
|
|
11116
|
-
return;
|
|
11117
11206
|
}
|
|
11118
11207
|
// 默认行为:跳转到商品链接
|
|
11119
11208
|
if (product === null || product === void 0 ? void 0 : product.link) {
|
|
@@ -12083,7 +12172,7 @@ var settingRender$d = [
|
|
|
12083
12172
|
|
|
12084
12173
|
const AddToCartPopup$1 = ({ isActive = true }) => {
|
|
12085
12174
|
var _a, _b, _c, _d, _e, _f, _g, _h, _j;
|
|
12086
|
-
const { popupDetailData, globalConfig } = useSxpDataSource();
|
|
12175
|
+
const { popupDetailData, globalConfig, bffFbReport } = useSxpDataSource();
|
|
12087
12176
|
const [productData, setProductData] = React.useState(null);
|
|
12088
12177
|
const [selectedOptions, setSelectedOptions] = React.useState({});
|
|
12089
12178
|
const [selectedVariant, setSelectedVariant] = React.useState(null);
|
|
@@ -12223,6 +12312,18 @@ const AddToCartPopup$1 = ({ isActive = true }) => {
|
|
|
12223
12312
|
shopifyDomain,
|
|
12224
12313
|
selectedVariant
|
|
12225
12314
|
});
|
|
12315
|
+
// 上报 sessionCompleted 事件(问题4)
|
|
12316
|
+
bffFbReport === null || bffFbReport === void 0 ? void 0 : bffFbReport({
|
|
12317
|
+
eventName: 'sessionCompleted',
|
|
12318
|
+
product: product ? [product] : undefined,
|
|
12319
|
+
contentType: 'product',
|
|
12320
|
+
rec: data,
|
|
12321
|
+
position: data === null || data === void 0 ? void 0 : data.index,
|
|
12322
|
+
cta_text: 'Add To Cart',
|
|
12323
|
+
cta_action_type: 'add_to_cart',
|
|
12324
|
+
target_content_id: product === null || product === void 0 ? void 0 : product.itemId,
|
|
12325
|
+
target_url: `https://${shopifyDomain}/cart/add`
|
|
12326
|
+
});
|
|
12226
12327
|
// 使用 Shopify 的 /cart/add 接口,通过查询参数添加商品
|
|
12227
12328
|
// 这种方式会跳转到购物车页面而不是结算页面
|
|
12228
12329
|
const params = new URLSearchParams({
|
|
@@ -12237,6 +12338,10 @@ const AddToCartPopup$1 = ({ isActive = true }) => {
|
|
|
12237
12338
|
const totalPrice = selectedVariant
|
|
12238
12339
|
? (parseFloat(selectedVariant.price.amount) * quantity).toFixed(2)
|
|
12239
12340
|
: '0.00';
|
|
12341
|
+
// 只有选择了 variant 后才显示货币符号
|
|
12342
|
+
const displayPrice = selectedVariant
|
|
12343
|
+
? `${getCurrencySymbol(selectedVariant.price.currencyCode)}${totalPrice}`
|
|
12344
|
+
: totalPrice;
|
|
12240
12345
|
if (loading) {
|
|
12241
12346
|
return (React.createElement("div", { className: 'add-to-cart-popup' },
|
|
12242
12347
|
React.createElement("div", { className: 'loading' }, "Loading...")));
|
|
@@ -12270,9 +12375,7 @@ const AddToCartPopup$1 = ({ isActive = true }) => {
|
|
|
12270
12375
|
"Available: ",
|
|
12271
12376
|
selectedVariant.quantityAvailable))),
|
|
12272
12377
|
React.createElement("div", { className: 'variant-price-row' },
|
|
12273
|
-
React.createElement("div", { className: 'price' },
|
|
12274
|
-
"$",
|
|
12275
|
-
totalPrice),
|
|
12378
|
+
React.createElement("div", { className: 'price' }, displayPrice),
|
|
12276
12379
|
React.createElement("div", { className: 'quantity-selector' },
|
|
12277
12380
|
React.createElement("button", { className: 'qty-btn', onClick: () => setQuantity(Math.max(1, quantity - 1)), disabled: quantity <= 1 }, "\u2212"),
|
|
12278
12381
|
React.createElement("span", { className: 'qty-value' }, quantity),
|
|
@@ -12280,16 +12383,26 @@ const AddToCartPopup$1 = ({ isActive = true }) => {
|
|
|
12280
12383
|
React.createElement("div", { className: 'variant-options' }, productData.options.map(option => (React.createElement("div", { key: option.name, className: 'option-group' },
|
|
12281
12384
|
React.createElement("div", { className: 'option-label' }, option.name),
|
|
12282
12385
|
React.createElement("div", { className: 'option-values' }, option.values.map(value => {
|
|
12283
|
-
//
|
|
12386
|
+
// 检查这个选项值与当前已选择的其他选项组合后是否可用
|
|
12284
12387
|
const isAvailable = productData.variants.edges.some(({ node: variant }) => {
|
|
12388
|
+
// 检查这个variant是否匹配当前选项值
|
|
12285
12389
|
const hasThisOption = variant.selectedOptions.some(opt => opt.name === option.name && opt.value === value);
|
|
12286
|
-
if (!hasThisOption
|
|
12390
|
+
if (!hasThisOption)
|
|
12287
12391
|
return false;
|
|
12288
|
-
//
|
|
12289
|
-
|
|
12290
|
-
|
|
12291
|
-
|
|
12292
|
-
|
|
12392
|
+
// 检查这个variant是否匹配其他已选择的选项
|
|
12393
|
+
const matchesOtherSelections = Object.entries(selectedOptions).every(([key, val]) => {
|
|
12394
|
+
// 跳过当前正在检查的选项
|
|
12395
|
+
if (key === option.name)
|
|
12396
|
+
return true;
|
|
12397
|
+
return variant.selectedOptions.some(opt => opt.name === key && opt.value === val);
|
|
12398
|
+
});
|
|
12399
|
+
if (!matchesOtherSelections)
|
|
12400
|
+
return false;
|
|
12401
|
+
// 检查是否可售
|
|
12402
|
+
if (!variant.availableForSale)
|
|
12403
|
+
return false;
|
|
12404
|
+
// 如果有 quantityAvailable 字段且为0,但 availableForSale 为 true,仍然可选(问题2)
|
|
12405
|
+
// 如果 quantityAvailable 不存在,只要 availableForSale 为 true 就可选
|
|
12293
12406
|
return true;
|
|
12294
12407
|
});
|
|
12295
12408
|
const isSelected = selectedOptions[option.name] === value;
|
|
@@ -12340,7 +12453,35 @@ const CommodityDetailDiroNew$1 = (_a) => {
|
|
|
12340
12453
|
}
|
|
12341
12454
|
const handleLink = (e) => {
|
|
12342
12455
|
e.preventDefault();
|
|
12343
|
-
//
|
|
12456
|
+
// 问题3:只有 Shopify 商品(有 shopifyId)才打开加购弹窗
|
|
12457
|
+
if (!(product === null || product === void 0 ? void 0 : product.shopifyId)) {
|
|
12458
|
+
console.warn('[CommodityDetailDiroNew] 非 Shopify 商品,跳转到外链');
|
|
12459
|
+
// 上报点击事件
|
|
12460
|
+
ctaEvent === null || ctaEvent === void 0 ? void 0 : ctaEvent({
|
|
12461
|
+
eventSubject: 'clickCta',
|
|
12462
|
+
eventDescription: 'User clicked the CTA'
|
|
12463
|
+
}, data, product, position);
|
|
12464
|
+
bffFbReport === null || bffFbReport === void 0 ? void 0 : bffFbReport({
|
|
12465
|
+
eventName: 'ClickCTA',
|
|
12466
|
+
product: product ? [product] : undefined,
|
|
12467
|
+
contentType: 'product',
|
|
12468
|
+
data,
|
|
12469
|
+
position,
|
|
12470
|
+
cta_text: cta === null || cta === void 0 ? void 0 : cta.enTitle,
|
|
12471
|
+
cta_action_type: 'open_external_link',
|
|
12472
|
+
target_content_id: product === null || product === void 0 ? void 0 : product.itemId,
|
|
12473
|
+
target_url: product === null || product === void 0 ? void 0 : product.link
|
|
12474
|
+
});
|
|
12475
|
+
if (!isPost) {
|
|
12476
|
+
productView(data, product, cta, viewTime || curTimeRef.current, position);
|
|
12477
|
+
}
|
|
12478
|
+
// 跳转到商品链接
|
|
12479
|
+
if (product === null || product === void 0 ? void 0 : product.link) {
|
|
12480
|
+
window.location.href = window.getJointUtmLink(product.link);
|
|
12481
|
+
}
|
|
12482
|
+
return;
|
|
12483
|
+
}
|
|
12484
|
+
// Shopify 商品:上报点击事件
|
|
12344
12485
|
ctaEvent === null || ctaEvent === void 0 ? void 0 : ctaEvent({
|
|
12345
12486
|
eventSubject: 'clickCta',
|
|
12346
12487
|
eventDescription: 'User clicked the CTA'
|