功能:
- 标题、副标题、倒计时、角标、优惠券代码复制
- Translate & Adapt多语言翻译
- 倒计时显示/隐藏
- 字体大小、颜色、粗细等细节自定义
使用方式:
- shopify 主题 snippets 文件夹下新建文件 countdown-promo-block.liquid,粘贴以下代码
Liquid
<div id="countdown-promo-{{ block.id }}" class="countdown-promo" {{ block.shopify_attributes }}
style="
--cp-bg: {{ block.settings.wrap_bg | default: '#ffffff' }};
--cp-border-color: {{ block.settings.wrap_border_color | default: '#000000' }};
--cp-border-style: {{ block.settings.wrap_border_style }};
--cp-border-width: {{ block.settings.wrap_border_width }}px;
--cp-radius: {{ block.settings.wrap_radius }}px;
--cp-padding-block: {{ block.settings.wrap_padding_y }}px;
--cp-padding-inline: {{ block.settings.wrap_padding_x }}px;
--cp-margin-block: {{ block.settings.wrap_margin_y }}px;
--cp-margin-inline: {{ block.settings.wrap_margin_x }}px;
--title-color: {{ block.settings.title_color | default: '#111111' }};
--title-size: {{ block.settings.title_size }}px;
--title-weight: {{ block.settings.title_weight | default: 700 }};
--subtitle-color: {{ block.settings.subtitle_color | default: '#333333' }};
--subtitle-size: {{ block.settings.subtitle_size }}px;
--subtitle-weight: {{ block.settings.subtitle_weight | default: 500 }};
--num-bg: {{ block.settings.num_bg | default: '#000000' }};
--num-color: {{ block.settings.num_color | default: '#ffffff' }};
--num-size: {{ block.settings.num_size }}px;
--label-bg: {{ block.settings.label_bg | default: 'transparent' }};
--label-color: {{ block.settings.label_color | default: '#333333' }};
--label-size: {{ block.settings.label_size }}px;
--label-weight: {{ block.settings.label_weight | default: 500 }};
--coupon-bg: {{ block.settings.coupon_bg | default: '#ffffff' }};
--coupon-color: {{ block.settings.coupon_color | default: '#111111' }};
--coupon-border-color: {{ block.settings.coupon_border_color | default: '#111111' }};
--coupon-border-style: {{ block.settings.coupon_border_style }};
--coupon-border-width: {{ block.settings.coupon_border_width }}px;
--coupon-radius: {{ block.settings.coupon_radius }}px;
--coupon-size: {{ block.settings.coupon_size }}px;
--coupon-weight: {{ block.settings.coupon_weight | default: 600 }};
--ribbon-bg: {{ block.settings.ribbon_bg | default: '#111111' }};
--ribbon-color: {{ block.settings.ribbon_color | default: '#ffffff' }};
"
data-ribbon-corner="{{ block.settings.ribbon_corner }}"
>
<style>
#countdown-promo-{{ block.id }}{
position: relative;
background: var(--cp-bg);
border: var(--cp-border-width) var(--cp-border-style) var(--cp-border-color);
border-radius: var(--cp-radius);
padding: var(--cp-padding-block) var(--cp-padding-inline);
margin: var(--cp-margin-block) var(--cp-margin-inline);
max-width: 560px;
}
#countdown-promo-{{ block.id }} .cp-inner{ text-align:center }
#countdown-promo-{{ block.id }} .cp-ribbon{
position: absolute;
top: 10px;
padding: 6px 14px;
background: var(--ribbon-bg);
color: var(--ribbon-color);
font-size: 12px;
font-weight: 700;
letter-spacing: .02em;
border-radius: 999px;
line-height: 1;
white-space: nowrap;
pointer-events: none;
z-index: 2;
}
#countdown-promo-{{ block.id }}[data-ribbon-corner="right"] .cp-ribbon{ right: 10px; }
#countdown-promo-{{ block.id }}[data-ribbon-corner="left"] .cp-ribbon{ left: 10px; }
#countdown-promo-{{ block.id }} .cp-title{
margin:0 0 8px;color:var(--title-color);font-size:var(--title-size);line-height:1.2;font-weight:var(--title-weight);
{% if block.settings.title_font != blank %}font-family: {{ block.settings.title_font.family }}, {{ block.settings.title_font.fallback_families }};{% endif %}
display:inline-flex;align-items:center;gap:.4em;
}
#countdown-promo-{{ block.id }} .cp-subtitle{
margin:0 0 16px;color:var(--subtitle-color);font-size:var(--subtitle-size);line-height:1.4;font-weight:var(--subtitle-weight);
{% if block.settings.subtitle_font != blank %}font-family: {{ block.settings.subtitle_font.family }}, {{ block.settings.subtitle_font.fallback_families }};{% endif %}
}
#countdown-promo-{{ block.id }} .cp-timer{
display:flex;width:100%;justify-content:center;gap:14px;align-items:flex-end;margin-bottom:12px
}
#countdown-promo-{{ block.id }} .cp-unit{display:grid;grid-template-rows:auto auto;gap:6px;justify-items:center;min-width:68px}
#countdown-promo-{{ block.id }} .cp-num{
background:var(--num-bg);color:var(--num-color);font-size:var(--num-size);line-height:1;
padding:10px 12px;border-radius:8px;box-shadow:0 2px 0 rgba(0,0,0,.15), inset 0 -2px 0 rgba(255,255,255,.15);
{% if block.settings.num_font != blank %}font-family: {{ block.settings.num_font.family }}, {{ block.settings.num_font.fallback_families }};{% endif %}
font-weight:700;letter-spacing:.02em;
}
#countdown-promo-{{ block.id }} .cp-label{
background:var(--label-bg);color:var(--label-color);font-size:var(--label-size);line-height:1.1;padding:2px 6px;border-radius:6px;
{% if block.settings.label_font != blank %}font-family: {{ block.settings.label_font.family }}, {{ block.settings.label_font.fallback_families }};{% endif %}
font-weight: var(--label-weight);
}
#countdown-promo-{{ block.id }} .cp-coupon{
display:inline-flex;align-items:center;gap:10px;margin-top:10px;padding:10px 14px;background:var(--coupon-bg);color:var(--coupon-color);
border:var(--coupon-border-width) var(--coupon-border-style) var(--coupon-border-color);border-radius:var(--coupon-radius);
font-size:var(--coupon-size);cursor:pointer;user-select:none;position:relative;
font-weight: var(--coupon-weight);
{% if block.settings.coupon_font != blank %}font-family: {{ block.settings.coupon_font.family }}, {{ block.settings.coupon_font.fallback_families }};{% endif %}
}
#countdown-promo-{{ block.id }} .cp-scissors{ display:inline-flex; width:16px; height:16px; }
#countdown-promo-{{ block.id }} .cp-scissors svg{ width:16px; height:16px; display:block; }
#countdown-promo-{{ block.id }} .cp-coupon .cp-copy-tip{position:absolute;inset:0;display:grid;place-items:center;pointer-events:none;opacity:0;transition:opacity .2s}
#countdown-promo-{{ block.id }} .cp-coupon.copied .cp-copy-tip{opacity:1;background-color: #D3FFE0;}
#countdown-promo-{{ block.id }} .cp-coupon.copied .cp-text{opacity:0}
@media (max-width:480px){
#countdown-promo-{{ block.id }} .cp-timer{gap:8px}
#countdown-promo-{{ block.id }} .cp-unit{min-width:58px}
}
</style>
{%- if block.settings.ribbon_enable and block.settings.ribbon_text != blank -%}
<div class="cp-ribbon">{{ block.settings.ribbon_text }}</div>
{%- endif -%}
<div class="cp-inner">
{% if block.settings.title != blank %}
<h3 class="cp-title">
<span>{{ block.settings.title }}</span>
</h3>
{% endif %}
{% if block.settings.subtitle != blank %}
<p class="cp-subtitle">{{ block.settings.subtitle }}</p>
{% endif %}
{%- if block.settings.enable_timer -%}
<div class="cp-timer" role="timer" aria-live="polite"
data-days="{{ block.settings.init_days | default: 0 }}"
data-hours="{{ block.settings.init_hours | default: 0 }}"
data-mins="{{ block.settings.init_minutes | default: 0 }}"
data-secs="{{ block.settings.init_seconds | default: 0 }}">
<div class="cp-unit"><div class="cp-num" data-num="days">00</div><div class="cp-label">{{ block.settings.label_days | default: 'Days' }}</div></div>
<div class="cp-unit"><div class="cp-num" data-num="hours">00</div><div class="cp-label">{{ block.settings.label_hours | default: 'Hrs' }}</div></div>
<div class="cp-unit"><div class="cp-num" data-num="mins">00</div><div class="cp-label">{{ block.settings.label_minutes | default: 'Min.' }}</div></div>
<div class="cp-unit"><div class="cp-num" data-num="secs">00</div><div class="cp-label">{{ block.settings.label_seconds | default: 'Sec.' }}</div></div>
</div>
{%- endif -%}
{% if block.settings.coupon_text != blank %}
<div class="cp-coupon"
data-code="{{ block.settings.coupon_code | escape }}"
data-copied="{{ block.settings.coupon_copied | escape }}">
<span class="cp-text">{{ block.settings.coupon_text }}</span>
<span class="cp-scissors" aria-hidden="true">
<svg width="800px" height="800px" viewBox="0 0 24 24" id="scissors-2" data-name="Flat Line" xmlns="http://www.w3.org/2000/svg" class="icon flat-line"><path id="primary" d="M16.91,4.32c1.55-.68,3.29-.25,3.89,1S20.63,8,19.09,8.68s-3.29.25-3.89-1S15.37,5,16.91,4.32ZM3,16,19.09,8.68m-2.18,11c1.55.68,3.29.25,3.89-1s-.17-2.73-1.71-3.4-3.29-.25-3.89,1S15.37,19,16.91,19.68Zm2.18-4.36L3,8" style="fill: none; stroke: #000000; stroke-linecap: round; stroke-linejoin: round; stroke-width: 2;"></path></svg>
</span>
<span class="cp-copy-tip">{{ block.settings.coupon_copied }}</span>
</div>
{% endif %}
</div>
<script>
(function(){
const root = document.getElementById('countdown-promo-{{ block.id }}');
if(!root) return;
{% if block.settings.enable_timer %}
const t = root.querySelector('.cp-timer');
if (t){
const d = parseInt(t.dataset.days || '0',10),
h = parseInt(t.dataset.hours||'0',10),
m = parseInt(t.dataset.mins ||'0',10),
s = parseInt(t.dataset.secs ||'0',10);
const target = new Date(Date.now() + (((d*24 + h)*60 + m)*60 + s) * 1000);
const pad = n => (n<10?'0':'') + n;
function tick(){
let diff = Math.max(0, Math.floor((target - new Date())/1000));
const dd = Math.floor(diff/86400); diff -= dd*86400;
const hh = Math.floor(diff/3600); diff -= hh*3600;
const mm = Math.floor(diff/60); diff -= mm*60;
const ss = diff;
t.querySelector('[data-num="days"]').textContent = pad(dd);
t.querySelector('[data-num="hours"]').textContent = pad(hh);
t.querySelector('[data-num="mins"]').textContent = pad(mm);
t.querySelector('[data-num="secs"]').textContent = pad(ss);
}
tick();
const iv = setInterval(()=>{ tick();
if(t.querySelector('[data-num="days"]').textContent==='00' &&
t.querySelector('[data-num="hours"]').textContent==='00' &&
t.querySelector('[data-num="mins"]').textContent==='00' &&
t.querySelector('[data-num="secs"]').textContent==='00'){ clearInterval(iv); }
},1000);
}
{% endif %}
const coupon = root.querySelector('.cp-coupon');
if(coupon){
coupon.addEventListener('click', async ()=>{
const code = coupon.dataset.code || '';
try{ await navigator.clipboard.writeText(code); }catch(e){
const ta=document.createElement('textarea'); ta.value=code; document.body.appendChild(ta);
ta.select(); try{ document.execCommand('copy'); }catch(_){}
ta.remove();
}
coupon.classList.add('copied'); setTimeout(()=>coupon.classList.remove('copied'),2000);
}, {passive:true});
}
})();
</script>
</div>
shopify 主题 sections目录下,找到main-product.liquid文件,在 main-product.liquid 中有一段类似:
Liquid
{% for block in section.blocks %}
{% case block.type %}
...
{% endcase %}
{% endfor %}
在 case 里加入一条分支:
Liquid
{% when 'countdown_promo' %}
{% render 'countdown-promo-block', block: block %}
然后在同文件底部的 {% schema %} → “blocks”: [ … ] 数组中,新增一个 block 定义(可放在合适位置)。下面是完整可用的 block schema
Liquid
{
"type": "countdown_promo",
"name": "Countdown Promo",
"limit": 1,
"settings": [
{ "type": "checkbox", "id": "enable_timer", "label": "显示倒计时", "default": true },
{ "type": "header", "content": "Wrapper (背景/边框/间距)" },
{ "type": "color", "id": "wrap_bg", "label": "模块背景色", "default": "#ffffff" },
{ "type": "color", "id": "wrap_border_color", "label": "边框颜色", "default": "#111111" },
{ "type": "select", "id": "wrap_border_style", "label": "边框样式", "options": [
{ "value": "solid", "label": "solid" }, { "value": "dashed", "label": "dashed" }, { "value": "dotted", "label": "dotted" }
], "default": "solid" },
{ "type": "range", "id": "wrap_border_width", "min": 0, "max": 8, "step": 1, "unit": "px", "label": "边框宽度", "default": 1 },
{ "type": "range", "id": "wrap_radius", "min": 0, "max": 24, "step": 1, "unit": "px", "label": "圆角", "default": 10 },
{ "type": "range", "id": "wrap_padding_y", "min": 0, "max": 60, "step": 2, "unit": "px", "label": "上下内边距", "default": 20 },
{ "type": "range", "id": "wrap_padding_x", "min": 0, "max": 60, "step": 2, "unit": "px", "label": "左右内边距", "default": 20 },
{ "type": "range", "id": "wrap_margin_y", "min": 0, "max": 60, "step": 2, "unit": "px", "label": "上下外边距", "default": 10 },
{ "type": "range", "id": "wrap_margin_x", "min": 0, "max": 60, "step": 2, "unit": "px", "label": "左右外边距", "default": 0 },
{ "type": "header", "content": "标题/副标题" },
{ "type": "text", "id": "title", "label": "标题", "default": "🔥 Autumn Collection on Sale 🔥" },
{ "type": "font_picker", "id": "title_font", "label": "标题字体", "default": "roboto_n4" },
{ "type": "range", "id": "title_size", "min": 14, "max": 56, "step": 1, "unit": "px", "label": "标题字号", "default": 28 },
{ "type": "range", "id": "title_weight", "min": 100, "max": 900, "step": 50, "label": "标题粗细", "default": 700 },
{ "type": "color", "id": "title_color", "label": "标题颜色", "default": "#111111" },
{ "type": "text", "id": "subtitle", "label": "副标题", "default": "Innovative Comfort Technology ⏳" },
{ "type": "font_picker", "id": "subtitle_font", "label": "副标题字体", "default": "roboto_n4" },
{ "type": "range", "id": "subtitle_size", "min": 12, "max": 32, "step": 1, "unit": "px", "label": "副标题字号", "default": 16 },
{ "type": "range", "id": "subtitle_weight", "min": 100, "max": 900, "step": 50, "label": "副标题粗细", "default": 500 },
{ "type": "color", "id": "subtitle_color", "label": "副标题颜色", "default": "#333333" },
{ "type": "header", "content": "倒计时" },
{ "type": "range", "id": "init_days", "min": 0, "max": 30, "step": 1, "label": "天", "default": 0 },
{ "type": "range", "id": "init_hours", "min": 0, "max": 72, "step": 1, "label": "小时", "default": 7 },
{ "type": "range", "id": "init_minutes", "min": 0, "max": 59, "step": 1, "label": "分钟", "default": 2 },
{ "type": "range", "id": "init_seconds", "min": 0, "max": 59, "step": 1, "label": "秒钟", "default": 30 },
{ "type": "header", "content": "倒计时数字样式" },
{ "type": "font_picker", "id": "num_font", "label": "数字字体", "default": "roboto_n4" },
{ "type": "range", "id": "num_size", "min": 16, "max": 64, "step": 1, "unit": "px", "label": "数字字号", "default": 32 },
{ "type": "color", "id": "num_color", "label": "数字颜色", "default": "#ffffff" },
{ "type": "color", "id": "num_bg", "label": "数字背景色", "default": "#000000" },
{ "type": "header", "content": "时间单位标签" },
{ "type": "text", "id": "label_days", "label": "“天”标签文本", "default": "Days" },
{ "type": "text", "id": "label_hours", "label": "“小时”标签文本", "default": "Hrs" },
{ "type": "text", "id": "label_minutes", "label": "“分钟”标签文本", "default": "Min." },
{ "type": "text", "id": "label_seconds", "label": "“秒钟”标签文本", "default": "Sec." },
{ "type": "font_picker", "id": "label_font", "label": "标签字体", "default": "roboto_n4" },
{ "type": "range", "id": "label_size", "min": 10, "max": 24, "step": 1, "unit": "px", "label": "标签字号", "default": 12 },
{ "type": "range", "id": "label_weight", "min": 100, "max": 900, "step": 50, "label": "标签粗细", "default": 500 },
{ "type": "color", "id": "label_color", "label": "标签颜色", "default": "#333333" },
{ "type": "color", "id": "label_bg", "label": "标签背景色", "default": "#00000000" },
{ "type": "header", "content": "优惠券" },
{ "type": "text", "id": "coupon_text", "label": "优惠券展示文本", "default": "10% Off New Arrivals" },
{ "type": "text", "id": "coupon_code", "label": "点击复制的优惠码", "default": "FALL10" },
{ "type": "text", "id": "coupon_copied", "label": "复制成功提示", "default": "Code Copied!" },
{ "type": "font_picker", "id": "coupon_font", "label": "优惠券字体", "default": "roboto_n4" },
{ "type": "range", "id": "coupon_size", "min": 12, "max": 24, "step": 1, "unit": "px", "label": "优惠券字号", "default": 14 },
{ "type": "range", "id": "coupon_weight", "min": 100, "max": 900, "step": 50, "label": "优惠券粗细", "default": 600 },
{ "type": "color", "id": "coupon_bg", "label": "优惠券背景色", "default": "#ffffff" },
{ "type": "color", "id": "coupon_color", "label": "优惠券文字颜色", "default": "#111111" },
{ "type": "color", "id": "coupon_border_color", "label": "优惠券边框颜色", "default": "#111111" },
{ "type": "select", "id": "coupon_border_style", "label": "优惠券边框样式", "options": [
{ "value": "dashed", "label": "dashed" }, { "value": "solid", "label": "solid" }, { "value": "dotted", "label": "dotted" }
], "default": "dashed" },
{ "type": "range", "id": "coupon_border_width", "min": 0, "max": 6, "step": 1, "unit": "px", "label": "优惠券边框宽度", "default": 1 },
{ "type": "range", "id": "coupon_radius", "min": 0, "max": 20, "step": 1, "unit": "px", "label": "优惠券圆角", "default": 8 },
{ "type": "header", "content": "角标" },
{ "type": "checkbox", "id": "ribbon_enable", "label": "显示角标", "default": true },
{ "type": "text", "id": "ribbon_text", "label": "角标文字", "default": "SALE" },
{ "type": "select", "id": "ribbon_corner", "label": "角标位置", "options": [
{ "value": "right", "label": "右上角" }, { "value": "left", "label": "左上角" }
], "default": "right" },
{ "type": "color", "id": "ribbon_bg", "label": "角标背景色", "default": "#111111" },
{ "type": "color", "id": "ribbon_color", "label": "角标文字颜色", "default": "#ffffff" }
]
},


