From e990847c4560a502535600446b1e0d454f14d602 Mon Sep 17 00:00:00 2001 From: JenniferW <1627055433@qq.com> Date: Tue, 16 Dec 2025 14:52:06 +0800 Subject: [PATCH] =?UTF-8?q?=E6=90=9C=E7=B4=A2=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api/order/index.js | 6 +- src/views/order/intention/search.vue | 165 ++++++++++++++++++++++++--- 2 files changed, 151 insertions(+), 20 deletions(-) diff --git a/src/api/order/index.js b/src/api/order/index.js index 5313aad..09deca7 100644 --- a/src/api/order/index.js +++ b/src/api/order/index.js @@ -1,11 +1,11 @@ import request from '@/utils/request' // 智能搜索接口 - 根据输入内容获取对应的key和value -export function searchHint(query) { +export function searchHint(data) { return request({ url: '/products/search/smart', - method: 'get', - params: query + method: 'post', + data: data }) } diff --git a/src/views/order/intention/search.vue b/src/views/order/intention/search.vue index df40f07..03ab13f 100644 --- a/src/views/order/intention/search.vue +++ b/src/views/order/intention/search.vue @@ -316,7 +316,7 @@ { valueFieldCounts[val.fieldKey].count += val.weight; }); - possibleFields.value = Object.values(valueFieldCounts) - .filter( - (item) => - item.count > 1 && item.field && !usedLabels.has(item.field.label) - ) - .sort((a, b) => b.count - a.count) - .map((item) => item.field); + // 只有在没有从接口获取字段时才设置 + if (!fieldsFromApi.value) { + possibleFields.value = Object.values(valueFieldCounts) + .filter( + (item) => + item.count > 1 && item.field && !usedLabels.has(item.field.label) + ) + .sort((a, b) => b.count - a.count) + .map((item) => item.field); + } // 合并建议并按相关性排序 let allSuggestions = [...fieldSuggestions, ...valueSuggestions]; @@ -1155,14 +1159,16 @@ const updateSuggestionsFromValue = (value) => { valueFieldCounts[val.fieldKey].count += val.weight; }); - // 提取并排序可能的字段 - possibleFields.value = Object.values(valueFieldCounts) - .filter( - (item) => - item.count > 1 && item.field && !usedLabels.has(item.field.label) - ) // 只显示有足够匹配度的字段且未使用 - .sort((a, b) => b.count - a.count) // 按匹配度排序 - .map((item) => item.field); + // 提取并排序可能的字段(只有在没有从接口获取字段时才设置) + if (!fieldsFromApi.value) { + possibleFields.value = Object.values(valueFieldCounts) + .filter( + (item) => + item.count > 1 && item.field && !usedLabels.has(item.field.label) + ) // 只显示有足够匹配度的字段且未使用 + .sort((a, b) => b.count - a.count) // 按匹配度排序 + .map((item) => item.field); + } valueSuggestions = potentialValues; } else { @@ -1250,6 +1256,11 @@ const updateSuggestionsFromValue = (value) => { // 处理输入事件,实时生成建议并调度远程提示 const handleInput = (value, options = {}) => { const normalizedValue = value ?? ""; + // 如果输入为空,重置接口字段标记 + if (!normalizedValue.trim()) { + fieldsFromApi.value = false; + possibleFields.value = []; + } updateSuggestionsFromValue(normalizedValue); if (!normalizedValue.trim()) { keyDiffFields.value = []; @@ -1316,8 +1327,127 @@ const fetchSearchHints = async (keyword) => { : Array.isArray(res) ? res : []; + + // 若接口无数据:若已有接口缓存,则保持缓存并继续用缓存给出建议;否则关闭下拉 + if (!hintList.length) { + if (!allFields.value.length) { + suggestions.value = []; + possibleFields.value = []; + allFields.value = []; + allValues.value = []; + fieldValueMap.value = {}; + fieldsFromApi.value = false; + showSuggestions.value = false; + return; + } + // 有缓存则继续用缓存生成建议 + updateSuggestionsFromValue(currentInput.value); + showSuggestions.value = suggestions.value.length > 0; + return; + } + + // 处理返回的数据:合并字段元数据(仅来自接口) mergeFieldMetadata(hintList); - updateSuggestionsFromValue(currentInput.value); + + // 从返回的数据中提取字段信息用于"可能属于的字段"下拉框 + // 只有在没有明确字段时(当前输入不包含冒号)才显示可能字段 + const parts = currentInput.value.split(/[;;]/); + const currentPart = parts[parts.length - 1]?.trim() || ""; + const cursorIndex = findCursorConditionIndex(); + const isEditingExistingField = + cursorIndex >= 0 && cursorIndex < parts.length - 1; + + if ( + !isEditingExistingField && + !currentPart.includes(":") && + hintList.length > 0 + ) { + // 提取所有字段作为可能的字段选项(所有 fieldName) + const fieldsFromHint = hintList + .filter((item) => item.fieldName && item.fieldKey) + .map((item) => ({ + key: item.fieldKey, + label: item.fieldName, + })); + + // 去重,只保留未使用的字段 + const usedLabels = getUsedFieldLabels(cursorIndex); + const uniqueFields = fieldsFromHint.filter( + (field) => !usedLabels.has(field.label) + ); + + // 如果当前输入有值,过滤出包含该值的字段 + if (currentPart) { + const valueQuery = currentPart.includes(":") + ? currentPart.split(":").slice(1).join(":").trim() + : currentPart; + const valueQueryLower = valueQuery.toLowerCase(); + const matchingFields = uniqueFields.filter((field) => { + const fieldItem = hintList.find( + (item) => item.fieldKey === field.key + ); + if (!fieldItem || !Array.isArray(fieldItem.fieldValues)) return false; + return fieldItem.fieldValues.some((value) => + String(value).toLowerCase().includes(valueQueryLower) + ); + }); + + // 如果有关联的字段,优先显示这些字段 + possibleFields.value = + matchingFields.length > 0 ? matchingFields : uniqueFields; + } else { + possibleFields.value = uniqueFields; + } + + // 标记字段来自接口 + fieldsFromApi.value = true; + } else { + possibleFields.value = []; + fieldsFromApi.value = false; + } + + // 基于接口返回的 fieldValues 直接构建值建议,仅展示接口值、不做数量限制 + const valueQuery = currentPart.includes(":") + ? currentPart.split(":").slice(1).join(":").trim() + : currentPart; + const valueQueryLower = (valueQuery || "").toLowerCase(); + const apiValueSuggestions = []; + hintList.forEach((item) => { + if (!Array.isArray(item.fieldValues)) return; + const fieldKey = item.fieldKey || item.key || ""; + const fieldLabel = item.fieldName || item.label || item.fieldLabel || ""; + item.fieldValues.forEach((val) => { + const strVal = + val === null || val === undefined ? "" : String(val).trim(); + if (!strVal) return; + if ( + valueQueryLower && + !strVal.toLowerCase().includes(valueQueryLower) + ) { + return; + } + apiValueSuggestions.push({ + type: "value", + label: strVal, + value: strVal, + fieldKey, + fieldLabel, + weight: 5, // 接口值优先展示 + }); + }); + }); + + // 只用接口返回的值作为下拉建议,并去重 + const seen = new Set(); + const uniqueSuggestions = []; + apiValueSuggestions.forEach((s) => { + const key = s.label; // 按展示文本去重 + if (seen.has(key)) return; + seen.add(key); + uniqueSuggestions.push(s); + }); + suggestions.value = uniqueSuggestions; + showSuggestions.value = uniqueSuggestions.length > 0; } catch (error) { console.error("searchHint error:", error); } @@ -1912,6 +2042,7 @@ const clearAll = () => { showResults.value = false; showSuggestions.value = false; possibleFields.value = []; + fieldsFromApi.value = false; // 重置接口字段标记 selectedConditionIndex.value = -1; // 重置关键差异提示 keyDiffFields.value = [];