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.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
|
|
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
|
-
|
|
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 = (
|
|
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
|
-
(
|
|
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 &&
|
|
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:${(
|
|
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
|
-
|
|
11075
|
-
|
|
11076
|
-
|
|
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
|
-
|
|
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
|
-
//
|
|
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
|
|
12368
|
+
if (!hasThisOption)
|
|
12265
12369
|
return false;
|
|
12266
|
-
//
|
|
12267
|
-
|
|
12268
|
-
|
|
12269
|
-
|
|
12270
|
-
|
|
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'
|