feat: 消息问答的调整

This commit is contained in:
2026-04-03 00:43:11 +08:00
parent 679bea9135
commit d2fc0973dd
3 changed files with 64 additions and 18 deletions

View File

@@ -15,11 +15,10 @@
<view class="area-msg-list-content" v-for="item in chatMsgList" :key="item.msgId" :id="item.msgId">
<template v-if="item.msgType === MessageRole.AI">
<ChatCardAI class="flex flex-justify-start" :key="`ai-${item.msgId}-${item.msg ? item.msg.length : 0}`"
:text="item.finish && item.componentName ? '' : item.msg || ''" :isLoading="item.isLoading">
<template #content v-if="item.toolCall || item.componentName">
<AnswerComponent v-if="
item.componentName === CompName.longTextCard
" :text="item.msg" :title="item.title" />
:text="item.componentName && item.componentName === CompName.longTextCard ? '' : item.msg || ''" :isLoading="item.isLoading">
<template #content v-if="item.toolCall || item.componentName && item.componentName === CompName.longTextCard">
<AnswerComponent v-if=" item.componentName === CompName.longTextCard
" :text="(item.componentMsg || item.msg)" :title="item.title" :finish="item.finish" />
<QuickBookingComponent v-if="
item.toolCall && item.toolCall.componentName === CompName.quickBookingCard
" />
@@ -545,11 +544,29 @@ const handleWebSocketMessage = (data) => {
}
}
// 防护:确保 aiMsgIndex 有效
if (aiMsgIndex < 0 || aiMsgIndex >= chatMsgList.value.length) {
console.error('无效的 aiMsgIndex:', aiMsgIndex);
return;
}
// replyMessageId
if(data.replyMessageId) {
chatMsgList.value[aiMsgIndex].replyMessageId = data.replyMessageId;
}
// 如果服务端在分片中就带来了 componentName提前记录并将已缓存的 msg 转移到 componentMsg
const aiItem = chatMsgList.value[aiMsgIndex];
if (data.componentName) {
aiItem.componentName = data.componentName;
if (data.componentName === CompName.longTextCard) {
if (aiItem.msg && aiItem.msg.length > 0) {
aiItem.componentMsg = (aiItem.componentMsg || "") + aiItem.msg;
aiItem.msg = "";
}
}
}
// 确保消息内容是字符串类型
if (data.content && typeof data.content !== "string") {
try {
@@ -561,13 +578,24 @@ const handleWebSocketMessage = (data) => {
// 直接拼接内容到对应 AI 消息
if (data.content) {
if (chatMsgList.value[aiMsgIndex].isLoading) {
// 首次收到内容:替换“加载中”文案并取消 loading 状态(恢复原始渲染逻辑)
chatMsgList.value[aiMsgIndex].msg = data.content;
chatMsgList.value[aiMsgIndex].isLoading = false;
// 如果该条消息属于 longTextCard使用 componentMsg 存储内容并保持 ChatCardAI 的 text 为空
const isLongText = aiItem.componentName === CompName.longTextCard || data.componentName === CompName.longTextCard;
if (isLongText) {
if (aiItem.isLoading) {
aiItem.componentMsg = (aiItem.componentMsg || "") + data.content;
aiItem.isLoading = false;
} else {
aiItem.componentMsg = (aiItem.componentMsg || "") + data.content;
}
} else {
// 后续流式内容追加
chatMsgList.value[aiMsgIndex].msg += data.content;
if (aiItem.isLoading) {
// 首次收到内容:替换“加载中”文案并取消 loading 状态(恢复原始渲染逻辑)
aiItem.msg = data.content;
aiItem.isLoading = false;
} else {
// 后续流式内容追加
aiItem.msg += data.content;
}
}
nextTick(() => scrollToBottom());
}

View File

@@ -2,20 +2,25 @@
<view class="w-full bg-white border-box border-ff overflow-hidden rounded-20 flex flex-col">
<!-- 占位撑开 -->
<view class="w-vw"></view>
<view class="flex flex-col p-16 border-box">
<view class="flex flex-row flex-items-start flex-justify-start">
<view class="flex flex-col p-16 border-box border-left-4">
<view v-if="title" class="flex flex-row flex-items-start flex-justify-start mb-8">
<uni-icons class="icon-active" type="fire-filled" size="18" color="opacity" />
<text class="font-size-16 font-500 text-color-900 ml-6">游玩划重点</text>
<text class="font-size-16 font-500 text-color-900 ml-6"> {{ title }}</text>
</view>
<!-- 文字内容最多显示3行 -->
<view class="answer-content font-size-12 font-color-600 mt-8">
<view class="answer-content font-size-12 font-color-600">
<ChatMarkdown :key="textKey" :text="processedText" />
</view>
<!-- 超过3行时显示...提示 -->
<view class="flex flex-row flex-items-center mt-8" v-if="isOverflow" @click="lookDetailAction">
<view v-if="!finish" class="flex flex-row flex-items-center mt-8">
<text class="font-size-12 font-400 font-color-600">正在生成</text>
<DotLoading />
</view>
<view v-if="isOverflow && finish" class="flex flex-row flex-items-center mt-8" @click="lookDetailAction">
<text class="font-size-12 font-400 theme-color-500 mr-4">查看详情</text>
<uni-icons class="icon-active" type="right" size="14" color="opacity"></uni-icons>
</view>
</view>
</view>
@@ -25,6 +30,7 @@
import { defineProps, computed, ref, watch } from "vue";
import ChatMarkdown from "../../chat/ChatMarkdown/index.vue";
import DotLoading from "../../loading/DotLoading.vue";
const isOverflow = ref(false)
@@ -37,7 +43,11 @@ const props = defineProps({
text: {
type: String,
default: "",
}
},
finish: {
type: Boolean,
default: false,
},
});
// 用于强制重新渲染的key
@@ -102,5 +112,9 @@ const lookDetailAction = () => {
overflow: hidden;
text-overflow: ellipsis;
line-height: 16px;
max-height: 80px;
}
.border-left-4 {
border-left: 4px solid $theme-color-500;
}
</style>

View File

@@ -1,6 +1,6 @@
<template>
<view class="bg-F5F7FA flex flex-col h-screen overflow-hidden">
<TopNavBar title="详情" backgroundColor="transparent" />
<TopNavBar :title="title" backgroundColor="transparent" />
<view class="flex-full overflow-hidden scroll-y p-12 border-box">
<ChatMarkdown :text="answerText" />
</view>
@@ -20,9 +20,13 @@ const props = defineProps({
});
const answerText = ref(props.answerText || "");
const title = ref("");
onLoad(({ message = "" }) => {
answerText.value = decodeURIComponent(message);
if (answerText.value.length > 6) {
title.value = answerText.value.substring(0, 6) + "...";
}
});
</script>