Vizen Shop

Family cards on a category page

/docs/guide-family-cardscurrentМашинный перевод с английского· проверено 2026-10-25

Статус: current · проверенный: 2026-10-25, source обзор по компонентам и API контракты; нейтральный стиль обучения, а не live принятие владелец: гладиатр API документация · Служить: GET /docs/guide-family-cards связанный: /docs/authentication, /docs/components, /docs/own-markup, /docs/catalogue, /docs/chrome, /docs/troubleshooting

1. Результат и предпосылки

Вы замените один category's сетка запаса с двумя вставками одного многоразового использования Компонент: семья cards и а combo полоска. size Цветной чип переключает целое SKU панелями, включая картинку, запас, price и exact combo Цитата: Это link Также работает без JavaScript. Выберите это path когда card design должен быть твой; keep запас listing когда существует design достаточно.

Используйте key и руководство по разрешению before любой API работа. Вам нужен существующий category, product groups с size/colour Топоры, опубликованные members, и опубликованный combo sets. конфигурировать Доступ к списку покупателей для обоих selected attributes и group топоры first: Каталог § 8.3. Это каноническое section Также объясняет, effect фильтры; изменение доступа Просто для получения чипов может выставить filter, Поэтому проверьте result. Проверяйте каждый field Используется ниже /docs/vz-keys.json → scope before издатель.

Пример использует TOPLOFT коды bed_size и bed_color; Замените свой own Коды. document и product ids Ниже приведен пример, а не платформа. Решите и проверьте свои own ids. Нет. production Писать - это required то Прочитайте или адаптируйте этот учебник.

Найди его. ids с тем же самым key и contour:

  • GET /product-groups → result[].id, members и axes[].attribute_id.
  • GET /attributes → атрибут id и code. The shop исходит из key; company_id не является поддерживаемым селектором для этой конечной точки;.
  • GET /products?filter.category_id=<combo-category-id>&page.number=1&page.limit=48 → проверять kind:"combo" и select тот set product ids. filter.kind не поддерживается; при необходимости, пагинат.

The standard сетка block иметь payload.kind:"productListing". Замена его удаляет его встроенные фильтры, сортировка, пагинация UI и ItemList JSON-LD; смотреть Компоненты §4.7. Ан own-вставки разметки ограничиваются 48 selected ids / items или groups; использовать own разметка §2 для feed контракт.

2.Подготовить два компонента files

создавать index.html и component.json в той же папке компонентов. Опубликовать как бы level-1 компонент через Компоненты §4.1. Полное HTML следовать. CSS Он является локальным, локальным для fc- классы, и держит нейтральные цвета. tl-section class принадлежит к TOPLOFT theme; адаптировать Как описано в §4, нет custom script или клиент-side price расчет.

index.html:

