From 50f811399f22b835fd2fc33375fe01ff8eb83dd8 Mon Sep 17 00:00:00 2001
From: wujingjing <gersonwu@qq.com>
Date: 星期一, 21 十月 2024 13:50:04 +0800
Subject: [PATCH] 查询高亮指标

---
 src/api/ai/chat.ts                                 |   10 ++
 vite.config.ts                                     |    2 
 src/components/chat/components/playBar/PlayBar.vue |  194 ++++++++++++++++++++++++++++++++++++++++++++++-
 3 files changed, 197 insertions(+), 9 deletions(-)

diff --git a/src/api/ai/chat.ts b/src/api/ai/chat.ts
index f503e76..b517867 100644
--- a/src/api/ai/chat.ts
+++ b/src/api/ai/chat.ts
@@ -315,7 +315,15 @@
 		},
 	});
 };
-
+export const getMetricsNames = async (req: any = request) => {
+	return req({
+		url: 'chat/get_metrics_names',
+		method: 'POST',
+		headers: {
+			'Content-Type': 'application/x-www-form-urlencoded',
+		},
+	});
+};
 export const filterQuery = async (params, req: any = request) => {
 	return req({
 		url: 'chat/filter_query',
diff --git a/src/components/chat/components/playBar/PlayBar.vue b/src/components/chat/components/playBar/PlayBar.vue
index 663f339..28f6947 100644
--- a/src/components/chat/components/playBar/PlayBar.vue
+++ b/src/components/chat/components/playBar/PlayBar.vue
@@ -5,7 +5,7 @@
 				<img src="/static/images/wave/PlugIn.png" class="set-icon box-border" />
 			</el-button>
 		</div>
-		<InfoDetail class="text-base" v-model="infoDetailIsShow" :item="detailMapRow"  />
+		<InfoDetail class="text-base" v-model="infoDetailIsShow" :item="detailMapRow" />
 
 		<div class="set-input">
 			<!-- @input="inputText" -->
@@ -39,8 +39,16 @@
 						@click="similarClick(item)"
 					>
 						<span class="text-sm text-gray-500 pr-1.5">{{ index + 1 }}</span>
-						<span> {{ item?.question }} </span>
-						<!-- <span class="text-blue-400 font-bold cursor-pointer hover:underline" @click.stop="tipMetricsClick">娴嬭瘯鏄�</span> -->
+						<template v-if="sentenceSplitMap?.[item.question]">
+							<template v-for="part in sentenceSplitMap[item.question]">
+								<span
+									v-if="part.isKeyword"
+									class="text-blue-400 font-bold cursor-pointer"
+									>{{ part.partStr }}</span
+								>
+								<span v-else>{{ part.partStr }}</span>
+							</template>
+						</template>
 					</div>
 				</div>
 			</div>
@@ -78,12 +86,12 @@
 import { ElMessage } from 'element-plus';
 import getCaretCoordinates from 'textarea-caret';
 import { computed, nextTick, ref } from 'vue';
-import VoicePage from './voicePage/VoicePage.vue';
-import { querySimilarityHistory } from '/@/api/ai/chat';
-import { useClickOther } from '/@/hooks/useClickOther';
 import InfoDetail from './InfoDetail.vue';
+import VoicePage from './voicePage/VoicePage.vue';
+import { getMetricsNames, querySimilarityHistory } from '/@/api/ai/chat';
 
 import { onClickOutside } from '@vueuse/core';
+import _ from 'lodash';
 const emits = defineEmits(['sendClick']);
 const props = defineProps(['isTalking', 'isHome']);
 const voicePageIsShow = defineModel('voicePageIsShow', {
@@ -153,13 +161,25 @@
 			popUpPosition.value.left = caret.left + leftOffset;
 			popUpPosition.value.bottom = container.offsetHeight + bottomOffset;
 			triggerShow.value = true;
+
 			if (lastIsFinish) {
 				querySimilarityApi(text);
 			}
 		}, 0);
 	});
 };
-
+// 瀵� question 杩涜鍒嗗壊
+const sentenceSplitMap = ref<
+	Record<
+		string,
+		{
+			partStr: string;
+			startIndex: number;
+			endIndex: number;
+			isKeyword: boolean;
+		}[]
+	>
+>({});
 const similarList = ref([]);
 let lastIsFinish = true;
 const querySimilarityApi = async (text: string) => {
@@ -172,6 +192,12 @@
 	const handleValues = res?.values ?? [];
 
 	similarList.value = props.isHome ? handleValues.slice(0, 3) : handleValues;
+	metricsNamesPromise.then((value) => {
+		sentenceSplitMap.value = getSentenceMatchMap(
+			similarList.value.map((item) => item.question),
+			value as string[]
+		);
+	});
 };
 const audioChangeWord = () => {
 	navigator.getUserMedia(
@@ -184,7 +210,161 @@
 		}
 	);
 };
