The current produc does not participate any Rebate. Switch the participating product to check the design.
(This prompt will not be displayed on the client-side.)
${function() {
const show = rebate.format_rules.length > data.maxShowCount;
return `
${rule}
${function() {
if(!show) return "";
return `
`;
}()}
`;
}()}
${originData.rebate.format_rules.join(", ")}
var theme = window.C_SETTINGS && C_SETTINGS.theme && C_SETTINGS.theme.merchant_theme_name;
var isFlash = /Flash/gi.test(theme);
var isGeek = /Geek/gi.test(theme);
var isNova23 = /Nova 2023/gi.test(theme);
var isWind = /Wind/gi.test(theme);
var isOnePage = /OnePage/gi.test(theme);
var isHero = /Hero/gi.test(theme);
var isBoost = /Boost/gi.test(theme);
var isEva = /Eva/gi.test(theme);
var isFarida = /Farida/gi.test(theme);
var isPluto = /Pluto/gi.test(theme);
var isLifeStyle = /Life Style/gi.test(theme);
if(window.self === window.top) {
(window.disabled_exts ||=[]).push('product_detail_rebate');
}
class SpzRebateComponent extends SPZ.BaseElement {
constructor(element) {
super(element);
}
xhr_ = SPZServices.xhrFor(this.win);
viewport_ = this.getViewport();
action_ = null;
lang = document.documentElement.lang || 'en-US';
landPage = "\/promotions\/rebate\/";
pageType = 1;
cart = [];
initData = null;
rebateInfo = null;
renderData = null;
footerImage = `${this.win.SHOPLAZZA["image_domain"]}oss/operation/e8ebb03dbb710457ca3b4b6a70898ab2.svg`;
isLayoutSupported(layout) {
return layout == SPZCore.Layout.LOGIC;
}
buildCallback() {
this.initData = this.getProduct();
this.action_ = SPZServices.actionServiceForDoc(this.element);
this.registerAction("triggerGetRenderData", () => {
const event = SPZUtils.Event.create(this.win, "triggerGetRenderData", this.renderData);
this.action_.trigger(this.element, "getRenderData", event);
});
this.registerAction("bindPropagation", () => {
document.querySelector(".product_detail_rebate_list").addEventListener("click", e => {
e.stopPropagation();
this.win.sa &&
this.win.sa.track("plugin_rebate_promotion_click", {
plugin_timestamp: Date.now(),
plugin_location: "info",
product_id: this.initData.product.id,
discount_id: this.rebateInfo.discount_list.map((item) => item.discount_id)[0],
});
});
});
}
async mountCallback() {
document.addEventListener("dj.variantChange", e => {
const data = e.detail;
if (document.querySelector("#product-select-modal.show")) return;
this.initData = this.getProductJson(data);
if (this.initData && this.initData.product && data.product && this.initData.product.id === data.product.id) {
this.initRebate(this.initData, true);
} else {
this.getRebateInfo();
}
});
document.addEventListener("dj.addToCart", e => {
const v = e.detail;
this.rebateInfo &&
this.win.sa &&
this.win.sa.track("plugin_rebate_atc", {
variant_discount_id: this.getVariantDiscountId(v.variant_id).map(item => item.discount_id),
discount_ids: this.rebateInfo.discount_list.map(item => item.discount_id),
variant_id: v.variant_id,
product_id: v.product_id,
price: v.item_price,
number: v.number,
});
});
await this.getRebateInfo();
setTimeout(()=>{
if (document.querySelector(".plugin-container__bottom-fixed")) {
this.showDiscountPopupsInfoBar();
} else {
this.win.addEventListener("extloaded", () => {
this.showDiscountPopupsInfoBar();
});
}
},1000)
}
getProductJson = (mergeData = {}) => {
const productJson = document.querySelector("#product-json");
let productJsonData = {};
if (productJson && productJson.textContent) {
try {
productJsonData = JSON.parse(productJson.textContent);
} catch (e) {}
}
// 深度合并函数
const deepMerge = (target, source) => {
if (source === null || source === undefined) {
return target;
}
if (typeof source !== 'object' || Array.isArray(source)) {
return source;
}
const result = { ...target };
for (const key in source) {
if (source.hasOwnProperty(key)) {
if (
typeof source[key] === 'object' &&
source[key] !== null &&
!Array.isArray(source[key]) &&
typeof target[key] === 'object' &&
target[key] !== null &&
!Array.isArray(target[key])
) {
result[key] = deepMerge(target[key], source[key]);
} else {
result[key] = source[key];
}
}
}
return result;
};
return deepMerge(productJsonData, mergeData);
}
getProduct = (() => {
document.addEventListener("dj.variantChange", e => {
if (!e.detail || !e.detail.product) return;
let productJsonData = getProductJson(e.detail);
if (this.win.jQuery && this.win.jQuery.fn && this.win.jQuery(document).data("djproduct") && productJsonData) {
this.win.jQuery(document).data("djproduct", productJsonData);
}
});
return () => {
let productData = null;
if (this.win.jQuery && this.win.jQuery.fn) {
try {
let product = this.win.jQuery(document).data("djproduct");
if (product) {
productData = JSON.parse(JSON.stringify(product));
} else {
productData = null;
}
} catch (error) {
productData = null;
}
}
if (!productData) {
const productJson = document.querySelector("#product-json");
productData = (productJson && productJson.textContent && JSON.parse(productJson.textContent)) || null;
}
return productData;
};
})();
clearRebateInfoDom = () => {
// 1. 清除 apis.render 渲染的 DOM (app_rebate_section)
const rebateSection = document.getElementById('app_rebate_section');
if (rebateSection) {
const rebateRuleSection = rebateSection.querySelector('.rebate_rule_section');
if (rebateRuleSection) {
rebateRuleSection.remove();
}
}
// 2. 清除 templates_.renderTemplate 渲染的 DOM (app_rebate_block)
const rebateBlock = document.getElementById('app_rebate_block');
if (rebateBlock) {
const appRebateList = rebateBlock.querySelector('.app_rebate_list');
if (appRebateList) {
appRebateList.remove();
}
}
// 3. 清除 insertProductDetailRebateTag 插入的 DOM
// 清除所有 rebate-tag 元素
document.querySelectorAll('.slider-discount-tag.dj_skin_product_title.rebate-tag').forEach(tag => {
tag.remove();
});
// 移除 data-rebate-tag 属性
const productContainer = document.querySelector('.product-details, .product-details, .page_container, .product-images, [data-section-type="product"]');
if (productContainer && productContainer.hasAttribute('data-rebate-tag')) {
productContainer.removeAttribute('data-rebate-tag');
}
};
initRebate = this.win.SPZCore.Types.debounce(
this.win,
(async (data) => {
let discount_list = Object.assign([], this.rebateInfo?.discount_list);
/* 按子商品的多少对优惠信息进行排序 */
discount_list &&
discount_list.sort((a, b) => {
return b.variant_ids.length - a.variant_ids.length;
});
/* 选中子商品时 筛选子商品的优惠信息 */
if (data.selected && data.selected.id) {
discount_list = this.getVariantDiscountId(data.selected.id);
}
/* 无满减信息 */
if (!(discount_list && discount_list.length)) {
this.clearRebateInfoDom();
return;
}
const isSection = !!document.querySelector(
`div[data-section-type^="shoplazza://apps/publicapp/blocks/rebate"] #rebate_custom_component`
);
if (
(this.rebateInfo.rebate_type == "sku" && data && data.selected && data.selected.id) ||
this.rebateInfo.rebate_type == "spu"
) {
let nowLandpage = this.landPage;
if (discount_list[0]) {
nowLandpage = this.landPage + discount_list[0].discount_id || "";
}
const info = {
rebate: discount_list[0],
maxShowCount: this.win.innerWidth > 768 ? 3 : 1,
landPage: nowLandpage,
modalFooterImg: `url(${`${this.win.SHOPLAZZA["image_domain"]}oss/operation/e8ebb03dbb710457ca3b4b6a70898ab2.svg`})`,
};
this.renderData = info;
if(isSection) {
SPZ.whenApiDefined(
document.getElementById("app_rebate_section")
).then(apis => {
apis.render(info, true);
});
} else {
// 重新渲染 抖动问题处理
this.templates_ = SPZServices.templatesForDoc();
const newTplDom = await this.templates_.renderTemplate(document.querySelector('#appRebateBlockTpl'), info)
const parentDiv = document.querySelector('#app_rebate_block');
const oldDom = parentDiv.querySelector('.app_rebate_list');
if(oldDom){
parentDiv.replaceChild(newTplDom, oldDom);
} else {
parentDiv.appendChild(newTplDom);
}
}
}
this.insertProductDetailRebateTag(this.rebateInfo.tag);
var pluginCurrencyEvent = new CustomEvent("plugin_currency_update");
document.dispatchEvent(pluginCurrencyEvent);
}).bind(this),
10
);
getRebateInfo = async () => {
if (this.initData && this.initData.product && this.initData.product.id) {
var variant_ids = this.initData.product.variants.map(variant => variant.id);
const res = await this.xhr_.fetchJson(
"\/api\/discount-rebate\/product-discount",
{
method: "POST",
body: {
product_id: this.initData.product.id,
product_type: this.initData.product.product_type,
variant_ids: variant_ids,
},
}
);
if (!SPZCore.Types.isEmptyObject(res.rebate_info)) {
res.rebate_info.tag = res.tag;
res.rebate_info.rebate_type = res.rebate_type;
this.rebateInfo = res.rebate_info;
this.initRebate(this.initData);
} else {
if (this.win.top !== this.win.self) {
const noActivity = document.getElementById("no-rebate-activity");
noActivity && (noActivity["style"].display = "block");
}
}
}
};
getVariantDiscountId = (variant_id) => {
if (!variant_id || !this.rebateInfo) return [];
var rebateId = this.rebateInfo.variant_discount_map[variant_id];
return this.rebateInfo.discount_list.filter(item => item.discount_id == rebateId) || [];
};
insertProductDetailRebateTag = (tag) => {
if (!tag) return
// 旧判断逻辑
const productSelectModal = document.querySelector('#product-select-modal');
if (productSelectModal && productSelectModal.classList.contains('show')) {
return;
}
setTimeout(() => {
var $tag_container = [];
if (isNova23) {
$tag_container = document.querySelectorAll('.product-details .product-images-container');
} else if (isFlash) {
$tag_container = document.querySelectorAll('.product-detail .product-images .product-main-images-container');
} else if (isGeek) {
$tag_container = document.querySelectorAll('.product-images #product-images-inner-container spz-carousel .i-spzhtml-slide-item');
} else if (isWind) {
$tag_container = document.querySelectorAll('.product-detail .product-images-container .i-spzhtml-slides-container');
} else if (isOnePage) {
$tag_container = document.querySelectorAll('.product-details .product-main-images');
} else if (isHero) {
$tag_container = document.querySelectorAll('.product-detail #product-images-container #product-images-carousel .spz-carousel-slide');
} else if (isBoost) {
$tag_container = document.querySelectorAll('.boost-product-detail .product-image__layout-list .slides .slides-item .product-info__slide .slider-zoom');
} else if (isEva) {
$tag_container = document.querySelectorAll('.page_container [data-section-type="product"] .support-slick');
} else if (isFarida) {
$tag_container = document.querySelectorAll('.product-details .product-images-container');
} else if (isLifeStyle) {
$tag_container = document.querySelectorAll('.page_container [data-section-type="product_detail"] .sep-slider,.support-slick');
} else if (isPluto) {
$tag_container = document.querySelectorAll('.page_container [data-section-type="product_detail"] .sep-slider,.support-slick');
}
if($tag_container.length === 0) return;
// 给商祥页添加满送插件的标识属性
const $product_container = document.querySelector('.product-details, .product-details, .page_container, .product-images, [data-section-type="product"]')
if($product_container) {
$product_container.setAttribute('data-rebate-tag', 'true');
}
// 部分主题需要调整样式
if (isWind) {
Array.from($tag_container).forEach(container => {
container.style.position = 'relative';
});
}
document.querySelectorAll('.slider-discount-tag.dj_skin_product_title.rebate-tag').forEach(tag => tag.remove());
// 遍历所有容器并插入标签
Array.from($tag_container).forEach(container => {
container.insertAdjacentHTML('beforeend', `<div class="slider-discount-tag dj_skin_product_title rebate-tag">${tag}</div>`);
});
}, 1000)
};
fetchInfoBar = async () => {
let discount_ids = [];
if (this.pageType === 1) {
discount_ids = this.rebateInfo && this.rebateInfo.discount_list.map(item => item.discount_id);
} else if (this.pageType === 38) {
discount_ids = [this.win.rebateObj.rebateCollection_id] || [];
}
const productObj = this.getProduct();
const { cart } = await this.xhr_.fetchJson('/api/cart')
return this.xhr_.fetchJson("\/api\/discount-rebate\/global-text", {
method: "POST",
body: {
product_type: productObj && productObj.product && productObj.product.product_type,
line_items: (cart?.line_items || []).map(item => ({
variant_id: item.variant_id,
product_id: item.product_id,
quantity: item.quantity,
price: item.price,
selected: !item.unchecked,
})),
discount_ids: discount_ids,
},
});
};
renderBottomBanner = res => {
if (!res.tips) return;
document.querySelector(".discount__info-bar")?.remove();
var bar_style = `background:linear-gradient(90deg,${res.config.background_color_start},${res.config.background_color_end}); color:${res.config.color};`;
let data = { tips: res.tips, landPage: this.landPage + res.id, bar_style };
const html = SPZCore.Dom.htmlFor(this.element);
const banner = html([
`<a impr="1" imprevt="1" id="rebate_bottom_bar" href=${data.landPage} class="discount__info-bar text-truncate" data-activity-type="rebate" style="${data.bar_style}">${data.tips}</a>`,
]);
document.querySelector(".plugin-container__bottom-fixed").appendChild(banner);
const pluginCurrencyEvent = new CustomEvent("plugin_currency_update");
document.dispatchEvent(pluginCurrencyEvent);
if (res.id) {
var trackParams = {
page: this.pageType,
discount_id: res.id,
product_id: this.getProduct()?.product.id,
};
banner.addEventListener("click", () => {
this.win.sa &&
this.win.sa.track("plugin_rebate_promotion_click", {
plugin_timestamp: Date.now(),
plugin_location: "bottom_bar",
product_id: trackParams.product_id,
discount_id: trackParams.discount_id,
});
});
this.win.sa && this.win.sa.track("plugin_rebate_banner_pv", trackParams);
}
};
showDiscountPopupsInfoBar = () => {
if ([13, 14, 19, 30, 31].includes(this.pageType)) return;
if (document.querySelector(".plugin-container__bottom-fixed .discount__info-bar")) return;
this.fetchInfoBar().then(this.renderBottomBanner);
document.addEventListener("dj.cartChange", () => {
this.fetchInfoBar().then(this.renderBottomBanner);
});
};
}
SPZ.defineElement("spz-custom-rebate", SpzRebateComponent);
The current item does not participate in the discount gift campaign. Switch the participating items to check the design.
(This prompt will not be displayed on the client-side)
${(function () {
const automatic_discount_list = originData.automatic_discount_list;
// 显示类型
const DISPLAY_TYPE = {
DTE_FOLD: 'DTE_FOLD', // 折叠
DTE_TILE: 'DTE_TILE' // 平铺
}
const DEFAULT_CONFIG = {
BG: 'rgba(235, 57, 27, 0.04)',
TEXT_COLOR: '#EB391B',
BORDER_COLOR: 'rgb(235, 57, 27)',
ADD_TO_CART_BG: 'transparent',
ADD_TO_CART_TEXT_COLOR: 'rgb(235, 57, 27)',
ADD_TO_CART_BORDER_COLOR: 'rgb(235, 57, 27)',
};
const isExist = automatic_discount_list?.length > 0 && automatic_discount_list.some(item => item.discount[0].product_enabled);
// 如果没有任何自动折扣,则隐藏,防止gap占位
if (!isExist) {
return `
`;
} else {
return `
${(function () {
return automatic_discount_list.map((item) => {
// 模版类型
const template_type = item.discount[0].template_type;
// 是否显示自动折扣
const is_show_automatic_discount = item.discount[0].product_enabled;
// 是否跳转落地页
const is_redirection = item.discount[0].is_redirection;
// 折扣图标
const discount_icon = item.discount_icon;
// 第一个自动折扣
const first_automatic_discount = item.discount[0];
// 显示折叠展示
const isFold = (item.discount[0].display_type || DISPLAY_TYPE.DTE_FOLD) === DISPLAY_TYPE.DTE_FOLD;
// 文本数组
const text_arr = item.discount[0].config.texts;
// 条件值数组
const condition_values = item?.discount[0]?.condition_values || [];
// 落地页链接
const first_landing_url = `/promotions/discount-default/${first_automatic_discount.discount_id}`;
// 自动折扣总数
const automatic_discount_total = item.discount.length;
// 是否显示折扣图标
const isHasDiscountIcon = discount_icon ? true : false;
// 是否显示折扣图标且模版类型不为tag和add_to_cart
const isHasDiscountIconWithNoTag = (template_type != 'tag' && template_type != 'add_to_cart' && isHasDiscountIcon)? true : false;
// 文本颜色
let text_color = DEFAULT_CONFIG.TEXT_COLOR;
// 背景颜色
const bgFn = (curBg) => template_type === "text" ? "transparent" : curBg;
let bg_color = bgFn(DEFAULT_CONFIG.BG);
// 边框颜色
const borderFn = (curBorder) => template_type == "tag" ? curBorder : "initial";
let border_color = borderFn(DEFAULT_CONFIG.BORDER_COLOR);
// 模版配置
let template_config = first_automatic_discount.template_config;
// 一键加购样式
let addToCartBtnBgColor = DEFAULT_CONFIG.ADD_TO_CART_BG;
let addToCartBtnTextColor = DEFAULT_CONFIG.ADD_TO_CART_TEXT_COLOR;
let addToCartBtnBorderColor = DEFAULT_CONFIG.ADD_TO_CART_BORDER_COLOR;
// 兜底方案
try {
if(template_config.length !== 0){
template_config = JSON.parse(template_config);
text_color= isHasDiscountIconWithNoTag ? template_config.color[template_type].icon_text_color : template_config.color[template_type].text_color;
bg_color = bgFn(template_config.color[template_type].background_color);
const arrayRgba = bg_color.split(",");
arrayRgba.splice(3, 1, " 1)");
border_color = borderFn(`${arrayRgba.join(",")}`);
addToCartBtnTextColor = template_config.color[template_type].button_text_color;
addToCartBtnBorderColor = template_config.color[template_type].button_border_color;
addToCartBtnBgColor = template_config.color[template_type].button_background_color;
}
} catch (error) {
console.error('template_config_error', error);
template_config = {
color: {
[template_type]: {
icon_text_color: DEFAULT_CONFIG.TEXT_COLOR,
text_color: DEFAULT_CONFIG.TEXT_COLOR,
background_color: DEFAULT_CONFIG.BG
}
}
};
}
// 标签
const isTag = template_type == 'tag';
// 文字和横幅
const isTextAndBanner = template_type == 'text' || template_type == 'banner';
// 是否一键加购
const isAddToCart = template_type == 'add_to_cart';
// 文字样式
const textStyle = `color: ${text_color}; background-color: transparent; border: none;`;
// 标签样式
const labelStyle = `color: ${text_color};border: 1px solid ${border_color};background-color:${bg_color};padding: 4px;`;
// 横幅样式
const bannerStyle = `color: ${text_color};border: none; background-color:${bg_color}`;
// 一键加购单个容器样式(只包含动态样式)
const addToCartSingleContainerStyle = `color: ${text_color}; background-color:${bg_color};`;
// 一键加购按钮样式(只包含配置的动态样式)
const addToCartBtnStyle = `color: ${addToCartBtnTextColor}; background-color:${addToCartBtnBgColor}; border:1px solid ${addToCartBtnBorderColor};`;
// 外层样式在标签样式下不展示颜色配置,除开标签类型,颜色都可以在外层覆盖
let outerStyle = '';
if (template_type == 'text') {
outerStyle = textStyle;
} else if (template_type == 'tag') {
outerStyle = "border: none;";
} else if (template_type == 'banner') {
outerStyle = bannerStyle;
}
/**
* 1. 标签一定是单独样式展示的
* 2. 折叠:横向布局,文字和横幅,合并成一行文本; 标签:单独样式处理
* 3. 平铺:纵向布局,文字、横幅和标签; 标签:单独样式处理;一键加购默认都是平铺
*/
let txtHtml = ``;
if (isFold) {
if(isTag) {
// 标签
const spanText = text_arr.map((text) => {
return `
${text}`;
}).join('');
txtHtml = `
${spanText}
`;
} else {
// 文字和横幅
txtHtml = `
${first_automatic_discount.config.text}
`;
}
} else {
// 文字和横幅, 但标签有自己的样式,且一键加购有单独样式
const spanText = text_arr.map((text, index) => {
const condition_value = condition_values[index];
if(isAddToCart) {
return `
${text}
`
} else {
return `
${text}`;
}
}).join('');
// 都是纵向布局,标签有间距
txtHtml = `
${spanText}
`;
}
/**
* 显示图标的判断
*/
const discount_type = item.discount_type;
const isShowRebateIcon = ["DT_REBATE_CTQ_OTP", "DT_REBATE_CTQ_OTR", "DT_REBATE_CTA_OTP", "DT_REBATE_CTA_OTR", "DT_M_N_DISCOUNT"].includes(discount_type) && isTextAndBanner
const isShowBxgyIcon = ["DT_BUY_ONE_GET_ONE", "DT_BUY_X_GET_Y"].includes(discount_type)
const isShowBundleIcon = ["DT_CLASSIC_BUNDLE","DT_MIX_MATCH_BUNDLE"].includes(discount_type);
/**
* 渲染下拉框或抽屉的折扣列表
*/
const discount_list_html = (curItem) => {
return `
${function() {
return curItem.discount.map(childItem => {
return `
`}).join('');
}()}
`;
}
return `
${discount_list_html(item)}
${function() {
return text_arr.map((text) => {
return `
${text}
`;
}).join('');
}()}
`;
}).join('');
})()}
`
}
})()}
const TAG = "spz-custom-product-automatic";
class SpzCustomProductAutomatic extends SPZ.BaseElement {
constructor(element) {
super(element);
this.variant_id = '71d17a7b-5f32-44ba-b382-015d23492f80';
this.isRTL = SPZ.win.document.dir === 'rtl';
this.isAddingToCart_ = false; // 加购中状态
}
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.viewport_ = this.getViewport();
}
mountCallback() {
this.init();
// 监听事件
this.bindEvent_();
}
async init() {
this.handleFitTheme();
const data = await this.getDiscountList();
this.renderApiData_(data);
}
async getDiscountList() {
const productId = '17bda5f8-71dd-4b45-a2f7-75213acbaee5';
const variantId = this.variant_id;
const productType = 'default';
const reqBody = {
product_id: productId,
variant_id: variantId,
discount_method: "DM_AUTOMATIC",
customer: {
customer_id: window.C_SETTINGS.customer.customer_id,
email: window.C_SETTINGS.customer.customer_email
},
product_type: productType
}
const url = `/api/storefront/promotion/display_setting/text/list`;
const data = await this.xhr_.fetchJson(url, {
method: "post",
body: reqBody
}).then(res => {
return res;
}).catch(err => {
this.setContainerDisabled(false);
})
return data;
}
async renderDiscountList() {
this.setContainerDisabled(true);
const data = await this.getDiscountList();
this.setContainerDisabled(false);
// 重新渲染 抖动问题处理
this.renderApiData_(data);
}
clearDom() {
const children = this.element.querySelector('*:not(template)');
children && SPZCore.Dom.removeElement(children);
}
async renderApiData_(data) {
const parentDiv = document.querySelector('.automatic_discount_container');
const newTplDom = await this.getRenderTemplate(data);
if (parentDiv) {
parentDiv.innerHTML = '';
parentDiv.appendChild(newTplDom);
} else {
console.log('automatic_discount_container is null');
}
}
doRender_(data) {
const renderData = data || {};
return this.templates_
.findAndRenderTemplate(this.element, renderData)
.then((el) => {
this.clearDom();
this.element.appendChild(el);
});
}
async getRenderTemplate(data) {
const renderData = data || {};
return this.templates_
.findAndRenderTemplate(this.element, { ...renderData, isRTL: this.isRTL })
.then((el) => {
this.clearDom();
return el;
});
}
setContainerDisabled(isDisable) {
const automaticDiscountEl = document.querySelector('.automatic_discount_container_outer');
if(isDisable) {
automaticDiscountEl.setAttribute('disabled', '');
} else {
automaticDiscountEl.removeAttribute('disabled');
}
}
// 绑定事件
bindEvent_() {
window.addEventListener('click', (e) => {
let containerNodes = document.querySelectorAll(".automatic-container .panel");
let bool;
Array.from(containerNodes).forEach((node) => {
if(node.contains(e.target)){
bool = true;
}
})
// 是否popover面板点击范围
if (bool) {
return;
}
if(e.target.classList.contains('drowdown-icon') || e.target.parentNode.classList.contains('drowdown-icon')){
return;
}
const nodes = document.querySelectorAll('.automatic-container');
Array.from(nodes).forEach((node) => {
node.classList.remove('open-dropdown');
})
// 兼容主题
this.toggleProductSticky(true);
})
// 监听变体变化
document.addEventListener('dj.variantChange', async(event) => {
// 重新渲染
const variant = event.detail.selected;
if (variant.product_id == '17bda5f8-71dd-4b45-a2f7-75213acbaee5' && variant.id != this.variant_id) {
this.variant_id = variant.id;
this.renderDiscountList();
}
});
}
// 兼容主题
handleFitTheme() {
// top 属性影响抖动
let productInfoEl = null;
if (window.SHOPLAZZA.theme.merchant_theme_name === 'Wind' || window.SHOPLAZZA.theme.merchant_theme_name === 'Flash') {
productInfoEl = document.querySelector('.product-info-body .product-sticky-container');
} else if (window.SHOPLAZZA.theme.merchant_theme_name === 'Hero') {
productInfoEl = document.querySelector('.product__info-wrapper .properties-content');
}
if(productInfoEl){
productInfoEl.classList.add('force-top-auto');
}
}
// 兼容 wind/flash /hero 主题 (sticky属性影响 popover 层级展示, 会被其他元素覆盖)
toggleProductSticky(isSticky) {
let productInfoEl = null;
if (window.SHOPLAZZA.theme.merchant_theme_name === 'Wind' || window.SHOPLAZZA.theme.merchant_theme_name === 'Flash') {
productInfoEl = document.querySelector('.product-info-body .product-sticky-container');
} else if (window.SHOPLAZZA.theme.merchant_theme_name === 'Hero') {
productInfoEl = document.querySelector('.product__info-wrapper .properties-content');
}
if(productInfoEl){
if(isSticky) {
// 还原该主题原有的sticky属性值
productInfoEl.classList.remove('force-position-static');
return;
}
productInfoEl.classList.toggle('force-position-static');
}
}
setupAction_() {
this.registerAction('handleDropdown', (invocation) => {
const discount_id = invocation.args.discount_id;
const nodes = document.querySelectorAll('.automatic-container');
Array.from(nodes).forEach((node) => {
if(node.getAttribute('id') != `automatic-${discount_id}`) {
node.classList.remove('open-dropdown');
}
})
const $discount_item = document.querySelector(`#automatic-${discount_id}`);
$discount_item && $discount_item.classList.toggle('open-dropdown');
// 兼容主题
this.toggleProductSticky();
});
// 加购事件
this.registerAction('handleAddToCart', (invocation) => {
// 阻止事件冒泡
const event = invocation.event;
if (event) {
event.stopPropagation();
event.preventDefault();
}
// 如果正在加购中,直接返回
if (this.isAddingToCart_) {
return;
}
const quantity = invocation.args.quantity || 1;
this.addToCart(quantity);
});
}
// 加购方法
async addToCart(quantity) {
// 设置加购中状态
this.isAddingToCart_ = true;
const productId = '17bda5f8-71dd-4b45-a2f7-75213acbaee5';
const variantId = this.variant_id;
const url = '/api/cart';
const reqBody = {
product_id: productId,
variant_id: variantId,
quantity: quantity
};
try {
const data = await this.xhr_.fetchJson(url, {
method: 'POST',
body: reqBody
});
// 触发加购成功提示
this.triggerAddToCartToast_();
return data;
} catch (error) {
error.then(err=>{
this.showToast_(err?.message || err?.errors?.[0] || 'Unknown error');
})
} finally {
// 无论成功失败,都重置加购状态
this.isAddingToCart_ = false;
}
}
showToast_(message) {
const toastEl = document.querySelector("#apps-match-drawer-add_to_cart_toast");
if (toastEl) {
SPZ.whenApiDefined(toastEl).then((apis) => {
apis.showToast(message);
});
}
}
// 触发加购成功提示
triggerAddToCartToast_() {
// 如果主题有自己的加购提示,则不显示
const themeAddToCartToastEl = document.querySelector('#add-cart-event-proxy');
if (themeAddToCartToastEl) return;
// 显示应用的加购成功提示
this.showToast_("Added successfully");
}
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, SpzCustomProductAutomatic);
class SpzCustomDiscountBundle extends SPZ.BaseElement {
constructor(element) {
super(element);
}
isLayoutSupported(layout) {
return layout == SPZCore.Layout.LOGIC;
}
mountCallback() {}
unmountCallback() {}
setupAction_() {
this.registerAction('showAddToCartToast', () => {
const themeAddToCartToastEl = document.querySelector('#add-cart-event-proxy')
if(themeAddToCartToastEl) return
const toastEl = document.querySelector('#apps-match-drawer-add_to_cart_toast')
SPZ.whenApiDefined(toastEl).then((apis) => {
apis.showToast("Added successfully");
});
});
}
buildCallback() {
this.setupAction_();
};
}
SPZ.defineElement('spz-custom-discount-toast', SpzCustomDiscountBundle);
Zoom Vomero 5 WMNS "Pure Platinum"
Zoom Vomero 5 WMNS "Pure Platinum"
${function() {
const variantData = data.variant || {"id":"71d17a7b-5f32-44ba-b382-015d23492f80","product_id":"17bda5f8-71dd-4b45-a2f7-75213acbaee5","title":"4W","weight_unit":"kg","inventory_quantity":1000,"sku":"131939|FN6742 002|4W","barcode":"","position":1,"option1":"4W","option2":"","option3":"","note":"","image":{"src":"\/\/img.staticdj.com\/3cbd1e07f759bc7aad1b86c675decb0a.png","path":"3cbd1e07f759bc7aad1b86c675decb0a.png","width":2000,"height":1200,"alt":"","aspect_ratio":1.6666666666666667},"wholesale_price":[{"price":34.95,"min_quantity":1}],"weight":"0","compare_at_price":"130","price":"34.95","retail_price":"130","available":true,"url":"\/products\/zoom-vomero-5-wmns-pure-platinum-131939?variant=71d17a7b-5f32-44ba-b382-015d23492f80","available_quantity":999999999,"options":[{"name":"Size","value":"4W"}],"off_ratio":"73","flashsale_info":{"variant_id":"71d17a7b-5f32-44ba-b382-015d23492f80","product_id":"","quantity":0,"discount_id":"","limit_time":0,"limit_buy":0,"user_limit_buy":0,"discount_sales":0,"discount_sales_rate":"","discount_stock":0,"ends_at":0,"starts_at":0,"allow_oversold":"","allocation_method":"","price":"34.95","compare_at_price":"","discount_price":"34.95","customary_saved_price":"","customary_off_ratio":"","discount_saved_price":"","discount_off_ratio":"73","use_before_price":false,"before_price":"","title":"","properties":"","color_setting_promotional_copy":"","discount_quantity":0,"is_need_split":false},"sales":0};
const saveType = null;
const productSaveLabel = null;
return `
-
${ variantData.off_ratio }%
`; }()}
${function() {
const minInventory = parseInt('7');
const maxInventory = parseInt('10');
const randomInventory = Math.round(Math.random() * (maxInventory - minInventory)) + minInventory;
const customText = "Only {stock} item(s) left in stock!".replace(/\{stock\}/g, '' + randomInventory + '');
const barWidth = (randomInventory / maxInventory) * 100 + '%';
return `
`;
}()}
people are viewing this right now
Please select a Size
${function(){
return `
Please select a Size
`;
}()}
Product was out of stock.
${function(){
const variantData = data.variant || null;
return `
Vendor by :
${data.product && data.product.vendor}
Weight :
${variantData && variantData.weight}${variantData && variantData.weight_unit}
Barcode :
${variantData && variantData.barcode}
Sku :
${variantData && variantData.sku}
Inventory :
${variantData && variantData.available_quantity}
` }()}
${function(){
// 获取基础配置数据
const isRTL = originData.isRTL; // 是否从右到左显示
const isMobile = originData.isMobile; // 是否移动端
const inProductDetail = originData.inProductDetail; // 是否在商品详情页
const image_domain = originData.image_domain; // 图片域名
const copyBtnClass = originData.copyBtnClass; // 复制按钮类名
const copyClass = originData.copyClass; // 复制内容类名
// 优惠码列表
const list = originData.discountCodeData.list || [];
if (list.length === 0) {
return ``;
}
// 显示模式: 平铺或折叠
const isTiled = originData.discountCodeData.display_type === "DTE_TILE";
// 获取第一个配置作为默认配置
const productSetting = list[0].product_setting;
const { template_type, template_config } = productSetting;
const { text, tag, banner, coupon } = template_config.color;
// 优惠券样式配置
const {
coupon_border_color, // 边框颜色
coupon_background_color, // 背景色起始色
coupon_background_color_end, // 背景色结束色
coupon_color, // 文字颜色
coupon_button_background_color_start, // 按钮背景起始色
coupon_button_background_color_end, // 按钮背景结束色
coupon_button_color // 按钮文字颜色
} = coupon;
// 颜色透明度转换函数
const colorToRGBA = (color, alpha) => {
if (color.startsWith('#')) {
const hex = color.slice(1);
const r = parseInt(hex.slice(0, 2), 16);
const g = parseInt(hex.slice(2, 4), 16);
const b = parseInt(hex.slice(4, 6), 16);
return `rgba(${r}, ${g}, ${b}, ${alpha})`;
}
else if (color.includes('rgb')) {
const rgb = color.slice(color.indexOf('(') + 1, color.indexOf(')')).split(',');
const r = parseInt(rgb[0]);
const g = parseInt(rgb[1]);
const b = parseInt(rgb[2]);
return `rgba(${r}, ${g}, ${b}, ${alpha})`;
}
else {
return color
}
}
// 渲染平铺样式的优惠券列表
const renderTiledList = (list, isFold = false) => {
const rate = isRTL ? '34%' : '66%'; // RTL布局时调整分割线位置
let curDom = `
`;
// 循环渲染优惠券列表
for(const item of list) {
curDom += `
${item.discount_text}
${(isFold || item.product_setting.show_effective_date) && +item.ends_at !== -1 ? `${item.starts_at} - ${item.ends_at}` : ""}
`
}
return curDom;
}
let Dom = ``;
// 根据显示模式选择渲染方式
if (isTiled || list.length === 1) {
// 根据模板类型渲染不同样式
switch(template_type) {
// 文本样式
case 'text': {
Dom = `
${function(){
let textDom = '';
for(const item of list) {
textDom += `
${ item.discount_text }
Code:
${ item.code }
`
}
return textDom;
}()}
`;
break;
}
// 标签样式
case 'tag': {
const { text_color, background_color } = tag;
Dom = `
${function(){
let textDom = '';
for(const item of list) {
textDom += `
${ item.discount_text }
Code:
${ item.code }
`;
}
return textDom;
}()}
`
break;
}
// 横幅样式
case 'banner': {
Dom = `
${function(){
let textDom = '';
for(const item of list) {
textDom += `
${ item.discount_text }
Code:
${ item.code }
`;
}
return textDom;
}()}
`;
break;
}
// 优惠券样式
case 'coupon': {
Dom = `
${renderTiledList(list)}
`
break;
}
}
} else {
// 折叠模式样式
const foldStyle = `
`;
// 只显示前3个优惠券
const showList = list.slice(0, 3);
let couponDom = "";
for(const item of showList) {
couponDom += `
${item.discount_text}
`
}
// PC端弹窗
const webModal = `
${function(){
return renderTiledList(list, true);
}()}
`
// 移动端侧边栏
const mobileModal = `
`
couponDom += `
Click to claim
${isMobile ? mobileModal : webModal}
`;
Dom = `
${foldStyle}
${couponDom}
`
}
return `
${Dom}
`;
}()}
/**
* 优惠码组件模型类
* 处理优惠码的显示和交互逻辑
*/
class SpzCustomDiscountCodeModel extends SPZ.BaseElement {
constructor(element) {
super(element);
// 复制按钮和内容的类名
this.copyBtnClass = "discount_code_btn"
this.copyClass = "discount_code_value"
}
isLayoutSupported(layout) {
return layout == SPZCore.Layout.LOGIC;
}
buildCallback() {
// 初始化服务
this.action_ = SPZServices.actionServiceForDoc(this.element);
this.templates_ = SPZServices.templatesForDoc(this.element);
this.xhr_ = SPZServices.xhrFor(this.win);
}
/**
* 渲染优惠码组件
* @param {Object} data - 渲染数据
*/
doRender_(data) {
return this.templates_
.findAndRenderTemplate(this.element,
Object.assign(this.getDefaultData(), data)
)
.then((el) => {
this.clearDom();
this.element.appendChild(el);
// 绑定复制代码功能
this.copyCode(el, data);
});
}
/**
* 获取渲染模板
* @param {Object} data - 渲染数据
*/
getRenderTemplate(data) {
const renderData = Object.assign(this.getDefaultData(), data);
return this.templates_
.findAndRenderTemplate(this.element, renderData)
.then((el) => {
this.clearDom();
return el;
});
}
/**
* 清除DOM内容
*/
clearDom() {
const children = this.element.querySelector('*:not(template)');
children && SPZCore.Dom.removeElement(children);
}
/**
* 获取默认数据
* @returns {Object} 默认数据对象
*/
getDefaultData() {
return {
isMobile: appDiscountUtils.judgeMobile(),
isRTL: appDiscountUtils.judgeRTL(),
image_domain: this.win.SHOPLAZZA.image_domain,
copyBtnClass: this.copyBtnClass,
copyClass: this.copyClass
}
}
/**
* 复制优惠码功能
* @param {Element} el - 当前元素
*/
copyCode(el) {
const copyBtnList = el.querySelectorAll(`.${this.copyBtnClass}`);
if (copyBtnList.length > 0) {
copyBtnList.forEach(item => {
item.onclick = async () => {
// 确保获取正确的元素和内容
const codeElement = item.querySelector(`.${this.copyClass}`);
if (!codeElement) return;
// 获取纯文本内容
const textToCopy = codeElement.innerText.trim();
// 尝试使用现代API,如果失败则使用备用方案
try {
if (navigator.clipboard && navigator.clipboard.writeText) {
await navigator.clipboard.writeText(textToCopy);
} else {
throw new Error('Clipboard API not available');
}
// 显示复制成功提示
this.showCopySuccessToast(textToCopy, el);
} catch (err) {
console.error('Modern clipboard API failed, trying fallback...', err);
// 使用备用复制方案
this.fallbackCopy(textToCopy, el);
}
const discountId = item.dataset["discountId"];
// 是否跳转落地页配置
const redirection = item.dataset["redirection"] === "true";
// 跳转到落地页
if (redirection && appDiscountUtils.inProductBody(this.element)) {
this.win.open(`/promotions/discount-default/${discountId}`);
}
}
})
}
}
/**
* 使用 execCommand 的复制方案
* @param {string} codeText - 要复制的文本
* @param {Element} el - 当前元素
*/
fallbackCopy(codeText, el) {
const textarea = this.win.document.createElement('textarea');
textarea.value = codeText;
// 设置样式使文本框不可见
textarea.style.position = 'fixed';
textarea.style.left = '-9999px';
textarea.style.top = '0';
// 添加 readonly 属性防止移动端虚拟键盘弹出
textarea.setAttribute('readonly', 'readonly');
this.win.document.body.appendChild(textarea);
textarea.focus();
textarea.select();
try {
this.win.document.execCommand('copy');
// 显示复制成功提示
this.showCopySuccessToast(codeText, el);
} catch (err) {
console.error('Copy failed:', err);
}
this.win.document.body.removeChild(textarea);
}
/**
* 创建 Toast 元素
* @returns {Element} 创建的 Toast 元素
*/
createToastEl_() {
const toast = document.createElement('ljs-toast');
toast.setAttribute('layout', 'nodisplay');
toast.setAttribute('hidden', '');
toast.setAttribute('id', 'discount-code-toast');
toast.style.zIndex = '1051';
return toast;
}
/**
* 挂载 Toast 元素到 body
* @returns {Element} 挂载的 Toast 元素
*/
mountToastToBody_() {
const existingToast = this.win.document.getElementById('discount-code-toast');
if (existingToast) {
return existingToast;
}
const toast = this.createToastEl_();
this.win.document.body.appendChild(toast);
return toast;
}
/**
* 复制成功的提醒
* @param {string} codeText - 要复制的文本
* @param {Element} el - 当前元素
*/
showCopySuccessToast(codeText, el) {
const $toast = this.mountToastToBody_();
SPZ.whenApiDefined($toast).then(toast => {
toast.showToast("Discount code copied !");
this.codeCopyInSessionStorage(codeText);
});
}
/**
* 复制优惠码成功后要存一份到本地存储中,购物车使用
* @param {string} codeText - 要复制的文本
*/
codeCopyInSessionStorage(codeText) {
try {
sessionStorage.setItem('other-copied-coupon', codeText);
} catch (error) {
console.error(error)
}
}
}
// 注册自定义元素
SPZ.defineElement('spz-custom-discount-code-model', SpzCustomDiscountCodeModel);
${function(){
return `
Discount code cannot be displayed here. Please move it to the product detail area.
(This prompt will not be displayed on the client-side)
`;
}()}
/**
* Custom discount code component that handles displaying and managing discount codes
* @extends {SPZ.BaseElement}
*/
class SpzCustomDiscountCode extends SPZ.BaseElement {
constructor(element) {
super(element);
// API endpoint for fetching discount codes
this.getDiscountCodeApi = "\/api\/storefront\/promotion\/code\/list";
// Debounce timer for resize events
this.timer = null;
// Current variant ID
this.variantId = "71d17a7b-5f32-44ba-b382-015d23492f80";
// Store discount code data
this.discountCodeData = {}
}
/**
* Check if layout is supported
* @param {string} layout - Layout type
* @return {boolean}
*/
isLayoutSupported(layout) {
return layout == SPZCore.Layout.LOGIC;
}
/**
* Initialize component after build
*/
buildCallback() {
this.templates_ = SPZServices.templatesForDoc();
this.viewport_ = this.getViewport();
// Bind methods to maintain context
this.render = this.render.bind(this);
this.resize = this.resize.bind(this);
this.switchVariant = this.switchVariant.bind(this);
}
/**
* Setup component when mounted
*/
mountCallback() {
this.getData();
// Add event listeners
this.viewport_.onResize(this.resize);
this.win.document.addEventListener('dj.variantChange', this.switchVariant);
}
/**
* Cleanup when component is unmounted
*/
unmountCallback() {
this.viewport_.removeResize(this.resize);
this.win.document.removeEventListener('dj.variantChange', this.switchVariant);
// 清除定时器
if (this.timer) {
clearTimeout(this.timer);
this.timer = null;
}
}
/**
* Handle resize events with debouncing
*/
resize() {
if (this.timer) {
clearTimeout(this.timer)
this.timer = null;
}
this.timer = setTimeout(() => {
if (appDiscountUtils.inProductBody(this.element)) {
this.render();
} else {
this.renderSkeleton();
}
}, 200);
}
/**
* Handle variant changes
* @param {Event} event - Variant change event
*/
switchVariant(event) {
const variant = event.detail.selected;
if (variant.product_id == '17bda5f8-71dd-4b45-a2f7-75213acbaee5' && variant.id != this.variantId) {
this.variantId = variant.id;
this.getData();
}
}
/**
* Fetch discount code data from API
*/
getData() {
if (appDiscountUtils.inProductBody(this.element)) {
const reqBody = {
product_id: "17bda5f8-71dd-4b45-a2f7-75213acbaee5",
variant_id: this.variantId,
product_type: "default",
}
if (!reqBody.product_id || !reqBody.variant_id) return;
this.discountCodeData = {};
this.win.fetch(this.getDiscountCodeApi, {
method: "POST",
body: JSON.stringify(reqBody),
headers: {
"Content-Type": "application/json"
}
}).then(async (response) => {
if (response.ok) {
let data = await response.json();
if (data.list && data.list.length > 0) {
data.list[0].product_setting.template_config = JSON.parse(data.list[0].product_setting.template_config);
// Format timestamps to local timezone
const zone = this.win.SHOPLAZZA.shop.time_zone;
data.list = data.list.map(item => {
if(+item.ends_at !== -1) {
item.ends_at = appDiscountUtils.convertTimestampToFormat(+item.ends_at, zone);
}
item.starts_at = appDiscountUtils.convertTimestampToFormat(+item.starts_at, zone);
return item;
});
}
this.discountCodeData = data;
this.render();
} else {
this.clearDom();
}
}).catch(err => {
console.error("discount_code", err)
this.clearDom();
});
} else {
this.renderSkeleton();
}
}
/**
* Clear component DOM except template
*/
clearDom() {
const children = this.element.querySelector('*:not(template)');
children && SPZCore.Dom.removeElement(children);
}
/**
* Render discount codes with formatted dates
*/
render() {
// Render using discount code model
SPZ.whenApiDefined(document.querySelector('#spz_custom_discount_code_model')).then(renderApi => {
renderApi.doRender_({
discountCodeData: this.discountCodeData
})
}).catch(err => {
this.clearDom();
})
}
renderSkeleton() {
// Render template for non-product pages
this.templates_
.findAndRenderTemplate(this.element, {
isMobile: appDiscountUtils.judgeMobile()
})
.then((el) => {
this.clearDom();
this.element.appendChild(el);
})
.catch(err => {
this.clearDom();
});
}
}
// Register custom element
SPZ.defineElement('spz-custom-discount-code', SpzCustomDiscountCode);
${function(){
const isRTL = originData.isRTL;
const isMobile = originData.isMobile;
const inProductDetail = originData.inProductDetail;
if (!inProductDetail) {
return `
Flash sale cannot be displayed here. Please move it to the product detail area.
(This prompt will not be displayed on the client-side)
`;
}
const flashsaleData = originData.flashsaleData;
const image_domain = originData.image_domain;
const discount_info = flashsaleData.discount_info;
const setting = flashsaleData.product_setting;
if (!discount_info || !setting) return ``;
const displayType = setting.display_type;
const banner = setting.banner;
const productDisplay = setting.product_display;
const bannerConfig = JSON.parse(banner.config);
const productDisplayConfig = JSON.parse(productDisplay.config);
const colorConfig = productDisplayConfig.color;
const countdownConfig = productDisplayConfig.countdown;
let titleIcon = ``;
let bgImg = ``;
const deg = `${isRTL ? -90 : 90}deg`;
const { banner_bg_start, banner_bg_end, banner_text } = colorConfig;
let bgStyle = `background: linear-gradient(${deg}, ${banner_bg_start} 0%, ${banner_bg_end} 100%);`;
let bannerColor = `color: ${banner_text};`
if (banner.type === "TYPE_CUSTOM") {
const { desktop, mobile, image_render } = bannerConfig;
const bgSize = image_render === "fill" ? "background-size: cover;background-position: center;" : "background-position: center;background-size: auto 100%;";
if (isMobile && mobile) {
bgStyle = `background: URL(${image_domain + mobile});${bgSize}`;
} else if (!isMobile && desktop) {
bgStyle = `background: URL(${image_domain + desktop});${bgSize}`;
}
} else {
if (banner.type === "TYPE_ONE") {
titleIcon = productDisplay.text ? `
` : "";
bgImg = ``
}
if (banner.type === "TYPE_TWO") {
titleIcon = productDisplay.text ? `
` : ""
}
}
const { sale_bar_background_color, progress_sale_bar_background_color_start, progress_sale_bar_background_color_end } = colorConfig;
const rate = discount_info.discount_sales_rate;
const progressBarStyle = `background: linear-gradient(${deg}, ${progress_sale_bar_background_color_start} 0%, ${progress_sale_bar_background_color_end} 100%);`;
const saleCount = productDisplay.sales_progress.format === "FORMAT_NUMBER" ? discount_info.discount_sales : `${rate}%`;
const progressBarDom = productDisplay.sales_progress.enabled && rate > 0 ? `
` : ``;
const { countdown_bg, countdown_text } = colorConfig;
const { end_opened, end_format } = countdownConfig;
const tempMap = {
"DD_SSS": "DD:HH:mm:ss:SSS",
"HH_SSS": "HH:mm:ss:SSS",
"DD_ss": "DD:HH:mm:ss",
"HH_ss": "HH:mm:ss"
}
const isShowDD = [tempMap.DD_SSS, tempMap.DD_ss].includes(end_format);
const isShowSSS = [tempMap.DD_SSS, tempMap.HH_SSS].includes(end_format);
const countdown = discount_info.ends_remaining_seconds;
const countdownDom = end_opened ? `
${function() {
if (banner.type === "TYPE_TWO") return `
`
return ``;
}()}
` : ``;
const flashSaleDesc = discount_info.limit_user_product_discount > -1 ? `
Promo products limited to ${discount_info.limit_user_product_discount} item per person
` : "";
return `
${bgImg}
${titleIcon}
${productDisplay.text}
${progressBarDom}
${countdownDom}
${flashSaleDesc}
`}()}
${function(){
const dd = data.dd; const hh = data.hh; const mm = data.mm; const ss = data.ss; const sss = data.SSS;
const hours = data.d * 24 + data.h;
return `
${dd}D
·
${hours}
${hh}
:
${mm}
:
${ss}
.
${sss}
`
}()}
class SpzCustomDiscountFlashsale extends SPZ.BaseElement {
constructor(element) {
super(element);
this.xhr_ = SPZServices.xhrFor(this.win);
this.getFlashSaleApi = "\/api\/storefront\/promotion\/flashsale\/display_setting\/product_setting";
this.timer = null;
this.variantId = "71d17a7b-5f32-44ba-b382-015d23492f80";
// 促销活动数据
this.flashsaleData = {}
}
isLayoutSupported(layout) {
return layout == SPZCore.Layout.CONTAINER;
}
buildCallback() {
this.templates_ = SPZServices.templatesForDoc();
this.viewport_ = this.getViewport();
// 挂载bind函数 解决this指向问题
this.render = this.render.bind(this);
this.resize = this.resize.bind(this);
this.switchVariant = this.switchVariant.bind(this);
}
mountCallback() {
// 获取数据
this.getData();
this.element.onclick = (e) => {
const cur = this.win.document.querySelector(".app_discount_flashsale_desc");
if (this.flashsaleData.product_setting.is_redirection && appDiscountUtils.inProductBody(this.element) && e.target !== cur) {
this.win.open(`/promotions/discount-default/${this.flashsaleData.discount_info.id}`);
}
}
// 绑定
this.viewport_.onResize(this.resize);
// 监听子款式切换,重新渲染
this.win.document.addEventListener('dj.variantChange', this.switchVariant);
}
unmountCallback() {
// 解绑
this.viewport_.removeResize(this.resize);
this.win.document.removeEventListener('dj.variantChange', this.switchVariant);
// 清除定时器
if (this.timer) {
clearTimeout(this.timer);
this.timer = null;
}
}
resize() {
if (this.timer) {
clearTimeout(this.timer)
this.timer = null;
}
this.timer = setTimeout(() => {
this.render();
}, 200)
}
switchVariant(event) {
const variant = event.detail.selected;
if (variant.product_id == '17bda5f8-71dd-4b45-a2f7-75213acbaee5' && variant.id != this.variantId) {
this.variantId = variant.id;
this.getData();
}
}
getData() {
const reqBody = {
product_id: "17bda5f8-71dd-4b45-a2f7-75213acbaee5",
product_type: "default",
variant_id: this.variantId
}
this.flashsaleData = {};
this.win.fetch(this.getFlashSaleApi, {
method: "POST",
body: JSON.stringify(reqBody),
headers: {
"Content-Type": "application/json"
}
}).then(async (response) => {
if (response.ok) {
this.flashsaleData = await response.json();
this.render();
} else {
this.clearDom();
}
}).catch(err => {
this.clearDom();
});
}
clearDom() {
const children = this.element.querySelector('*:not(template)');
children && SPZCore.Dom.removeElement(children);
}
render() {
this.templates_
.findAndRenderTemplate(this.element, {
isMobile: appDiscountUtils.judgeMobile(),
isRTL: appDiscountUtils.judgeRTL(),
inProductDetail: appDiscountUtils.inProductBody(this.element),
flashsaleData: this.flashsaleData,
image_domain: this.win.SHOPLAZZA.image_domain,
})
.then((el) => {
this.clearDom();
this.element.appendChild(el);
})
}
}
SPZ.defineElement('spz-custom-discount-flashsale', SpzCustomDiscountFlashsale);