feat: 兼容老的长文本

This commit is contained in:
2026-06-05 15:01:15 +08:00
parent be175591cc
commit 9d7a75a307
3 changed files with 55 additions and 36 deletions

View File

@@ -8,25 +8,29 @@
<!-- 滚动区域 --> <!-- 滚动区域 -->
<scroll-view class="flex-full overflow-hidden chat-scroll" scroll-y :scroll-into-view="scrollIntoViewId" scroll-with-animation @scroll="onScroll" @touchstart="onTouchStart" @touchend="onTouchEnd" @touchcancel="onTouchEnd"> <scroll-view class="flex-full overflow-hidden chat-scroll" scroll-y :scroll-into-view="scrollIntoViewId" scroll-with-animation @scroll="onScroll" @touchstart="onTouchStart" @touchend="onTouchEnd" @touchcancel="onTouchEnd">
<view class="flex flex-col pt-12 px-16 pb-24 border-box gap-8"> <view class="flex flex-col pt-12 px-16 pb-24 border-box gap-8">
<view v-if="headerSections.title || headerSections.tag" class="long-answer-header"> <template v-if="hasStructuredLongTextData">
<view v-if="headerSections.title" class="long-answer-title"> <view v-if="headerSections.title || headerSections.tag" class="long-answer-header">
{{ headerSections.title.contentValue }} <view v-if="headerSections.title" class="long-answer-title">
{{ headerSections.title.contentValue }}
</view>
<view v-if="headerSections.tag" class="long-answer-tag" :style="longAnswerTagStyle">
{{ headerSections.tag.contentValue }}
</view>
</view> </view>
<view v-if="headerSections.tag" class="long-answer-tag" :style="longAnswerTagStyle">
{{ headerSections.tag.contentValue }}
</view>
</view>
<template v-for="section in contentSections" :key="section.contentKey"> <template v-for="section in contentSections" :key="section.contentKey">
<ParsedValueView <ParsedValueView
v-if="shouldUseParsedValueView(section)" v-if="shouldUseParsedValueView(section)"
:field-key="section.contentKey" :field-key="section.contentKey"
:value="section.parsedValue !== null ? section.parsedValue : section.contentValue" :value="section.parsedValue !== null ? section.parsedValue : section.contentValue"
/> />
<ChatMarkdown v-else :text="section.contentValue" /> <ChatMarkdown v-else :text="section.contentValue" />
</template>
</template> </template>
<ChatMarkdown v-else-if="answerText" :text="answerText" />
<!-- 底部锚点必须存在 --> <!-- 底部锚点必须存在 -->
<view id="bottom-anchor"></view> <view id="bottom-anchor"></view>
</view> </view>
@@ -64,6 +68,10 @@ const longAnswerTagStyle = computed(() => buildTagToneStyle(longAnswerTagColor.v
let unsubscribe = null; let unsubscribe = null;
const HIDDEN_DETAIL_SECTION_KEYS = []; const HIDDEN_DETAIL_SECTION_KEYS = [];
const hasStructuredLongTextData = computed(() => {
const values = longTextData.value?.values;
return !!(values && Object.keys(values).length > 0);
});
const shouldUseParsedValueView = (section) => { const shouldUseParsedValueView = (section) => {
return ( return (
@@ -75,19 +83,14 @@ const shouldUseParsedValueView = (section) => {
}; };
const renderSections = computed(() => { const renderSections = computed(() => {
const data = longTextData.value; if (!hasStructuredLongTextData.value) return [];
if (data && data.values) {
return getLongTextSections(data)
.filter((section) => section.contentValue)
.map((section) => ({
...section,
fromLongTextData: true,
}));
}
return answerText.value return getLongTextSections(longTextData.value)
? [{ contentKey: "content", contentValue: answerText.value }] .filter((section) => section.contentValue)
: []; .map((section) => ({
...section,
fromLongTextData: true,
}));
}); });
const headerSections = computed(() => { const headerSections = computed(() => {

View File

@@ -74,15 +74,16 @@
" "
> >
<AnswerComponent <AnswerComponent
v-if="isLongTextCard(item.componentName)" v-if="isLongTextCard(item.componentName) && (item.componentName === CompName.longTextCard)"
:content="item.componentMsg || ''"
:longTextData="item.longTextData" :longTextData="item.longTextData"
:finish="item.finish" :finish="item.finish"
/> />
<!-- <LongTextGuideCardPreview <LongTextGuideCardPreview
v-if="isLongTextCard(item.componentName) && (item.componentName !== CompName.longTextCard)" v-if="isLongTextCard(item.componentName) && (item.componentName !== CompName.longTextCard)"
:componentName="item.componentName" :componentName="item.componentName"
/> --> />
<QuickBookingComponent <QuickBookingComponent
v-if=" v-if="
@@ -798,6 +799,7 @@ const handleWebSocketMessage = (data) => {
messageId: currentSessionMessageId, messageId: currentSessionMessageId,
replyMessageId: data.replyMessageId || "", replyMessageId: data.replyMessageId || "",
componentName: "", componentName: "",
componentMsg: "",
longTextData: null, longTextData: null,
finish: false, finish: false,
}; };
@@ -820,6 +822,7 @@ const handleWebSocketMessage = (data) => {
messageId: currentSessionMessageId, messageId: currentSessionMessageId,
replyMessageId: data.replyMessageId || "", replyMessageId: data.replyMessageId || "",
componentName: "", componentName: "",
componentMsg: "",
longTextData: null, longTextData: null,
finish: false, finish: false,
}; };
@@ -1213,6 +1216,7 @@ const sendChat = async (message, isInstruct = false) => {
messageId: currentSessionMessageId, messageId: currentSessionMessageId,
replyMessageId: "", replyMessageId: "",
componentName: "", componentName: "",
componentMsg: "",
longTextData: null, longTextData: null,
finish: false, finish: false,
}; };

View File

@@ -1,5 +1,5 @@
<template> <template>
<view v-if="longTextData?.values" class="w-full bg-white border-box border-ff overflow-hidden rounded-20 flex flex-col"> <view v-if="shouldRenderCard" class="w-full bg-white border-box border-ff overflow-hidden rounded-20 flex flex-col">
<!-- 占位撑开 --> <!-- 占位撑开 -->
<view class="w-vw"></view> <view class="w-vw"></view>
<view class="flex flex-col px-16 pt-16 pb-12 border-box" @click="lookDetailAction"> <view class="flex flex-col px-16 pt-16 pb-12 border-box" @click="lookDetailAction">
@@ -60,8 +60,20 @@ const tag = computed(() => getLongTextValue(props.longTextData, LONG_TEXT_KEYS.t
const title = computed(() => getLongTextValue(props.longTextData, LONG_TEXT_KEYS.title)); const title = computed(() => getLongTextValue(props.longTextData, LONG_TEXT_KEYS.title));
const longAnswerTagColor = ref(pickRandomTagToneColor()); const longAnswerTagColor = ref(pickRandomTagToneColor());
const longAnswerTagStyle = computed(() => buildTagToneStyle(longAnswerTagColor.value)); const longAnswerTagStyle = computed(() => buildTagToneStyle(longAnswerTagColor.value));
const hasStructuredLongTextData = computed(() => {
const values = props.longTextData?.values;
return !!(values && Object.keys(values).length > 0);
});
const detailLongTextData = computed(() => {
return hasStructuredLongTextData.value ? props.longTextData : null;
});
const previewContent = computed(() => { const previewContent = computed(() => {
return getLongTextPreviewText(props.longTextData, [LONG_TEXT_KEYS.contentSummary]); const structuredPreview = getLongTextPreviewText(props.longTextData, [LONG_TEXT_KEYS.contentSummary]);
if (structuredPreview) return structuredPreview;
return hasStructuredLongTextData.value ? "" : props.content || "";
});
const shouldRenderCard = computed(() => {
return hasStructuredLongTextData.value || !!previewContent.value || !props.finish;
}); });
// 处理文本内容:按行截断以保证预览最多显示两行(更贴近视觉行数) // 处理文本内容:按行截断以保证预览最多显示两行(更贴近视觉行数)
@@ -92,7 +104,7 @@ const isOverflow = computed(() => {
const contentStr = previewContent.value ? String(previewContent.value) : ""; const contentStr = previewContent.value ? String(previewContent.value) : "";
const lines = contentStr.split(/\r?\n/); const lines = contentStr.split(/\r?\n/);
return ( return (
hasLongTextExtraSections(props.longTextData) || (hasStructuredLongTextData.value && hasLongTextExtraSections(props.longTextData)) ||
lines.length > PREVIEW_LINES || lines.length > PREVIEW_LINES ||
contentStr.length > PREVIEW_CHAR_LIMIT contentStr.length > PREVIEW_CHAR_LIMIT
); );
@@ -128,11 +140,11 @@ const lookDetailAction = () => {
streamId, streamId,
previewContent.value ? String(previewContent.value) : "", previewContent.value ? String(previewContent.value) : "",
!!props.finish, !!props.finish,
props.longTextData || null, detailLongTextData.value,
); );
}; };
StreamManager.openStream(streamId, message, !!props.finish, props.longTextData || null); StreamManager.openStream(streamId, message, !!props.finish, detailLongTextData.value);
cleanupStreamWatchers(); cleanupStreamWatchers();
@@ -154,7 +166,7 @@ const lookDetailAction = () => {
streamId, streamId,
previewContent.value ? String(previewContent.value) : "", previewContent.value ? String(previewContent.value) : "",
!!f, !!f,
props.longTextData || null, detailLongTextData.value,
); );
if (f) { if (f) {
cleanupStreamWatchers(); cleanupStreamWatchers();
@@ -179,7 +191,7 @@ const lookDetailAction = () => {
overflow: hidden; overflow: hidden;
text-overflow: ellipsis; text-overflow: ellipsis;
line-height: 16px; line-height: 16px;
max-height: 52px; max-height: 62px;
} }
.long-answer-tag { .long-answer-tag {
display: inline-flex; display: inline-flex;