Browse Source

添加文字滚动效果

wangyi/feature-20251022162725-启动页登录注册
Ethereal 1 month ago
parent
commit
de93dcda75
  1. 156
      pages/deepMate/deepMate.vue

156
pages/deepMate/deepMate.vue

@ -1,6 +1,6 @@
<template>
<view class="deepMate-page">
<!-- 顶部导航栏 -->
<!-- 顶部导航栏 - 固定定位 -->
<view class="header" :style="{ paddingTop: safeAreaInsets?.top + 'px' }">
<view class="header-left">
<image
@ -29,6 +29,9 @@
<!-- 主要内容区域 -->
<view class="main-content">
<!-- 顶部固定区域占位符 -->
<view class="banner-placeholder"></view>
<view class="banner-panel"
:class="messages.length === 0 ? '' : 'panelShow'"
>
@ -102,37 +105,40 @@
<!-- 聊天区域 -->
<view class="chat-container" v-if="messages.length > 0">
<view class="message-list" id="messageList">
<view
v-for="(message, index) in messages"
:key="index"
:class="
message.isUser ? 'message user-message' : 'message bot-message'
"
>
<!-- 会话图标 -->
<text
<!-- 给聊天容器添加滚动引用 -->
<scroll-view class="chat-scroll-view" scroll-y="true" :scroll-top="scrollTop">
<view class="message-list" id="messageList">
<view
v-for="(message, index) in messages"
:key="index"
:class="
message.isUser
? 'fa-solid fa-user message-icon'
: 'fa-solid fa-robot message-icon'
message.isUser ? 'message user-message' : 'message bot-message'
"
></text>
<!-- 会话内容 -->
<view class="message-content">
<text class="message-text">{{ message.content }}</text>
<!-- loading -->
<view
class="loading-dots"
v-if="message.isThinking "
>
<text class="dot"></text>
<text class="dot"></text>
<text class="dot"></text>
>
<!-- 会话图标 -->
<text
:class="
message.isUser
? 'fa-solid fa-user message-icon'
: 'fa-solid fa-robot message-icon'
"
></text>
<!-- 会话内容 -->
<view class="message-content">
<text class="message-text">{{ message.content }}</text>
<!-- loading -->
<view
class="loading-dots"
v-if="message.isThinking "
>
<text class="dot"></text>
<text class="dot"></text>
<text class="dot"></text>
</view>
</view>
</view>
</view>
</view>
</scroll-view>
</view>
</view>
@ -171,7 +177,7 @@
<script setup>
const { safeAreaInsets } = uni.getSystemInfoSync();
import { ref, onMounted, nextTick } from "vue";
import { ref, onMounted, nextTick, watch } from "vue";
import footerBar from "../../components/footerBar-cn.vue";
@ -180,6 +186,7 @@ const inputMessage = ref("");
const isSending = ref(false);
const uuid = ref("");
const messages = ref([]);
const scrollTop = ref(0); // scroll-view
const hotTopics = ref([
{
id: 1,
@ -208,12 +215,20 @@ onMounted(() => {
initUUID();
//
if (messages.value.length > 0) {
nextTick(() => {
setTimeout(() => {
scrollToBottom();
});
}, 200);
}
});
//
watch(messages, (newMessages) => {
// DOM
setTimeout(() => {
scrollToBottom();
}, 100);
}, { deep: true });
// UUID
const initUUID = () => {
let storedUUID = uni.getStorageSync("user_uuid");
@ -262,9 +277,9 @@ const sendMessage = () => {
inputMessage.value = "";
//
nextTick(() => {
setTimeout(() => {
scrollToBottom();
});
}, 100);
//
simulateBotResponse(userMessage.content);
@ -285,9 +300,9 @@ const sendMessageList = (listMessage) => {
inputMessage.value = "";
//
nextTick(() => {
setTimeout(() => {
scrollToBottom();
});
}, 100);
//
simulateBotResponse(userMessage.content);
@ -308,9 +323,9 @@ const simulateBotResponse = (userMessage) => {
messages.value.push(botMsg);
//
nextTick(() => {
setTimeout(() => {
scrollToBottom();
});
}, 100);
//
let responseText = `我已经收到您的消息: "${userMessage}"。作为您的股市顾问,我可以为您提供专业的投资建议。请问您想了解哪方面的信息?`;
@ -322,15 +337,19 @@ const simulateBotResponse = (userMessage) => {
messages.value[messages.value.length - 1].content = responseText.substring(0, index + 1);
index++;
//
nextTick(() => {
//
setTimeout(() => {
scrollToBottom();
});
}, 20);
setTimeout(typeWriter, 30);
} else {
messages.value[messages.value.length - 1].isTyping = false;
isSending.value = false;
//
setTimeout(() => {
scrollToBottom();
}, 100);
}
};
@ -339,21 +358,21 @@ const simulateBotResponse = (userMessage) => {
//
const scrollToBottom = () => {
// 使scroll-viewscrollTop
const query = uni.createSelectorQuery();
query.select("#messageList").boundingClientRect();
query.selectViewport().scrollOffset();
query.exec((res) => {
if (res[0] && res[1]) {
uni.pageScrollTo({
scrollTop: res[0].height,
duration: 100,
});
if (res[0]) {
// scrollTop
scrollTop.value = res[0].height;
}
});
};
const scrollToTop = () => {
uni.pageScrollTo({ scrollTop: 0, duration: 200 });
//
scrollTop.value = 0;
};
</script>
@ -364,16 +383,33 @@ const scrollToTop = () => {
height: 100vh;
background-color: #ffffff;
padding: 20rpx 0rpx;
position: relative;
overflow: hidden; /* 禁止页面整体滚动 */
}
/* 顶部导航栏 - 固定定位 */
.header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 20rpx 30rpx;
background-color: #ffffff;
position: fixed;
top: 0;
left: 0;
right: 0;
z-index: 999;
box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.1);
}
/* 顶部固定区域占位符 */
.header-placeholder {
height: 120rpx; /* 与header高度一致 */
}
/* 顶部固定区域占位符 */
.banner-placeholder {
height: 80rpx; /* 与header高度一致,防止内容被固定头部遮挡 */
}
.header-left,
@ -410,9 +446,9 @@ const scrollToTop = () => {
.main-content {
flex: 1;
padding: 20rpx;
overflow-y: auto;
overflow-y: hidden; /* 禁止主内容区域滚动 */
margin-top: 20rpx;
margin-bottom: 120rpx;
margin-bottom: 250rpx;
}
.robot-container {
@ -578,8 +614,14 @@ const scrollToTop = () => {
/* overflow-y: auto; */
}
.chat-scroll-view {
height: calc(80vh - 250rpx); /* 根据需要调整高度 */
margin-top: 180rpx;
}
.message-list {
/* padding: 20rpx; */
/* margin-top: 200rpx; */
}
.message {
@ -685,11 +727,12 @@ const scrollToTop = () => {
.input-area {
position: fixed;
bottom: 0;
bottom: 70rpx;
left: 0;
right: 0;
padding: 0 40rpx 80rpx 40rpx;
background-color: #ffffff;
z-index: 999;
}
.input-wrapper {
@ -762,6 +805,10 @@ const scrollToTop = () => {
}
.panelShow{
height: 12%;
position: fixed;
top: 70rpx;
z-index: 999;
width: 95%;
}
.pray-banner {
@ -799,5 +846,10 @@ const scrollToTop = () => {
.static-footer {
position: fixed;
bottom: 0;
z-index: 999;
}
/* 顶部固定区域占位符 */
.banner-placeholder {
height: 60rpx; /* 与header高度一致,防止内容被固定头部遮挡 */
}
</style>
</style>
Loading…
Cancel
Save