下拉菜单没有数据,不知道是啥情况。元字段的id没有输错,但是用下面的调试代码,调试值为null;(代码是用的DS V3写的,提示词用的基本和up160视频一样)
<!-- 在Liquid中检查元字段原始值 -->
{% assign test_product = collections.all.products.first %}
Make: {{ test_product.metafields.custom.car_make | json }}
Model: {{ test_product.metafields.custom.car_model | json }}
Year: {{ test_product.metafields.custom.specifications | json }}
Js部分是这样的
<script>
document.addEventListener('DOMContentLoaded', function() {
// 获取所有产品数据(严格按您提供的元字段类型)
const allProducts = [];
{% for product in collections.all.products %}
allProducts.push({
id: {{ product.id | json }},
title: {{ product.title | json }},
// 严格按元字段类型处理:
make: {{ product.metafields.custom.car_make | json }} || null, // 单行文本
model: {{ product.metafields.custom.car_model | json }} || null, // 单行文本
year: {% if product.metafields.custom.specifications %}
{{ product.metafields.custom.specifications | times: 1 | json }} // 强制转为整数
{% else %}
null
{% endif %}
});
{% endfor %}
// 构建筛选缓存(严格区分文本和数字类型)
const filterCache = {
// 品牌列表(单行文本)
makes: [...new Set(allProducts
.map(p => p.make)
.filter(m => typeof m === 'string' && m.trim() !== ''))].sort(),
// 车型字典 {make: [model1, model2]}
models: allProducts.reduce((acc, product) => {
if (typeof product.make === 'string' &&
typeof product.model === 'string' &&
product.make.trim() !== '' &&
product.model.trim() !== '') {
acc[product.make] = [...new Set([...(acc[product.make] || []), product.model])];
}
return acc;
}, {}),
// 年份字典 {make|model: [year1, year2]}(整数)
years: allProducts.reduce((acc, product) => {
if (typeof product.make === 'string' &&
typeof product.model === 'string' &&
Number.isInteger(product.year) &&
product.make.trim() !== '' &&
product.model.trim() !== '') {
const key = `${product.make}|${product.model}`;
acc[key] = [...new Set([...(acc[key] || []), product.year])]
.sort((a, b) => b - a); // 年份降序
}
return acc;
}, {})
};
// DOM元素
const makeFilter = document.getElementById('make-filter');
const modelFilter = document.getElementById('model-filter');
const yearFilter = document.getElementById('year-filter');
const searchButton = document.getElementById('search-button');
const resultsContainer = document.getElementById('search-results');
// 品牌选择变化时
makeFilter.addEventListener('change', function() {
const make = this.value;
// 重置下级筛选器
modelFilter.innerHTML = '<option value="">All Models</option>';
yearFilter.innerHTML = '<option value="">All Years</option>';
yearFilter.disabled = true;
searchButton.disabled = true;
if (make) {
// 动态填充车型选项(单行文本)
const models = filterCache.models[make] || [];
models.forEach(model => {
const option = new Option(model, model);
modelFilter.add(option);
});
modelFilter.disabled = models.length === 0;
} else {
modelFilter.disabled = true;
}
});
// 车型选择变化时
modelFilter.addEventListener('change', function() {
const make = makeFilter.value;
const model = this.value;
// 重置年份选择器
yearFilter.innerHTML = '<option value="">All Years</option>';
searchButton.disabled = true;
if (make && model) {
// 动态填充年份选项(整数)
const years = filterCache.years[`${make}|${model}`] || [];
years.forEach(year => {
const option = new Option(year, year);
yearFilter.add(option);
});
yearFilter.disabled = years.length === 0;
} else {
yearFilter.disabled = true;
}
});
// 执行搜索(严格类型比较)
searchButton.addEventListener('click', function() {
const make = makeFilter.value;
const model = modelFilter.value;
const year = yearFilter.value;
const results = allProducts.filter(product => {
const makeMatch = !make || product.make === make;
const modelMatch = !model || product.model === model;
// 年份比较:输入是字符串,元字段是整数,需转换类型
const yearMatch = !year || product.year === parseInt(year, 10);
return makeMatch && modelMatch && yearMatch;
});
renderResults(results);
});
// 渲染结果函数(类型安全显示)
function renderResults(products) {
resultsContainer.innerHTML = '';
if (!products.length) {
resultsContainer.innerHTML = '<p class="no-results">No matching products found</p>';
return;
}
products.forEach(product => {
const card = document.createElement('div');
card.className = 'product-card';
card.innerHTML = `
<a href="/products/${product.handle}">
<h3>${product.title}</h3>
<div class="product-meta">
${product.make ? `<span>Make: ${product.make}</span>` : ''}
${product.model ? `<span>Model: ${product.model}</span>` : ''}
${product.year ? `<span>Year: ${product.year}</span>` : ''}
</div>
</a>
`;
resultsContainer.appendChild(card);
});
}
});
</script>
Liquid部分
<!-- 在 sections/multi-level-search.liquid 中 -->
<div class="multi-level-search">
<div class="search-filters">
<!-- 第一级:品牌选择 (Make) -->
<div class="filter-group">
<label for="make-filter">Make</label>
<select id="make-filter" class="filter-select">
<option value="">All Makes</option>
{% comment %} 动态生成品牌选项(单行文本类型){% endcomment %}
{% assign all_makes = "" | split: "," %}
{% for product in collections.all.products %}
{% assign make = product.metafields.custom.car_make | strip | default: "" %}
{% if make != "" %}
{% assign all_makes = all_makes | push: make %}
{% endif %}
{% endfor %}
{% assign unique_makes = all_makes | uniq | sort %}
{% for make in unique_makes %}
<option value="{{ make | escape }}">{{ make }}</option>
{% endfor %}
</select>
</div>
<!-- 第二级:车型选择 (Model) -->
<div class="filter-group">
<label for="model-filter">Model</label>
<select id="model-filter" class="filter-select" disabled>
<option value="">Select Make First</option>
</select>
</div>
<!-- 第三级:年份选择 (Year) -->
<div class="filter-group">
<label for="year-filter">Year</label>
<select id="year-filter" class="filter-select" disabled>
<option value="">Select Model First</option>
</select>
</div>
<button id="search-button" class="search-btn" disabled>Search</button>
</div>
<div id="search-results" class="search-results-grid"></div>
</div>
元字段里是有值的