Fix AI search: use window.D instead of bare D references
Browse files- ai-search-fix.js +48 -16
ai-search-fix.js
CHANGED
|
@@ -8,6 +8,8 @@
|
|
| 8 |
* properly loaded and contains full NL search logic.
|
| 9 |
*
|
| 10 |
* Additional fix: Handle multi-product search (comma/semicolon separated codes).
|
|
|
|
|
|
|
| 11 |
*/
|
| 12 |
|
| 13 |
window.doAISearch = function() {
|
|
@@ -25,23 +27,34 @@ window.doAISearch = function() {
|
|
| 25 |
resultsDiv.style.display = 'block';
|
| 26 |
resultsDiv.innerHTML = '⏳ Đang tìm...';
|
| 27 |
|
|
|
|
|
|
|
|
|
|
| 28 |
// Multi-product search: if query contains comma/semicolon, search by product codes
|
| 29 |
var queries = query.split(/[,;]+/).map(function(c) { return c.trim(); }).filter(function(c) { return c.length >= 2; });
|
| 30 |
|
| 31 |
-
|
|
|
|
|
|
|
| 32 |
// Multi-code search mode
|
| 33 |
var allResults = [];
|
| 34 |
-
var
|
| 35 |
|
| 36 |
queries.forEach(function(q) {
|
| 37 |
-
var qNorm =
|
| 38 |
for (var i = 0; i < D.length && allResults.length < 30; i++) {
|
| 39 |
var p = D[i];
|
| 40 |
if (!p) continue;
|
| 41 |
-
var
|
| 42 |
-
|
| 43 |
-
|
| 44 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 45 |
allResults.push(p);
|
| 46 |
}
|
| 47 |
}
|
|
@@ -53,7 +66,7 @@ window.doAISearch = function() {
|
|
| 53 |
}
|
| 54 |
}
|
| 55 |
|
| 56 |
-
if (typeof window.aiSearch === 'function' &&
|
| 57 |
var aiToken = (window.huggingface && window.huggingface.variables && window.huggingface.variables.VAISTUDIO) || '';
|
| 58 |
window.aiSearch(query, D, aiToken).then(function(aiResult) {
|
| 59 |
if (!aiResult || (!aiResult.results.length && !aiResult.aiAnswer)) {
|
|
@@ -184,8 +197,9 @@ function _renderAIResultsToDiv(aiResult, container, query) {
|
|
| 184 |
}
|
| 185 |
|
| 186 |
function _fallbackAISearch(query, container) {
|
| 187 |
-
|
| 188 |
-
|
|
|
|
| 189 |
return;
|
| 190 |
}
|
| 191 |
var qNorm = query.toLowerCase().normalize('NFD').replace(/[̀-ͯ]/g, '').replace(/đ/g, 'd');
|
|
@@ -195,22 +209,40 @@ function _fallbackAISearch(query, container) {
|
|
| 195 |
if (!p) continue;
|
| 196 |
var nameNorm = (p.name || '').toLowerCase().normalize('NFD').replace(/[̀-ͯ]/g, '').replace(/đ/g, 'd');
|
| 197 |
var skuNorm = (p.sku || p.mod || '').toLowerCase();
|
| 198 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 199 |
results.push(p);
|
| 200 |
}
|
| 201 |
}
|
| 202 |
if (!results.length) {
|
| 203 |
-
container.innerHTML = '❌ Không tìm thấy "' + query + '". Thử: "bếp từ", "máy hút mùi"';
|
| 204 |
return;
|
| 205 |
}
|
| 206 |
container.innerHTML = '<div style="font-size:.78rem;color:#64748b;margin-bottom:10px"><strong>' + results.length + '</strong> kết quả</div>' +
|
| 207 |
'<div style="display:grid;grid-template-columns:repeat(auto-fill,minmax(180px,1fr));gap:12px">' +
|
| 208 |
-
results.map(function(p
|
|
|
|
|
|
|
| 209 |
var imgSrc = p.image || p.i || '';
|
| 210 |
var priceStr = p.price || (p.pn ? p.pn : 'Liên hệ');
|
| 211 |
return '<div class="pc fade" onclick="showDetail(' + idx + ')" style="cursor:pointer">' +
|
| 212 |
-
'<div class="pi" style="height:150px"><img src="' + imgSrc + '" alt="' + p.name + '" loading="lazy"></div>' +
|
| 213 |
-
'<div class="pb" style="padding:10px"><div
|
|
|
|
| 214 |
'<div class="pf" style="margin-top:6px"><span class="pp" style="font-size:.92rem">' + priceStr + '</span></div></div></div>';
|
| 215 |
}).join('') + '</div>';
|
| 216 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 8 |
* properly loaded and contains full NL search logic.
|
| 9 |
*
|
| 10 |
* Additional fix: Handle multi-product search (comma/semicolon separated codes).
|
| 11 |
+
* Critical fix: All references to D must use window.D since let D in index.html
|
| 12 |
+
* does NOT create a global property on window object.
|
| 13 |
*/
|
| 14 |
|
| 15 |
window.doAISearch = function() {
|
|
|
|
| 27 |
resultsDiv.style.display = 'block';
|
| 28 |
resultsDiv.innerHTML = '⏳ Đang tìm...';
|
| 29 |
|
| 30 |
+
// Wait for data to be ready
|
| 31 |
+
function getD() { return (typeof window.D !== 'undefined' && window.D.length > 0) ? window.D : null; }
|
| 32 |
+
|
| 33 |
// Multi-product search: if query contains comma/semicolon, search by product codes
|
| 34 |
var queries = query.split(/[,;]+/).map(function(c) { return c.trim(); }).filter(function(c) { return c.length >= 2; });
|
| 35 |
|
| 36 |
+
var D = getD();
|
| 37 |
+
|
| 38 |
+
if (queries.length > 1 && D) {
|
| 39 |
// Multi-code search mode
|
| 40 |
var allResults = [];
|
| 41 |
+
var normSimple = function(s) { return String(s || '').toLowerCase().replace(/[.\/\-]/g, ''); };
|
| 42 |
|
| 43 |
queries.forEach(function(q) {
|
| 44 |
+
var qNorm = normSimple(q);
|
| 45 |
for (var i = 0; i < D.length && allResults.length < 30; i++) {
|
| 46 |
var p = D[i];
|
| 47 |
if (!p) continue;
|
| 48 |
+
var nameField = (p.name || '').toLowerCase();
|
| 49 |
+
var modField = (p.mod || '').toLowerCase();
|
| 50 |
+
var skuField = normSimple(p.sku || '');
|
| 51 |
+
var modelField = (p.model || '').toLowerCase();
|
| 52 |
+
var slugField = (p.slug || '').toLowerCase();
|
| 53 |
+
|
| 54 |
+
if (skuField === qNorm ||
|
| 55 |
+
modField.replace(/[.\/\- ]/g, '').includes(qNorm) ||
|
| 56 |
+
nameField.replace(/[.\/\- ]/g, '').includes(qNorm) ||
|
| 57 |
+
slugField.replace(/[.\/\- ]/g, '').includes(qNorm)) {
|
| 58 |
allResults.push(p);
|
| 59 |
}
|
| 60 |
}
|
|
|
|
| 66 |
}
|
| 67 |
}
|
| 68 |
|
| 69 |
+
if (typeof window.aiSearch === 'function' && D) {
|
| 70 |
var aiToken = (window.huggingface && window.huggingface.variables && window.huggingface.variables.VAISTUDIO) || '';
|
| 71 |
window.aiSearch(query, D, aiToken).then(function(aiResult) {
|
| 72 |
if (!aiResult || (!aiResult.results.length && !aiResult.aiAnswer)) {
|
|
|
|
| 197 |
}
|
| 198 |
|
| 199 |
function _fallbackAISearch(query, container) {
|
| 200 |
+
var D = (typeof window.D !== 'undefined') ? window.D : null;
|
| 201 |
+
if (!D || !D.length) {
|
| 202 |
+
container.innerHTML = '⏳ Đang tải dữ liệu sản phẩm... Vui lòng chờ.';
|
| 203 |
return;
|
| 204 |
}
|
| 205 |
var qNorm = query.toLowerCase().normalize('NFD').replace(/[̀-ͯ]/g, '').replace(/đ/g, 'd');
|
|
|
|
| 209 |
if (!p) continue;
|
| 210 |
var nameNorm = (p.name || '').toLowerCase().normalize('NFD').replace(/[̀-ͯ]/g, '').replace(/đ/g, 'd');
|
| 211 |
var skuNorm = (p.sku || p.mod || '').toLowerCase();
|
| 212 |
+
var catNorm = (p.cat || '').toLowerCase().normalize('NFD').replace(/[̀-ͯ]/g, '').replace(/đ/g, 'd');
|
| 213 |
+
var brandNorm = (p.brand || '').toLowerCase();
|
| 214 |
+
if (nameNorm.indexOf(qNorm) !== -1 ||
|
| 215 |
+
(skuNorm && skuNorm.indexOf(qNorm) !== -1) ||
|
| 216 |
+
(catNorm && catNorm.indexOf(qNorm) !== -1) ||
|
| 217 |
+
(brandNorm && brandNorm.indexOf(qNorm) !== -1) ||
|
| 218 |
+
(p._idx && typeof p._idx === 'string' && p._idx.toLowerCase().indexOf(qNorm) !== -1)) {
|
| 219 |
results.push(p);
|
| 220 |
}
|
| 221 |
}
|
| 222 |
if (!results.length) {
|
| 223 |
+
container.innerHTML = '❌ Không tìm thấy "' + query + '". Thử: "bếp từ", "máy hút mùi", "Malloca", "Eurogold"';
|
| 224 |
return;
|
| 225 |
}
|
| 226 |
container.innerHTML = '<div style="font-size:.78rem;color:#64748b;margin-bottom:10px"><strong>' + results.length + '</strong> kết quả</div>' +
|
| 227 |
'<div style="display:grid;grid-template-columns:repeat(auto-fill,minmax(180px,1fr));gap:12px">' +
|
| 228 |
+
results.map(function(p) {
|
| 229 |
+
var idx = window.D ? window.D.indexOf(p) : -1;
|
| 230 |
+
var brandColor = p.brand === 'Eurogold' ? '#c8102e' : (p.brand === 'Grob' ? '#2e7d32' : '#003f62');
|
| 231 |
var imgSrc = p.image || p.i || '';
|
| 232 |
var priceStr = p.price || (p.pn ? p.pn : 'Liên hệ');
|
| 233 |
return '<div class="pc fade" onclick="showDetail(' + idx + ')" style="cursor:pointer">' +
|
| 234 |
+
'<div class="pi" style="height:150px"><img src="' + imgSrc + '" alt="' + p.name + '" loading="lazy" onerror="this.style.display=\'none\'"></div>' +
|
| 235 |
+
'<div class="pb" style="padding:10px"><div style="font-size:.62rem;font-weight:600;color:' + brandColor + ';margin-bottom:3px">' + (p.brand || '') + '</div>' +
|
| 236 |
+
'<div class="pn" style="font-size:.76rem">' + p.name + '</div>' +
|
| 237 |
'<div class="pf" style="margin-top:6px"><span class="pp" style="font-size:.92rem">' + priceStr + '</span></div></div></div>';
|
| 238 |
}).join('') + '</div>';
|
| 239 |
+
|
| 240 |
+
if (window.requestAnimationFrame) {
|
| 241 |
+
requestAnimationFrame(function() {
|
| 242 |
+
var fadeEls = container.querySelectorAll('.fade');
|
| 243 |
+
for (var j = 0; j < fadeEls.length; j++) {
|
| 244 |
+
fadeEls[j].classList.add('vis');
|
| 245 |
+
}
|
| 246 |
+
});
|
| 247 |
+
}
|
| 248 |
+
}
|