From 1a20b21d285bc008f6a45fad132bc808a377f853 Mon Sep 17 00:00:00 2001
From: wujingjing <gersonwu@qq.com>
Date: 星期日, 19 一月 2025 11:21:31 +0800
Subject: [PATCH] 对话修改

---
 src/components/chat/smallChat/index.vue |  163 +++++++++++++++++++++++++-----------------------------
 1 files changed, 76 insertions(+), 87 deletions(-)

diff --git a/src/components/chat/smallChat/index.vue b/src/components/chat/smallChat/index.vue
index e40d41a..10bb079 100644
--- a/src/components/chat/smallChat/index.vue
+++ b/src/components/chat/smallChat/index.vue
@@ -1,18 +1,9 @@
 <template>
-	<div class="relative">
-		<el-tooltip v-if="!isOpen" content="浣犲ソ锛屾垜鏄疉I鍔╃悊锛屽彲浠ヨВ绛旈棶棰樸�佹帹鑽愯В鍐虫柟妗堢瓑" placement="right">
-			<div
-				class="flex flex-col items-center gap-1 cursor-pointer bg-white rounded-lg shadow-lg p-1 absolute bottom-4 right-4 opacity-80"
-				@click="openChat"
-			>
-				<img :src="assistantPic" class="size-10" alt="AI澶村儚" />
-				<span class="text-lg text-center w-5">AI鍔╂墜</span>
-			</div>
-		</el-tooltip>
-		<div v-else class="bg-white rounded-lg shadow-lg flex flex-col w-[400px] h-[600px] absolute bottom-4 right-4">
+	<div ref="chatContainerRef" :style="chatContainerStyle" class="opacity-90 small-chat-container" @mousedown="startDrag">
+		<div class="bg-white rounded-lg shadow-lg flex flex-col w-[400px] max-h-[600px] absolute bottom-4 right-4">
 			<!-- 澶撮儴 -->
-			<div class="h-12 flex items-center justify-between px-4 border-b">
-				<div class="text-base font-medium">WI姘村姟鏅鸿兘鍔╃悊</div>
+			<div ref="chatHeaderRef" :style="handleStyle" class="small-chat-header h-12 flex items-center justify-between px-4 border-b">
+				<div class="text-lg font-medium">WI姘村姟鏅鸿兘鍔╃悊</div>
 				<div class="flex items-center gap-2">
 					<!-- <el-icon class="cursor-pointer text-gray-400 hover:text-gray-600">
 					<Refresh />
@@ -23,14 +14,14 @@
 				<el-icon class="cursor-pointer text-gray-400 hover:text-gray-600">
 					<Star />
 				</el-icon> -->
-					<el-icon class="cursor-pointer text-gray-400 hover:text-gray-600" @click="closeChat">
+					<!-- <el-icon class="cursor-pointer text-gray-400 hover:text-gray-600" @click="closeChat">
 						<Close />
-					</el-icon>
+					</el-icon> -->
 				</div>
 			</div>
 
 			<!-- 鍐呭鍖� -->
-			<div class="flex-1 overflow-y-auto p-4">
+			<div class="flex-1 overflow-y-auto p-4" ref="chatContentRef" v-show="showHistory">
 				<div v-if="isInit">
 					<!-- 娆㈣繋璇� -->
 					<div class="flex flex-col items-center gap-4 mt-8">
@@ -48,10 +39,6 @@
 						>
 							{{ item }}
 						</div>
-						<!-- <div class="cursor-pointer hover:bg-gray-50 p-3 rounded-lg border border-solid border-gray-400">
-						闃块噷浜戜骇鍝佹�庝箞璐拱,閲嶇偣鏈夊摢浜涘姛鑳�?
-					</div>
-					<div class="cursor-pointer hover:bg-gray-50 p-3 rounded-lg border border-solid border-gray-400">AI 鍔╃悊鑳戒负鎴戝仛浠�涔�?</div> -->
 					</div>
 				</div>
 				<div v-else class="flex flex-col gap-4">
