Horizon 徽章、评分与订阅表单:内置能力与缺口
本文基于 Horizon 4.2.0,源码固定到 5acd1b6(核验于 2026-10-07)。结论限于此提交,不表示其他版本行为相同;本篇为静态源码分析,未完成店铺运行验证。Dawn 上游已发布 v16.0.0(2026-08-10,GitHub Releases 核对),本库 Dawn 正文统一以 v15.3.0 为基线,升级前需重新核对;本库 Horizon 正文统一以 4.2.0 为基线(固定提交中 config/settings_schema.json 的 theme_version 为 4.2.0)。
对应哪些通用模式
覆盖 Badge、Countdown Timer、Table 与模块 评价展示、订阅获取、尺码与适配指引。这六项里,徽章、评分星标和邮件订阅有内置实现;倒计时、尺码表、评论列表、弹窗订阅在此提交中没有。本篇的主要价值是哪些内置、哪些没有,以及内置部分与通用页面的差距。
入口与文件
| 能力 | 固定提交中的结论 | 文件 |
|---|---|---|
| 商品卡“售罄”“Sale”徽章 | 内置:商品级,一次只显示一个 | _product-card-gallery.liquid、card-gallery.liquid、product-badges-styles.liquid |
| 热点里的 “Sold out” | 内置 | _hotspot-product.liquid |
| 评分星标 | 内置块 review,只读评分 metafield | review.liquid |
| 邮件订阅 | 内置块 email-signup | email-signup.liquid,用于 footer.liquid 预设与 password.json |
| 表格 | 只有富文本表格的包装与样式,无表格组件 | rte-formatter.js、base.css |
| 尺码表、倒计时、评论列表、弹窗订阅、新品与畅销标签 | 未找到(见下) | — |
未内置结论的依据(均为在固定提交全仓库含 sections、snippets、blocks、assets、templates、locales、config 的搜索,未找到不等于平台不能做):
- 倒计时:搜索
countdown、count.down、time left、ends in、hurry、deadline、ends_at、flash.?sale无命中;\btimer\b只出现在product-hotspot.js(悬停延迟)。 - 尺码表:搜索
size.?chart、size.?guide、sizing chart、size_chart、fit.?guide、measurement只命中无关的测量代码。 - 评论列表、分布、筛选:搜索单词
rating、review(s)、star(s),除review.liquid与相关 schema 外无实现;metafields.只有reviews.rating、reviews.rating_count、shopify.disclosure;aggregateRating无命中。 - 新品、畅销、预售、百分比折扣:搜索
best.?seller、preorder、coming soon、percent、save_、savings、compare_at_price_varies只命中演示文案与无关的宽度设置。 - 弹窗订阅与同意:搜索
consent、accepts_marketing、contact[tags]、privacy、klaviyo、exit.?intent无命中;localStorage只用于最近浏览。
数据从哪来
徽章:product.available == false 显示 “Sold out”(content.product_badge_sold_out),否则 product.compare_at_price > product.price 显示 “Sale”,均取商品级字段;全局“徽章”设置有 badge_position、badge_corner_radius、badge_sale_*、badge_sold_out_* 颜色、badge_font_family、badge_text_transform。商品页没有徽章:售罄体现在 buy-buttons.liquid 的按钮文案(“Sold out” 或 “Unavailable”)和 product-inventory 块的库存状态(阈值 inventory_threshold)。价格行由 price.liquid 按所选变体的 price 与 compare_at_price 输出,并带视觉隐藏的 “Regular price” 与 “Sale price”。
评分:review.liquid 取 closest.product.metafields.reviews.rating.value.rating、.scale_max 与 metafields.reviews.rating_count,块内提示写明需要应用提供评分。设置有 stars_style(outline、shaded、single)、show_number。在 templates、config 与各 Section 预设中,只有 featured-product-information 的预设放了它,默认商品模板与商品卡都不显示星标。
订阅:email-signup.liquid 用 form 'customer',可见字段只有 contact[email];文案来自 blocks.email_signup.*,结果来自 form.posted_successfully? 与 form.errors。
交互怎样运行
徽章与评分是纯服务端输出,无脚本。订阅是普通表单提交,assets 中没有订阅相关脚本;成功与错误在重载后的页面里渲染。富文本里的表格由 rte-formatter 在 page-content、文章正文与 text 块(rte 或 paragraph 预设)中包一层 div.rte-table-wrapper(overflow-x: auto)。
与通用契约的一致与差距
Badge
- 一致:徽章是真实文本;“Sold out” 只在
product.available == false时出现,与 Badge 页“部分变体不可售不得写成整体售罄”一致;每张卡最多一个,售罄优先于折扣;文字色未设置时由contrast-override优先用页面文字色,对比不足才取调色板极值。 - 差距:
- 只有 “Sale”,没有百分比,也不判断
compare_at_price_varies;折扣码与自动折扣不触发它。 - 徽章取商品级
compare_at_price与price,价格行取所选变体价格,多变体商品上两者可能不一致(推断,未核验)。 - 商家设置了
badge_sale_text_color或badge_sold_out_text_color后,智能对比被跳过,不再保证对比度。 - 没有新品时间窗、Best seller 口径、自定义标签或商品页徽章,这些需在其他位置自行实现并保存规则。
- 徽章在 DOM 中紧跟卡片图片,通常先于后面的商品名块,读屏可能先读 “Sold out”(推断)。
- 只有 “Sale”,没有百分比,也不判断
评分(评价展示)
- 一致:数值取自运行时 metafield;没有评分时整块不输出,不显示占位星星。
- 差距:
- 只显示星星与数量,没有评论列表、分布、筛选、商家回复、写评价入口,也无“暂无评价”文案;评论区需要
@app块(商品详情块允许应用块)。 div.rating只有aria-label而无role,文案取翻译键accessibility.rating,但各语言文案都把满分写成 5(英文 “out of 5”、中文 “/5”),而星星数量取scale_max;读屏是否读出该标签未核验。- 星标不链接到评价区;
structured_data过滤器输出的 JSON-LD 是否含评分未核验。
- 只显示星星与数量,没有评论列表、分布、筛选、商家回复、写评价入口,也无“暂无评价”文案;评论区需要
订阅(订阅获取)
- 一致:无 JavaScript 也能提交;输入有视觉隐藏但真实的
label、type="email"、required、autocomplete;出错时输入带aria-invalid、aria-describedby并autofocus;图标按钮有aria-label;成功文案说明已订阅。 - 差距:
- 没有同意文案、隐私链接、预勾选或勾选项、短信、折扣兑现、发送频率与退订说明,均需商家在相邻文本块中自行补足。
- 没有弹窗、触发规则、频次上限或关闭记忆,也没有“已订阅”状态;页面与模块要求的这些运行时规则不在主题里。
- 成功提示
tabindex="-1"但无role="status"或焦点移动,重载后是否被读出未核验。 - 没有像联系表单那样带
contact[id];同页放置多个订阅块(例如页脚加正文)时,结果是否只出现在被提交的那个未核验。
倒计时与尺码表:主题未内置,因此倒计时的同源时间、不重置、减少动态等要求,以及尺码表的单位、口径与适配推荐,都完全由商家用 custom-liquid 或 @app 块实现。可用的通用块是 popup-link(原生 dialog,可作模态或抽屉)加 page 块(输出页面标题与 .rte 内容);按 schema,商品详情块允许 @theme 块,此组合应可用,但未在编辑器验证。
Table:富文本表格被包进可横向滚动的容器,符合“外层容器承担滚动”的做法;差距是该 div 没有 tabindex 或名称,键盘用户无法滚动,caption、scope 完全取决于商家输入的 HTML;table { width: 100% !important } 会覆盖内联宽度;表头以 thead 或无 td 的行加粗大写,与内容语义无关。购物车用了带 caption 与 th scope 的语义表格,但只服务购物车。
定制入口与风险
商家可改全局“徽章”设置、review 块的 stars_style、show_number,email-signup 的标题、按钮文字与样式设置。开发者要加百分比或新品标签,需要同时改 _product-card-gallery.liquid 与 card-gallery.liquid(后者用同一条件决定 card-gallery--badge-* 布局类);改 review.liquid 的 metafield 键会与评价应用的写入约定耦合。
建议的验证范围
本篇未执行。用全变体售罄、部分变体售罄、有对比价的商品各看一次商品卡与价格行;用有评分与无评分的商品测星标;提交空邮箱、错误邮箱与正确邮箱,核对焦点与读屏结果,并在同页放两个订阅块测试结果归属;在富文本中放一张宽表,用键盘测试能否滚动。