${firstDiscount.display_name}
${anotherData.map((item, index) => {
return `
${item.display_name}
`;
}).join('')}
${originData.discount_text}
${function() {
return `
`;
}()}
const TAG = 'spz-custom-discount-default';
const API = {
CAMPAIGN: "\/api\/storefront\/promotion\/landing_page\/campaign?discount_id=",
PRODUCT_LIST: "\/api\/storefront\/promotion\/landing_page\/product\/list",
DISCOUNT_I18N: "\/api\/discount-i18n"
};
const SHOP_ID = "1199785";
const E_TAB_MAP = {
scenario_buy: { value: "1", domId: "product_list_buy_products" },
scenario_obtain: { value: "2", domId: "product_list_obtain_products" }
};
const SORT_DICT = {
recommend_asc: { by: 'recommend', direction: 'asc' },
title_asc: { by: 'title', direction: 'asc' },
title_desc: { by: 'title', direction: 'desc' },
price_asc: { by: 'price', direction: 'asc' },
price_desc: { by: 'price', direction: 'desc' },
created_at_desc: { by: 'created_at', direction: 'desc' },
sales_desc: { by: 'sales', direction: 'desc' },
add_to_cart_count_desc: { by: 'add_to_cart_count', direction: 'desc' },
views_desc: { by: 'views', direction: 'desc' }
};
const SORT_OPTIONS = [
{ value: 'recommend_asc', text: "Recommend" },
{ value: 'price_asc', text: "Price, low to high" },
{ value: 'price_desc', text: "Price, high to low" },
{ value: 'title_asc', text: "Name, A to Z" },
{ value: 'title_desc', text: "Name, Z to A" },
{ value: 'created_at_desc', text: "Newest in" },
{ value: 'sales_desc', text: "Total sales, high to low" },
{ value: 'add_to_cart_count_desc', text: "Purchases, high to low" },
{ value: 'views_desc', text: "Page views, high to low" }
];
class SpzCustomDiscountDefault extends SPZ.BaseElement {
constructor(element) {
super(element);
this.templates_ = null;
this.discountId = ''; // 活动 id
this.discountType = "";
this.discountI18n = {};
this.bundleProducts = [];
this.tabContentIdMap = {};
this.currentTab = E_TAB_MAP.scenario_buy.value;
this.modelMap = {
[E_TAB_MAP.scenario_buy.value]: {},
[E_TAB_MAP.scenario_obtain.value]: {}
}
}
static deferredMount() {
return false;
}
buildCallback() {
this.action_ = SPZServices.actionServiceForDoc(this.element);
this.templates_ = SPZServices.templatesForDoc(this.element);
this.xhr_ = SPZServices.xhrFor(this.win);
this.setupAction_();
this.initTabContentMap_();
SPZUtils.Event.listen(document.getElementById('discount-match-mask'), 'click', (e) => {
e.stopPropagation();
this.handleCloseDiscountDrawer_();
});
}
initTabContentMap_() {
Object.entries(E_TAB_MAP).forEach(([key, valueObj]) => {
this.tabContentIdMap[valueObj.value] = valueObj.domId;
});
}
// 初始化
initData_(data) {
this.discountId = data.discount_info.id;
this.discountType = data.discount_info.discount_type;
const model_buy_map = {
discount_id: this.discountId, //活动id
scenario: 1, // 枚举值,1:购买商品,2:获得商品
sort: { by :"recommend", direction :"asc"},
page: 2, //分页码
limit: 20, // 每页数量
loading: false, // 请求数据标示
has_more: true // 是否还有数据
};
const model_get_map = {
discount_id: this.discountId,
scenario: 2,
sort: { by :"recommend", direction :"asc"},
page: 2,
limit: 20,
loading: false,
has_more: true
};
this.modelMap = {
[E_TAB_MAP.scenario_buy.value]: model_buy_map,
[E_TAB_MAP.scenario_obtain.value]: model_get_map
}
this.renderSort_();
}
getDiscountI18n_() {
this.xhr_.fetchJson(API.DISCOUNT_I18N, {
method: "GET",
}).then((res)=>{
this.discountI18n = res;
this.bindEvent();
});
}
renderSort_() {
const renderSort = (sortId, model) => {
const $sortElement = document.getElementById(sortId);
if ($sortElement) {
SPZ.whenApiDefined($sortElement).then((api) => {
const defaultValue = `${model.sort.by}_${model.sort.direction}` || "title_asc";
api.doRender_({ options: SORT_OPTIONS, defaultValue, id: sortId });
});
}
};
renderSort('spz_custom_sort_products_x', this.modelMap[E_TAB_MAP.scenario_buy.value]);
renderSort('spz_custom_sort_products_y', this.modelMap[E_TAB_MAP.scenario_obtain.value]);
}
// 获取数据,拼接html模板
async getData(cb) {
// 请求数据
const model = this.modelMap[this.currentTab];
if (!model.has_more || model.loading) return;
model.loading = true;
this.handleLoading_({type: 'product', action: 'show'});
const $content = document.querySelector(`#${this.tabContentIdMap[this.currentTab]} .discount-default__productlist-wrap`) || document.querySelector(`.discount-default__productlist-wrap`);
//查询活动商品接口
const reqBody = {
discount_id: model.discount_id,
page: model.page,
limit: model.limit,
apply_scenario: model.scenario,
sort: model.sort,
sales_channel: { sale_channel_type: "online", sale_channel_id: SHOP_ID }
}
this.xhr_.fetchJson(API.PRODUCT_LIST, {
method: "POST",
body: reqBody
}).then(async(res)=>{
this.handleLoading_({type: 'product', action: 'close'});
const count = res.count;
model.has_more = res.has_more;
if (count > 0) {
model.page++;
if (res.products && res.products.length > 0) {
const products = res.products.map((product) => {
return {
...product,
discount_id: model.discount_id,
apply_scenario: model.scenario,
url: appDiscountUtils.globalizePath(product.url),
image_padding_bottom: appDiscountUtils.image_padding_bottom(product.image.width, product.image.height,'no-limit'),
discount_type: this.discountType
}
});
// 获取商品列表渲染模板, dom挂载
const renderApi = await SPZ.whenApiDefined(document.querySelector('#app-discount_match_drawer_products_render'));
const el = await renderApi.getRenderTemplate({ products: products, discountI18n: this.discountI18n });
const childNodes = el.querySelectorAll('.as-render-product-item');
if (childNodes && childNodes.length > 0) {
$content.append(...el.childNodes);
}
this.bundleProducts = [...this.bundleProducts, ...res.products];
SPZ.whenApiDefined(document.getElementById("appDiscountBundleProductsFunc")).then((api) => {
api.setBundleData(this.bundleProducts);
})
if(this.discountType === 'DT_MIX_MATCH_BUNDLE') {
const productSelector = SPZCore.Dom.scopedQuerySelector(document.body, `#promotionProductSelector`);
productSelector && SPZ.whenApiDefined(productSelector).then((api) => {
api.init();
});
}
// 监听load去掉灰色背景
document.dispatchEvent(new CustomEvent('fire.load.img'));
// 触发懒加载
cb && cb(products);
window.lazyLoadInstance && window.lazyLoadInstance.update();
} else {
}
}
model.loading = false;
}).catch((err)=>{
console.error(err);
model.loading = false;
this.handleLoading_({type: 'product', action: 'close'});
}).finally(() => {
if(this.discountType === 'DT_MIX_MATCH_BUNDLE') {
SPZ.whenApiDefined(document.getElementById("appDiscountBundleProductsFunc")).then((api) => {
api.handleChangeSort();
})
}
})
}
bindEvent() {
// 监听滚动,请求数据
const $el = document.querySelector(".discount-match-drawer-content");
if ($el) {
$el.addEventListener("scroll", this.win.SPZCore.Types.debounce(this.win, () => {
const model = this.modelMap[this.currentTab];
if (!model.loading && model.has_more && appDiscountUtils.isToPageEnd(`[data-drawer-id='${this.discountId}']`)) {
this.getData();
}
}, 50));
}
window.addEventListener("resize", this.setMatchDrawerHeight_);
}
// 商品排序
handleSort_(data) {
const sortKey = data.value;
this.modelMap[this.currentTab].sort = SORT_DICT[sortKey || 'title_asc'];
this.modelMap[this.currentTab].page = 1;
this.modelMap[this.currentTab].has_more = true;
this.clearProductListDom_();
this.getData((products) => {});
}
// tab 切换
tabChange_(value) {
this.currentTab = value || E_TAB_MAP.scenario_buy.value;
}
setMatchDrawerHeight_() {
//设置凑单弹窗高度为90%,一些移动端浏览器上方帮助栏会影响视口大小,因此使用window.innerHeight
const modalContent = document.querySelector(".discount-match-drawer");
const windowHeight = window.innerHeight;
modalContent.style.maxHeight = windowHeight * 0.9 + "px";
}
showDiscountToast(message) {
SPZ.whenApiDefined(document.getElementById("discount_toast")).then((apis) => {
apis.showToast(message);
});
}
handleLoading_(event) {
const { type, action } = event;
const loadingElementId = type === 'product' ? '#discount-match-drawer-products_loading' : '#apps-discount-whole-loading';
const loadingElement = document.querySelector(loadingElementId);
if (loadingElement) {
SPZ.whenApiDefined(loadingElement).then((api) => {
if (action === 'show') {
api.show_();
} else {
api.close_();
}
});
}
}
setupAction_() {
// Buy X Get Y Tab 切换
this.registerAction('handleBuyXGetYTabChange', (invocation) => {
const { panelId } = invocation.args.data;
this.tabChange_(panelId);
});
// 监听排序组件 选中选项
this.registerAction('handleSort', (invocation) => {
const data = invocation.args.data;
if (this.discountType === "DT_MIX_MATCH_BUNDLE") {
const bundleFun = document.getElementById("appDiscountBundleProductsFunc");
SPZ.whenApiDefined(bundleFun).then((api) => {
const oldProductInfo = api.productStyleInfo;
const newData = oldProductInfo.filter(item => {
const currentProductOption = SPZCore.Dom.scopedQuerySelector(document.body, `#promotionSelectOption-${item.product_id}`);
return currentProductOption && currentProductOption.hasAttribute('selected')
})
api.init(newData);
})
.then(() => {
this.handleSort_(data);
})
} else {
this.handleSort_(data);
}
});
//初始化弹窗数据
this.registerAction('showDiscountDrawer', async (data) => {
const discountId = data.args.discountId || '';
const activeTab = data.args.activeTab || E_TAB_MAP.scenario_buy.value;
this.tabChange_(activeTab);
this.triggerEvent_('setTab', { activeTab });
this.getDiscountI18n_();
this.getCampaignDetail_(discountId).then(() => {
this.handleShowDiscountDrawer_();
});
});
// 关闭弹窗
this.registerAction('removeDiscountElement', () => {
this.handleCloseDiscountDrawer_();
});
// 切换多个活动
this.registerAction('discountSelectorChange', (invocation) => {
const { targetOption } = invocation.args.data;
this.handleDiscountSelectorChange_(targetOption);
});
}
handleDiscountSelectorChange_(targetOption) {
this.modelMap[this.currentTab].sort = SORT_DICT['title_asc'];
this.modelMap[this.currentTab].page = 1;
this.modelMap[this.currentTab].has_more = true;
this.clearProductListDom_();
this.handleLoading_({ type: 'product', action: 'show' });
this.getCampaignDetail_(targetOption).finally(() => {
this.handleLoading_({ type: 'product', action: 'close' });
});
}
// 清空商品列表dom, 重新请求排序数据渲染
clearProductListDom_() {
const $productList = document.querySelector(`#${this.tabContentIdMap[this.currentTab]} .discount-default__productlist-wrap`) || document.querySelector(`.discount-default__productlist-wrap`);
if ($productList) $productList.innerHTML = '';
}
handleShowDiscountDrawer_() {
this.setMatchDrawerHeight_();
const $el = document.querySelector("#discount-match-drawer");
document.body.appendChild($el);
$el.style.display="block";
document.documentElement.classList.add("i-spzhtml-scroll-disabled");
}
handleCloseDiscountDrawer_() {
document.querySelector("#discount-match-drawer").style.display="none";
document.documentElement.classList.remove("i-spzhtml-scroll-disabled");
this.clearProductListDom_();
const bannerEL = document.querySelector(".discount_match_drawer_banner_inner");
const productEL = document.querySelector(".discount-default");
bannerEL && SPZCore.Dom.removeChildren(bannerEL);
productEL && SPZCore.Dom.removeChildren(productEL);
const bundleFun = document.getElementById("appDiscountBundleProductsFunc");
SPZ.whenApiDefined(bundleFun).then((api) => {
api.init();
})
const bundleButtonEL = document.querySelector(".app-bundle-discount_bottom_container");
bundleButtonEL && SPZCore.Dom.removeChildren(bundleButtonEL);
}
getCampaignDetail_(discount_id) {
return this.xhr_.fetchJson(API.CAMPAIGN + discount_id, { method: "GET" }).then((data) => {
this.bundleProducts = data.buy_product_info.product;
if(data.discount_info.progress == "PROGRESS_FINISHED") {
this.showDiscountToast("The discount has finished");
return Promise.reject({});
} else {
SPZ.whenApiDefined(document.getElementById("discount-match-drawer-container")).then(apis => {
apis.render(data, true).then(() => {
this.initData_(data);
const type = data.discount_info.discount_type;
document.querySelector(".discount-match-drawer").dataset.discountType = type;
//给捆绑组件传值
if(type === "DT_MIX_MATCH_BUNDLE" || type === "DT_CLASSIC_BUNDLE") {
// 重置
const bundleButtonEL = document.querySelector(".app-bundle-discount_bottom_container");
bundleButtonEL && SPZCore.Dom.removeChildren(bundleButtonEL);
//购物车默认加购
data.landing_page_info.button.redirect_page = "cart";
SPZ.whenApiDefined(document.getElementById("appDiscountBundleProductsFunc")).then((api) => {
api.init(); // 切换 Tab 重置数据
api.setBundleData(data.buy_product_info.product, data.landing_page_info, data.discount_info.id, data.discount_info.discount_type, data.discount_info);
});
if(type === "DT_CLASSIC_BUNDLE") {
SPZ.whenApiDefined(document.getElementById("promotionBottomContainer")).then((api) => {
const buttonData = {
setting: data.landing_page_info,
...data.buy_product_info.total_price
}
api.render(buttonData, true);
})
}
}
});
});
}
}).catch(e => {
e.then((data) => {
if(data.code == 10003001) {
this.showDiscountToast("The discount has finished");
}
});
});
}
triggerEvent_(name, data) {
const event = SPZUtils.Event.create(this.win, `${ TAG }.${ name }`, data || {});
this.action_.trigger(this.element, name, event);
}
isLayoutSupported(layout) {
return layout == SPZCore.Layout.CONTAINER;
}
}
SPZ.defineElement(TAG, SpzCustomDiscountDefault)
(function () {
const TAG = "spz-custom-render-products";
class SpzCustomProducts extends SPZ.BaseElement {
constructor(element) {
super(element);
}
buildCallback() {
this.action_ = SPZServices.actionServiceForDoc(this.element);
this.templates_ = SPZServices.templatesForDoc(this.element);
this.xhr_ = SPZServices.xhrFor(this.win);
}
doRender_(data) {
return this.templates_
.findAndRenderTemplate(this.element, data)
.then((el) => {
const children = this.element.querySelector('*:not(template)');
children && SPZCore.Dom.removeElement(children);
this.element.appendChild(el);
});
}
getRenderTemplate(data) {
const renderData = data || {};
return this.templates_
.findAndRenderTemplate(this.element, renderData)
.then((el) => {
const children = this.element.querySelector('*:not(template)');
children && SPZCore.Dom.removeElement(children);
return el;
});
}
triggerEvent_(name, data) {
const event = SPZUtils.Event.create(this.win, '${ TAG }.${ name }', data || {});
this.action_.trigger(this.element, name, event);
}
isLayoutSupported(layout) {
return layout == SPZCore.Layout.CONTAINER;
}
}
SPZ.defineElement(TAG, SpzCustomProducts)
})()
${function() {
const options = data.options;
const defaultValue = data.defaultValue || options[0].value;
let defaultText = options[0].text;
const hasOption = Array.apply(null, options).find((option) => {
return option.value === defaultValue;
});
if(hasOption){
defaultText = hasOption.text;
}
return `
`
}()}
const TAG = 'spz-custom-sort';
class SpzCustomSort extends SPZ.BaseElement {
constructor(element) {
super(element);
this.spz_custom_id = '';
}
static deferredMount() {
return false;
}
buildCallback() {
this.action_ = SPZServices.actionServiceForDoc(this.element);
this.templates_ = SPZServices.templatesForDoc(this.element);
this.xhr_ = SPZServices.xhrFor(this.win);
this.setupAction_();
}
init() {
this.bindEvent();
}
bindEvent() {
const $selectList = SPZCore.Dom.scopedQuerySelectorAll(
this.element,
".sort_custom_content li"
);
const $customerSelect = SPZCore.Dom.scopedQuerySelector(
this.element,
".sort_custom_select"
);
// 选择下拉选项
Array.from($selectList).forEach((node) => {
SPZUtils.Event.listen(node, 'click', ()=> {
let value = node.getAttribute('value');
let text = node.getAttribute('text');
// 触发selectChange 事件
this.triggerEvent_('selectChange', {
value: value,
name: value
})
$customerSelect.innerHTML = text;
const panelChilds = this.element.querySelectorAll(".sort_custom_panel li");
// 清空其他选项的勾选状态
Array.from(panelChilds).forEach((el) => {
if(el.getAttribute('value') == value) {
el.classList.add("active")
} else {
el.classList.remove('active');
}
})
});
})
}
// 渲染界面
async doRender_(data) {
// 操作该组件的dom id
this.spz_custom_id = data.id;
return this.templates_
.findAndRenderTemplate(this.element, data)
.then((el) => {
const children = this.element.querySelector('*:not(template)');
children && SPZCore.Dom.removeElement(children);
this.element.appendChild(el);
}).then(() => {
this.init();
});
}
setupAction_() {
this.registerAction('render', async(invocation) => {
const data = invocation.args.data;
this.doRender_(data)
});
this.registerAction('handleSelect', async(invocation) => {
const data = invocation.args.data;
});
this.registerAction('handleDropdownOpen', async(invocation) => {
const $selectDropDown = SPZCore.Dom.scopedQuerySelector(
this.element,
".select_drop_down"
);
$selectDropDown.classList.add('select_drop_down_rotate');
});
this.registerAction('handleDropdownClose', async(invocation) => {
const $selectDropDown = SPZCore.Dom.scopedQuerySelector(
this.element,
".select_drop_down"
);
$selectDropDown.classList.remove('select_drop_down_rotate');
});
}
triggerEvent_(name, data) {
const event = SPZUtils.Event.create(this.win, `${ TAG }.${ name }`, data || {});
this.action_.trigger(this.element, name, event);
}
isLayoutSupported(layout) {
return layout == SPZCore.Layout.CONTAINER;
}
}
SPZ.defineElement(TAG, SpzCustomSort)
${function() {
const selectedVariant = data.variant || data.variants[0];
const image = selectedVariant.image || data.product.image;
const imageWidth = image?.width || 120;
const imageHeight = image?.height || 120;
return `
`
}()}
${function() {
const defaultVariant = data.variants?.find(v => (v.available && v.is_hit_discount == true)) || data.variants?.[0];
const selectedVariant = data.variant || defaultVariant;
const isHasRrice = (selectedVariant.price || selectedVariant.price == 0) ? true : false;
if(selectedVariant.flash_sale_info && selectedVariant.flash_sale_info.discount_price) {
selectedVariant.price = selectedVariant.flash_sale_info.discount_price;
}
if(data.flash_sale_info && data.flash_sale_info.discount_price) {
data.price = data.flash_sale_info.discount_price;
}
return !!selectedVariant ? `
` : `
-
`;
}()}
${function(){
const defaultVariant = data.variants?.find(v => (v.available && v.is_hit_discount == true)) || data.variants?.[0];
const selectedVariant = data.variant || defaultVariant;
let show_flashsale_limit_tip = false;
let limit_user_product_discount;
if(selectedVariant.flash_sale_info && selectedVariant.flash_sale_info?.limit_user_product_type != "LUPT_NO_LIMIT" && selectedVariant.flash_sale_info?.limit_user_product_discount > 0) {
show_flashsale_limit_tip = true;
limit_user_product_discount = selectedVariant.flash_sale_info?.limit_user_product_discount;
}
if(data.flash_sale_info && data.flash_sale_info?.limit_user_product_type != "LUPT_NO_LIMIT" && data.flash_sale_info?.limit_user_product_discount > 0) {
show_flashsale_limit_tip = true;
limit_user_product_discount = data.flash_sale_info?.limit_user_product_discount;
}
return `
`
}()}
`
} ()}
`).replace(/\{received_discounts\}/g, ` `);
return `
`
}()}
${function(){
return `
class SpzCustomDiscountBundleProducts extends SPZ.BaseElement {
constructor(element) {
super(element);
this.xhr_ = SPZServices.xhrFor(this.win);
this.getDiscountPriceApi = "\/api\/storefront\/promotion\/calculate\/discounted_price";
this.buyNowApi = "\/api\/checkout\/order";
this.batchAtcApi = "\/api\/cart\/batch";
// 款式信息集合
this.productStyleInfo = [];
// 弹窗内选择款式集合
this.modalVariantInfo = [];
this.show_classic_bundle_spu_style = false;
this.bundleProducts = []; //捆绑商品
this.bundleConfig = {}; //下方按钮配置
this.discountId = "";
this.discountType = "";
this.discountInfo = "";
this.lineItems = [];
this.tempCss = {};
this.renderQuickShop_ = this.win.SPZCore.Types.debounce(this.win, this.renderQuickShopModal.bind(this), 500);
}
isLayoutSupported(layout) {
return layout == SPZCore.Layout.LOGIC;
}
buildCallback() {
this.setupAction_();
};
init(data = []) {
this.productStyleInfo = data;
}
handleRequestError_(data) {
this.showToast(data?.message || data?.errors?.[0] || 'Unknown error');
};
showToast(message) {
SPZ.whenApiDefined(document.getElementById("discount_toast")).then((apis) => {
apis.showToast(message);
});
}
//外部组件调用传值
setBundleData(products, config = "", id = "", type = "", info = {}) {
this.bundleProducts = products;
if(config) {
this.bundleConfig = config;
this.discountId = id;
this.discountType = type;
this.discountInfo = info;
this.show_classic_bundle_spu_style = type === 'DT_CLASSIC_BUNDLE' && info.enable_min_purchase_qty && info.min_purchase_qty_type == 'spu';
// 经典捆绑初始化商品数据
if(type == 'DT_CLASSIC_BUNDLE') {
this.productStyleInfo = products.map((item) => {
return this.getFilteredVariants_(item, 'single');
});
}
}
}
handleChangeSort() {
const result = this.productStyleInfo.reduce((map, item) => {
if (!map[item.product_id]) {
map[item.product_id] = [];
}
map[item.product_id].push(item);
return map;
}, {});
Object.values(result).forEach((item) => {
this.handleSpzVariantRender_(item, item[0].product_id);
this.handleProductOption_(item[0].product_id, true);
});
}
// 调用spz-tag组件的doRender方法
handleSpzVariantRender_(data, id) {
const spzVariantTag = SPZCore.Dom.scopedQuerySelector(document.body, `#promotionSpzVariantTags-${id}`);
spzVariantTag && SPZ.whenApiDefined(spzVariantTag).then((api) => {
api.render(data, true);
});
}
// 执行经典捆绑最低购买数量更新
handleMinPurchaseQtyUpdate_(data, id) {
const minPruchaseQty = SPZCore.Dom.scopedQuerySelector(document.body, `#promotionMinPurchaseQty-${id}`);
minPruchaseQty && SPZ.whenApiDefined(minPruchaseQty).then((api) => {
api.render(data, true);
});
}
// 更新价格
updateProductPrice_(data) {
const bottomBtnContainer = SPZCore.Dom.scopedQuerySelector(document.body, `#promotionBottomContainer`);
if (data.length == 0) {
bottomBtnContainer && SPZ.whenApiDefined(bottomBtnContainer).then((api) => {
const renderInfo = {
setting: this.bundleConfig,
...{
original_price: 0,
received_discounts: 0,
picked_qty: 0
}
}
api.render({original_price: 0, received_discounts: 0}, true);
});
return;
}
const reqBody = {
discount_id: this.discountId,
customer: {
customer_id: '',
email: '',
},
sales_channel: {
sale_channel_type: "online",
sale_channel_id: '1199785'
},
line_items: data
}
// 如果已经有一个请求在等待,那么取消这个请求
if (this.debounceTimer) {
clearTimeout(this.debounceTimer);
}
this.debounceTimer = setTimeout(() => {
this.xhr_.fetchJson(this.getDiscountPriceApi, {
method: "post",
body: reqBody
}).then((res)=>{
// 更新商品列表价格
Object.keys(res.line_items).forEach((key) => {
const currentProductPrice = SPZCore.Dom.scopedQuerySelector(document.body, `#appDiscountProductPrice-${key}`);
currentProductPrice && SPZ.whenApiDefined(currentProductPrice).then((api) => {
api.render(res.line_items[key], true);
});
});
// 更新底部按钮总价/总折扣价
const picked_qty = data.reduce((acc, item) => {
return acc + item.quantity;
}, 0);
bottomBtnContainer && SPZ.whenApiDefined(bottomBtnContainer).then((api) => {
const data = {
setting: this.bundleConfig,
...{
...res.total_price,
picked_qty
}
}
api.render(data, true);
});
}).catch((err)=>{
this.handleRequestError_(err);
}).finally(()=>{
})
}, 100);
}
// 还原商品价格
resetProductPrice_(data) {
const {price, compare_at_price, id} = data;
const currentProductPrice = SPZCore.Dom.scopedQuerySelector(document.body, `#appDiscountProductPrice-${id}`);
currentProductPrice && SPZ.whenApiDefined(currentProductPrice).then((api) => {
api.render({total_received_discounts: price, total_price: compare_at_price}, true);
});
}
//处理与selector组件的交互
handleProductOption_(productId, show) {
const currentProductOption = SPZCore.Dom.scopedQuerySelector(document.body, `#promotionSelectOption-${productId}`);
if (!currentProductOption) {
return;
};
currentProductOption.toggleAttribute('show', show);
const isSelected = currentProductOption.hasAttribute('selected');
// !show 取消选中
// !isSelected 选中商品
if (!show || !isSelected) {
const productSelector = SPZCore.Dom.scopedQuerySelector(document.body, `#promotionProductSelector`);
productSelector && SPZ.whenApiDefined(productSelector).then((api) => {
api.toggle_({ option: productId, value: show });
});
}
}
// 混搭弹窗内的前端库存校验
handleModalInventoryCheck_(data) {
if(this.discountType == 'DT_MIX_MATCH_BUNDLE' || this.discountType == 'DT_CLASSIC_BUNDLE') {
const currentVariantAddNum = this.modalVariantInfo.find((item) => item.variant_id == data.variant_id)?.quantity || 0;
const quickShopBody = SPZCore.Dom.scopedQuerySelector(document.body, '#apps-discount-quick-shop-body');
if(!!data.variant && currentVariantAddNum == Number(data.variant.available_quantity)) {
quickShopBody && quickShopBody.setAttribute('status', 'soldout');
} else {
quickShopBody && quickShopBody.setAttribute('status', 'available');
}
} else {
return;
}
}
// 添加商品子款式
renderVariantTag() {
let variantInfo;
const quickShopBody = SPZCore.Dom.scopedQuerySelector(document.body, '#apps-discount-quick-shop-body');
quickShopBody && SPZ.whenApiDefined(quickShopBody).then((api) => {
variantInfo = api.getVariantsData();
const productId = variantInfo.product_id;
const variantId = variantInfo.variant_id;
const minPruchaseQtyRender = variantInfo.product.discount_min_purchase_qty || variantInfo.variant.discount_info.discount_min_purchase_qty;
if(this.discountType === 'DT_MIX_MATCH_BUNDLE') {
const index = this.productStyleInfo.findIndex((item) => item.variant_id == variantInfo.variant_id);
if (index != -1) {
this.productStyleInfo[index].quantity = Number(this.productStyleInfo[index].quantity) + Number(variantInfo.quantity);
this.updateProductPrice_(this.productStyleInfo);
} else {
this.productStyleInfo.push(this.getFilteredVariants_(variantInfo));
// 若当前商品已选中,更新商品价格
const currentProductOption = SPZCore.Dom.scopedQuerySelector(document.body, `#promotionSelectOption-${productId}`);
const isSelected = currentProductOption && currentProductOption.hasAttribute('selected');
isSelected && this.updateProductPrice_(this.productStyleInfo);
}
const selectedVariantsFilter = this.productStyleInfo.filter((item) => item.product_id == productId);
this.handleSpzVariantRender_(selectedVariantsFilter, productId);
this.handleProductOption_(productId, true);
} else {
if(this.discountInfo.enable_min_purchase_qty == true && this.discountInfo.min_purchase_qty_type == 'spu' && minPruchaseQtyRender > 1) {
const index = this.modalVariantInfo.findIndex((item) => item.variant_id == variantId);
if (index != -1) {
this.modalVariantInfo[index].quantity = Number(this.modalVariantInfo[index].quantity) + 1;
} else {
this.modalVariantInfo.push(this.getFilteredVariants_(variantInfo, 'classic_spu'));
}
const modalVariantTag = SPZCore.Dom.scopedQuerySelector(document.body, '#promotionModalVariantTagRender');
modalVariantTag && SPZ.whenApiDefined(modalVariantTag).then((api) => {
api.render(this.modalVariantInfo, true);
});
this.handleModalInventoryCheck_(variantInfo);
const selectedVariantsNum = this.modalVariantInfo.reduce((acc, item) => {
return acc + item.quantity;
}, 0);
if(selectedVariantsNum == minPruchaseQtyRender) {
this.handleSpzVariantRender_([this.getFilteredVariants_(variantInfo)], productId);
this.productStyleInfo = this.productStyleInfo.filter((item) => item.product_id != productId).concat(this.modalVariantInfo);
const renderData = this.productStyleInfo.filter((item) => item.product_id == productId).map((item) => {
return {
...item,
is_classic_bundle_product_list_variant_tag: true
}
});
const classicSpuTag = SPZCore.Dom.scopedQuerySelector(document.body, `#promotionClassicSpuTags-${productId}`);
classicSpuTag && SPZ.whenApiDefined(classicSpuTag).then((api) => {
api.render(renderData, true);
});
this.updateProductPrice_(this.productStyleInfo);
const quickView = SPZCore.Dom.scopedQuerySelector(document.body, '#apps-discount-quick-view');
quickView && SPZ.whenApiDefined(quickView).then((api)=>{
api.close();
});
this.modalVariantInfo = [];
} else {
return;
}
}
// this.productStyleInfo 中已存在与productId, variantId都相同的商品 则直接return 关闭弹窗
const isExist = this.productStyleInfo.some((item) => item.product_id == productId && item.variant_id == variantId);
if (isExist) {
const quickView = SPZCore.Dom.scopedQuerySelector(document.body, '#apps-discount-quick-view');
quickView && SPZ.whenApiDefined(quickView).then((api)=>{
api.close();
});
return;
}
// 若 this.productStyleInfo 中已存在与productId相同的商品,则不再添加 否则替换
const index = this.productStyleInfo.findIndex((item) => item.product_id == productId);
if (index != -1) {
this.productStyleInfo[index] = this.getFilteredVariants_(variantInfo);
} else {
this.productStyleInfo.push(this.getFilteredVariants_(variantInfo));
}
const selectedVariantsFilter = this.productStyleInfo.filter((item) => item.product_id == productId);
this.handleSpzVariantRender_(selectedVariantsFilter, productId);
this.handleMinPurchaseQtyUpdate_({discount_min_purchase_qty: minPruchaseQtyRender}, productId);
this.updateProductPrice_(this.productStyleInfo);
}
const quickView = SPZCore.Dom.scopedQuerySelector(document.body, '#apps-discount-quick-view');
quickView && SPZ.whenApiDefined(quickView).then((api)=>{
api.close();
});
});
}
// 单变体点击添加按钮
renderSingleVariant(data) {
const { product_id } = data;
const currentProduct = this.bundleProducts.find((product) => product.id == product_id);
// 若当前商品已存在,则不再添加 而是更新数量
const index = this.productStyleInfo.findIndex((item) => item.product_id == product_id);
if (index != -1) {
this.productStyleInfo[index].quantity = Number(this.productStyleInfo[index].quantity) + 1;
this.updateProductPrice_(this.productStyleInfo);
} else {
this.productStyleInfo.push(this.getFilteredVariants_(currentProduct, 'single'));
}
const renderProductArr = this.productStyleInfo.filter((item) => item.product_id == product_id);
this.handleSpzVariantRender_(renderProductArr, product_id);
this.handleProductOption_(product_id, true);
}
// 过滤选中商品的子款式 获取有用的信息 product_id,variant_id,price,compare_at_price,quantity,title,variant_title
getFilteredVariants_(data, type = '') {
const { id, title, variants, inventory_tracking, inventory_policy, inventory_quantity, product_type } = data;
const { product_id, variant_id, variant, quantity, product, discount_min_purchase_qty } = data;
const isSingle = type == 'single';
const variantData = isSingle ? (variants[0] || data) : variant;
const productData = isSingle ? data : product;
let item_quantity = 0;
if (this.discountType === 'DT_MIX_MATCH_BUNDLE') {
item_quantity = isSingle ? 1 : Number(quantity);
} else if (type === 'classic_spu') {
item_quantity = 1;
} else {
item_quantity = discount_min_purchase_qty || productData.discount_min_purchase_qty || variantData.discount_info.discount_min_purchase_qty || 1;
}
return {
product_id: isSingle ? id : product_id,
variant_id: variantData?.id || '',
price: variantData?.price || '0.00',
compare_at_price: variantData?.compare_at_price || '0.00',
quantity: item_quantity,
inventory_tracking: productData.inventory_tracking,
inventory_policy: productData.inventory_policy,
inventory_quantity: productData.inventory_quantity,
product_type: productData.product_type || this.bundleProducts.find((item) => item.id == product_id)?.product_type || this.bundleProducts.find((item) => item.id == id)?.product_type || '',
title: productData.title,
variant_title: variantData?.options.map((option) => option.value).join('/') || '',
is_multi_style: productData.variants.length > 1,
}
}
handleLoading_ (event) {
const { type, action } = event;
const loadingElementId = type === 'product' ? '#discount-match-drawer-products_loading' : '#apps-discount-whole-loading';
const loadingElement = document.querySelector(loadingElementId);
if (loadingElement) {
SPZ.whenApiDefined(loadingElement).then((api) => {
if (action === 'show') {
api.show_();
} else {
api.close_();
}
});
}
}
handleSelectProduct(productArr) {
// 从this.productStyleInfo 过滤出选中的商品
const selectedProducts = this.productStyleInfo.filter((item) => productArr.includes(item.product_id));
this.updateProductPrice_(selectedProducts);
}
// 渲染加购弹窗内容
async renderQuickShopModal(data){
this.handleLoading_({type: 'whole', action: 'show'});
this.xhr_.fetchJson(`/api/storefront/promotion/landing_page/product?product_id=${data.product_id}&discount_id=${this.discountId}&apply_scenario=1`, {
method: "get",
}).then(async(res)=>{
//flash主题放block有层级问题
if(/Flash/.test(window.C_SETTINGS.theme.merchant_theme_name) && document.querySelector(".productInfoSection")) {
this.tempCss.zIndex = document.querySelector(".product-info-body").style.zIndex;
document.querySelector('.product-info-body').style.zIndex="1048";
}
this.handleLoading_({type: 'whole', action: 'close'});
const $quickShop = await SPZ.whenApiDefined(document.querySelector('#apps-discount-quick-view-render'));
// 定义默认渲染的子款式
const selectedVariant = res.product.variants.find((v)=> (v.available && v.is_hit_discount)) || res.product.variants[0];
let selectedValues = {};
selectedVariant.options.length && selectedVariant.options.forEach(item => {
selectedValues[item.name] = item.value;
})
// 默认选中的 子款式、 options
res.product.defaultSelectValues = selectedValues;
let data = {...res.product, product:res.product, selectedVariant, show_classic_bundle_spu_style: this.show_classic_bundle_spu_style, discountType: this.discountType};
$quickShop.render(data);
// 打开加购弹窗
SPZ.whenApiDefined(document.querySelector(`#apps-discount-quick-view`)).then((api)=>{
api.open();
});
}).catch((err)=>{
this.handleLoading_({type: 'whole', action: 'close'});
})
}
// 获取选中的商品ids
getDefaultSelectorOptions_() {
try {
const selectedOptions = SPZCore.Dom.scopedQuerySelectorAll(document.body, '[id^="promotionSelectOption-"][selected]');
return SPZCore.Types.toArray(selectedOptions).map((item) => item.getAttribute('option'));
} catch (error) {
return [];
}
}
// 删除商品子款式
deleteVariantTag(data) {
const { product_id, variant_id } = data;
if(this.discountInfo.enable_min_purchase_qty == true && this.discountInfo.min_purchase_qty_type == 'spu') {
const modalProductVariants = this.modalVariantInfo.filter((item) => item.product_id == product_id && item.variant_id != variant_id);
const modalVariantTag = SPZCore.Dom.scopedQuerySelector(document.body, '#promotionModalVariantTagRender');
modalVariantTag && SPZ.whenApiDefined(modalVariantTag).then((api) => {
api.render(modalProductVariants, true);
});
this.handleModalInventoryCheck_(data);
this.modalVariantInfo = modalProductVariants;
return;
}
const currentProductVariants = this.productStyleInfo.filter((item) => item.product_id == product_id && item.variant_id != variant_id);
this.handleSpzVariantRender_(currentProductVariants, product_id);
// 更新selectedVariants
this.productStyleInfo = this.productStyleInfo.filter((item) => item.variant_id != variant_id);
if(currentProductVariants.length > 0) {
// currentProductVariants 中只要有一项是多款式商品,就更新价格
const isMultiStyle = currentProductVariants.some((item) => item.is_multi_style);
if (!isMultiStyle) return;
this.handleProductOption_(product_id, true);
const selected = this.getDefaultSelectorOptions_();
this.updateProductPrice_(this.productStyleInfo.filter((item) => selected.includes(item.product_id)));
} else {
this.handleProductOption_(product_id, false);
this.resetProductPrice_(this.bundleProducts.find((item) => item.id == product_id));
}
}
// 加购弹窗未参与活动 加购按钮不可点击 TODO 拆出来
handleNotHitDiscount_(data) {
const $quickShopBody = document.querySelector('#apps-discount-quick-shop-body');
//当前子框式未命中活动
if(data.variant.is_hit_discount == false) {
$quickShopBody.setAttribute('variantstatus', 'notHitDiscount')
} else {
$quickShopBody.setAttribute('variantstatus', '')
}
}
setupAction_() {
// 子款式 未参与活动
this.registerAction('handleNotHitDiscount', (invocation) => {
const data = invocation.args.data;
this.handleNotHitDiscount_(data);
});
// 渲染加购弹窗
this.registerAction('renderQuickShop', (invocation) => {
const data = invocation.args;
this.renderQuickShop_(data);
});
this.registerAction('renderSingleVariant', (invocation) => {
const data = invocation.args;
this.renderSingleVariant(data);
});
this.registerAction('getVariantInfo', (invocation) => {
this.renderVariantTag();
});
this.registerAction('deleteVariantTag', (invocation) => {
const data = invocation.args;
this.deleteVariantTag(data);
});
this.registerAction('getSelectedProduct', (invocation) => {
const data = invocation.args.data;
this.handleSelectProduct(data);
});
//TODO 加购下单逻辑单独拆组件
this.registerAction('handleClick', (data) => {
if(this.discountType == 'DT_CLASSIC_BUNDLE') {
this.lineItems = this.productStyleInfo;
} else {
const selectedOptions = SPZCore.Dom.scopedQuerySelectorAll(document.body, '[id^="promotionSelectOption-"]');
const idArr = [...selectedOptions].reduce((acc, item) => {
if (item.hasAttribute('selected')) {
const optionValue = item.getAttribute('option');
if (optionValue) {
acc.push(optionValue);
}
}
return acc;
}, []);
this.lineItems = this.productStyleInfo.filter((item) => idArr.includes(item.product_id));
}
const action = data.args.action === "cart";
if(action) {
//add to cart
this.xhr_
.fetchJson(this.batchAtcApi, {
method: 'POST',
body: {
line_items: this.lineItems.map((item) => {
return {
product_id: item.product_id,
variant_id: item.variant_id,
quantity: Number(item.quantity)
}
})
}
})
.then((data) => {
setTimeout(() => {
window.location.href = '/cart';
});
})
.catch(async (error) => {
await error.then((data) => {
this.handleRequestError_(data);
});
});
} else {
//checkout
this.xhr_
.fetchJson(this.buyNowApi, {
method: 'POST',
body: {
line_items: (this.lineItems || []).map((product) => {
return {
quantity: Number(product.quantity),
variant_id: product.variant_id,
note: product.note || '',
properties: product.properties || {}
}
}),
refer_info: { source: 'buy_now' }
}
})
.then(async (data) => {
if (data.state === 'success') {
window.location.href = data.data?.checkout_url;
}
this.handleRequestError_(data);
})
.catch(async (error) => {
await error.then((data) => {
this.handleRequestError_(data);
});
});
}
});
this.registerAction('resetModalVariantInfo', () => {
//flash主题放block有层级问题
if(/Flash/.test(window.C_SETTINGS.theme.merchant_theme_name) && document.querySelector(".productInfoSection")) {
document.querySelector('.product-info-body').style.zIndex = this.tempCss.zIndex;
}
this.modalVariantInfo = [];
});
this.registerAction('handleModalInventoryCheck', (invocation) => {
const data = invocation.args.data;
this.handleModalInventoryCheck_(data);
});
};
};
SPZ.defineElement('spz-custom-discount-bundle-products', SpzCustomDiscountBundleProducts);
class SpzCustomDiscountAtcAction extends SPZ.BaseElement {
constructor(element) {
super(element);
this.xhr_ = SPZServices.xhrFor(this.win);
this.product_title = "";
}
isLayoutSupported(layout) {
return layout == SPZCore.Layout.LOGIC;
}
async getProductTitle_ (data){
this.product_title = data.product_title;
}
handleLoading_ (event) {
const { type, action } = event;
const loadingElementId = '#apps-discount-whole-loading';
const loadingElement = document.querySelector(loadingElementId);
if (loadingElement) {
SPZ.whenApiDefined(loadingElement).then((api) => {
if (action === 'show') {
api.show_();
} else {
api.close_();
}
});
}
}
// 渲染加购弹窗内容
async renderQuickShop_ (data) {
this.handleLoading_({type: 'whole', action: 'show'});
const apply_scenario = data.apply_scenario;
const discount_id = data.discount_id;
const product_id = data.product_id;
const limit_purchase = data.limit_purchase;
this.xhr_.fetchJson(`/api/storefront/promotion/landing_page/product?product_id=${product_id}&discount_id=${discount_id}&apply_scenario=${apply_scenario}`, {
method: "get",
}).then(async(res)=>{
this.handleLoading_({type: 'whole', action: 'close'});
const $quickShop = await SPZ.whenApiDefined(document.querySelector('#apps-discount-quick-view-render'));
// 定义默认渲染的子款式
const selectedVariant = res.product.variants.find((v)=> (v.available && v.is_hit_discount)) || res.product.variants[0];
let selectedValues = {};
selectedVariant.options.length && selectedVariant.options.forEach(item => {
selectedValues[item.name] = item.value;
})
// 默认选中的 子款式、 options
res.product.defaultSelectValues = selectedValues;
let data = {...res.product, product:res.product, selectedVariant};
data.need_atc = true;
data.limit_purchase = limit_purchase;
$quickShop.render(data);
// 打开加购弹窗
SPZ.whenApiDefined(document.querySelector(`#apps-discount-quick-view`)).then((api)=>{
api.open();
});
}).catch((err)=>{
this.handleLoading_({type: 'whole', action: 'close'});
})
}
// 加入购物车
addToCart_(data) {
const apply_scenario = data.apply_scenario;
const discount_id = data.discount_id;
const product_id = data.product_id;
this.xhr_.fetchJson(`/api/storefront/promotion/landing_page/product?product_id=${data.product_id}&discount_id=${discount_id}&apply_scenario=${apply_scenario}`, {
method: "get",
}).then(async(res)=>{
// 单款式加购
const variant_id = res.product.variants[0]?.id;
const $productFormInput = document.querySelector(`#apps-discount-product-form-${data.product_id} input[name='variant_id'`);
$productFormInput.value = variant_id;
SPZ.whenApiDefined(document.querySelector(`#apps-discount-product-form-${data.product_id}`)).then((api)=>{
api.handleAddToCart_();
});
}).catch((err)=> {
this.handleLoading_({type: 'whole', action: 'close'});
})
}
// 加购弹窗未参与活动 加购按钮不可点击
handleNotHitDiscount_(data) {
const $quickShopBody = document.querySelector('#apps-discount-quick-shop-body');
const $limitTip = document.querySelector('.apps_discount_limit_purchase_tip');
//当前子框式未命中活动
if(data.variant.is_hit_discount == false) {
$quickShopBody.setAttribute('variantstatus', 'notHitDiscount');
$limitTip && $limitTip.setAttribute('selectedvariantstatus', 'notHitDiscount');
} else {
$quickShopBody.setAttribute('variantstatus', '');
$limitTip && $limitTip.setAttribute('selectedvariantstatus', '')
}
}
setupAction_() {
this.registerAction('renderQuickShop', (invocation) => {
const data = invocation.args;
this.renderQuickShop_(data);
});
// 加购
this.registerAction('addToCart', (invocation) => {
const data = invocation.args;
this.addToCart_(data);
});
// 子款式 未参与活动
this.registerAction('handleNotHitDiscount', (invocation) => {
const data = invocation.args.data;
this.handleNotHitDiscount_(data);
});
this.registerAction('getCartCount', (invocation) => {
//一些老主题还未用spz重构,需要手动触发一次老方法以更新购物车图标的数量
window.$ && $(document).trigger('dj.common.cart.change');
});
this.registerAction('getProductTitle', (invocation) => {
const data = invocation.args;
this.getProductTitle_(data);
});
this.registerAction('handleButton', (invocation) => {
const data = invocation.args;
window.location.href = this.product_title;
});
};
buildCallback() {
this.setupAction_();
};
}
SPZ.defineElement('spz-custom-discount-atc-action', SpzCustomDiscountAtcAction);
${function(){
const discount_info = originData.discount_info;
const landing_page_info = originData.landing_page_info;
const buy_product_info = originData.buy_product_info;
const dom = originData.discount_info.discount_type === 'DT_BUY_X_GET_Y' ?
`
` :
`
`;
return dom;
}()}
${(function() {
const productsInfo = data.products || data.product;
const product_display = originData?.product_display;
const show_atc = product_display ? !!product_display?.show_add_to_cart : true;
const show_discount_label = !!product_display?.show_discount_label;
const show_sales_progress = !!product_display?.sales_progress?.enabled;
const sales_progress_format = product_display?.sales_progress?.format || '';
const limit_purchase = originData.limit_purchase;
const productConfig = product_display ? JSON.parse(product_display?.config).color : '';
const sale_progress_bg = productConfig?.sale_bar_background_color || '#F2F2F2';
const sale_progress_bg_start = productConfig?.progress_sale_bar_background_color_start || '#FF9C57';
const sale_progress_bg_end = productConfig?.progress_sale_bar_background_color_end || '#FF4559';
const sale_count_text = productConfig?.sale_bar_atc_color || '#FC5161';
const discount_label_start = productConfig?.discount_sign_background_color_start || '#FF9C57';
const discount_label_end = productConfig?.discount_sign_background_color_end || '#FF4559';
const discount_label_text = productConfig?.discount_sign_color || '#FFFFFF';
//限时促销首页卡片尺寸
const discount_image_size = data.discount_image_size || '100%';
//点击加购按钮需要的参数
let discount_id = data.discount_id;
let apply_scenario = data.apply_scenario;
if(!productsInfo.length) return '';
return productsInfo.map(product => {
let price = product.price || 0;
let priceMin = product.price_min || 0;
let priceMax = product.price_max || 0;
let compareAtPriceMax = product.compare_at_price_max || 0;
let compareAtPrice = product.compare_at_price || 0;
let title = product.title || '';
let id = product.id || '';
let url = product.url || '';
let type = product.type || '';
let is_sold_out = false;
if (product.available == false && product.inventory_policy != 'continue') {
is_sold_out = true;
}
const soldOutLang1 = "Sold out";
const soldOutLang2 = "Sold out";
const discountType = product.discount_type;
const noNeedBtn = discountType !== "DT_MIX_MATCH_BUNDLE" && discountType !== "DT_CLASSIC_BUNDLE";
const defaultVariantTitle = product.variants[0]?.title.replace('-', '/');
const flash_sale_info = product?.flash_sale_info;
const is_flashsale_sold_out = flash_sale_info?.discount_sales_rate == "100";
const show_product_sold_progress = flash_sale_info?.discount_sales_rate > 0;
const off_ratio = flash_sale_info?.off_ratio;
price = flash_sale_info?.discount_price || price;
discount_id = discount_id || product.discount_id;
apply_scenario = apply_scenario || product.apply_scenario;
let imageWidth;
if (product.image.width) {
imageWidth = product.image.width;
} else {
imageWidth = 300;
}
let imageHeight;
if (product.image.height) {
imageHeight= product.image.height;
} else {
imageHeight = 300;
}
if (discount_image_size !== 'natural') {
imageHeight = (imageWidth * parseFloat(discount_image_size)) / 100;
}
if (product.published) {
return `
`
} else {
return ``;
}
}).join('');
})()}
-${off_ratio}%
${function(){
if (soldOutLang1){
return `
${soldOutLang1}
`
}else{
return `
${soldOutLang2}
`
}
}()}
${product.title}
Almost sold out
${flash_sale_info?.discount_sales}
${flash_sale_info?.discount_sales_rate}%
sold
${defaultVariantTitle}
Sort by
-
${item.text}
Sort by
${options.map((item) => {
return `
Promo products limited to ${limit_user_product_discount} item per person
${function() {
const currentProduct = data.product;
return (currentProduct.options || []).map((option, index) => {
const optionName = option.name || '';
const optionId = option.id || '';
const position = `option${index + 1}`;
return `
${function() {
const value = (data.originData && data.originData.value) || data.value;
const isHasValue = value ? true : false;
return `
`;
}).join('')
}()}
${value}
`
}()}
${function(){
return `
${data.map((variant) => {
return `
${function(){
const { original_price, received_discounts, picked_qty } = data;
const button_text = originData.setting.button.text;
const button_config = JSON.parse(originData.setting.button.config);
const button_action = originData.setting.button.redirect_page;
const text = originData.setting.price_text_config.text;
const price_config = JSON.parse(originData.setting.price_text_config.config);
const price_text = text.replace(/\{picked_qty\}/g, `${picked_qty}`).replace(/\{original_price\}/g, `
x${variant.quantity}
${variant.variant_title || variant.title}
`;
}).join('')}
${price_text}
${data[0].variant_title}
`
} ()}
x ${data.discount_min_purchase_qty}
- ${landing_page_info.product.buy_product.text}
- ${landing_page_info.product.obtain_product.text}
${originData.buy_product_info.count} Products
Sort by
${(function() {
const productsInfo = "spz_custom_sort_products_x" === "spz_custom_sort_products_x" ? data.buy_product_info.product : data.obtain_product_info.product;
//点击加购按钮需要的参数
const discount_id = data.discount_info.id;
const apply_scenario = "spz_custom_sort_products_x" === "spz_custom_sort_products_x" ? 1 : 2 ;
return productsInfo.map((product, index) => {
let price = product.price || 0;
let priceMin = product.price_min || 0;
let priceMax = product.price_max || 0;
let compareAtPriceMax = product.compare_at_price_max || 0;
let compareAtPrice = product.compare_at_price || 0;
let title = product.title || '';
let id = product.id || '';
let url = product.url || '';
let type = product.type || '';
let is_sold_out = false;
if (product.available == false && product.inventory_policy != 'continue') {
is_sold_out = true;
}
const soldOutLang1 = "Sold out";
const soldOutLang2 = "Sold out";
const discountType = originData.discount_info.discount_type;
const noNeedBtn = discountType !== "DT_MIX_MATCH_BUNDLE" && discountType !== "DT_CLASSIC_BUNDLE";
const defaultVariantTitle = product.variants[0]?.title.replace('-', '/');
const variantDiscountInfo = product.variants[0]?.discount_info || {};
let discount_min_purchase_qty = 0;
if(discountType === "DT_CLASSIC_BUNDLE" && data.discount_info.enable_min_purchase_qty) {
discount_min_purchase_qty = data.discount_info.min_purchase_qty_type === "spu" ? product.discount_min_purchase_qty : product.variants[0].discount_info.discount_min_purchase_qty;
}
let imageWidth;
if (product.image.width) {
imageWidth = product.image.width;
} else {
imageWidth = "300px";
}
let imageHeight;
if (product.image.height) {
imageHeight= product.image.height;
} else {
imageHeight = "300px";
}
if (product.published) {
return `
${product.title}
`
} else {
return ``;
}
}).join('');
})()}
${function(){
if (soldOutLang1){
return `
${soldOutLang1}
`
}else{
return `
${soldOutLang2}
`
}
}()}
x ${discount_min_purchase_qty}
${defaultVariantTitle}
${originData.obtain_product_info.count} Products
Sort by
${(function() {
const productsInfo = "spz_custom_sort_products_y" === "spz_custom_sort_products_x" ? data.buy_product_info.product : data.obtain_product_info.product;
//点击加购按钮需要的参数
const discount_id = data.discount_info.id;
const apply_scenario = "spz_custom_sort_products_y" === "spz_custom_sort_products_x" ? 1 : 2 ;
return productsInfo.map((product, index) => {
let price = product.price || 0;
let priceMin = product.price_min || 0;
let priceMax = product.price_max || 0;
let compareAtPriceMax = product.compare_at_price_max || 0;
let compareAtPrice = product.compare_at_price || 0;
let title = product.title || '';
let id = product.id || '';
let url = product.url || '';
let type = product.type || '';
let is_sold_out = false;
if (product.available == false && product.inventory_policy != 'continue') {
is_sold_out = true;
}
const soldOutLang1 = "Sold out";
const soldOutLang2 = "Sold out";
const discountType = originData.discount_info.discount_type;
const noNeedBtn = discountType !== "DT_MIX_MATCH_BUNDLE" && discountType !== "DT_CLASSIC_BUNDLE";
const defaultVariantTitle = product.variants[0]?.title.replace('-', '/');
const variantDiscountInfo = product.variants[0]?.discount_info || {};
let discount_min_purchase_qty = 0;
if(discountType === "DT_CLASSIC_BUNDLE" && data.discount_info.enable_min_purchase_qty) {
discount_min_purchase_qty = data.discount_info.min_purchase_qty_type === "spu" ? product.discount_min_purchase_qty : product.variants[0].discount_info.discount_min_purchase_qty;
}
let imageWidth;
if (product.image.width) {
imageWidth = product.image.width;
} else {
imageWidth = "300px";
}
let imageHeight;
if (product.image.height) {
imageHeight= product.image.height;
} else {
imageHeight = "300px";
}
if (product.published) {
return `
${product.title}
`
} else {
return ``;
}
}).join('');
})()}
${function(){
if (soldOutLang1){
return `
${soldOutLang1}
`
}else{
return `
${soldOutLang2}
`
}
}()}
x ${discount_min_purchase_qty}
${defaultVariantTitle}
${originData.buy_product_info.count} Products
Sort by
${(function() {
const productsInfo = "spz_custom_sort_products_x" === "spz_custom_sort_products_x" ? data.buy_product_info.product : data.obtain_product_info.product;
//点击加购按钮需要的参数
const discount_id = data.discount_info.id;
const apply_scenario = "spz_custom_sort_products_x" === "spz_custom_sort_products_x" ? 1 : 2 ;
return productsInfo.map((product, index) => {
let price = product.price || 0;
let priceMin = product.price_min || 0;
let priceMax = product.price_max || 0;
let compareAtPriceMax = product.compare_at_price_max || 0;
let compareAtPrice = product.compare_at_price || 0;
let title = product.title || '';
let id = product.id || '';
let url = product.url || '';
let type = product.type || '';
let is_sold_out = false;
if (product.available == false && product.inventory_policy != 'continue') {
is_sold_out = true;
}
const soldOutLang1 = "Sold out";
const soldOutLang2 = "Sold out";
const discountType = originData.discount_info.discount_type;
const noNeedBtn = discountType !== "DT_MIX_MATCH_BUNDLE" && discountType !== "DT_CLASSIC_BUNDLE";
const defaultVariantTitle = product.variants[0]?.title.replace('-', '/');
const variantDiscountInfo = product.variants[0]?.discount_info || {};
let discount_min_purchase_qty = 0;
if(discountType === "DT_CLASSIC_BUNDLE" && data.discount_info.enable_min_purchase_qty) {
discount_min_purchase_qty = data.discount_info.min_purchase_qty_type === "spu" ? product.discount_min_purchase_qty : product.variants[0].discount_info.discount_min_purchase_qty;
}
let imageWidth;
if (product.image.width) {
imageWidth = product.image.width;
} else {
imageWidth = "300px";
}
let imageHeight;
if (product.image.height) {
imageHeight= product.image.height;
} else {
imageHeight = "300px";
}
if (product.published) {
return `
${product.title}
`
} else {
return ``;
}
}).join('');
})()}
${function(){
if (soldOutLang1){
return `
${soldOutLang1}
`
}else{
return `
${soldOutLang2}
`
}
}()}
x ${discount_min_purchase_qty}
${defaultVariantTitle}
${data.mm}m
${data.ss}s
const TAG = 'spz-custom-cart-script';
class SpzCustomCartScript extends SPZ.BaseElement {
constructor(element) {
super(element);
}
static deferredMount() {
return false;
}
buildCallback = () => {
this.setupAction_();
}
setupAction_ = () => {
this.registerAction('domUpdate', (invocation) => {
document.dispatchEvent(new Event('dj.cartChange'));
});
}
isLayoutSupported = (layout) => {
return layout == SPZCore.Layout.CONTAINER;
}
}
SPZ.defineElement(TAG, SpzCustomCartScript)
${("Your Cart ({{count}} items)").replace(/\{\{\s*count\s*\}\}/, data.line_items.reduce((total, item) => total + parseInt(item.quantity), 0))}
${
data.checkAll==='checked'
?` `
:` `
}
-
${item.product_title} ${discount_item.title} ) ${item.options.map(option => `
${option.name}: ${option.value}`).join('')}${propertie.name} / ${propertie.isImage ? `View image` : propertie.value}
Free giftMixed LotPriceQuantity*${item.quantity}${item.item_text}Total${item.item_text}
Discount
-
${data.invalid_msg}
Subtotal:
${(data.checkoutable !== undefined && data.checkoutable) ?
`` :
``
}
Your shopping bag is empty
Continue shoppingCart recommendations