feat: 修复回答组件跳动的问题
This commit is contained in:
@@ -2,14 +2,14 @@
|
|||||||
<view class="w-full bg-white border-box border-ff overflow-hidden rounded-20 flex flex-col">
|
<view 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 p-16 border-box border-left-4">
|
<view class="flex flex-col px-12 pb-12 pt-4 border-box border-left-4">
|
||||||
<view v-if="title" class="flex flex-row flex-items-start flex-justify-start mb-8">
|
<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" />
|
<uni-icons class="icon-active" type="fire-filled" size="18" color="opacity" />
|
||||||
<text class="font-size-16 font-500 text-color-900 ml-6"> {{ title }}</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">
|
<view class="answer-content font-size-12 font-color-600">
|
||||||
<ChatMarkdown :key="textKey" :text="processedText" />
|
<ChatMarkdown :text="processedText" />
|
||||||
</view>
|
</view>
|
||||||
<!-- 超过3行时显示...提示 -->
|
<!-- 超过3行时显示...提示 -->
|
||||||
<view v-if="!finish" class="flex flex-row flex-items-center mt-8">
|
<view v-if="!finish" class="flex flex-row flex-items-center mt-8">
|
||||||
@@ -27,14 +27,12 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { defineProps, computed, ref, watch, onBeforeUnmount } from "vue";
|
import { defineProps, computed, watch, onBeforeUnmount } from "vue";
|
||||||
|
|
||||||
import ChatMarkdown from "../../ChatMain/ChatMarkdown/index.vue";
|
import ChatMarkdown from "../../ChatMain/ChatMarkdown/index.vue";
|
||||||
import ChatLoading from "../../ChatMain/ChatLoading/index.vue";
|
import ChatLoading from "../../ChatMain/ChatLoading/index.vue";
|
||||||
import StreamManager from '@/utils/StreamManager.js';
|
import StreamManager from '@/utils/StreamManager.js';
|
||||||
|
|
||||||
const isOverflow = ref(false)
|
|
||||||
|
|
||||||
// 直接根据文字长度判断,超过约100个字符认为会溢出(约3行)
|
// 直接根据文字长度判断,超过约100个字符认为会溢出(约3行)
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
title: {
|
title: {
|
||||||
@@ -51,9 +49,6 @@ const props = defineProps({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
// 用于强制重新渲染的key
|
|
||||||
const textKey = ref(0);
|
|
||||||
|
|
||||||
// 处理文本内容:按行截断以保证预览最多显示三行(更贴近视觉行数)
|
// 处理文本内容:按行截断以保证预览最多显示三行(更贴近视觉行数)
|
||||||
// 点击“查看详情”会跳转到完整页面(不受预览截断影响)。
|
// 点击“查看详情”会跳转到完整页面(不受预览截断影响)。
|
||||||
const PREVIEW_LINES = 3;
|
const PREVIEW_LINES = 3;
|
||||||
@@ -78,19 +73,27 @@ const processedText = computed(() => {
|
|||||||
return txt;
|
return txt;
|
||||||
});
|
});
|
||||||
|
|
||||||
// 监听 text 变化:更新 textKey 并同步 isOverflow(合并为单一响应函数,避免冗余)
|
const isOverflow = computed(() => {
|
||||||
watch(
|
const textStr = props.text ? String(props.text) : "";
|
||||||
() => props.text,
|
const lines = textStr.split(/\r?\n/);
|
||||||
(newText, oldText) => {
|
return lines.length > PREVIEW_LINES || textStr.length > PREVIEW_CHAR_LIMIT;
|
||||||
const textStr = newText ? String(newText) : "";
|
});
|
||||||
const lines = textStr.split(/\r?\n/);
|
|
||||||
isOverflow.value = lines.length > PREVIEW_LINES || textStr.length > PREVIEW_CHAR_LIMIT;
|
let stopForwardWatcher = null;
|
||||||
if (newText !== oldText) {
|
let stopFinishWatcher = null;
|
||||||
textKey.value++;
|
|
||||||
}
|
const cleanupStreamWatchers = () => {
|
||||||
},
|
if (stopForwardWatcher) {
|
||||||
{ immediate: true }
|
stopForwardWatcher();
|
||||||
);
|
stopForwardWatcher = null;
|
||||||
|
}
|
||||||
|
if (stopFinishWatcher) {
|
||||||
|
stopFinishWatcher();
|
||||||
|
stopFinishWatcher = null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
onBeforeUnmount(cleanupStreamWatchers);
|
||||||
|
|
||||||
const lookDetailAction = () => {
|
const lookDetailAction = () => {
|
||||||
const message = props.text ? String(props.text) : "";
|
const message = props.text ? String(props.text) : "";
|
||||||
@@ -98,31 +101,26 @@ const lookDetailAction = () => {
|
|||||||
const streamId = `stream_${Date.now()}_${Math.random().toString(36).slice(2,8)}`;
|
const streamId = `stream_${Date.now()}_${Math.random().toString(36).slice(2,8)}`;
|
||||||
StreamManager.openStream(streamId, message, !!props.finish);
|
StreamManager.openStream(streamId, message, !!props.finish);
|
||||||
|
|
||||||
// 将当前组件后续 props.text/props.finish 的更新转发到 StreamManager
|
cleanupStreamWatchers();
|
||||||
const stopForward = watch(
|
|
||||||
() => props.text,
|
|
||||||
(v) => {
|
|
||||||
StreamManager.updateStream(streamId, v ? String(v) : "", !!props.finish);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
const stopFinishWatcher = watch(
|
|
||||||
() => props.finish,
|
|
||||||
(f) => {
|
|
||||||
StreamManager.updateStream(streamId, props.text ? String(props.text) : "", !!f);
|
|
||||||
if (f) {
|
|
||||||
stopForward();
|
|
||||||
stopFinishWatcher();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
// 清理:组件卸载时停止转发(若仍存在)
|
if (!props.finish) {
|
||||||
onBeforeUnmount(() => {
|
// 将当前组件后续 props.text/props.finish 的更新转发到 StreamManager
|
||||||
try {
|
stopForwardWatcher = watch(
|
||||||
stopForward && stopForward();
|
() => props.text,
|
||||||
stopFinishWatcher && stopFinishWatcher();
|
(v) => {
|
||||||
} catch (e) {}
|
StreamManager.updateStream(streamId, v ? String(v) : "", !!props.finish);
|
||||||
});
|
}
|
||||||
|
);
|
||||||
|
stopFinishWatcher = watch(
|
||||||
|
() => props.finish,
|
||||||
|
(f) => {
|
||||||
|
StreamManager.updateStream(streamId, props.text ? String(props.text) : "", !!f);
|
||||||
|
if (f) {
|
||||||
|
cleanupStreamWatchers();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
// 传递 finished 参数,完成状态下不自动滚到底部
|
// 传递 finished 参数,完成状态下不自动滚到底部
|
||||||
uni.navigateTo({ url: `/pages/ChatMain/ChatLongAnswer/index?streamId=${encodeURIComponent(streamId)}&finished=${props.finish ? '1' : '0'}` });
|
uni.navigateTo({ url: `/pages/ChatMain/ChatLongAnswer/index?streamId=${encodeURIComponent(streamId)}&finished=${props.finish ? '1' : '0'}` });
|
||||||
@@ -147,4 +145,4 @@ const lookDetailAction = () => {
|
|||||||
.border-left-4 {
|
.border-left-4 {
|
||||||
border-left: 4px solid $theme-color-500;
|
border-left: 4px solid $theme-color-500;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
Reference in New Issue
Block a user