fix: highlight full knowledge search terms
This commit is contained in:
@@ -388,20 +388,24 @@ function matchedLabel(values: string[]) {
|
||||
return labels.join("、");
|
||||
}
|
||||
|
||||
function highlightSnippet(text: string) {
|
||||
const keyword = contentSearch.keyword.trim();
|
||||
if (!keyword) return [{ text, match: false }];
|
||||
function highlightSnippet(text: string, terms: string[] = []) {
|
||||
const keywords = Array.from(new Set([...terms, contentSearch.keyword.trim()].filter(Boolean)))
|
||||
.sort((left, right) => right.length - left.length);
|
||||
if (!keywords.length) return [{ text, match: false }];
|
||||
const parts: Array<{ text: string; match: boolean }> = [];
|
||||
const source = text || "";
|
||||
const lowerSource = source.toLowerCase();
|
||||
const lowerKeyword = keyword.toLowerCase();
|
||||
let cursor = 0;
|
||||
while (cursor < source.length) {
|
||||
const index = lowerSource.indexOf(lowerKeyword, cursor);
|
||||
if (index < 0) {
|
||||
const next = keywords
|
||||
.map((keyword) => ({ keyword, index: lowerSource.indexOf(keyword.toLowerCase(), cursor) }))
|
||||
.filter((item) => item.index >= 0)
|
||||
.sort((left, right) => left.index - right.index || right.keyword.length - left.keyword.length)[0];
|
||||
if (!next) {
|
||||
parts.push({ text: source.slice(cursor), match: false });
|
||||
break;
|
||||
}
|
||||
const { index, keyword } = next;
|
||||
if (index > cursor) parts.push({ text: source.slice(cursor, index), match: false });
|
||||
parts.push({ text: source.slice(index, index + keyword.length), match: true });
|
||||
cursor = index + keyword.length;
|
||||
@@ -493,7 +497,7 @@ async function confirmAction(
|
||||
{{ item.knowledgeName }} · V{{ item.versionNo }} · {{ item.sectionKey }} · 命中{{ matchedLabel(item.matchedIn) }}
|
||||
</p>
|
||||
<p class="content-search-hit-snippet">
|
||||
<template v-for="(part, index) in highlightSnippet(item.snippet)" :key="index">
|
||||
<template v-for="(part, index) in highlightSnippet(item.snippet, item.highlightTerms)" :key="index">
|
||||
<mark v-if="part.match">{{ part.text }}</mark><span v-else>{{ part.text }}</span>
|
||||
</template>
|
||||
</p>
|
||||
|
||||
@@ -227,6 +227,7 @@ export interface KnowledgeContentSearchItem {
|
||||
sectionKey: string;
|
||||
title: string;
|
||||
snippet: string;
|
||||
highlightTerms?: string[];
|
||||
matchedIn: Array<"title" | "content">;
|
||||
hasChunks: boolean;
|
||||
isCurrentVersion: boolean;
|
||||
|
||||
Reference in New Issue
Block a user