@@ -83,108 +70,113 @@
 			</div>
 
 			<!-- 搴曢儴杈撳叆妗� -->
-			<div class="p-4 border-t">
-				<ChatInput v-model="inputText" @sendClick="sendClick" />
+			<div class="p-2 border-t">
+				<ChatInput v-model="inputText" @sendClick="sendClick" @toggleHistory="toggleHistory" :showHistory="showHistory" />
 			</div>
 		</div>
 	</div>
 </template>
 
 <script setup lang="ts" name="smallChat">
-import { computed, onMounted, ref } from 'vue';
+import { computed, nextTick, onMounted, ref } from 'vue';
 import ChatInput from './ChatInput.vue';
 import type { ChatMessage } from './types';
 import { AssistantContent } from './types';
-import { agentStreamByPost, question_stream_reply } from '/@/api/ai/chat';
+import { agentStreamByPost } from '/@/api/ai/chat';
 import { Logger } from '/@/model/logger/Logger';
 import type { OLMap } from '/@/model/map/OLMap';
 import assistantPic from '/static/images/role/assistant-200x192.png';
 import userPic from '/static/images/role/user-200x206.png';
+import { useDrag } from '/@/hooks/useDrag';
 
 const props = defineProps<{
 	olMap?: OLMap;
 }>();
 const isOpen = ref(false);
 const inputText = ref('');
+/** @description 瀵硅瘽瀹屾垚鍓嶆槸鍚︽椂鍒濆鐘舵�� */
+let lastIsInit = true;
 const closeChat = () => {
 	isOpen.value = false;
 };
+const chatHeaderRef = ref<HTMLDivElement>(null);
+
+const chatContainerRef = ref<HTMLDivElement>(null);
+
+const { startDrag, style: chatContainerStyle, handleStyle } = useDrag({
+	handle: chatHeaderRef,
+});
+
 const historyMessages = ref<ChatMessage[]>([]);
 const isInit = computed(() => historyMessages.value.length === 0);
-const initQuestionList = ref(null);
+const initQuestionList = ref(['鏀惧ぇ', '缂╁皬']);
+const chatContentRef = ref<HTMLDivElement>(null);
+
 const getLastAssistantMessage = () => {
 	const last = historyMessages.value[historyMessages.value.length - 1];
 	const result = last.role === 'assistant' ? last : null;
 	return result as ChatMessage<AssistantContent>;
 };
