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/pb-ui.js
CHANGED
|
@@ -413,6 +413,54 @@
|
|
|
413
413
|
}
|
|
414
414
|
return (_b = params[key]) !== null && _b !== void 0 ? _b : '';
|
|
415
415
|
}
|
|
416
|
+
/**
|
|
417
|
+
* 货币代码到货币符号的映射
|
|
418
|
+
* 根据 Shopify 返回的 currencyCode 获取对应的货币符号
|
|
419
|
+
*/
|
|
420
|
+
function getCurrencySymbol(currencyCode) {
|
|
421
|
+
const currencySymbolMap = {
|
|
422
|
+
// 主要货币
|
|
423
|
+
USD: '$', // 美元
|
|
424
|
+
EUR: '€', // 欧元
|
|
425
|
+
GBP: '£', // 英镑
|
|
426
|
+
JPY: '¥', // 日元
|
|
427
|
+
CNY: '¥', // 人民币
|
|
428
|
+
KRW: '₩', // 韩元
|
|
429
|
+
INR: '₹', // 印度卢比
|
|
430
|
+
RUB: '₽', // 俄罗斯卢布
|
|
431
|
+
BRL: 'R$', // 巴西雷亚尔
|
|
432
|
+
CAD: 'CA$', // 加拿大元
|
|
433
|
+
AUD: 'A$', // 澳元
|
|
434
|
+
CHF: 'CHF', // 瑞士法郎
|
|
435
|
+
SEK: 'kr', // 瑞典克朗
|
|
436
|
+
NOK: 'kr', // 挪威克朗
|
|
437
|
+
DKK: 'kr', // 丹麦克朗
|
|
438
|
+
PLN: 'zł', // 波兰兹罗提
|
|
439
|
+
THB: '฿', // 泰铢
|
|
440
|
+
IDR: 'Rp', // 印尼盾
|
|
441
|
+
MYR: 'RM', // 马来西亚林吉特
|
|
442
|
+
PHP: '₱', // 菲律宾比索
|
|
443
|
+
SGD: 'S$', // 新加坡元
|
|
444
|
+
HKD: 'HK$', // 港币
|
|
445
|
+
TWD: 'NT$', // 新台币
|
|
446
|
+
NZD: 'NZ$', // 新西兰元
|
|
447
|
+
MXN: 'MX$', // 墨西哥比索
|
|
448
|
+
ZAR: 'R', // 南非兰特
|
|
449
|
+
TRY: '₺', // 土耳其里拉
|
|
450
|
+
AED: 'AED', // 阿联酋迪拉姆
|
|
451
|
+
SAR: 'SAR', // 沙特里亚尔
|
|
452
|
+
ILS: '₪', // 以色列新谢克尔
|
|
453
|
+
ARS: 'AR$', // 阿根廷比索
|
|
454
|
+
CLP: 'CL$', // 智利比索
|
|
455
|
+
COP: 'CO$', // 哥伦比亚比索
|
|
456
|
+
VND: '₫', // 越南盾
|
|
457
|
+
EGP: 'E£', // 埃及镑
|
|
458
|
+
NGN: '₦', // 尼日利亚奈拉
|
|
459
|
+
PKR: '₨', // 巴基斯坦卢比
|
|
460
|
+
BDT: '৳', // 孟加拉塔卡
|
|
461
|
+
};
|
|
462
|
+
return currencySymbolMap[currencyCode.toUpperCase()] || currencyCode;
|
|
463
|
+
}
|
|
416
464
|
|
|
417
465
|
var tool = /*#__PURE__*/Object.freeze({
|
|
418
466
|
__proto__: null,
|
|
@@ -420,6 +468,7 @@
|
|
|
420
468
|
generateRandomString: generateRandomString,
|
|
421
469
|
getBrowserInfo: getBrowserInfo,
|
|
422
470
|
getCookie: getCookie,
|
|
471
|
+
getCurrencySymbol: getCurrencySymbol,
|
|
423
472
|
getDevice: getDevice$1,
|
|
424
473
|
getIndexByblockType: getIndexByblockType,
|
|
425
474
|
getScreenReader: getScreenReader,
|
|
@@ -10997,7 +11046,7 @@
|
|
|
10997
11046
|
: '';
|
|
10998
11047
|
};
|
|
10999
11048
|
const getPriceText = ({ product, enableFormattedPrice, globalConfig, isHiddenDef, style }) => {
|
|
11000
|
-
var _a, _b, _c, _d, _e
|
|
11049
|
+
var _a, _b, _c, _d, _e;
|
|
11001
11050
|
let text = '';
|
|
11002
11051
|
if ((!(product === null || product === void 0 ? void 0 : product.currency) || !(product === null || product === void 0 ? void 0 : product.price)) && isHiddenDef)
|
|
11003
11052
|
return null;
|
|
@@ -11005,18 +11054,51 @@
|
|
|
11005
11054
|
if (typeof price !== 'number')
|
|
11006
11055
|
return text;
|
|
11007
11056
|
let priceSymbol = globalConfig === null || globalConfig === void 0 ? void 0 : globalConfig.priceSymbol;
|
|
11008
|
-
|
|
11057
|
+
// 从 product.currency 中提取货币代码
|
|
11058
|
+
// 支持多种格式:
|
|
11059
|
+
// 1. "EUR" - 直接是货币代码
|
|
11060
|
+
// 2. "USD-$" - 货币代码-货币符号
|
|
11061
|
+
// 3. "$-USD" - 货币符号-货币代码 (不常见)
|
|
11062
|
+
let currencyCode = '';
|
|
11063
|
+
if (product === null || product === void 0 ? void 0 : product.currency) {
|
|
11064
|
+
const parts = product.currency.split('-');
|
|
11065
|
+
if (parts.length > 1) {
|
|
11066
|
+
// 判断哪一部分是货币代码(通常是3个大写字母)
|
|
11067
|
+
// 货币代码通常是3个字母,如 USD, EUR, GBP
|
|
11068
|
+
const firstPart = parts[0].toUpperCase();
|
|
11069
|
+
const secondPart = parts[1].toUpperCase();
|
|
11070
|
+
// 如果第一部分是3个字母,则认为是货币代码
|
|
11071
|
+
if (/^[A-Z]{3}$/.test(firstPart)) {
|
|
11072
|
+
currencyCode = firstPart;
|
|
11073
|
+
}
|
|
11074
|
+
else if (/^[A-Z]{3}$/.test(secondPart)) {
|
|
11075
|
+
currencyCode = secondPart;
|
|
11076
|
+
}
|
|
11077
|
+
else {
|
|
11078
|
+
// 都不是标准格式,取第一部分
|
|
11079
|
+
currencyCode = firstPart;
|
|
11080
|
+
}
|
|
11081
|
+
}
|
|
11082
|
+
else {
|
|
11083
|
+
currencyCode = parts[0].toUpperCase();
|
|
11084
|
+
}
|
|
11085
|
+
}
|
|
11086
|
+
else {
|
|
11087
|
+
currencyCode = 'USD'; // 默认美元
|
|
11088
|
+
}
|
|
11089
|
+
// 使用货币代码映射获取货币符号
|
|
11090
|
+
let currency = getCurrencySymbol(currencyCode);
|
|
11009
11091
|
const isToLocStr = enableFormattedPrice === undefined || enableFormattedPrice;
|
|
11010
11092
|
let decPic = price === null || price === void 0 ? void 0 : price.toString();
|
|
11011
11093
|
if (priceSymbol === null || priceSymbol === void 0 ? void 0 : priceSymbol.showTwoDecimalPoint) {
|
|
11012
11094
|
decPic = price === null || price === void 0 ? void 0 : price.toFixed(2);
|
|
11013
11095
|
}
|
|
11014
|
-
let decInd = (
|
|
11096
|
+
let decInd = (_a = decPic === null || decPic === void 0 ? void 0 : decPic.indexOf('.')) !== null && _a !== void 0 ? _a : -1;
|
|
11015
11097
|
if (isToLocStr) {
|
|
11016
11098
|
text =
|
|
11017
|
-
(
|
|
11099
|
+
(_b = price === null || price === void 0 ? void 0 : price.toLocaleString('zh', {
|
|
11018
11100
|
minimumFractionDigits: (priceSymbol === null || priceSymbol === void 0 ? void 0 : priceSymbol.showTwoDecimalPoint) ? 2 : 0
|
|
11019
|
-
})) !== null &&
|
|
11101
|
+
})) !== null && _b !== void 0 ? _b : '';
|
|
11020
11102
|
let startIndex = 0;
|
|
11021
11103
|
let endIndex = decInd !== null && decInd !== void 0 ? decInd : text === null || text === void 0 ? void 0 : text.length;
|
|
11022
11104
|
if ((priceSymbol === null || priceSymbol === void 0 ? void 0 : priceSymbol.millesimalSymbol) === '.') {
|
|
@@ -11047,7 +11129,7 @@
|
|
|
11047
11129
|
}
|
|
11048
11130
|
});
|
|
11049
11131
|
}
|
|
11050
|
-
currency = `<span style="font-family:${(
|
|
11132
|
+
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>`;
|
|
11051
11133
|
text = setFontForText(text, style);
|
|
11052
11134
|
if ((priceSymbol === null || priceSymbol === void 0 ? void 0 : priceSymbol.currencyPosition) && (priceSymbol === null || priceSymbol === void 0 ? void 0 : priceSymbol.currencyPosition) !== 'none') {
|
|
11053
11135
|
text = (priceSymbol === null || priceSymbol === void 0 ? void 0 : priceSymbol.currencyPosition) === 'left' ? currency + text : text + currency;
|
|
@@ -11083,30 +11165,37 @@
|
|
|
11083
11165
|
cta = p === null || p === void 0 ? void 0 : p.bindCta;
|
|
11084
11166
|
}
|
|
11085
11167
|
const handleLink = (e) => {
|
|
11086
|
-
// 如果启用了加购功能且配置了加购弹窗ID
|
|
11168
|
+
// 如果启用了加购功能且配置了加购弹窗ID,检查是否是 Shopify 商品
|
|
11087
11169
|
if (enableAddToCart && addToCartPopupId) {
|
|
11088
|
-
//
|
|
11089
|
-
|
|
11090
|
-
|
|
11091
|
-
|
|
11092
|
-
eventName: 'ClickCTA',
|
|
11093
|
-
product: product ? [product] : undefined,
|
|
11094
|
-
contentType: 'product',
|
|
11095
|
-
data,
|
|
11096
|
-
position,
|
|
11097
|
-
cta_text: cta === null || cta === void 0 ? void 0 : cta.enTitle,
|
|
11098
|
-
cta_action_type: 'open_internal_popup',
|
|
11099
|
-
target_content_id: product === null || product === void 0 ? void 0 : product.itemId
|
|
11100
|
-
});
|
|
11101
|
-
console.log('[CommodityDetail] 打开加购弹窗:', addToCartPopupId);
|
|
11102
|
-
// 打开加购弹窗
|
|
11103
|
-
if (typeof window !== 'undefined' && window.sxpPopup) {
|
|
11104
|
-
window.sxpPopup(addToCartPopupId);
|
|
11170
|
+
// 问题3:只有 Shopify 商品(有 shopifyId)才打开加购弹窗
|
|
11171
|
+
if (!(product === null || product === void 0 ? void 0 : product.shopifyId)) {
|
|
11172
|
+
console.warn('[CommodityDetail] 非 Shopify 商品,跳过加购弹窗');
|
|
11173
|
+
// 继续执行默认行为(跳转链接)
|
|
11105
11174
|
}
|
|
11106
11175
|
else {
|
|
11107
|
-
|
|
11176
|
+
// 设置弹窗数据
|
|
11177
|
+
setPopupDetailData === null || setPopupDetailData === void 0 ? void 0 : setPopupDetailData(Object.assign(Object.assign({}, data), { index: position }));
|
|
11178
|
+
// 上报点击事件
|
|
11179
|
+
bffFbReport === null || bffFbReport === void 0 ? void 0 : bffFbReport({
|
|
11180
|
+
eventName: 'ClickCTA',
|
|
11181
|
+
product: product ? [product] : undefined,
|
|
11182
|
+
contentType: 'product',
|
|
11183
|
+
data,
|
|
11184
|
+
position,
|
|
11185
|
+
cta_text: cta === null || cta === void 0 ? void 0 : cta.enTitle,
|
|
11186
|
+
cta_action_type: 'open_internal_popup',
|
|
11187
|
+
target_content_id: product === null || product === void 0 ? void 0 : product.itemId
|
|
11188
|
+
});
|
|
11189
|
+
console.log('[CommodityDetail] 打开加购弹窗:', addToCartPopupId);
|
|
11190
|
+
// 打开加购弹窗
|
|
11191
|
+
if (typeof window !== 'undefined' && window.sxpPopup) {
|
|
11192
|
+
window.sxpPopup(addToCartPopupId);
|
|
11193
|
+
}
|
|
11194
|
+
else {
|
|
11195
|
+
console.warn('[CommodityDetail] sxpPopup 方法不存在');
|
|
11196
|
+
}
|
|
11197
|
+
return;
|
|
11108
11198
|
}
|
|
11109
|
-
return;
|
|
11110
11199
|
}
|
|
11111
11200
|
// 默认行为:跳转到商品链接
|
|
11112
11201
|
if (product === null || product === void 0 ? void 0 : product.link) {
|
|
@@ -12076,7 +12165,7 @@
|
|
|
12076
12165
|
|
|
12077
12166
|
const AddToCartPopup$1 = ({ isActive = true }) => {
|
|
12078
12167
|
var _a, _b, _c, _d, _e, _f, _g, _h, _j;
|
|
12079
|
-
const { popupDetailData, globalConfig } = useSxpDataSource();
|
|
12168
|
+
const { popupDetailData, globalConfig, bffFbReport } = useSxpDataSource();
|
|
12080
12169
|
const [productData, setProductData] = React.useState(null);
|
|
12081
12170
|
const [selectedOptions, setSelectedOptions] = React.useState({});
|
|
12082
12171
|
const [selectedVariant, setSelectedVariant] = React.useState(null);
|
|
@@ -12216,6 +12305,18 @@
|
|
|
12216
12305
|
shopifyDomain,
|
|
12217
12306
|
selectedVariant
|
|
12218
12307
|
});
|
|
12308
|
+
// 上报 sessionCompleted 事件(问题4)
|
|
12309
|
+
bffFbReport === null || bffFbReport === void 0 ? void 0 : bffFbReport({
|
|
12310
|
+
eventName: 'sessionCompleted',
|
|
12311
|
+
product: product ? [product] : undefined,
|
|
12312
|
+
contentType: 'product',
|
|
12313
|
+
rec: data,
|
|
12314
|
+
position: data === null || data === void 0 ? void 0 : data.index,
|
|
12315
|
+
cta_text: 'Add To Cart',
|
|
12316
|
+
cta_action_type: 'add_to_cart',
|
|
12317
|
+
target_content_id: product === null || product === void 0 ? void 0 : product.itemId,
|
|
12318
|
+
target_url: `https://${shopifyDomain}/cart/add`
|
|
12319
|
+
});
|
|
12219
12320
|
// 使用 Shopify 的 /cart/add 接口,通过查询参数添加商品
|
|
12220
12321
|
// 这种方式会跳转到购物车页面而不是结算页面
|
|
12221
12322
|
const params = new URLSearchParams({
|
|
@@ -12230,6 +12331,10 @@
|
|
|
12230
12331
|
const totalPrice = selectedVariant
|
|
12231
12332
|
? (parseFloat(selectedVariant.price.amount) * quantity).toFixed(2)
|
|
12232
12333
|
: '0.00';
|
|
12334
|
+
// 只有选择了 variant 后才显示货币符号
|
|
12335
|
+
const displayPrice = selectedVariant
|
|
12336
|
+
? `${getCurrencySymbol(selectedVariant.price.currencyCode)}${totalPrice}`
|
|
12337
|
+
: totalPrice;
|
|
12233
12338
|
if (loading) {
|
|
12234
12339
|
return (React.createElement("div", { className: 'add-to-cart-popup' },
|
|
12235
12340
|
React.createElement("div", { className: 'loading' }, "Loading...")));
|
|
@@ -12263,9 +12368,7 @@
|
|
|
12263
12368
|
"Available: ",
|
|
12264
12369
|
selectedVariant.quantityAvailable))),
|
|
12265
12370
|
React.createElement("div", { className: 'variant-price-row' },
|
|
12266
|
-
React.createElement("div", { className: 'price' },
|
|
12267
|
-
"$",
|
|
12268
|
-
totalPrice),
|
|
12371
|
+
React.createElement("div", { className: 'price' }, displayPrice),
|
|
12269
12372
|
React.createElement("div", { className: 'quantity-selector' },
|
|
12270
12373
|
React.createElement("button", { className: 'qty-btn', onClick: () => setQuantity(Math.max(1, quantity - 1)), disabled: quantity <= 1 }, "\u2212"),
|
|
12271
12374
|
React.createElement("span", { className: 'qty-value' }, quantity),
|
|
@@ -12273,16 +12376,26 @@
|
|
|
12273
12376
|
React.createElement("div", { className: 'variant-options' }, productData.options.map(option => (React.createElement("div", { key: option.name, className: 'option-group' },
|
|
12274
12377
|
React.createElement("div", { className: 'option-label' }, option.name),
|
|
12275
12378
|
React.createElement("div", { className: 'option-values' }, option.values.map(value => {
|
|
12276
|
-
//
|
|
12379
|
+
// 检查这个选项值与当前已选择的其他选项组合后是否可用
|
|
12277
12380
|
const isAvailable = productData.variants.edges.some(({ node: variant }) => {
|
|
12381
|
+
// 检查这个variant是否匹配当前选项值
|
|
12278
12382
|
const hasThisOption = variant.selectedOptions.some(opt => opt.name === option.name && opt.value === value);
|
|
12279
|
-
if (!hasThisOption
|
|
12383
|
+
if (!hasThisOption)
|
|
12280
12384
|
return false;
|
|
12281
|
-
//
|
|
12282
|
-
|
|
12283
|
-
|
|
12284
|
-
|
|
12285
|
-
|
|
12385
|
+
// 检查这个variant是否匹配其他已选择的选项
|
|
12386
|
+
const matchesOtherSelections = Object.entries(selectedOptions).every(([key, val]) => {
|
|
12387
|
+
// 跳过当前正在检查的选项
|
|
12388
|
+
if (key === option.name)
|
|
12389
|
+
return true;
|
|
12390
|
+
return variant.selectedOptions.some(opt => opt.name === key && opt.value === val);
|
|
12391
|
+
});
|
|
12392
|
+
if (!matchesOtherSelections)
|
|
12393
|
+
return false;
|
|
12394
|
+
// 检查是否可售
|
|
12395
|
+
if (!variant.availableForSale)
|
|
12396
|
+
return false;
|
|
12397
|
+
// 如果有 quantityAvailable 字段且为0,但 availableForSale 为 true,仍然可选(问题2)
|
|
12398
|
+
// 如果 quantityAvailable 不存在,只要 availableForSale 为 true 就可选
|
|
12286
12399
|
return true;
|
|
12287
12400
|
});
|
|
12288
12401
|
const isSelected = selectedOptions[option.name] === value;
|
|
@@ -12333,7 +12446,35 @@
|
|
|
12333
12446
|
}
|
|
12334
12447
|
const handleLink = (e) => {
|
|
12335
12448
|
e.preventDefault();
|
|
12336
|
-
//
|
|
12449
|
+
// 问题3:只有 Shopify 商品(有 shopifyId)才打开加购弹窗
|
|
12450
|
+
if (!(product === null || product === void 0 ? void 0 : product.shopifyId)) {
|
|
12451
|
+
console.warn('[CommodityDetailDiroNew] 非 Shopify 商品,跳转到外链');
|
|
12452
|
+
// 上报点击事件
|
|
12453
|
+
ctaEvent === null || ctaEvent === void 0 ? void 0 : ctaEvent({
|
|
12454
|
+
eventSubject: 'clickCta',
|
|
12455
|
+
eventDescription: 'User clicked the CTA'
|
|
12456
|
+
}, data, product, position);
|
|
12457
|
+
bffFbReport === null || bffFbReport === void 0 ? void 0 : bffFbReport({
|
|
12458
|
+
eventName: 'ClickCTA',
|
|
12459
|
+
product: product ? [product] : undefined,
|
|
12460
|
+
contentType: 'product',
|
|
12461
|
+
data,
|
|
12462
|
+
position,
|
|
12463
|
+
cta_text: cta === null || cta === void 0 ? void 0 : cta.enTitle,
|
|
12464
|
+
cta_action_type: 'open_external_link',
|
|
12465
|
+
target_content_id: product === null || product === void 0 ? void 0 : product.itemId,
|
|
12466
|
+
target_url: product === null || product === void 0 ? void 0 : product.link
|
|
12467
|
+
});
|
|
12468
|
+
if (!isPost) {
|
|
12469
|
+
productView(data, product, cta, viewTime || curTimeRef.current, position);
|
|
12470
|
+
}
|
|
12471
|
+
// 跳转到商品链接
|
|
12472
|
+
if (product === null || product === void 0 ? void 0 : product.link) {
|
|
12473
|
+
window.location.href = window.getJointUtmLink(product.link);
|
|
12474
|
+
}
|
|
12475
|
+
return;
|
|
12476
|
+
}
|
|
12477
|
+
// Shopify 商品:上报点击事件
|
|
12337
12478
|
ctaEvent === null || ctaEvent === void 0 ? void 0 : ctaEvent({
|
|
12338
12479
|
eventSubject: 'clickCta',
|
|
12339
12480
|
eventDescription: 'User clicked the CTA'
|