feat: 长文本组件的调试
This commit is contained in:
@@ -33,6 +33,16 @@
|
|||||||
"navigationBarTextStyle": "black"
|
"navigationBarTextStyle": "black"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
,
|
||||||
|
{
|
||||||
|
"path": "pages/long-answer/index",
|
||||||
|
"style": {
|
||||||
|
"navigationStyle": "custom",
|
||||||
|
"backgroundColor": "#FFFFFF",
|
||||||
|
"navigationBarBackgroundColor": "#FFFFFF",
|
||||||
|
"navigationBarTextStyle": "black"
|
||||||
|
}
|
||||||
|
}
|
||||||
],
|
],
|
||||||
"subPackages": [
|
"subPackages": [
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -19,31 +19,31 @@
|
|||||||
<template #content v-if="item.toolCall || item.componentName">
|
<template #content v-if="item.toolCall || item.componentName">
|
||||||
<AnswerComponent v-if="
|
<AnswerComponent v-if="
|
||||||
item.componentName === CompName.longTextCard
|
item.componentName === CompName.longTextCard
|
||||||
" :answer-text="item.msg" />
|
" :answer-text="item.msg" :title="item.title" />
|
||||||
|
|
||||||
<QuickBookingComponent v-if="
|
<QuickBookingComponent v-if="
|
||||||
item.toolCall.componentName === CompName.quickBookingCard
|
item.toolCall && item.toolCall.componentName === CompName.quickBookingCard
|
||||||
" />
|
" />
|
||||||
<DiscoveryCardComponent v-else-if="
|
<DiscoveryCardComponent v-else-if="
|
||||||
item.toolCall.componentName === CompName.discoveryCard
|
item.toolCall && item.toolCall.componentName === CompName.discoveryCard
|
||||||
" />
|
" />
|
||||||
<CreateServiceOrder v-else-if="
|
<CreateServiceOrder v-else-if="
|
||||||
item.toolCall.componentName === CompName.callServiceCard
|
item.toolCall && item.toolCall.componentName === CompName.callServiceCard
|
||||||
" :toolCall="item.toolCall" />
|
" :toolCall="item.toolCall" />
|
||||||
<OpenMapComponent v-else-if="
|
<OpenMapComponent v-else-if="
|
||||||
item.toolCall.componentName === CompName.openMapCard
|
item.toolCall && item.toolCall.componentName === CompName.openMapCard
|
||||||
" />
|
" />
|
||||||
<Feedback v-else-if="
|
<Feedback v-else-if="
|
||||||
item.toolCall.componentName === CompName.feedbackCard
|
item.toolCall && item.toolCall.componentName === CompName.feedbackCard
|
||||||
" :toolCall="item.toolCall" />
|
" :toolCall="item.toolCall" />
|
||||||
<DetailCardCompontent v-else-if="
|
<DetailCardCompontent v-else-if="
|
||||||
item.toolCall.componentName === CompName.pictureAndCommodityCard
|
item.toolCall && item.toolCall.componentName === CompName.pictureAndCommodityCard
|
||||||
" :toolCall="item.toolCall" />
|
" :toolCall="item.toolCall" />
|
||||||
<AddCarCrad v-else-if="
|
<AddCarCrad v-else-if="
|
||||||
item.toolCall.componentName === CompName.enterLicensePlateCard
|
item.toolCall && item.toolCall.componentName === CompName.enterLicensePlateCard
|
||||||
" :toolCall="item.toolCall" />
|
" :toolCall="item.toolCall" />
|
||||||
<SurveyQuestionnaire v-else-if="
|
<SurveyQuestionnaire v-else-if="
|
||||||
item.toolCall.componentName === CompName.callSurveyQuestionnaire
|
item.toolCall && item.toolCall.componentName === CompName.callSurveyQuestionnaire
|
||||||
" :toolCall="item.toolCall" />
|
" :toolCall="item.toolCall" />
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -473,25 +473,32 @@ const handleWebSocketMessage = (data) => {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 确保消息内容是字符串类型
|
|
||||||
if (data.content && typeof data.content !== "string") {
|
|
||||||
try {
|
|
||||||
data.content = JSON.stringify(data.content);
|
|
||||||
} catch (e) {
|
|
||||||
data.content = String(data.content);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 优先使用 messageId 进行匹配
|
|
||||||
const msgId = data.messageId || data.id || data.msgId || data.replyMessageId;
|
|
||||||
let aiMsgIndex = -1;
|
let aiMsgIndex = -1;
|
||||||
if (msgId && pendingMap.has(msgId)) {
|
if (currentSessionMessageId && pendingMap.has(currentSessionMessageId)) {
|
||||||
aiMsgIndex = pendingMap.get(msgId);
|
|
||||||
} else if (!msgId && currentSessionMessageId && pendingMap.has(currentSessionMessageId)) {
|
|
||||||
// 服务端未返回 messageId 的场景:优先使用当前会话的 messageId 映射
|
|
||||||
aiMsgIndex = pendingMap.get(currentSessionMessageId);
|
aiMsgIndex = pendingMap.get(currentSessionMessageId);
|
||||||
|
if (aiMsgIndex >= 0 && aiMsgIndex < chatMsgList.value.length) {
|
||||||
|
const item = chatMsgList.value[aiMsgIndex];
|
||||||
|
if (item && item.msgType === MessageRole.AI &&
|
||||||
|
item.replyMessageId.length > 0 && data.replyMessageId &&
|
||||||
|
item.replyMessageId !== data.replyMessageId) {
|
||||||
|
// 已经存在对应的AI消息项,继续使用
|
||||||
|
const aiMsg = {
|
||||||
|
msgId: `msg_${chatMsgList.value.length}`,
|
||||||
|
msgType: MessageRole.AI,
|
||||||
|
msg: "",
|
||||||
|
isLoading: false,
|
||||||
|
messageId: currentSessionMessageId,
|
||||||
|
replyMessageId: '',
|
||||||
|
componentName: "",
|
||||||
|
title: "",
|
||||||
|
finish: false,
|
||||||
|
};
|
||||||
|
chatMsgList.value.push(aiMsg);
|
||||||
|
aiMsgIndex = chatMsgList.value.length - 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// 向后搜索最近的 AI 消息
|
// 向后搜索最近的 AI 消息(回退逻辑)
|
||||||
for (let i = chatMsgList.value.length - 1; i >= 0; i--) {
|
for (let i = chatMsgList.value.length - 1; i >= 0; i--) {
|
||||||
if (chatMsgList.value[i] && chatMsgList.value[i].msgType === MessageRole.AI) {
|
if (chatMsgList.value[i] && chatMsgList.value[i].msgType === MessageRole.AI) {
|
||||||
aiMsgIndex = i;
|
aiMsgIndex = i;
|
||||||
@@ -504,6 +511,20 @@ const handleWebSocketMessage = (data) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// replyMessageId
|
||||||
|
if(data.replyMessageId) {
|
||||||
|
chatMsgList.value[aiMsgIndex].replyMessageId = data.replyMessageId;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 确保消息内容是字符串类型
|
||||||
|
if (data.content && typeof data.content !== "string") {
|
||||||
|
try {
|
||||||
|
data.content = JSON.stringify(data.content);
|
||||||
|
} catch (e) {
|
||||||
|
data.content = String(data.content);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 直接拼接内容到对应 AI 消息
|
// 直接拼接内容到对应 AI 消息
|
||||||
if (data.content) {
|
if (data.content) {
|
||||||
if (chatMsgList.value[aiMsgIndex].isLoading) {
|
if (chatMsgList.value[aiMsgIndex].isLoading) {
|
||||||
@@ -522,15 +543,18 @@ const handleWebSocketMessage = (data) => {
|
|||||||
chatMsgList.value[aiMsgIndex].finish = true;
|
chatMsgList.value[aiMsgIndex].finish = true;
|
||||||
const msg = chatMsgList.value[aiMsgIndex].msg;
|
const msg = chatMsgList.value[aiMsgIndex].msg;
|
||||||
if (!msg || chatMsgList.value[aiMsgIndex].isLoading) {
|
if (!msg || chatMsgList.value[aiMsgIndex].isLoading) {
|
||||||
chatMsgList.value[aiMsgIndex].msg = "未获取到内容,请重试";
|
// 如果服务器返回了 componentName 或 toolCall,应保留空消息以供组件渲染;否则显示错误占位
|
||||||
chatMsgList.value[aiMsgIndex].isLoading = false;
|
if (data.toolCall || data.componentName) {
|
||||||
if (data.toolCall) {
|
|
||||||
chatMsgList.value[aiMsgIndex].msg = "";
|
chatMsgList.value[aiMsgIndex].msg = "";
|
||||||
|
} else {
|
||||||
|
chatMsgList.value[aiMsgIndex].msg = "未获取到内容,请重试";
|
||||||
}
|
}
|
||||||
|
chatMsgList.value[aiMsgIndex].isLoading = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 处理组件调用
|
// 处理组件调用
|
||||||
if (data.componentName) {
|
if (data.componentName) {
|
||||||
|
chatMsgList.value[aiMsgIndex].title = data.content;
|
||||||
chatMsgList.value[aiMsgIndex].componentName = data.componentName;
|
chatMsgList.value[aiMsgIndex].componentName = data.componentName;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -558,6 +582,8 @@ const handleWebSocketMessage = (data) => {
|
|||||||
isSessionActive.value = false;
|
isSessionActive.value = false;
|
||||||
// 清理当前会话的 messageId,避免保留陈旧 id
|
// 清理当前会话的 messageId,避免保留陈旧 id
|
||||||
resetMessageState();
|
resetMessageState();
|
||||||
|
|
||||||
|
nextTick(() => scrollToBottom());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -763,7 +789,9 @@ const sendChat = async (message, isInstruct = false) => {
|
|||||||
msg: "加载中",
|
msg: "加载中",
|
||||||
isLoading: true,
|
isLoading: true,
|
||||||
messageId: currentSessionMessageId,
|
messageId: currentSessionMessageId,
|
||||||
|
replyMessageId: '',
|
||||||
componentName: "",
|
componentName: "",
|
||||||
|
title: "",
|
||||||
finish: false,
|
finish: false,
|
||||||
};
|
};
|
||||||
chatMsgList.value.push(aiMsg);
|
chatMsgList.value.push(aiMsg);
|
||||||
|
|||||||
@@ -5,15 +5,15 @@
|
|||||||
<view class="flex flex-col p-16 border-box">
|
<view class="flex flex-col p-16 border-box">
|
||||||
<view class="flex flex-row flex-items-center justify-center">
|
<view class="flex flex-row flex-items-center justify-center">
|
||||||
<uni-icons class="icon-active" type="fire-filled" size="18" color="opacity" />
|
<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>
|
</view>
|
||||||
<!-- 文字内容,最多显示3行 -->
|
<!-- 文字内容,最多显示3行 -->
|
||||||
<view class="answer-content font-size-12 font-color-600 mt-8">
|
<view class="answer-content font-size-12 font-color-600 mt-8">
|
||||||
{{ answerText }}
|
<ChatMarkdown :text="answerText" />
|
||||||
</view>
|
</view>
|
||||||
<!-- 超过3行时显示...提示 -->
|
<!-- 超过3行时显示...提示 -->
|
||||||
<view class="fles flex-row mt-8" v-if="isOverflow">
|
<view class="fles flex-row mt-8" v-if="isOverflow" @click="lookDetailAction">
|
||||||
<text class="font-size-12 font-400 theme-color-500 mr-4">查看完整攻略</text>
|
<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>
|
<uni-icons class="icon-active" type="right" size="14" color="opacity"></uni-icons>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
@@ -22,12 +22,17 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref } from 'vue'
|
import { ref, defineProps } from 'vue'
|
||||||
|
import ChatMarkdown from "../../chat/ChatMarkdown/index.vue";
|
||||||
|
|
||||||
const isOverflow = ref(true)
|
const isOverflow = ref(true)
|
||||||
|
|
||||||
// 直接根据文字长度判断,超过约100个字符认为会溢出(约3行)
|
// 直接根据文字长度判断,超过约100个字符认为会溢出(约3行)
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
|
title: {
|
||||||
|
type: String,
|
||||||
|
default: "",
|
||||||
|
},
|
||||||
answerText: {
|
answerText: {
|
||||||
type: String,
|
type: String,
|
||||||
default: "",
|
default: "",
|
||||||
@@ -37,6 +42,12 @@ const props = defineProps({
|
|||||||
// 简单判断:12号字体3行约100个字符
|
// 简单判断:12号字体3行约100个字符
|
||||||
isOverflow.value = props.answerText.length > 100
|
isOverflow.value = props.answerText.length > 100
|
||||||
|
|
||||||
|
const lookDetailAction = () => {
|
||||||
|
uni.navigateTo({
|
||||||
|
url: `/pages/long-answer/index?message=${props.answerText}`,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
|
|||||||
18
src/pages/long-answer/index.vue
Normal file
18
src/pages/long-answer/index.vue
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
<template>
|
||||||
|
<ChatMarkdown :text="answerText" />
|
||||||
|
</template>
|
||||||
|
<script setup>
|
||||||
|
import ChatMarkdown from "../index/components/chat/ChatMarkdown/index.vue";
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
answerText: {
|
||||||
|
type: String,
|
||||||
|
default: "",
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
onLoad(({ message = "" }) => {
|
||||||
|
props.answerText = message;
|
||||||
|
});
|
||||||
|
|
||||||
|
</script>
|
||||||
Reference in New Issue
Block a user