<style>
.fc-catalog,.fc-combos{color:inherit;font:inherit}
.fc-catalog *,.fc-combos *{box-sizing:border-box}
.fc-catalog a,.fc-combos a{color:inherit;text-decoration:none}
.fc-catalog a:focus-visible,.fc-combos a:focus-visible{outline:2px solid currentColor;outline-offset:3px}
.fc-grid,.fc-combo-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:24px}
.fc-card,.fc-combo-card{min-width:0;border:1px solid #ddd;border-radius:12px;overflow:hidden}
.fc-media{position:relative;background:#f5f5f5}
.fc-image,.fc-combo-picture{display:block}
.fc-image img{display:block;width:100%;height:auto;aspect-ratio:4/3;object-fit:cover}
.fc-photo-title,.fc-body,.fc-combo-body{padding:16px}
.fc-photo-title h3,.fc-combo-name{margin:0 0 8px}
.fc-detail{margin:0}
.fc-promo,.fc-stock{display:inline-block;margin:0 0 12px 16px;padding:4px 8px;background:#eee;border-radius:4px}
.fc-combo-tag{display:block;margin:0 16px 12px;padding:10px;border:1px solid currentColor;border-radius:4px}
.fc-combo-heading{display:block}
.fc-combo-regular,.fc-old{margin-left:8px;color:#666}
.fc-controls,.fc-axis{margin-bottom:12px}
.fc-sizes,.fc-colors,.fc-prices{display:flex;flex-wrap:wrap;gap:8px;align-items:center}
.fc-size,.fc-color{display:inline-flex;align-items:center;justify-content:center;gap:4px;border:1px solid #bbb;border-radius:4px}
.fc-size{min-height:38px;padding:6px 10px}
.fc-color{width:42px;height:42px}
.fc-color img{display:block;width:38px;height:38px;object-fit:cover;border-radius:3px}
.fc-size[aria-current="true"],.fc-color[aria-current="true"]{outline:2px solid currentColor;outline-offset:1px}
.fc-size[aria-disabled="true"],.fc-color[aria-disabled="true"]{opacity:.4}
.fc-combo-dot{width:6px;height:6px;background:currentColor;border-radius:50%}
.fc-price,.fc-combo-total b{font-size:1.2em}
.fc-combo-price{text-decoration:underline!important}
.fc-combos{margin-top:32px}
.fc-combos-heading{display:flex;flex-wrap:wrap;justify-content:space-between;align-items:center;gap:16px}
.fc-combo-picture img{display:block;width:100%;height:auto;aspect-ratio:1;object-fit:cover}
.fc-combo-eyebrow{font-size:.8em}
.fc-combo-total{margin:12px 0}
.fc-combo-items{display:grid;gap:10px}
.fc-combo-item{display:flex;align-items:center;gap:10px}
.fc-combo-item img{width:44px;height:44px;object-fit:cover;flex:none}
.fc-combo-item-copy,.fc-combo-item-name{display:block;min-width:0}
.fc-combo-item-name{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.fc-combo-cta{display:inline-block;margin-top:16px;text-decoration:underline!important}
@media(max-width:767px){.fc-grid,.fc-combo-grid{grid-template-columns:1fr}.fc-combo-item img{width:32px;height:32px}}
</style>
{{#show_catalog}}
<section class="tl-section fc-catalog" aria-label="{{ catalog_label }}">
  <div class="fc-grid">
    <article class="fc-card" vz-for="p in products" vz-panes>
      <div vz-for="m in p.members" vz-pane="{{ m.id }}" vz-hidden="!m.selected">
        <div class="fc-media">
          <a class="fc-image" vz-href="m.url" aria-label="{{ m.name }}">
            <img vz-src="m.preview" srcset="{{ m.preview_srcset }}" sizes="(max-width: 767px) calc(100vw - 32px), calc(50vw - 62px)" alt="{{ m.name }}" width="1024" height="768" decoding="async" loading="lazy">
          </a>
          <div class="fc-photo-title">
            <h3><a vz-href="m.url" title="{{ m.name }}"><span vz-if="p.group">{{ p.group.name }}</span><span vz-if="!p.group">{{ m.name }}</span></a></h3>
            <p class="fc-detail"><span vz-if="m.attrs.bed_size">{{ m.attrs.bed_size.value }}</span><span vz-if="m.attrs.bed_color"> · {{ m.attrs.bed_color.value }}</span></p>
          </div>
          <span class="fc-promo" vz-if="m.combo" aria-hidden="true">%</span>
          <a class="fc-combo-tag" vz-if="m.combo" vz-href="m.combo.url" aria-label="{{ m.combo.name }}">
            <span class="fc-combo-heading">В комбо выгоднее</span>
            <span class="fc-combo-tag-price"><b class="fc-combo-item-price">{{ m.combo.item_price_text }}</b><s class="fc-combo-regular">{{ m.combo.item_regular_price_text }}</s></span>
          </a>
          <span class="fc-stock" vz-if="m.in_stock">В наличии</span>
          <span class="fc-stock fc-stock-off" vz-if="!m.in_stock">Под заказ</span>
        </div>
        <div class="fc-body">
          <div class="fc-controls">
            <div class="fc-axis" vz-for="ax in m.variants">
              <div vz-if="ax.options.1">
                <div class="fc-sizes" vz-if="!ax.options.0.image_url" role="group" aria-label="{{ ax.name }}">
                  <span vz-for="o in ax.options" class="fc-opt">
                    <a class="fc-size" vz-if="o.available" vz-href="o.url" vz-pick="{{ o.member_id }}" aria-current="{{ o.current }}"><span>{{ o.label }}</span><span class="fc-combo-dot" vz-if="o.has_combo" aria-hidden="true"></span></a>
                    <span class="fc-size" vz-if="!o.available" aria-disabled="true">{{ o.label }}</span>
                  </span>
                </div>
                <div class="fc-colors" vz-if="ax.options.0.image_url" role="group" aria-label="{{ ax.name }}">
                  <span vz-for="o in ax.options" class="fc-opt">
                    <a class="fc-color" vz-if="o.available" vz-href="o.url" vz-pick="{{ o.member_id }}" aria-current="{{ o.current }}" title="{{ o.label }}" aria-label="{{ o.label }}"><img vz-src="o.image_thumb" srcset="{{ o.image_srcset }}" sizes="38px" alt="" width="38" height="38" loading="lazy"></a>
                    <span class="fc-color" vz-if="!o.available" aria-disabled="true" title="{{ o.label }}"><img vz-src="o.image_thumb" srcset="{{ o.image_srcset }}" sizes="38px" alt="" width="38" height="38" loading="lazy"></span>
                  </span>
                </div>
              </div>
            </div>
          </div>
          <div class="fc-prices">
            <b class="fc-price">{{ m.price_text }}</b>
            <a class="fc-combo-price" vz-if="m.combo" vz-href="m.combo.url" title="Цена этой модели в комбо-наборе"><span class="fc-price-fire" aria-hidden="true">🔥</span><span>{{ m.combo.item_price_text }}</span></a>
            <s class="fc-old" vz-if="m.old_price_text">{{ m.old_price_text }}</s>
          </div>
        </div>
      </div>
    </article>
  </div>
</section>
{{/show_catalog}}
{{#show_combos}}
<section class="fc-combos" aria-label="{{ combo_heading }}">
  <div class="tl-section fc-combos-inner">
    <div class="fc-combos-heading"><h2>{{ combo_heading }}</h2><a href="{{ combo_all_url }}">Все наборы ↗</a></div>
    <div class="fc-combo-grid">
      <article class="fc-combo-card" vz-for="c in products">
        <a class="fc-combo-picture" vz-href="c.url" aria-label="{{ c.name }}"><img vz-src="c.preview" srcset="{{ c.preview_srcset }}" sizes="(max-width: 767px) calc(100vw - 32px), calc(50vw - 62px)" alt="{{ c.name }}" width="640" height="640" loading="lazy"></a>
        <div class="fc-combo-body">
          <span class="fc-combo-eyebrow">КОМБО-НАБОР</span>
          <h3 class="fc-combo-name" title="{{ c.name }}">{{ c.name }}</h3>
          <div class="fc-combo-total"><b>{{ c.price_text }}</b><s vz-if="c.old_price_text">{{ c.old_price_text }}</s></div>
          <div class="fc-combo-items">
            <a class="fc-combo-item" vz-for="it in c.combo_items" vz-href="it.url">
              <img vz-src="it.preview_url" srcset="{{ it.preview_srcset }}" sizes="(max-width: 767px) 32px, 44px" alt="" width="44" height="44" loading="lazy">
              <span class="fc-combo-item-copy"><span class="fc-combo-item-name" title="{{ it.name }}">{{ it.name }}</span><small>{{ it.price_text }} <s vz-if="it.regular_price_text">{{ it.regular_price_text }}</s></small></span>
            </a>
          </div>
          <a class="fc-combo-cta" vz-href="c.url">Показать комбо ↗</a>
        </div>
      </article>
    </div>
  </div>
</section>
{{/show_combos}}

component.json:

{
  "name": "Family cards and combo sets",
  "params": [
    {"key": "show_catalog", "type": "bool", "label": "Показывать модели", "default": true},
    {"key": "show_combos", "type": "bool", "label": "Показывать комбо", "default": false},
    {"key": "catalog_label", "type": "text", "label": "Название области каталога", "default": "Товары", "max": 100},
    {"key": "combo_heading", "type": "text", "label": "Заголовок комбо", "default": "Комбо-наборы", "max": 100},
    {"key": "combo_all_url", "type": "link", "label": "Все наборы", "default": "/catalog/combo"}
  ]
}

3. Настройка двух вставок

Следуй за мной. Канонический рабочий процесс замены компонентов §4.8 для API последовательность вызовов, snapshot, usage проверка, validation, активация и Откат.Два JSON кузова, расположенные ниже, снабжают вставку content для этого рабочий процесс; не связывайте их before Пропускной пункт. component.ref с Ваш опубликованный document id. Один и тот же компонент повторно используется для обеих вставок..

Семейная вставка, с явным order представитель products. productsIds содержит Один член семьи: Этот член является default selected SKU, и id order Это семья order (Каталог 4.1.).

{
  "item": {
    "name": "Category families",
    "sections": [{"type": "text", "payload": {
      "v": 2, "kind": "component",
      "props": {
        "blockWidth": "full",
        "paddingSides": {"top": 0, "right": 0, "bottom": 0, "left": 0},
        "component": {
          "ref": 189,
          "params": {"show_catalog": true, "show_combos": false, "catalog_label": "Кровати"},
          "productsMode": "collapse",
          "productsAttributes": ["bed_size", "bed_color"],
          "productsIds": [2503, 2509, 2498]
        }
      }
    }}]
  }
}

Комбо вставка, выбор set ids и явно отключать каталог:

{
  "item": {
    "name": "Category combo sets",
    "sections": [{"type": "text", "payload": {
      "v": 2, "kind": "component",
      "props": {
        "blockWidth": "full",
        "paddingSides": {"top": 0, "right": 0, "bottom": 0, "left": 0},
        "component": {
          "ref": 189,
          "params": {
            "show_catalog": false, "show_combos": true,
            "combo_heading": "Комбо-наборы", "combo_all_url": "/catalog/combo"
          },
          "productsIds": [2806, 2807]
        }
      }
    }}]
  }
}

Омить productsIds и использовать productsCategoryId Когда вы хотите, чтобы category feed Вместо выбора. Feed границы, упорядоченный отбор, группирование и limits Канонический в own разметка §2. productsAttributes При этом каждый из них имеет свой: другой. category может повторно использовать этот компонент с own Список атрибутов. template Если нужны разные коды. Недавно опубликованный член существующего selected Семья подхватывается без редактировать HTML; недавно selected семья или set требует изменения его вставки выбор.

4. Соединяйтесь с theme

Следуйте за мной. chrome §3.7 Чтобы обнаружить active theme и его content-container class. Читать GET /themes/{id}/site → active_release_id и files[].path, затем GET /themes/{id}/site/releases/{rid}/file?path=<css-path> → text. Используйте path Возвращаясь к этому освобождению, URL-закодированный в query; Если нет, то нет active Освобождение, нет theme-папка CSS повторно использовать. TOPLOFT это class это tl-section, Используется в обоих content В корнях выше. theme, Заменить его на найденный class. Держите вставку wrapper settings из §3 и уходить contentWidth Отключи, давай. theme own container width и водостоки Один раз, не добавляйте второй корень max-width горизонтальный padding компенсировать. перепроверять image sizes против полученного columns и фактические width (image правила). местный CSS cannot Изменить размер платформы's внешний wrapper.

5.Проверить before принятие

Используйте активацию и проверку считывания из компонентов §4.8, а затем проверьте page как Устранение неполадок §2 описание:

  • Без JavaScript, Начальный элемент виден, другие панели видны. hidden, Ссылки открываются правильным членом page.
  • меняться size Сохраняет цвет, когда существует комбинация. комбинация отключена; реальный неучтенный член остается выбираемым.
  • Изображение, атрибут text, price, акции, ссылки и combo Изменение цитаты вместе. The small Точка описывает o.has_combo, когда лента и цитата используют selected член's m.combo; Их контракт заключается own разметка §2.
  • Текстовые чипы и image Чипы идентифицируют current Измененный клик последующий link; член без рендеринга все еще открывает свою page.
  • The combo Вставка показывает только sets, цены на сервер и состав. Запросы на миниатюру совпадают display size и DPR; Не сломанный image source появляется.
  • Оба sections line Вместе с существующим banner на рабочем столе и mobile ширина. Иной category Оставаться неизменным, выглядеть неизменным.
  • Публикация другого члена selected Семья обновляет свои доступные choices без HTML Редактирование. Повторение обновлений рабочего процесса существующих вставок Вместо того, чтобы дублировать сетку.

Этот пример скрывает топоры с менее чем двумя options и выбирает image-чип отсчет от указанного first вариант's image_url. Если ваша ось использует смешанные image

  • покрытие, адаптируйте эту презентацию к вашему data Вместо того, чтобы принимать все

опция имеет текстуру. Не добавляйте клиент-side SKU Математика замещения или котировки.

6. Откатиться назад и поставить диагноз

Восстановить спасенное group Если же он изменяется, то сохраняется откат Шаг компонентов §4.8. Перечитывать и проверять page. Выпуск компонентов Откат отката отдельная: восстановление group Ссылки не восстанавливают общий компонент's Сохрани старое. blocks и снимки во время приема.

Если plain Появляются плитки, first проверка вставки mode и доступ покупателя к топорам; Если цитата отсутствует, проверьте члена's Фактический прибыль combo Вместо того, чтобы принуждение badge. Использовать устранение неполадок и канонический field ссылка /docs/vz-keys.json для дальнейшей диагностики.

Ссылки на документы используют heading Фрагменты на сайте: например, /docs/components#4-8-replace-a-category-s-stock-grid-through-a-pat-with-rollback. Для сырых API section использовать GET /docs/components?section=4-8-replace-a-category-s-stock-grid-through-a-pat-with-rollback. Точка внутри 4.8 становится дефисом (4-8, не 48). Фрагмент перемещается по выполненный page; не является select а section в HTTP запросить у API.

7.Безмолвно ignored

Неизвестные или невидимые коды атрибутов не создают атрибутов. values; охрана optional data с vz-if. Подробный feed и ignored-Правила, устанавливающие правила, должны то own разметка §§2,8, и правил параметра компонентов для компоненты. Успешное письмо само по себе не доказывает, что предназначенный feed или замена является active: выполнять read-back и браузер Проверки выше.

Исходник: https://api.vizen.shop/docs/guide-family-cards?full=1

Работает в демо-режиме