-let streamIsOpen = false;
-const startStream = () => {
+
+const startStream = (question: string) => {
+	if (lastIsInit) {
+		showHistory.value = false;
+	}
+	let haveMapOperate = false;
 	agentStreamByPost(
 		{
+			question: question,
 			agent_id: 'a_019471cdb0667a83956b76ac97283f1c',
 		},
 		(chunkRes) => {
-			if (!streamIsOpen) {
-				streamIsOpen = true;
-			}
 			Logger.info('agent stream response锛歕n\n' + JSON.stringify(chunkRes));
-			if (chunkRes.mode === 'question') {
-				if (chunkRes.type === 'json') {
-					if (!initQuestionList.value) {
-						initQuestionList.value = chunkRes.value?.options ?? [];
-					}
-					activeQuestionChunk = chunkRes;
-				}
-			}
+
 			if (chunkRes.mode === 'map') {
+				haveMapOperate = true;
 				if (chunkRes.type === 'string') {
 					const jsonData = JSON.parse(chunkRes.value);
 					handleMapCommand(jsonData);
 				}
 			}
-
 			if (chunkRes.mode === 'finish') {
-				isOpen.value = false;
-				streamIsOpen = false;
-				const last = getLastAssistantMessage();
-				if (last) {
-					last.content.value = '宸查��鍑�';
-					last.content.isLoading = false;
+				if (!haveMapOperate) {
+					refreshAssistantMessage({ value: `鏈瘑鍒埌鎿嶄綔锛�${question}` });
 				}
 			}
 		}
-	);
+	).catch((error) => {
+		Logger.error('agent stream error锛歕n\n' + error);
+		refreshAssistantMessage();
+	});
+};
+
+const refreshAssistantMessage = (content: Partial<AssistantContent> = { value: 'AI鍥炵瓟澶辫触' }) => {
+	const last = getLastAssistantMessage();
+	if (last) {
+		last.content.value = content.value;
+		last.content.isLoading = content.isLoading;
+	}
 };
 const handleMapCommand = (command: any) => {
 	if (!command) return;
-	const last = getLastAssistantMessage();
-	if (last) {
-		last.content.value = `宸叉墽琛屾搷浣�: ${command.operate}`;
-		switch (command.operate) {
-			case '鏀惧ぇ':
-				props.olMap.zoomIn();
-				break;
+	switch (command.operate) {
+		case '鏀惧ぇ':
+			props.olMap.zoomIn();
+			break;
 
-			case '缂╁皬':
-				props.olMap.zoomOut();
-				break;
-		}
-		last.content.isLoading = false;
+		case '缂╁皬':
+			props.olMap.zoomOut();
+			break;
 	}
+	refreshAssistantMessage({ value: `宸叉墽琛屾搷浣�: ${command.operate}` });
 };
 
 const scrollToBottom = () => {
-	const chatContainer = document.querySelector('.chat-container');
-	if (chatContainer) {
-		chatContainer.scrollTop = chatContainer.scrollHeight;
+	if (chatContentRef.value) {
+		chatContentRef.value.scrollTop = chatContentRef.value.scrollHeight;
 	}
 };
-const openChat = () => {
-	isOpen.value = true;
-	if (!streamIsOpen) {
-		startStream();
-	}
-};
+
 const applyMessage = () => {
 	const time = Date.now().toString();
 	const userMessageId = `user-${time}`;
@@ -206,44 +198,41 @@
 		},
 	};
 	historyMessages.value.push(assistantMessage);
+
+	nextTick(() => {
+		scrollToBottom();
+	});
 	const userReactive = historyMessages.value.find((item) => item.id === userMessageId);
 	const assistantReactive = historyMessages.value.find((item) => item.id === assistantMessageId);
 	return [userReactive, assistantReactive];
 };
 
-const resetActive = () => {
-	activeQuestionChunk = null;
-};
-
-const refreshMessageList = () => {
-	historyMessages.value = historyMessages.value.concat([]);
-};
 const sendClick = async () => {
-	if (!activeQuestionChunk) return;
 	if (!inputText.value.trim()) return;
+	lastIsInit = isInit.value;
 	const lastMessage = historyMessages.value[historyMessages.value.length - 1];
 	if (lastMessage && lastMessage.role === 'assistant' && (lastMessage.content as AssistantContent).isLoading) return;
 	const [userMessage, assistantMessage] = applyMessage();
 	const question = inputText.value;
 	inputText.value = '';
-
-	const assistantContent = assistantMessage.content as AssistantContent;
-	const res = await question_stream_reply({
-		select: question,
-		reply_id: activeQuestionChunk.value.reply_id,
-	}).catch(() => {
-		assistantContent.isLoading = false;
-		assistantContent.value = 'AI鍥炵瓟澶辫触';
-	});
-	resetActive();
+	
+	startStream(question);
 };
 
 const handleQuestionClick = (item: string) => {
 	inputText.value = item;
 	sendClick();
 };
-const isFinish = ref(false);
-let activeQuestionChunk = null;
+
+//#region ====================== 鍘嗗彶鏄剧ず鎺у埗 ======================
+const showHistory = ref(true);
+const toggleHistory = () => {
+	showHistory.value = !showHistory.value;
+	nextTick(() => {
+		scrollToBottom();
+	});
+};
+//#endregion
 onMounted(() => {});
 </script>
 

--
Gitblit v1.9.3