From 1d0eec6da86e3e9bcbf002d1a22142586fe023a3 Mon Sep 17 00:00:00 2001
From: wujingjing <gersonwu@qq.com>
Date: 星期二, 31 十二月 2024 11:34:15 +0800
Subject: [PATCH] 拆分组件 assistantMsg.vue

---
 src/components/chat/Chat.vue |  335 ++++---------------------------------------------------
 1 files changed, 25 insertions(+), 310 deletions(-)

diff --git a/src/components/chat/Chat.vue b/src/components/chat/Chat.vue
index 4cad518..ff4ec3f 100644
--- a/src/components/chat/Chat.vue
+++ b/src/components/chat/Chat.vue
@@ -12,267 +12,20 @@
 				<div v-for="(item, msgIndex) of computedMessageList" :key="`${item.historyId}_${item.role}`">
 					<UserMsg
 						:msg="item"
-						@copyMsg="copyClick"
 						@shareClick="shareClick"
 						@setCommonQuestion="setCommonQuestionClick"
 						v-if="item.role === RoleEnum.user"
 					></UserMsg>
 
-					<div v-else class="flex px-4 py-6 rounded-lg relative" :class="{ 'px-10': isShareCheck }">
-						<div class="absolute top-0 left-[72px] text-[#8d8e99]">{{ item?.createTime }}</div>
-
-						<img
-							class="rounded-full size-12 flex-0"
-							:class="{ 'mr-4': item.role === RoleEnum.assistant }"
-							:src="roleImageMap[item.role]"
-							alt=""
-							srcset=""
-						/>
-						<div class="flex-auto flex">
-							<div class="inline-flex flex-col" :class="{ 'w-full': item.role === RoleEnum.assistant }">
-								<div class="w-full">
-									<div class="rounded-[6px] p-4 leading-relaxed bg-white">
-										<!-- #region ====================== 娑堟伅鍐呭 ======================-->
-										<!-- <template v-if="item.content?.values"> -->
-										<!-- #region ====================== 鎶ラ敊淇℃伅 ======================-->
-										<div v-if="item.content?.errCode === ErrorCode.Message" class="flex-column w-full">
-											<p class="text-danger">
-												{{ item.content.errMsg }}
-											</p>
-											<div class="mt-3 flex" v-if="showFixQuestion(item)">
-												<div class="text-gray-600 flex-0 mb-auto py-3">
-													{{ '鐚滀綘鎯抽棶锛�' }}
-												</div>
-												<div class="flex-auto space-x-2 space-y-1 inline-flex flex-wrap items-center">
-													<div
-														v-for="fixItem in item.content.origin?.sample_question"
-														:key="fixItem"
-														class="bg-gray-200 p-3 hover:bg-[#c5e0ff] hover:text-[#1c86ff] cursor-pointer rounded-lg first-of-type:ml-2 first-of-type:mt-1"
-														@click="fixQuestionClick(fixItem, item.content.origin)"
-													>
-														{{ fixItem }}
-													</div>
-												</div>
-											</div>
-										</div>
-										<!-- #endregion -->
-										<!-- #region ====================== 鍥炵瓟缁勪欢 ======================-->
-										<template v-else>
-											<template v-if="item.content.type === AnswerType.Report">
-												<template v-if="item?.stepGroup?.length > 0">
-													<div v-for="(num, index) in item?.stepGroup?.length" :key="index">
-														<!-- #region ====================== 鎰忓浘鍒嗘瀽 ======================-->
-														<div class="flex flex-col" v-if="item?.stepGroup?.[index]?.value?.length > 0">
-															<!-- #region ====================== 鎰忓浘鍒嗘瀽 ======================-->
-															<div class="flex items-center">
-																<span class="mr-2">鎰忓浘鍒嗘瀽锛�</span>
-																<div
-																	@click="toggleStepList(item?.stepGroup?.[index])"
-																	class="cursor-pointer border border-gray-300 border-solid w-fit px-2 flex items-center space-x-2 rounded-lg hover:bg-gray-100 active:bg-gray-200"
-																>
-																	<span>
-																		{{ toggleStepLabel(item?.stepGroup?.[index]) }}
-																	</span>
-																	<span
-																		class="ywifont"
-																		:class="{
-																			'ywicon-unfold': !item?.stepGroup?.[index].isShow,
-																			'ywicon-fold': item?.stepGroup?.[index].isShow,
-																		}"
-																	></span>
-																</div>
-															</div>
-															<!-- #endregion -->
-
-															<!-- #region ====================== 杩囩▼杈撳嚭 ======================-->
-															<el-steps
-																v-show="item?.stepGroup?.[index].isShow"
-																class="mt-3"
-																direction="vertical"
-																:active="activeStep"
-															>
-																<el-step
-																	:key="`template-${stepIndex}`"
-																	v-for="(subItem, stepIndex) in item?.stepGroup?.[index].value"
-																	:title="subItem.title"
-																	:status="stepEnumMap[subItem.status]"
-																>
-																	<template
-																		#icon
-																		v-if="
-																			stepIndex + 1 === item?.stepGroup?.[index].value.length &&
-																			isTalking &&
-																			msgIndex === computedMessageList.length - 1
-																		"
-																	>
-																		<span class="ywifont ywicon-loading1 animate-spin !text-[24px]"></span>
-																	</template>
-																	<template #title>
-																		<span class="">
-																			{{ subItem.title }}
-
-																			<span v-if="subItem.ms" class="text-green-600">{{ `锛�${subItem.ms}锛塦 }}</span></span
-																		>
-																	</template>
-
-																	<template #description v-if="subItem?.subStep?.length > 0">
-																		<div class="my-1 flex flex-col gap-1 text-[14px]">
-																			<div
-																				:key="`${item.historyId}-${stepIndex + 1}-${multiChatIndex + 1}`"
-																				v-for="(multiChatItem, multiChatIndex) in subItem.subStep"
-																			>
-																				<component
-																					v-if="multiChatItem.type === MultiChatType.Select"
-																					:order="`${stepIndex + 1}-${multiChatIndex + 1}`"
-																					:item="multiChatItem"
-																					:is="multiChatTypeMapCom[multiChatItem.type]"
-																					:disabled="
-																						!(
-																							stepIndex + 1 === item?.stepGroup?.[index].value.length &&
-																							isTalking &&
-																							msgIndex === computedMessageList.length - 1
-																						)
-																					"
-																				/>
-																				<component
-																					v-else-if="multiChatItem.type === MultiChatType.Result"
-																					:is="answerTypeMapCom['summary']"
-																					:data="multiChatItem.data.content.values"
-																					:originData="multiChatItem.data"
-																				/>
-																				<div v-else-if="multiChatItem.type === MultiChatType.Summary" class="ml-4 mt-5 pb-10">
-																					<div class="text-gray-600 mb-5">浣犲彲浠ョ户缁棶鎴戯細</div>
-																					<div class="space-y-2 inline-flex flex-col">
-																						<div
-																							v-for="item in multiChatItem.data.content.askMoreList"
-																							:key="item.history_id"
-																							class="bg-white p-3 hover:bg-[#c5e0ff] hover:text-[#1c86ff] cursor-pointer rounded-lg"
-																							@click="askMoreClick(item)"
-																						>
-																							{{ item.question }}
-																						</div>
-																					</div>
-																				</div>
-																			</div>
-																		</div>
-																	</template>
-																</el-step>
-															</el-steps>
-															<!-- #endregion -->
-														</div>
-														<!-- #endregion -->
-
-														<component
-															v-if="item.content?.values?.[index]"
-															:reportIndex="index"
-															:conclusion="item.content.values[index].conclusion"
-															:is="answerTypeMapCom[item.content.values[index].content.type]"
-															:data="item.content.values[index].content.values"
-															:originData="item.content.values[index]"
-															:historyId="item.historyId"
-															:isTalking="isTalking && msgIndex === computedMessageList.length - 1"
-														/>
-													</div>
-												</template>
-												<p v-else class="text-info">鏆傛棤鍐呭锛岃閲嶈瘯</p>
-											</template>
-											<component
-												v-else
-												:historyId="item.historyId"
-												:conclusion="item.conclusion"
-												:is="answerTypeMapCom[item.content.type]"
-												:data="item.content.values"
-												:originData="item"
-												:isTalking="isTalking && msgIndex === computedMessageList.length - 1"
-											/>
-										</template>
-										<!-- #endregion -->
-										<!-- </template> -->
-
-										<!-- #endregion -->
-										<!-- #region ====================== 闄勫姞鍐呭 ======================-->
-										<!-- #region ====================== 鍋滄 ======================-->
-										<span v-if="item.isStopMsg && item?.role === RoleEnum.assistant" class="text-gray-400 text-[12px]"
-											>锛堝凡鍋滄锛�</span
-										>
-										<!-- parseContent 杩斿洖涓� null -->
-										<p v-if="!item.content && !isTalking && !item.isStopMsg" class="text-red-500">鏆傛棤鏁版嵁</p>
-										<!-- #endregion -->
-										<!-- #endregion -->
-									</div>
-									<!-- #region ====================== ai 娑堟伅鎿嶄綔 ======================-->
-									<div
-										v-if="item.role === RoleEnum.assistant && item.content?.values && !isSharePage && !isShareCheck"
-										class="absolute flex items-center right-0 mr-4 mt-2 space-x-2"
-									>
-										<div
-											class="flex items-center justify-center size-[15px]"
-											v-if="item.content?.type === AnswerType.Text || item.content?.type === AnswerType.Knowledge"
-										>
-											<i
-												class="p-2 ywifont ywicon-copy cursor-pointer hover:text-[#0284ff] hover:!text-[18px]"
-												@click="copyClick(item)"
-											/>
-										</div>
-										<template v-if="item.content.errCode !== ErrorCode.Message">
-											<el-tooltip effect="dark" content="鐐硅禐" placement="top">
-												<div class="flex items-center justify-center size-[15px]">
-													<i
-														:class="{ 'text-[#0284ff]': item.state === AnswerState.Like }"
-														class="p-2 ywifont ywicon-dianzan cursor-pointer hover:text-[#0284ff] font-medium hover:!text-[18px]"
-														@click="likeClick(item)"
-													/>
-												</div>
-											</el-tooltip>
-											<el-tooltip effect="dark" content="鐐硅俯" placement="top">
-												<div class="flex items-center justify-center size-[15px]">
-													<i
-														:class="{ 'text-[#0284ff]': item.state === AnswerState.Unlike }"
-														class="p-2 ywifont ywicon-buzan cursor-pointer hover:text-[#0284ff] !text-[13px] hover:!text-[15px]"
-														@click="unLikeClick(item)"
-													/>
-												</div>
-											</el-tooltip>
-										</template>
-										<el-tooltip effect="dark" content="鍒嗕韩" placement="top">
-											<div class="flex items-center justify-center size-[15px]">
-												<i
-													class="p-2 ywifont ywicon-fenxiang cursor-pointer hover:text-[#0284ff] !text-[15px] hover:!text-[18px]"
-													@click="shareClick(item)"
-												/>
-											</div>
-										</el-tooltip>
-										<el-tooltip effect="dark" content="鍙嶉" placement="top">
-											<div class="flex items-center justify-center size-[15px] relative">
-												<i
-													class="p-2 ywifont ywicon-wentifankui cursor-pointer hover:text-[#0284ff] !text-[13px] hover:!text-[15px]"
-													@click="
-														($event) =>
-															feedbackClick(
-																$event,
-																item,
-																computedMessageList
-																	.filter((v) => v.role === RoleEnum.assistant)
-																	.findIndex((v) => v.historyId === item.historyId)
-															)
-													"
-												/>
-												<FeedbackPanel
-													v-show="feedbackIsShow && currentFeedbackMapItem === item"
-													ref="feedbackPanelRef"
-													v-model:isShow="feedbackIsShow"
-													v-model:content="feedbackContent"
-													:chatItem="currentFeedbackMapItem"
-													:position="feedbackPosition"
-												/>
-											</div>
-										</el-tooltip>
-									</div>
-									<!-- #endregion -->
-								</div>
-							</div>
-						</div>
-					</div>
+					<AssistantMsg
+						v-else
+						:msg="item"
+						:msgList="computedMessageList"
+						:isLast="msgIndex === computedMessageList.length - 1"
+						@sendChatMessage="sendChatMessage"
+						@shareMsg="shareClick"
+						:isTalking="isTalking"
+					/>
 				</div>
 				<div v-if="showAskMore" class="ml-4 mt-5 pb-10">
 					<div class="text-gray-600 mb-5">浣犲彲浠ョ户缁棶鎴戯細</div>
@@ -322,35 +75,23 @@
 <script setup lang="ts">
 import type { CancelTokenSource } from 'axios';
 import axios from 'axios';
-import { findLast, orderBy } from 'lodash-es';
+import { orderBy } from 'lodash-es';
 import moment from 'moment';
 import { computed, onActivated, onMounted, ref } from 'vue';
-import useClipboard from 'vue-clipboard3';
 import { loadAmisSource } from '../amis/load';
-import FeedbackPanel from './components/FeedbackPanel.vue';
-import { useAssistantContentOpt } from './hooks/useAssistantContentOpt';
 import { convertProcessItem, convertProcessToStep, formatShowTimeYear, useScrollLoad } from './hooks/useScrollLoad';
 import type { ChatContent } from './model/types';
-import {
-	AnswerState,
-	AnswerType,
-	MultiChatType,
-	RoleEnum,
-	answerTypeMapCom,
-	roleImageMap,
-	stepEnumMap,
-	type ChatMessage,
-} from './model/types';
-import { extCallQuery, getShareChatJsonByPost, questionStreamByPost } from '/@/api/ai/chat';
+import { AnswerState, AnswerType, RoleEnum, type ChatMessage } from './model/types';
+import { getShareChatJsonByPost, questionStreamByPost } from '/@/api/ai/chat';
 import PlayBar from '/@/components/chat/components/playBar/PlayBar.vue';
 import CustomDrawer from '/@/components/drawer/CustomDrawer.vue';
 import { Logger } from '/@/model/logger/Logger';
 
 import { ElMessage } from 'element-plus';
+import AssistantMsg from './assistant/index.vue';
 import ChatContainer from './components/ChatContainer.vue';
 import ShareLinkDlg from './components/shareLink/index.vue';
 import UserMsg from './user/index.vue';
-import { multiChatTypeMapCom } from '/@/components/chat/chatComponents/multiChat';
 import router from '/@/router';
 import {
 	activeChatRoom,
@@ -362,7 +103,6 @@
 	roomConfig,
 } from '/@/stores/chatRoom';
 import emitter from '/@/utils/mitt';
-import { ErrorCode } from '/@/utils/request';
 import { useCompRef } from '/@/utils/types';
 import { toMyFixed } from '/@/utils/util';
 const containerRef = useCompRef(ChatContainer);
@@ -488,22 +228,9 @@
 	return content;
 };
 
-//#region ====================== 姝ラ step ======================
-const activeStep = ref(-1);
-
-const resetStep = () => {
-	activeStep.value = -1;
-};
-
-const toggleStepLabel = (item: any) => (item.isShow ? '鏀惰捣' : '灞曞紑');
-const toggleStepList = (item: any) => {
-	item.isShow = !item.isShow;
-};
-
-//#endregion
-
 let questionRes = null;
 let position = null;
+const preQuestion = ref(null);
 
 let lastAxiosSource: CancelTokenSource = null;
 const questionAi = async (text) => {
@@ -538,7 +265,6 @@
 		currentSampleId = '';
 	}
 
-	resetStep();
 	let lastTimestamp = new Date().getTime();
 	questionRes = {};
 	let lastIsResult = false;
@@ -706,8 +432,6 @@
 				computedMessageList.value.at(-1).stepGroup.forEach((item) => {
 					item.isShow = false;
 				});
-
-				resetStep();
 			});
 	});
 
@@ -730,7 +454,7 @@
 	lastAxiosSource?.cancel();
 	isTalking.value = false;
 	chatListLoading.value = false;
-	resetStep();
+
 	computedMessageList.value.at(-1).isStopMsg = true;
 };
 
@@ -942,25 +666,17 @@
 	messageContent.value.values = history_data.value[currentIndex.value].content.values;
 };
 //#endregion
-const {
-	copyClick,
-	likeClick,
-	unLikeClick,
-	feedbackPosition,
-	feedbackIsShow,
-	feedbackContent,
-	feedbackPanelRef,
-	currentFeedbackMapItem,
-	feedbackClick,
-	askMoreClick,
-	fixQuestionClick,
-	preQuestion,
-	showFixQuestion,
-	showAskMore,
-} = useAssistantContentOpt({
-	sendChatMessage,
-	displayMessageList: computedMessageList,
+const showAskMore = computed(() => {
+	if (!computedMessageList.value || computedMessageList.value.length === 0) return false;
+	const last = computedMessageList.value.at(-1);
+	const isShow = last?.role === RoleEnum.assistant && last?.content?.values && last.content?.askMoreList?.length > 0;
+	const result = isShow && !isSharePage.value;
+	return result;
 });
+const askMoreClick = (item) => {
+	if (!item.question) return;
+	sendChatMessage({ type: AnswerType.Text, values: item.question });
+};
 
 //#region ====================== 渚ц竟鏍廳rawer ======================
 const drawerIsShow = ref(false);
@@ -981,7 +697,6 @@
 //#region ====================== 鍒嗕韩 ======================
 
 const shareLinkDlgRef = useCompRef(ShareLinkDlg);
-const isShareCheck = ref(false);
 
 const shareClick = async (item: ChatMessage) => {
 	shareLinkDlgRef.value.openShare(item);

--
Gitblit v1.9.3