接口化
This commit is contained in:
parent
ab07644f22
commit
fc7fd4f2cf
|
|
@ -210,32 +210,32 @@
|
|||
<div class="result-card-list">
|
||||
<el-card
|
||||
v-for="item in currentPageData"
|
||||
:key="item.productNumber"
|
||||
:key="item.partNumber"
|
||||
class="result-card"
|
||||
:class="{ active: item.selected }"
|
||||
@click="toggleSelect(item)"
|
||||
>
|
||||
<div class="result-card-info">
|
||||
<div class="result-card-name" :title="item.name">
|
||||
{{ item.name }}
|
||||
<div class="result-card-name" :title="item.partName">
|
||||
{{ item.partName }}
|
||||
</div>
|
||||
<div
|
||||
class="result-card-parameter"
|
||||
:title="`品号:${item.productNumber}`"
|
||||
:title="`品号:${item.partNumber}`"
|
||||
>
|
||||
<span>品号:</span>{{ item.productNumber }}
|
||||
<span>品号:</span>{{ item.partNumber }}
|
||||
</div>
|
||||
<div
|
||||
class="result-card-parameter"
|
||||
:title="`品号-规格型号:${item.specificationModel}`"
|
||||
:title="`品号-规格型号:${item.partNumberSpec}`"
|
||||
>
|
||||
<span>品号-规格型号: </span>{{ item.specificationModel }}
|
||||
<span>品号-规格型号: </span>{{ item.partNumberSpec }}
|
||||
</div>
|
||||
<div
|
||||
class="result-card-parameter text-truncate"
|
||||
:title="`车型:${item.carModel}`"
|
||||
:title="`车型:${item.trainModel}`"
|
||||
>
|
||||
<span>车型:</span> {{ item.carModel }}
|
||||
<span>车型:</span> {{ item.trainModel }}
|
||||
</div>
|
||||
</div>
|
||||
</el-card>
|
||||
|
|
@ -309,9 +309,9 @@
|
|||
/>
|
||||
<el-table-column
|
||||
v-for="item in sortedCompareList"
|
||||
:key="item.productNumber"
|
||||
:label="item.productNumber"
|
||||
:prop="item.productNumber"
|
||||
:key="item.partNumber"
|
||||
:label="item.partNumber"
|
||||
:prop="item.partNumber"
|
||||
align="center"
|
||||
header-align="center"
|
||||
min-width="300"
|
||||
|
|
@ -344,8 +344,8 @@
|
|||
</span>
|
||||
<span style="font-size: 12px; color: #666">{{
|
||||
sortedCompareList.find(
|
||||
(i) => i.productNumber === column.label
|
||||
).name
|
||||
(i) => i.partNumber === column.label
|
||||
)?.partName || "-"
|
||||
}}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -407,14 +407,13 @@
|
|||
<script setup>
|
||||
import { ref, computed, watch, onMounted, nextTick } from "vue";
|
||||
import {
|
||||
paramsToCompare,
|
||||
fieldMap,
|
||||
allFields,
|
||||
mockData,
|
||||
fieldValueMap,
|
||||
} from "@/data/step2MockData";
|
||||
searchHint,
|
||||
search as searchProducts,
|
||||
differenceWords,
|
||||
compare,
|
||||
} from "@/api/order";
|
||||
import { ElMessage, ElEmpty, ElDialog } from "element-plus";
|
||||
import { Search, Edit, RefreshLeft, Microphone } from "@element-plus/icons-vue";
|
||||
import { Search, RefreshLeft, Microphone } from "@element-plus/icons-vue";
|
||||
|
||||
// 接收props和定义emit
|
||||
const props = defineProps({
|
||||
|
|
@ -448,6 +447,11 @@ const showSuggestions = ref(false);
|
|||
const activeSuggestionIndex = ref(-1);
|
||||
const possibleFields = ref([]);
|
||||
const activePossibleFieldIndex = ref(-1);
|
||||
const allFields = ref([]);
|
||||
const fieldValueMap = ref({});
|
||||
const allValues = ref([]);
|
||||
const hintTimer = ref(null);
|
||||
const pendingSearchTimer = ref(null);
|
||||
|
||||
// 语音输入弹窗控制
|
||||
const showVoicePopup = ref(false);
|
||||
|
|
@ -466,8 +470,7 @@ const totalItems = ref(0);
|
|||
|
||||
// 计算当前页数据
|
||||
const currentPageData = computed(() => {
|
||||
const startIndex = (currentPage.value - 1) * pageSize.value;
|
||||
return filteredData.value.slice(startIndex, startIndex + pageSize.value);
|
||||
return filteredData.value;
|
||||
});
|
||||
|
||||
// 计算选中的商品数量
|
||||
|
|
@ -478,7 +481,7 @@ const selectedCount = computed(() => {
|
|||
// 选中的商品品号
|
||||
const selectedProductNumber = computed(() => {
|
||||
const selected = filteredData.value.find((item) => item.selected);
|
||||
return selected ? selected.productNumber : "";
|
||||
return selected ? selected.partNumber : "";
|
||||
});
|
||||
|
||||
// 对比相关
|
||||
|
|
@ -506,8 +509,8 @@ const sortedCompareList = computed(() => {
|
|||
// 排序:根据品号结尾的五位数从大到小排序
|
||||
list.sort((a, b) => {
|
||||
// 提取品号结尾的五位数
|
||||
const aMatch = a.productNumber.match(/-(\d{5})$/);
|
||||
const bMatch = b.productNumber.match(/-(\d{5})$/);
|
||||
const aMatch = a.partNumber?.match(/-(\d{5})$/);
|
||||
const bMatch = b.partNumber?.match(/-(\d{5})$/);
|
||||
|
||||
const aNum = aMatch ? parseInt(aMatch[1], 10) : 0;
|
||||
const bNum = bMatch ? parseInt(bMatch[1], 10) : 0;
|
||||
|
|
@ -525,78 +528,21 @@ const sortedCompareList = computed(() => {
|
|||
return list;
|
||||
});
|
||||
|
||||
// 生成对比表格数据并分析差异
|
||||
const compareTableData = computed(() => {
|
||||
if (sortedCompareList.value.length === 0) {
|
||||
parameterDifferences.value = {};
|
||||
return [];
|
||||
}
|
||||
const compareTableData = ref([]);
|
||||
|
||||
// 重置差异映射
|
||||
const updateParameterDifferenceFlags = (rows) => {
|
||||
const differences = {};
|
||||
|
||||
// 获取当前时间和昨天的日期
|
||||
const today = new Date();
|
||||
const yesterday = new Date(today);
|
||||
yesterday.setDate(yesterday.getDate() - 1);
|
||||
|
||||
// 格式化日期为 yyyy-MM-dd
|
||||
const formatDate = (date) => {
|
||||
return date.toISOString().split("T")[0];
|
||||
};
|
||||
|
||||
const formattedToday = formatDate(today);
|
||||
const formattedYesterday = formatDate(yesterday);
|
||||
|
||||
// 构建对比数据,添加新参数
|
||||
const result = [
|
||||
// 原有参数
|
||||
{ param: "品号-规格型号" },
|
||||
// 新增参数:品号申请时间
|
||||
{ param: "品号申请时间" },
|
||||
{ param: "图号" },
|
||||
{ param: "技术规范编号" },
|
||||
{ param: "技术规范版本" },
|
||||
{ param: "技术规范名称" },
|
||||
// 新增参数:技术要求签订时间
|
||||
{ param: "技术要求签订时间" },
|
||||
{ param: "CBC编号" },
|
||||
{ param: "CBC版本" },
|
||||
{ param: "车型" },
|
||||
{ param: "型号" },
|
||||
{ param: "材质" },
|
||||
{ param: "采购属性" },
|
||||
{ param: "车轮踏面形式" },
|
||||
{ param: "油漆制造商" },
|
||||
].map((item) => {
|
||||
const row = { param: item.param };
|
||||
|
||||
// 为每个产品填充参数值
|
||||
sortedCompareList.value.forEach((product) => {
|
||||
// 处理新增的两个参数
|
||||
if (item.param === "品号申请时间") {
|
||||
row[product.productNumber] = formattedToday;
|
||||
} else if (item.param === "技术要求签订时间") {
|
||||
row[product.productNumber] = formattedYesterday;
|
||||
} else {
|
||||
// 处理原有参数
|
||||
const fieldKey = fieldMap[item.param];
|
||||
row[product.productNumber] = fieldKey ? product[fieldKey] ?? "-" : "-";
|
||||
}
|
||||
});
|
||||
|
||||
// 收集所有产品的参数值用于判断差异
|
||||
const values = sortedCompareList.value.map((p) => row[p.productNumber]);
|
||||
const allSame = values.every((v) => v === values[0]);
|
||||
differences[item.param] = !allSame;
|
||||
|
||||
return row;
|
||||
rows.forEach((row) => {
|
||||
if (!row || !row.param) return;
|
||||
const values = sortedCompareList.value.map((item) => row[item.partNumber]);
|
||||
const baseline = values.find(
|
||||
(val) => val !== undefined && val !== null && val !== "-"
|
||||
);
|
||||
differences[row.param] =
|
||||
baseline !== undefined && values.some((val) => val !== baseline);
|
||||
});
|
||||
|
||||
// 保存差异信息
|
||||
parameterDifferences.value = differences;
|
||||
return result;
|
||||
});
|
||||
};
|
||||
|
||||
// 过滤后的对比表格数据(根据"仅看不同项"选项)
|
||||
const filteredCompareTableData = computed(() => {
|
||||
|
|
@ -616,26 +562,24 @@ const isValueDifferent = (param) => {
|
|||
return parameterDifferences.value[param];
|
||||
};
|
||||
|
||||
// 收集所有可能的值用于匹配
|
||||
const allValues = ref([]);
|
||||
|
||||
// 初始化所有可能的值
|
||||
const initializeValues = () => {
|
||||
const values = [];
|
||||
allFields.forEach((field) => {
|
||||
allFields.value.forEach((field) => {
|
||||
const uniqueValues = [
|
||||
...new Set(
|
||||
mockData.map((item) => item[field.key] ?? "") // 将null转换为空字符串
|
||||
(fieldValueMap.value[field.key] || []).map((item) =>
|
||||
item === null || item === undefined ? "" : String(item)
|
||||
)
|
||||
),
|
||||
];
|
||||
uniqueValues.forEach((value) => {
|
||||
// 过滤空值,避免空提示
|
||||
if (value !== "") {
|
||||
values.push({
|
||||
value: String(value),
|
||||
value,
|
||||
fieldKey: field.key,
|
||||
fieldLabel: field.label,
|
||||
weight: fieldValueMap[field.key]?.includes(String(value)) ? 2 : 1,
|
||||
weight: 2,
|
||||
});
|
||||
}
|
||||
});
|
||||
|
|
@ -643,32 +587,30 @@ const initializeValues = () => {
|
|||
allValues.value = values;
|
||||
};
|
||||
|
||||
// 检查并更新关键差异字段提示
|
||||
const updateKeyDiffHint = () => {
|
||||
// 获取技术规范编号和CBC编号的字段信息
|
||||
const techSpecField = allFields.find(
|
||||
(field) => field.label === "技术规范编号"
|
||||
);
|
||||
const cbcField = allFields.find((field) => field.label === "CBC编号");
|
||||
|
||||
// 检查当前搜索条件中是否包含这两个字段
|
||||
const hasTechSpec = parsedConditions.value.some(
|
||||
(cond) => cond.field === techSpecField?.key
|
||||
);
|
||||
const hasCbc = parsedConditions.value.some(
|
||||
(cond) => cond.field === cbcField?.key
|
||||
const mergeFieldMetadata = (fields = []) => {
|
||||
if (!Array.isArray(fields) || fields.length === 0) return;
|
||||
const fieldMapCache = new Map(
|
||||
allFields.value.map((item) => [item.key, item])
|
||||
);
|
||||
|
||||
// 确定需要显示的关键差异字段
|
||||
const diffFields = [];
|
||||
if (!hasTechSpec && techSpecField) diffFields.push(techSpecField);
|
||||
if (!hasCbc && cbcField) diffFields.push(cbcField);
|
||||
fields.forEach((item) => {
|
||||
const label = item.fieldName || item.fieldLabel || item.label;
|
||||
const key = item.fieldKey || item.key;
|
||||
if (!label || !key) return;
|
||||
if (!fieldMapCache.has(key)) {
|
||||
fieldMapCache.set(key, { key, label });
|
||||
}
|
||||
|
||||
// 更新关键差异字段和显示状态
|
||||
keyDiffFields.value = diffFields;
|
||||
// 只有当有搜索条件且有关键差异字段时才显示提示
|
||||
showKeyDiffHint.value =
|
||||
currentInput.value.trim() !== "" && diffFields.length > 0;
|
||||
if (Array.isArray(item.fieldValues) && item.fieldValues.length > 0) {
|
||||
const existingValues = fieldValueMap.value[key] || [];
|
||||
fieldValueMap.value[key] = Array.from(
|
||||
new Set([...existingValues, ...item.fieldValues])
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
allFields.value = Array.from(fieldMapCache.values());
|
||||
initializeValues();
|
||||
};
|
||||
|
||||
// 点击差异字段时添加到输入框
|
||||
|
|
@ -834,7 +776,7 @@ const triggerConditionSuggestions = (conditionText) => {
|
|||
const fieldLabel = conditionText.substring(0, colonIndex).trim();
|
||||
const valuePart = conditionText.substring(colonIndex + 1).trim();
|
||||
|
||||
const field = allFields.find((f) => f.label === fieldLabel);
|
||||
const field = allFields.value.find((f) => f.label === fieldLabel);
|
||||
|
||||
if (field) {
|
||||
// 显示该字段的所有可能值
|
||||
|
|
@ -869,10 +811,11 @@ const triggerConditionSuggestions = (conditionText) => {
|
|||
}
|
||||
};
|
||||
|
||||
// 处理输入事件,实时生成建议
|
||||
const handleInput = (value) => {
|
||||
// 根据当前输入更新建议列表(不触发远程请求)
|
||||
const updateSuggestionsFromValue = (value) => {
|
||||
const normalizedValue = value ?? "";
|
||||
// 获取当前正在输入的条件部分(分号后面的部分)
|
||||
const parts = value.split(/[;;]/);
|
||||
const parts = normalizedValue.split(/[;;]/);
|
||||
const currentPart = parts[parts.length - 1].trim();
|
||||
|
||||
// 检查是否在编辑已有条件
|
||||
|
|
@ -884,7 +827,7 @@ const handleInput = (value) => {
|
|||
}
|
||||
|
||||
// 始终显示建议框,除非输入为空
|
||||
showSuggestions.value = value.trim() !== "";
|
||||
showSuggestions.value = normalizedValue.trim() !== "";
|
||||
|
||||
// 如果当前部分为空,不显示具体建议
|
||||
if (!currentPart) {
|
||||
|
|
@ -902,7 +845,7 @@ const handleInput = (value) => {
|
|||
|
||||
if (isEditingField) {
|
||||
// 正在输入字段或值的开始部分,同时查找字段和值
|
||||
fieldSuggestions = allFields
|
||||
fieldSuggestions = allFields.value
|
||||
.filter((field) =>
|
||||
field.label.toLowerCase().includes(currentPart.toLowerCase())
|
||||
)
|
||||
|
|
@ -934,7 +877,7 @@ const handleInput = (value) => {
|
|||
valueFieldCounts[val.fieldKey] = {
|
||||
count: 0,
|
||||
label: val.fieldLabel,
|
||||
field: allFields.find((f) => f.key === val.fieldKey),
|
||||
field: allFields.value.find((f) => f.key === val.fieldKey),
|
||||
};
|
||||
}
|
||||
valueFieldCounts[val.fieldKey].count += val.weight;
|
||||
|
|
@ -954,7 +897,7 @@ const handleInput = (value) => {
|
|||
const valuePart = currentPart.substring(colonIndex + 1).trim();
|
||||
|
||||
// 查找对应的字段
|
||||
const field = allFields.find((f) => f.label === fieldLabel);
|
||||
const field = allFields.value.find((f) => f.label === fieldLabel);
|
||||
|
||||
if (field) {
|
||||
// 只查找该字段的值
|
||||
|
|
@ -1029,6 +972,46 @@ const handleInput = (value) => {
|
|||
activePossibleFieldIndex.value = -1;
|
||||
};
|
||||
|
||||
// 处理输入事件,实时生成建议并调度远程提示
|
||||
const handleInput = (value, options = {}) => {
|
||||
const normalizedValue = value ?? "";
|
||||
updateSuggestionsFromValue(normalizedValue);
|
||||
if (options.skipFetch) {
|
||||
return;
|
||||
}
|
||||
const parts = normalizedValue.split(/[;;]/);
|
||||
const currentPart = parts[parts.length - 1]?.trim();
|
||||
if (currentPart) {
|
||||
scheduleSearchHint(currentPart);
|
||||
}
|
||||
};
|
||||
|
||||
const fetchSearchHints = async (keyword) => {
|
||||
if (!keyword) return;
|
||||
try {
|
||||
const res = await searchHint({ keyword });
|
||||
const hintList = Array.isArray(res?.data)
|
||||
? res.data
|
||||
: Array.isArray(res)
|
||||
? res
|
||||
: [];
|
||||
mergeFieldMetadata(hintList);
|
||||
updateSuggestionsFromValue(currentInput.value, { skipFetch: true });
|
||||
} catch (error) {
|
||||
console.error("searchHint error:", error);
|
||||
}
|
||||
};
|
||||
|
||||
const scheduleSearchHint = (keyword) => {
|
||||
if (hintTimer.value) {
|
||||
clearTimeout(hintTimer.value);
|
||||
}
|
||||
if (!keyword) return;
|
||||
hintTimer.value = setTimeout(() => {
|
||||
fetchSearchHints(keyword);
|
||||
}, 300);
|
||||
};
|
||||
|
||||
// 选择可能的字段 - 修复问题4
|
||||
const selectPossibleField = (field) => {
|
||||
// 始终在当前条件上操作,不修改其他条件
|
||||
|
|
@ -1252,7 +1235,7 @@ const parseConditions = (input) => {
|
|||
const valuePart = part.substring(colonIndex + 1).trim();
|
||||
|
||||
// 查找对应的字段key
|
||||
const field = allFields.find((f) => f.label === fieldLabel);
|
||||
const field = allFields.value.find((f) => f.label === fieldLabel);
|
||||
|
||||
conditions.push({
|
||||
fieldLabel,
|
||||
|
|
@ -1274,6 +1257,148 @@ const parseConditions = (input) => {
|
|||
return conditions;
|
||||
};
|
||||
|
||||
const getPreciseIndexSet = () => {
|
||||
const preciseIndexSet = new Set();
|
||||
preciseConditions.value.forEach((condition) => {
|
||||
if (typeof condition.originalIndex === "number") {
|
||||
preciseIndexSet.add(condition.originalIndex);
|
||||
} else {
|
||||
const idx = parsedConditions.value.findIndex(
|
||||
(item) =>
|
||||
item.field === condition.field && item.value === condition.value
|
||||
);
|
||||
if (idx !== -1) {
|
||||
preciseIndexSet.add(idx);
|
||||
}
|
||||
}
|
||||
});
|
||||
return preciseIndexSet;
|
||||
};
|
||||
|
||||
const buildFieldConditionsPayload = () => {
|
||||
const preciseIndexSet = getPreciseIndexSet();
|
||||
|
||||
return parsedConditions.value
|
||||
.filter((condition) => condition.value)
|
||||
.map((condition, index) => {
|
||||
const queryType = preciseIndexSet.has(index) ? "EXACT" : "FUZZY";
|
||||
|
||||
if (condition.valid && condition.field) {
|
||||
return {
|
||||
fieldName: condition.fieldLabel,
|
||||
fieldValue: condition.value,
|
||||
keyword: "",
|
||||
queryType,
|
||||
};
|
||||
}
|
||||
|
||||
const keyword = condition.fieldLabel
|
||||
? `${condition.fieldLabel}:${condition.value}`.replace(/:$/, "")
|
||||
: condition.value;
|
||||
|
||||
return {
|
||||
fieldName: "",
|
||||
fieldValue: "",
|
||||
keyword,
|
||||
queryType,
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
const executeSearch = async ({ page = currentPage.value } = {}) => {
|
||||
if (pendingSearchTimer.value) {
|
||||
clearTimeout(pendingSearchTimer.value);
|
||||
pendingSearchTimer.value = null;
|
||||
}
|
||||
const payload = {
|
||||
fieldConditions: buildFieldConditionsPayload(),
|
||||
inputWord: currentInput.value.trim(),
|
||||
page: Math.max(page - 1, 0),
|
||||
size: pageSize.value,
|
||||
};
|
||||
|
||||
try {
|
||||
const res = await searchProducts(payload);
|
||||
const pageData = res?.data ?? res ?? {};
|
||||
const list = pageData?.content ?? [];
|
||||
|
||||
filteredData.value = list.map((item) => ({
|
||||
...item,
|
||||
selected: false,
|
||||
}));
|
||||
totalItems.value = pageData?.totalElements ?? list.length;
|
||||
const serverPage = pageData?.number ?? Math.max(page - 1, 0);
|
||||
currentPage.value = serverPage + 1;
|
||||
pageSize.value = pageData?.size ?? pageSize.value;
|
||||
showResults.value = true;
|
||||
} catch (error) {
|
||||
console.error("search error:", error);
|
||||
}
|
||||
};
|
||||
|
||||
const scheduleSearchExecution = (page = 1) => {
|
||||
if (pendingSearchTimer.value) {
|
||||
clearTimeout(pendingSearchTimer.value);
|
||||
}
|
||||
pendingSearchTimer.value = setTimeout(() => {
|
||||
executeSearch({ page });
|
||||
}, 500);
|
||||
};
|
||||
|
||||
const fetchDifferenceRecommendations = async () => {
|
||||
if (!currentInput.value.trim()) {
|
||||
keyDiffFields.value = [];
|
||||
showKeyDiffHint.value = false;
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const res = await differenceWords({
|
||||
fieldConditions: buildFieldConditionsPayload(),
|
||||
inputWord: currentInput.value.trim(),
|
||||
});
|
||||
const diffList = Array.isArray(res?.data)
|
||||
? res.data
|
||||
: Array.isArray(res)
|
||||
? res
|
||||
: [];
|
||||
mergeFieldMetadata(diffList);
|
||||
keyDiffFields.value = diffList.slice(0, 5).map((item) => ({
|
||||
label: item.fieldName || "",
|
||||
key: item.fieldKey,
|
||||
}));
|
||||
showKeyDiffHint.value =
|
||||
keyDiffFields.value.length > 0 && currentInput.value.trim() !== "";
|
||||
} catch (error) {
|
||||
console.error("differenceWords error:", error);
|
||||
}
|
||||
};
|
||||
|
||||
const fetchCompareTable = async () => {
|
||||
const idList = selectedCompareList.value
|
||||
.map((item) => item.id || item.partNumber)
|
||||
.filter(Boolean);
|
||||
const ids = idList.join(",");
|
||||
if (!ids) {
|
||||
compareTableData.value = [];
|
||||
parameterDifferences.value = {};
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const res = await compare({ ids });
|
||||
const rows = Array.isArray(res?.data)
|
||||
? res.data
|
||||
: Array.isArray(res)
|
||||
? res
|
||||
: [];
|
||||
compareTableData.value = rows;
|
||||
updateParameterDifferenceFlags(rows);
|
||||
} catch (error) {
|
||||
console.error("compare error:", error);
|
||||
compareTableData.value = [];
|
||||
parameterDifferences.value = {};
|
||||
}
|
||||
};
|
||||
|
||||
// 添加精准查询条件
|
||||
const addPreciseCondition = (index) => {
|
||||
const condition = parsedConditions.value[index];
|
||||
|
|
@ -1284,34 +1409,27 @@ const addPreciseCondition = (index) => {
|
|||
|
||||
if (!exists) {
|
||||
preciseConditions.value.push({ ...condition, originalIndex: index });
|
||||
// 重新过滤数据,应用精准查询
|
||||
applyPreciseFilter();
|
||||
executeSearch({ page: 1 });
|
||||
}
|
||||
};
|
||||
|
||||
// 移除精准查询条件
|
||||
const removePreciseCondition = (index) => {
|
||||
preciseConditions.value.splice(index, 1);
|
||||
// 重新过滤数据
|
||||
applyPreciseFilter();
|
||||
executeSearch({ page: 1 });
|
||||
};
|
||||
|
||||
// 处理查询
|
||||
const handleSearch = () => {
|
||||
const handleSearch = async () => {
|
||||
// 解析条件
|
||||
parsedConditions.value = parseConditions(currentInput.value);
|
||||
|
||||
// 更新关键差异提示
|
||||
updateKeyDiffHint();
|
||||
|
||||
// 清空精准查询条件
|
||||
preciseConditions.value = [];
|
||||
|
||||
// 应用过滤
|
||||
applyPreciseFilter();
|
||||
|
||||
// 显示结果
|
||||
showResults.value = true;
|
||||
// 执行查询与关键差异词推荐
|
||||
await executeSearch({ page: 1 });
|
||||
await fetchDifferenceRecommendations();
|
||||
|
||||
// 隐藏建议
|
||||
showSuggestions.value = false;
|
||||
|
|
@ -1323,106 +1441,10 @@ const triggerRealTimeSearch = () => {
|
|||
// 只有当有有效条件时才触发实时查询
|
||||
if (currentInput.value.trim()) {
|
||||
parsedConditions.value = parseConditions(currentInput.value);
|
||||
// 更新关键差异提示
|
||||
updateKeyDiffHint();
|
||||
applyPreciseFilter();
|
||||
showResults.value = true;
|
||||
scheduleSearchExecution(1);
|
||||
}
|
||||
};
|
||||
|
||||
// 应用精准过滤
|
||||
const applyPreciseFilter = () => {
|
||||
// 先应用原始过滤
|
||||
let filtered = filterData(parsedConditions.value);
|
||||
|
||||
// 再应用精准过滤
|
||||
if (preciseConditions.value.length > 0) {
|
||||
filtered = filtered.filter((item) => {
|
||||
return preciseConditions.value.every((condition) => {
|
||||
if (!condition.valid) return false;
|
||||
|
||||
if (condition.field) {
|
||||
const fieldValue = item[condition.field];
|
||||
return checkPreciseCondition(fieldValue, condition.value);
|
||||
} else {
|
||||
return allFields.some((field) => {
|
||||
const fieldValue = item[field.key];
|
||||
return checkPreciseCondition(fieldValue, condition.value);
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// 更新过滤后的数据
|
||||
filteredData.value = filtered.map((item) => ({ ...item, selected: false }));
|
||||
totalItems.value = filteredData.value.length;
|
||||
currentPage.value = 1;
|
||||
};
|
||||
|
||||
// 根据条件过滤数据
|
||||
const filterData = (conditions) => {
|
||||
return mockData.filter((item) => {
|
||||
return conditions.every((condition) => {
|
||||
if (!condition.valid) return false;
|
||||
|
||||
// 如果指定了字段
|
||||
if (condition.field) {
|
||||
const fieldValue = item[condition.field];
|
||||
return checkCondition(fieldValue, condition.value);
|
||||
}
|
||||
// 没有指定字段,检查所有字段
|
||||
else {
|
||||
return allFields.some((field) => {
|
||||
const fieldValue = item[field.key];
|
||||
return checkCondition(fieldValue, condition.value);
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
// 检查单个条件(模糊匹配)
|
||||
const checkCondition = (fieldValue, conditionValue) => {
|
||||
// 将null转换为空字符串处理
|
||||
const processedValue = fieldValue ?? "";
|
||||
const processedCondition = conditionValue ?? "";
|
||||
|
||||
// 后续逻辑使用processedValue和processedCondition
|
||||
const operators = [
|
||||
{ symbol: ">=", func: (a, b) => a >= b },
|
||||
{ symbol: "<=", func: (a, b) => a <= b },
|
||||
{ symbol: "!=", func: (a, b) => a != b },
|
||||
{ symbol: ">", func: (a, b) => a > b },
|
||||
{ symbol: "<", func: (a, b) => a < b },
|
||||
{ symbol: "=", func: (a, b) => a == b },
|
||||
];
|
||||
|
||||
for (const op of operators) {
|
||||
if (processedCondition.startsWith(op.symbol)) {
|
||||
const value = processedCondition.substring(op.symbol.length).trim();
|
||||
if (!isNaN(Number(processedValue)) && !isNaN(Number(value))) {
|
||||
return op.func(Number(processedValue), Number(value));
|
||||
}
|
||||
return op.func(String(processedValue), value);
|
||||
}
|
||||
}
|
||||
|
||||
return String(processedValue)
|
||||
.toLowerCase()
|
||||
.includes(processedCondition.toLowerCase());
|
||||
};
|
||||
|
||||
// 检查精准条件(精确匹配)
|
||||
const checkPreciseCondition = (fieldValue, conditionValue) => {
|
||||
// 将null转换为空字符串处理
|
||||
const processedValue = fieldValue ?? "";
|
||||
const processedCondition = conditionValue ?? "";
|
||||
|
||||
// 精准匹配,不使用包含关系
|
||||
return String(processedValue) === processedCondition;
|
||||
};
|
||||
|
||||
// 移除单个条件
|
||||
const removeCondition = (index) => {
|
||||
const parts = currentInput.value.split(/[;;]/);
|
||||
|
|
@ -1444,8 +1466,8 @@ const removeCondition = (index) => {
|
|||
preciseConditions.value.splice(preciseIndex, 1);
|
||||
}
|
||||
|
||||
// 重新过滤数据
|
||||
applyPreciseFilter();
|
||||
// 重新查询
|
||||
executeSearch({ page: 1 });
|
||||
|
||||
// 重置选中的条件索引
|
||||
if (selectedConditionIndex.value === index) {
|
||||
|
|
@ -1479,10 +1501,12 @@ const clearAll = () => {
|
|||
const handleSizeChange = (val) => {
|
||||
pageSize.value = val;
|
||||
currentPage.value = 1; // 重置为第一页
|
||||
executeSearch({ page: 1 });
|
||||
};
|
||||
|
||||
const handleCurrentChange = (val) => {
|
||||
currentPage.value = val;
|
||||
executeSearch({ page: val });
|
||||
// 滚动到顶部
|
||||
window.scrollTo({ top: 0, behavior: "smooth" });
|
||||
};
|
||||
|
|
@ -1532,19 +1556,18 @@ watch(
|
|||
|
||||
// 切换选择状态
|
||||
function toggleSelect(item) {
|
||||
// 统计已选中的数量
|
||||
const selectedCount = filteredData.value.filter((i) => i.selected).length;
|
||||
item.selected = !item.selected;
|
||||
}
|
||||
|
||||
// 打开对比弹窗
|
||||
function onCompare() {
|
||||
const onCompare = async () => {
|
||||
if (selectedCompareList.value.length === 0) {
|
||||
ElMessage.warning("请先选择要对比的卡片");
|
||||
return;
|
||||
}
|
||||
await fetchCompareTable();
|
||||
compareDialogVisible.value = true;
|
||||
}
|
||||
};
|
||||
|
||||
// 确定按钮点击事件
|
||||
function handleConfirm() {
|
||||
|
|
|
|||
Loading…
Reference in New Issue