|
@@ -6,8 +6,24 @@
|
|
|
</view>
|
|
</view>
|
|
|
|
|
|
|
|
<!-- 聊天消息列表 -->
|
|
<!-- 聊天消息列表 -->
|
|
|
- <scroll-view class="message-list" :scroll-top="scrollTop" scroll-y :scroll-into-view="scrollIntoView" scroll-with-animation>
|
|
|
|
|
- <view class="message-item" v-for="(message, index) in messageList" :key="index" :id="'message-' + index">
|
|
|
|
|
|
|
+ <scroll-view
|
|
|
|
|
+ class="message-list"
|
|
|
|
|
+ :scroll-top="scrollTop"
|
|
|
|
|
+ scroll-y
|
|
|
|
|
+ :scroll-into-view="scrollIntoView"
|
|
|
|
|
+ :scroll-with-animation="scrollWithAnimation"
|
|
|
|
|
+ @scrolltoupper="loadMoreMessages"
|
|
|
|
|
+ >
|
|
|
|
|
+ <!-- 加载更多 -->
|
|
|
|
|
+ <view class="load-more" v-if="showLoadMore" @click="loadMoreMessages">
|
|
|
|
|
+ <text class="load-more-text">加载更多</text>
|
|
|
|
|
+ </view>
|
|
|
|
|
+ <view
|
|
|
|
|
+ class="message-item"
|
|
|
|
|
+ v-for="(message, index) in messageList"
|
|
|
|
|
+ :key="index"
|
|
|
|
|
+ :id="'message-' + message.id"
|
|
|
|
|
+ >
|
|
|
<!-- 左侧消息(商家/其他用户) -->
|
|
<!-- 左侧消息(商家/其他用户) -->
|
|
|
<view class="message-left" v-if="!message.isMine && !message.shopId">
|
|
<view class="message-left" v-if="!message.isMine && !message.shopId">
|
|
|
<view class="avatar-wrapper">
|
|
<view class="avatar-wrapper">
|
|
@@ -104,6 +120,12 @@ export default {
|
|
|
reconnectCount: 0,
|
|
reconnectCount: 0,
|
|
|
maxReconnectCount: 3,
|
|
maxReconnectCount: 3,
|
|
|
isManualDisconnect: false, // 添加标志位:是否主动断开连接
|
|
isManualDisconnect: false, // 添加标志位:是否主动断开连接
|
|
|
|
|
+ scrollWithAnimation: false, // 控制滚动动画
|
|
|
|
|
+ // 分页加载
|
|
|
|
|
+ allMessages: [], // 存储所有从API获取的消息
|
|
|
|
|
+ initialLoadSize: 50, // 首次加载数量
|
|
|
|
|
+ loadMoreSize: 100, // 每次加载更多的数量
|
|
|
|
|
+ showLoadMore: false, // 是否显示“加载更多”
|
|
|
// 键盘相关
|
|
// 键盘相关
|
|
|
keyboardHeight: 0, // 键盘高度
|
|
keyboardHeight: 0, // 键盘高度
|
|
|
isKeyboardShow: false, // 键盘是否显示
|
|
isKeyboardShow: false, // 键盘是否显示
|
|
@@ -194,14 +216,56 @@ export default {
|
|
|
userId: this.currentUser.id
|
|
userId: this.currentUser.id
|
|
|
}).then((res) => {
|
|
}).then((res) => {
|
|
|
if (res.code == 1 && res.data) {
|
|
if (res.code == 1 && res.data) {
|
|
|
- this.messageList = res.data;
|
|
|
|
|
|
|
+ this.allMessages = res.data.map((item, index) => ({
|
|
|
|
|
+ ...item,
|
|
|
|
|
+ id: `msg_${index}`, // 为每条消息添加唯一ID
|
|
|
|
|
+ }));
|
|
|
|
|
+
|
|
|
|
|
+ if (this.allMessages.length > this.initialLoadSize) {
|
|
|
|
|
+ this.messageList = this.allMessages.slice(
|
|
|
|
|
+ this.allMessages.length - this.initialLoadSize
|
|
|
|
|
+ );
|
|
|
|
|
+ this.showLoadMore = true;
|
|
|
|
|
+ } else {
|
|
|
|
|
+ this.messageList = this.allMessages;
|
|
|
|
|
+ this.showLoadMore = false;
|
|
|
|
|
+ }
|
|
|
this.$nextTick(() => {
|
|
this.$nextTick(() => {
|
|
|
- this.scrollToBottom();
|
|
|
|
|
|
|
+ this.scrollToBottom(false); // 初始加载时不使用动画
|
|
|
});
|
|
});
|
|
|
}
|
|
}
|
|
|
});
|
|
});
|
|
|
},
|
|
},
|
|
|
|
|
|
|
|
|
|
+ // 加载更多历史记录
|
|
|
|
|
+ loadMoreMessages() {
|
|
|
|
|
+ if (!this.showLoadMore) {
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+ const currentLoadedCount = this.messageList.length;
|
|
|
|
|
+ const remainingMessagesCount = this.allMessages.length - currentLoadedCount;
|
|
|
|
|
+ if (remainingMessagesCount <= 0) {
|
|
|
|
|
+ this.showLoadMore = false;
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+ const countToLoad = Math.min(this.loadMoreSize, remainingMessagesCount);
|
|
|
|
|
+ const moreMessages = this.allMessages.slice(
|
|
|
|
|
+ remainingMessagesCount - countToLoad,
|
|
|
|
|
+ remainingMessagesCount
|
|
|
|
|
+ );
|
|
|
|
|
+ const oldTopMessageId = this.messageList.length > 0 ? this.messageList[0].id : null;
|
|
|
|
|
+ this.messageList = [...moreMessages, ...this.messageList];
|
|
|
|
|
+ if (this.allMessages.length - (currentLoadedCount + countToLoad) <= 0) {
|
|
|
|
|
+ this.showLoadMore = false;
|
|
|
|
|
+ }
|
|
|
|
|
+ if (oldTopMessageId) {
|
|
|
|
|
+ this.$nextTick(() => {
|
|
|
|
|
+ this.scrollWithAnimation = false; // 加载更多时不使用动画
|
|
|
|
|
+ this.scrollIntoView = "message-" + oldTopMessageId;
|
|
|
|
|
+ });
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
|
|
+
|
|
|
// 获取主机地址
|
|
// 获取主机地址
|
|
|
getHost() {
|
|
getHost() {
|
|
|
// #ifdef H5
|
|
// #ifdef H5
|
|
@@ -587,7 +651,7 @@ export default {
|
|
|
|
|
|
|
|
// 滚动到底部
|
|
// 滚动到底部
|
|
|
this.$nextTick(() => {
|
|
this.$nextTick(() => {
|
|
|
- this.scrollToBottom();
|
|
|
|
|
|
|
+ this.scrollToBottom(); // 用户操作时使用动画
|
|
|
});
|
|
});
|
|
|
} catch (error) {
|
|
} catch (error) {
|
|
|
console.error('解析WebSocket消息失败:', error, data);
|
|
console.error('解析WebSocket消息失败:', error, data);
|
|
@@ -629,7 +693,7 @@ export default {
|
|
|
|
|
|
|
|
// 滚动到底部
|
|
// 滚动到底部
|
|
|
this.$nextTick(() => {
|
|
this.$nextTick(() => {
|
|
|
- this.scrollToBottom();
|
|
|
|
|
|
|
+ this.scrollToBottom(); // 用户操作时使用动画
|
|
|
});
|
|
});
|
|
|
|
|
|
|
|
// 构建要发送的消息数据
|
|
// 构建要发送的消息数据
|
|
@@ -678,9 +742,10 @@ export default {
|
|
|
},
|
|
},
|
|
|
|
|
|
|
|
// 滚动到底部
|
|
// 滚动到底部
|
|
|
- scrollToBottom() {
|
|
|
|
|
|
|
+ scrollToBottom(enableAnimation = true) {
|
|
|
|
|
+ this.scrollWithAnimation = enableAnimation;
|
|
|
if (this.messageList.length > 0) {
|
|
if (this.messageList.length > 0) {
|
|
|
- this.scrollIntoView = 'message-' + (this.messageList.length - 1);
|
|
|
|
|
|
|
+ this.scrollIntoView = "message-" + this.messageList[this.messageList.length - 1].id;
|
|
|
}
|
|
}
|
|
|
},
|
|
},
|
|
|
|
|
|
|
@@ -746,6 +811,16 @@ export default {
|
|
|
overflow-y: auto;
|
|
overflow-y: auto;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+.load-more {
|
|
|
|
|
+ text-align: center;
|
|
|
|
|
+ padding: 20upx 0;
|
|
|
|
|
+ .load-more-text {
|
|
|
|
|
+ color: #007aff;
|
|
|
|
|
+ font-size: 28upx;
|
|
|
|
|
+ cursor: pointer;
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
.message-item {
|
|
.message-item {
|
|
|
margin-bottom: 30upx;
|
|
margin-bottom: 30upx;
|
|
|
|
|
|