+/**
+ * 鍒囧垎鍙ュ瓙锛屽尮閰嶈瘝鐢� isKeyword 鏍囪
+ * @param sentences
+ * @param keywords
+ */
+const getSentenceMatchMap = (sentences: string[], keywords: any[]) => {
+	if (!sentences || sentences.length === 0) return null;
+	if (!keywords || keywords.length===0) {
+		return sentences.map((item) => ({
+			partStr: item,
+			startIndex: 0,
+			endIndex: item.length,
+			isKeyword: false,
+		}));
+	}
+	let sentenceMatchMap = {};
 
+	sentences.map((sentence) => {
+		if (!sentenceMatchMap[sentence]) {
+			let sentenceMatchList = [];
+			keywords.map((keyword) => {
+				const matchList = [...sentence.matchAll(keyword)].map((item) => {
+					return {
+						partStr: item[0],
+						startIndex: item.index,
+						endIndex: item.index + item[0].length,
+					};
+				});
+				sentenceMatchList = sentenceMatchList.concat(matchList);
+			});
+
+			let nextIsMerge = false;
+			const checkNextIsMerge = (value, index, array) => {
+				nextIsMerge = false;
+				if (index === array.length - 1) return;
+				const nextValue = array[index + 1];
+
+				// 閫氳繃 nextIsMerge 鎺у埗涓嬩竴鍏冪礌鏄惁闇�瑕佷娇鐢�
+				if (value.endIndex > nextValue.startIndex) {
+					nextIsMerge = true;
+				}
+			};
+
+			// 鎸� startIndex 鎺掑簭锛屾秷闄ゅ郊姝や箣闂撮噸鍚堝厓绱�
+			sentenceMatchList = _.sortBy(sentenceMatchList, (item) => item.startIndex).filter((value, index, array) => {
+				if (nextIsMerge) {
+					checkNextIsMerge(value, index, array);
+					return false;
+				}
+				checkNextIsMerge(value, index, array);
+				return true;
+			});
+
+			sentenceMatchMap[sentence] = sentenceMatchList;
+		}
+	});
+
+	for (const sentence of Object.keys(sentenceMatchMap)) {
+		const matchList = sentenceMatchMap[sentence];
+		const result = [];
+
+		if (matchList.length === 0) {
+			result.push({
+				partStr: sentence,
+				startIndex: 0,
+				endIndex: sentence.length,
+				isKeyword: false,
+			});
+
+			sentenceMatchMap[sentence] = result;
+
+			continue;
+		}
+
+		matchList.forEach((value, index, array) => {
+			// 鍖归厤璇嶆伆濂戒笉鏄綅浜庣粨鏉熶綅缃�
+			if (array.length - 1 === index && value.endIndex !== array.length) {
+				result.push({
+					...value,
+					isKeyword: true,
+				});
+
+				if (value.endIndex !== sentence.length) {
+					result.push({
+						partStr: sentence.slice(value.endIndex, sentence.length),
+						startIndex: value.endIndex,
+						endIndex: sentence.length,
+						isKeyword: false,
+					});
+				}
+
+				// 濡傛灉鏁扮粍鍙湁涓�涓厓绱狅紝鍓嶉潰鐨勪篃闇�瑕佸姞杩涘幓
+				if (array.length === 1 && value.startIndex !== 0) {
+					result.unshift({
+						partStr: sentence.slice(0, value.startIndex),
+						startIndex: 0,
+						endIndex: value.startIndex,
+						isKeyword: false,
+					});
+				}
+
+				return;
+			}
+
+			// 鍖归厤璇嶆伆濂戒笉鏄綅浜庤捣濮嬩綅缃�
+			if (value.startIndex !== 0 && index === 0) {
+				result.push({
+					...value,
+					isKeyword: true,
+				});
+				result.unshift({
+					partStr: sentence.slice(0, value.startIndex),
+					startIndex: 0,
+					endIndex: value.startIndex,
+					isKeyword: false,
+				});
+
+				return;
+			}
+
+			// 鎭板ソ浣嶄簬绗竴涓�
+			if (index === 0) {
+				result.push({
+					...value,
+					isKeyword: true,
+				});
+				return;
+			}
+
+			// 涓棿鏈夐潪鍏抽敭璇�
+			if (array[index - 1].endIndex !== value.startIndex) {
+				result.push({
+					partStr: sentence.slice(array[index - 1].endIndex, value.startIndex),
+					startIndex: array[index - 1].endIndex,
+					endIndex: value.startIndex,
+					isKeyword: false,
+				});
+
+				result.push({
+					...value,
+					isKeyword: true,
+				});
+			}
+		});
+
+		sentenceMatchMap[sentence] = result;
+	}
+
+	return sentenceMatchMap;
+};
+
+const metricsNamesPromise = new Promise(async (resolve, reject) => {
+	const metricNames = (await getMetricsNames())?.values ?? [];
+	resolve(metricNames);
+});
 
 //#region ======================  楂樹寒鎸囨爣鐐瑰嚮======================
 const infoDetailIsShow = ref(false);
diff --git a/vite.config.ts b/vite.config.ts
index e9c23f4..3cdb41a 100644
--- a/vite.config.ts
+++ b/vite.config.ts
@@ -35,7 +35,7 @@
 			host: '0.0.0.0',
 			port: env.VITE_PORT as unknown as number,
 			open: JSON.parse(env.VITE_OPEN),
-			hmr: true,
+			hmr: false,
 		},
 		build: {
 			// outDir: 'dist/' + mode.mode,

--
Gitblit v1.9.3