|
@@ -120,6 +120,9 @@
|
|
|
<el-row style="margin-left: 10px">
|
|
<el-row style="margin-left: 10px">
|
|
|
<el-col><div style="font-size: 12px; color: #999; margin-bottom: 3px;">{{ m.nickName }}</div></el-col>
|
|
<el-col><div style="font-size: 12px; color: #999; margin-bottom: 3px;">{{ m.nickName }}</div></el-col>
|
|
|
<el-col :span="24" style="max-width: 200px;">
|
|
<el-col :span="24" style="max-width: 200px;">
|
|
|
|
|
+ <div v-if="m.replyUserName || m.replyContent" style="font-size: 12px; color: #999; margin-bottom: 4px; word-break: break-all;">
|
|
|
|
|
+ 回复 {{ m.replyUserName || '用户' }}:{{ m.replyContent }}
|
|
|
|
|
+ </div>
|
|
|
<div style="white-space: normal; word-wrap: break-word;background-color: #f0f2f5; padding: 8px; border-radius: 5px;font-size: 14px;width: 100%;">
|
|
<div style="white-space: normal; word-wrap: break-word;background-color: #f0f2f5; padding: 8px; border-radius: 5px;font-size: 14px;width: 100%;">
|
|
|
{{ m.msg }}
|
|
{{ m.msg }}
|
|
|
</div>
|
|
</div>
|
|
@@ -139,6 +142,9 @@
|
|
|
<div style="display: flex;justify-content: flex-end">
|
|
<div style="display: flex;justify-content: flex-end">
|
|
|
<div style="display: flex;justify-content: flex-end;flex-direction: column;max-width: 200px;align-items: flex-end">
|
|
<div style="display: flex;justify-content: flex-end;flex-direction: column;max-width: 200px;align-items: flex-end">
|
|
|
<div style="font-size: 12px; color: #999; margin-bottom: 3px;">{{ m.nickName }}</div>
|
|
<div style="font-size: 12px; color: #999; margin-bottom: 3px;">{{ m.nickName }}</div>
|
|
|
|
|
+ <div v-if="m.replyUserName || m.replyContent" style="font-size: 12px; color: #999; margin-bottom: 4px; max-width: 200px; word-break: break-all; text-align: right;">
|
|
|
|
|
+ 回复 {{ m.replyUserName || '用户' }}:{{ m.replyContent }}
|
|
|
|
|
+ </div>
|
|
|
<div style="white-space: normal; word-wrap: break-word;width: 100%; background-color: #e6f7ff; padding: 8px; border-radius: 5px;font-size: 14px;">{{ m.msg }}</div>
|
|
<div style="white-space: normal; word-wrap: break-word;width: 100%; background-color: #e6f7ff; padding: 8px; border-radius: 5px;font-size: 14px;">{{ m.msg }}</div>
|
|
|
</div>
|
|
</div>
|
|
|
<el-avatar :src="m.avatar" style="margin-left: 10px; margin-right: 10px;"/>
|
|
<el-avatar :src="m.avatar" style="margin-left: 10px; margin-right: 10px;"/>
|
|
@@ -148,17 +154,17 @@
|
|
|
<!-- 底部留白 -->
|
|
<!-- 底部留白 -->
|
|
|
<div style="height: 20px;"></div>
|
|
<div style="height: 20px;"></div>
|
|
|
</el-scrollbar>
|
|
</el-scrollbar>
|
|
|
- <!-- 加载最新消息按钮 -->
|
|
|
|
|
|
|
+ <!-- 暂停后:回到最新并恢复实时滚动 -->
|
|
|
<el-button
|
|
<el-button
|
|
|
v-if="showLoadLatestBtn"
|
|
v-if="showLoadLatestBtn"
|
|
|
class="load-latest-btn"
|
|
class="load-latest-btn"
|
|
|
type="primary"
|
|
type="primary"
|
|
|
size="small"
|
|
size="small"
|
|
|
@click.stop="loadLatestMessages"
|
|
@click.stop="loadLatestMessages"
|
|
|
- :disabled="isLoadingLatest"
|
|
|
|
|
- :loading="isLoadingLatest"
|
|
|
|
|
- icon="el-icon-refresh">
|
|
|
|
|
- 加载最新消息
|
|
|
|
|
|
|
+ :disabled="isLoadingHistory"
|
|
|
|
|
+ :loading="isLoadingHistory"
|
|
|
|
|
+ icon="el-icon-bottom">
|
|
|
|
|
+ 回到最新
|
|
|
</el-button>
|
|
</el-button>
|
|
|
</div>
|
|
</div>
|
|
|
<!-- <div class="message-list">-->
|
|
<!-- <div class="message-list">-->
|
|
@@ -408,12 +414,20 @@ export default {
|
|
|
msg: '',
|
|
msg: '',
|
|
|
duration: 5
|
|
duration: 5
|
|
|
},
|
|
},
|
|
|
- // 消息滚动控制
|
|
|
|
|
- isAutoScrollEnabled: true, // 是否启用自动滚动
|
|
|
|
|
- autoScrollTimer: null, // 自动滚动定时器
|
|
|
|
|
- showLoadLatestBtn: false, // 是否显示加载最新消息按钮
|
|
|
|
|
- isLoadingLatest: false, // 是否正在加载最新消息
|
|
|
|
|
- scrollDebounceTimer: null, // 滚动防抖定时器
|
|
|
|
|
|
|
+ // 消息滚动控制:窗口固定 30 条,暂停后可上下游标翻页
|
|
|
|
|
+ MSG_WINDOW_SIZE: 30,
|
|
|
|
|
+ isAutoScrollEnabled: true,
|
|
|
|
|
+ autoScrollTimer: null,
|
|
|
|
|
+ showLoadLatestBtn: false,
|
|
|
|
|
+ isLoadingHistory: false,
|
|
|
|
|
+ hasMoreOlder: true,
|
|
|
|
|
+ hasMoreNewer: false,
|
|
|
|
|
+ // 边缘触达后需先离开再触达,才允许再次加载(防止贴边连打接口)
|
|
|
|
|
+ olderEdgeArmed: true,
|
|
|
|
|
+ newerEdgeArmed: true,
|
|
|
|
|
+ // 回到最新过程中忽略滚动暂停,避免清空列表触发 scroll 又把自动跟随关掉
|
|
|
|
|
+ suppressScrollPause: false,
|
|
|
|
|
+ scrollDebounceTimer: null,
|
|
|
msgParams: {
|
|
msgParams: {
|
|
|
pageNum: 1,
|
|
pageNum: 1,
|
|
|
pageSize: 30,
|
|
pageSize: 30,
|
|
@@ -459,65 +473,192 @@ export default {
|
|
|
this.initScrollListeners();
|
|
this.initScrollListeners();
|
|
|
},
|
|
},
|
|
|
methods: {
|
|
methods: {
|
|
|
- // 点击消息框
|
|
|
|
|
|
|
+ // 点击消息框:暂停实时滚动,显示「回到最新」
|
|
|
handleMessageBoxClick() {
|
|
handleMessageBoxClick() {
|
|
|
- // 点击消息框时,停止自动滚动
|
|
|
|
|
- this.isAutoScrollEnabled = false;
|
|
|
|
|
- // 停止自动滚动定时器
|
|
|
|
|
|
|
+ this.pauseMsgAutoScroll()
|
|
|
|
|
+ },
|
|
|
|
|
+ pauseMsgAutoScroll() {
|
|
|
|
|
+ this.isAutoScrollEnabled = false
|
|
|
if (this.autoScrollTimer) {
|
|
if (this.autoScrollTimer) {
|
|
|
- clearTimeout(this.autoScrollTimer);
|
|
|
|
|
- this.autoScrollTimer = null;
|
|
|
|
|
|
|
+ clearTimeout(this.autoScrollTimer)
|
|
|
|
|
+ this.autoScrollTimer = null
|
|
|
}
|
|
}
|
|
|
- // 检查是否在底部,如果不在底部则显示加载最新消息按钮
|
|
|
|
|
- this.$nextTick(() => {
|
|
|
|
|
- if (this.$refs.manageRightRef && this.$refs.manageRightRef.wrap) {
|
|
|
|
|
- const wrap = this.$refs.manageRightRef.wrap;
|
|
|
|
|
- const scrollHeight = wrap.scrollHeight;
|
|
|
|
|
- const clientHeight = wrap.clientHeight;
|
|
|
|
|
- const currentScrollTop = wrap.scrollTop;
|
|
|
|
|
- const maxScrollTop = scrollHeight - clientHeight;
|
|
|
|
|
-
|
|
|
|
|
- if (currentScrollTop < maxScrollTop - 50) {
|
|
|
|
|
- this.showLoadLatestBtn = true;
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- });
|
|
|
|
|
|
|
+ this.showLoadLatestBtn = true
|
|
|
},
|
|
},
|
|
|
- // 滚动到底部
|
|
|
|
|
scrollToBottom(forceScroll = false) {
|
|
scrollToBottom(forceScroll = false) {
|
|
|
- // 如果自动滚动被禁用且不是强制滚动,则不执行
|
|
|
|
|
if (!this.isAutoScrollEnabled && !forceScroll) {
|
|
if (!this.isAutoScrollEnabled && !forceScroll) {
|
|
|
- return;
|
|
|
|
|
|
|
+ return
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
if (this.$refs.manageRightRef && this.$refs.manageRightRef.wrap) {
|
|
if (this.$refs.manageRightRef && this.$refs.manageRightRef.wrap) {
|
|
|
this.$nextTick(() => {
|
|
this.$nextTick(() => {
|
|
|
- const wrap = this.$refs.manageRightRef.wrap;
|
|
|
|
|
- if (!wrap) return;
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
- // 强制滚动或启用自动滚动时,直接滚动到底部并隐藏按钮
|
|
|
|
|
|
|
+ const wrap = this.$refs.manageRightRef.wrap
|
|
|
|
|
+ if (!wrap) return
|
|
|
if (forceScroll || this.isAutoScrollEnabled) {
|
|
if (forceScroll || this.isAutoScrollEnabled) {
|
|
|
- this.showLoadLatestBtn = false;
|
|
|
|
|
- this.$refs.manageRightRef.wrap.scrollTop = this.$refs.manageRightRef.wrap.scrollHeight - this.$refs.manageRightRef.wrap.clientHeight
|
|
|
|
|
|
|
+ this.showLoadLatestBtn = false
|
|
|
|
|
+ wrap.scrollTop = wrap.scrollHeight - wrap.clientHeight
|
|
|
}
|
|
}
|
|
|
- });
|
|
|
|
|
|
|
+ })
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
|
|
+ scrollMsgToTop() {
|
|
|
|
|
+ if (this.$refs.manageRightRef && this.$refs.manageRightRef.wrap) {
|
|
|
|
|
+ this.$refs.manageRightRef.wrap.scrollTop = 0
|
|
|
}
|
|
}
|
|
|
},
|
|
},
|
|
|
- // 加载最新消息
|
|
|
|
|
|
|
+ scrollMsgToBottom() {
|
|
|
|
|
+ if (this.$refs.manageRightRef && this.$refs.manageRightRef.wrap) {
|
|
|
|
|
+ const wrap = this.$refs.manageRightRef.wrap
|
|
|
|
|
+ wrap.scrollTop = Math.max(0, wrap.scrollHeight - wrap.clientHeight)
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
|
|
+ // 回到最新:重新拉最近 30 条并恢复 socket 跟随滚动
|
|
|
loadLatestMessages() {
|
|
loadLatestMessages() {
|
|
|
- // 如果正在加载,直接返回
|
|
|
|
|
- if (this.isLoadingLatest) {
|
|
|
|
|
- return;
|
|
|
|
|
|
|
+ if (this.isLoadingHistory) {
|
|
|
|
|
+ return
|
|
|
|
|
+ }
|
|
|
|
|
+ this.suppressScrollPause = true
|
|
|
|
|
+ this.isLoadingHistory = true
|
|
|
|
|
+ this.showLoadLatestBtn = false
|
|
|
|
|
+ this.isAutoScrollEnabled = true
|
|
|
|
|
+ this.hasMoreOlder = true
|
|
|
|
|
+ this.hasMoreNewer = false
|
|
|
|
|
+ this.olderEdgeArmed = true
|
|
|
|
|
+ this.newerEdgeArmed = true
|
|
|
|
|
+ if (this.scrollDebounceTimer) {
|
|
|
|
|
+ clearTimeout(this.scrollDebounceTimer)
|
|
|
|
|
+ this.scrollDebounceTimer = null
|
|
|
|
|
+ }
|
|
|
|
|
+ this.msgList = []
|
|
|
|
|
+ this.msgParams.pageNum = 1
|
|
|
|
|
+ this.msgParams.pageSize = this.MSG_WINDOW_SIZE
|
|
|
|
|
+ this.loadMsgList(true)
|
|
|
|
|
+ },
|
|
|
|
|
+ decorateMsgRows(rows) {
|
|
|
|
|
+ if (!rows || !rows.length) {
|
|
|
|
|
+ return
|
|
|
|
|
+ }
|
|
|
|
|
+ rows.forEach(row => {
|
|
|
|
|
+ let user = this.alDisplayList.find(u => u.userId === row.userId)
|
|
|
|
|
+ row.msgStatus = user ? user.msgStatus : 0
|
|
|
|
|
+ if (row.userId != null) {
|
|
|
|
|
+ const uid = String(row.userId)
|
|
|
|
|
+ if (!Object.prototype.hasOwnProperty.call(this.userSingleVisibleMap, uid)) {
|
|
|
|
|
+ this.$set(this.userSingleVisibleMap, uid, Number(row.singleVisible) === 1 ? 1 : 0)
|
|
|
|
|
+ } else {
|
|
|
|
|
+ this.$set(row, 'singleVisible', Number(this.userSingleVisibleMap[uid]) === 1 ? 1 : 0)
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ })
|
|
|
|
|
+ this.alDisplayList.forEach(u => {
|
|
|
|
|
+ rows.filter(m => m.userId === u.userId).forEach(m => { m.msgStatus = u.msgStatus })
|
|
|
|
|
+ })
|
|
|
|
|
+ },
|
|
|
|
|
+ getFirstMsgId() {
|
|
|
|
|
+ for (let i = 0; i < this.msgList.length; i++) {
|
|
|
|
|
+ if (this.msgList[i] && this.msgList[i].msgId != null) {
|
|
|
|
|
+ return this.msgList[i].msgId
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ return null
|
|
|
|
|
+ },
|
|
|
|
|
+ getLastMsgId() {
|
|
|
|
|
+ for (let i = this.msgList.length - 1; i >= 0; i--) {
|
|
|
|
|
+ if (this.msgList[i] && this.msgList[i].msgId != null) {
|
|
|
|
|
+ return this.msgList[i].msgId
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ return null
|
|
|
|
|
+ },
|
|
|
|
|
+ // 向上翻:更早的 30 条,窗口裁剪后滚到中间
|
|
|
|
|
+ loadOlderMessages() {
|
|
|
|
|
+ if (this.isLoadingHistory || this.isAutoScrollEnabled || !this.hasMoreOlder) {
|
|
|
|
|
+ return
|
|
|
|
|
+ }
|
|
|
|
|
+ const beforeMsgId = this.getFirstMsgId()
|
|
|
|
|
+ if (beforeMsgId == null) {
|
|
|
|
|
+ return
|
|
|
|
|
+ }
|
|
|
|
|
+ this.isLoadingHistory = true
|
|
|
|
|
+ listLiveSingleMsg({
|
|
|
|
|
+ liveId: this.liveId,
|
|
|
|
|
+ pageNum: 1,
|
|
|
|
|
+ pageSize: this.MSG_WINDOW_SIZE,
|
|
|
|
|
+ beforeMsgId
|
|
|
|
|
+ }).then(response => {
|
|
|
|
|
+ const { code, rows } = response
|
|
|
|
|
+ if (code !== 200) {
|
|
|
|
|
+ return
|
|
|
|
|
+ }
|
|
|
|
|
+ let list = (rows || []).slice()
|
|
|
|
|
+ this.hasMoreOlder = list.length >= this.MSG_WINDOW_SIZE
|
|
|
|
|
+ list.reverse()
|
|
|
|
|
+ list = list.filter(r => r.msgId != null && !this.msgList.some(m => m.msgId === r.msgId))
|
|
|
|
|
+ this.decorateMsgRows(list)
|
|
|
|
|
+ if (!list.length) {
|
|
|
|
|
+ this.hasMoreOlder = false
|
|
|
|
|
+ this.olderEdgeArmed = false
|
|
|
|
|
+ this.$nextTick(() => this.scrollMsgToBottom())
|
|
|
|
|
+ return
|
|
|
|
|
+ }
|
|
|
|
|
+ this.msgList = list.concat(this.msgList)
|
|
|
|
|
+ if (this.msgList.length > this.MSG_WINDOW_SIZE) {
|
|
|
|
|
+ this.msgList = this.msgList.slice(0, this.MSG_WINDOW_SIZE)
|
|
|
|
|
+ this.hasMoreNewer = true
|
|
|
|
|
+ }
|
|
|
|
|
+ // 加载更早后滚到底:需先往下再滚回顶部,才能再次向上查
|
|
|
|
|
+ this.$nextTick(() => {
|
|
|
|
|
+ this.scrollMsgToBottom()
|
|
|
|
|
+ this.olderEdgeArmed = false
|
|
|
|
|
+ this.newerEdgeArmed = false
|
|
|
|
|
+ })
|
|
|
|
|
+ }).finally(() => {
|
|
|
|
|
+ this.isLoadingHistory = false
|
|
|
|
|
+ })
|
|
|
|
|
+ },
|
|
|
|
|
+ // 向下翻:更新的 30 条,窗口裁剪后滚到顶部
|
|
|
|
|
+ loadNewerMessages() {
|
|
|
|
|
+ if (this.isLoadingHistory || this.isAutoScrollEnabled || !this.hasMoreNewer) {
|
|
|
|
|
+ return
|
|
|
|
|
+ }
|
|
|
|
|
+ const afterMsgId = this.getLastMsgId()
|
|
|
|
|
+ if (afterMsgId == null) {
|
|
|
|
|
+ return
|
|
|
}
|
|
}
|
|
|
- this.isLoadingLatest = true;
|
|
|
|
|
- this.showLoadLatestBtn = false;
|
|
|
|
|
- // 恢复自动滚动
|
|
|
|
|
- this.isAutoScrollEnabled = true;
|
|
|
|
|
- // 重新请求最新消息
|
|
|
|
|
- this.resetMsgParams();
|
|
|
|
|
- // loadMsgList 中会自动滚动到底部,因为 isAutoScrollEnabled 已经是 true
|
|
|
|
|
- this.loadMsgList();
|
|
|
|
|
|
|
+ this.isLoadingHistory = true
|
|
|
|
|
+ listLiveSingleMsg({
|
|
|
|
|
+ liveId: this.liveId,
|
|
|
|
|
+ pageNum: 1,
|
|
|
|
|
+ pageSize: this.MSG_WINDOW_SIZE,
|
|
|
|
|
+ afterMsgId
|
|
|
|
|
+ }).then(response => {
|
|
|
|
|
+ const { code, rows } = response
|
|
|
|
|
+ if (code !== 200) {
|
|
|
|
|
+ return
|
|
|
|
|
+ }
|
|
|
|
|
+ let list = (rows || []).slice()
|
|
|
|
|
+ this.hasMoreNewer = list.length >= this.MSG_WINDOW_SIZE
|
|
|
|
|
+ list = list.filter(r => r.msgId != null && !this.msgList.some(m => m.msgId === r.msgId))
|
|
|
|
|
+ this.decorateMsgRows(list)
|
|
|
|
|
+ if (!list.length) {
|
|
|
|
|
+ this.hasMoreNewer = false
|
|
|
|
|
+ this.newerEdgeArmed = false
|
|
|
|
|
+ this.$nextTick(() => this.scrollMsgToTop())
|
|
|
|
|
+ return
|
|
|
|
|
+ }
|
|
|
|
|
+ this.msgList = this.msgList.concat(list)
|
|
|
|
|
+ if (this.msgList.length > this.MSG_WINDOW_SIZE) {
|
|
|
|
|
+ this.msgList = this.msgList.slice(this.msgList.length - this.MSG_WINDOW_SIZE)
|
|
|
|
|
+ this.hasMoreOlder = true
|
|
|
|
|
+ }
|
|
|
|
|
+ // 加载更新后滚到顶:需先往上再滚回底部,才能再次向下查
|
|
|
|
|
+ this.$nextTick(() => {
|
|
|
|
|
+ this.scrollMsgToTop()
|
|
|
|
|
+ this.olderEdgeArmed = false
|
|
|
|
|
+ this.newerEdgeArmed = false
|
|
|
|
|
+ })
|
|
|
|
|
+ }).finally(() => {
|
|
|
|
|
+ this.isLoadingHistory = false
|
|
|
|
|
+ })
|
|
|
},
|
|
},
|
|
|
msgRowKey(m, index) {
|
|
msgRowKey(m, index) {
|
|
|
if (m && m.msgId != null && m.msgId !== '') {
|
|
if (m && m.msgId != null && m.msgId !== '') {
|
|
@@ -576,7 +717,10 @@ export default {
|
|
|
cmd: 'replyUser',
|
|
cmd: 'replyUser',
|
|
|
msg: value.trim(),
|
|
msg: value.trim(),
|
|
|
avatar: this.$store.state.user.user.avatar,
|
|
avatar: this.$store.state.user.user.avatar,
|
|
|
- nickName: this.$store.state.user.user.nickName
|
|
|
|
|
|
|
+ nickName: this.$store.state.user.user.nickName,
|
|
|
|
|
+ replyMsgId: m.msgId,
|
|
|
|
|
+ replyUserName: m.nickName || '',
|
|
|
|
|
+ replyContent: m.msg || ''
|
|
|
}
|
|
}
|
|
|
this.socket.send(JSON.stringify(msg))
|
|
this.socket.send(JSON.stringify(msg))
|
|
|
}).catch(() => {})
|
|
}).catch(() => {})
|
|
@@ -788,21 +932,24 @@ export default {
|
|
|
this.$set(this.userSingleVisibleMap, uid, Number(message.singleVisible) === 1 ? 1 : 0)
|
|
this.$set(this.userSingleVisibleMap, uid, Number(message.singleVisible) === 1 ? 1 : 0)
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
- if(this.msgList.length > 50){
|
|
|
|
|
- this.msgList.shift()
|
|
|
|
|
|
|
+ // 暂停浏览历史时不插入实时消息,避免窗口膨胀;点「回到最新」再同步
|
|
|
|
|
+ if (!this.isAutoScrollEnabled) {
|
|
|
|
|
+ this.showLoadLatestBtn = true
|
|
|
|
|
+ return
|
|
|
|
|
+ }
|
|
|
|
|
+ if (message.msgId != null && this.msgList.some(m => m.msgId === message.msgId)) {
|
|
|
|
|
+ return
|
|
|
}
|
|
}
|
|
|
this.msgList.push(message)
|
|
this.msgList.push(message)
|
|
|
- // 如果启用自动滚动,自动滚动到底部
|
|
|
|
|
- if (this.isAutoScrollEnabled) {
|
|
|
|
|
- this.$nextTick(() => {
|
|
|
|
|
- this.autoScrollTimer = setTimeout(() => {
|
|
|
|
|
- this.scrollToBottom();
|
|
|
|
|
- }, 200);
|
|
|
|
|
- });
|
|
|
|
|
- } else {
|
|
|
|
|
- // 自动滚动被禁用时,显示加载最新消息按钮
|
|
|
|
|
- this.showLoadLatestBtn = true;
|
|
|
|
|
|
|
+ while (this.msgList.length > this.MSG_WINDOW_SIZE) {
|
|
|
|
|
+ this.msgList.shift()
|
|
|
|
|
+ this.hasMoreOlder = true
|
|
|
}
|
|
}
|
|
|
|
|
+ this.$nextTick(() => {
|
|
|
|
|
+ this.autoScrollTimer = setTimeout(() => {
|
|
|
|
|
+ this.scrollToBottom()
|
|
|
|
|
+ }, 200)
|
|
|
|
|
+ })
|
|
|
} else if (cmd === 'entry' || cmd === 'out') {
|
|
} else if (cmd === 'entry' || cmd === 'out') {
|
|
|
const user = data;
|
|
const user = data;
|
|
|
const online = cmd === 'entry' ? 0 : 1; // 0=在线,1=离线
|
|
const online = cmd === 'entry' ? 0 : 1; // 0=在线,1=离线
|
|
@@ -1021,21 +1168,51 @@ export default {
|
|
|
this.resetUserParams()
|
|
this.resetUserParams()
|
|
|
this.loadNextPage(this.currentTab)
|
|
this.loadNextPage(this.currentTab)
|
|
|
},
|
|
},
|
|
|
|
|
+ /** 按 Tab 组装列表查询参数,与 liveUserTotals 口径一致 */
|
|
|
|
|
+ buildWatchUserQuery(tabName, pageNum) {
|
|
|
|
|
+ const queryParams = {
|
|
|
|
|
+ liveId: this.liveId,
|
|
|
|
|
+ pageNum,
|
|
|
|
|
+ pageSize: 20,
|
|
|
|
|
+ userName: this.searchKeyword
|
|
|
|
|
+ };
|
|
|
|
|
+ if (tabName === 'al') {
|
|
|
|
|
+ queryParams.all = 1;
|
|
|
|
|
+ } else if (tabName === 'online') {
|
|
|
|
|
+ queryParams.online = 0;
|
|
|
|
|
+ queryParams.msgStatus = 0;
|
|
|
|
|
+ } else if (tabName === 'offline') {
|
|
|
|
|
+ queryParams.online = 1;
|
|
|
|
|
+ queryParams.msgStatus = 0;
|
|
|
|
|
+ } else if (tabName === 'silenced') {
|
|
|
|
|
+ // 禁言:不传 online,在线/离线禁言都查
|
|
|
|
|
+ queryParams.msgStatus = 1;
|
|
|
|
|
+ }
|
|
|
|
|
+ return queryParams;
|
|
|
|
|
+ },
|
|
|
|
|
+ /** Tab 人数与列表接口 total 保持一致 */
|
|
|
|
|
+ syncUserTotalFromList(tabName, total) {
|
|
|
|
|
+ const fieldMap = { al: 'al', online: 'online', offline: 'offline', silenced: 'silenced' };
|
|
|
|
|
+ const field = fieldMap[tabName];
|
|
|
|
|
+ if (field != null && total != null) {
|
|
|
|
|
+ this.$set(this.userTotal, field, total);
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
handleUserClick(tab){
|
|
handleUserClick(tab){
|
|
|
const tabName = tab.name;
|
|
const tabName = tab.name;
|
|
|
this.currentTab = tabName;
|
|
this.currentTab = tabName;
|
|
|
const params = this.pageParams[tabName];
|
|
const params = this.pageParams[tabName];
|
|
|
const displayList = this[`${tabName}DisplayList`];
|
|
const displayList = this[`${tabName}DisplayList`];
|
|
|
- // 首次切换到该Tab或列表为空时初始化
|
|
|
|
|
|
|
+ // 首次切换到该Tab或列表未满一页时重新拉取,保证人数与接口 total 一致
|
|
|
if (displayList.length < 20) {
|
|
if (displayList.length < 20) {
|
|
|
- // 重置分页参数
|
|
|
|
|
|
|
+ // 重置分页参数,清空本地缓存列表(避免前端乐观更新与接口不一致)
|
|
|
params.currentPage = 1;
|
|
params.currentPage = 1;
|
|
|
params.pageSize = 20;
|
|
params.pageSize = 20;
|
|
|
params.prevPage = 0;
|
|
params.prevPage = 0;
|
|
|
params.totalLoaded = 0;
|
|
params.totalLoaded = 0;
|
|
|
params.hasMore = true;
|
|
params.hasMore = true;
|
|
|
params.hasPrev = false;
|
|
params.hasPrev = false;
|
|
|
- // 加载第一页
|
|
|
|
|
|
|
+ this[`${tabName}DisplayList`] = [];
|
|
|
this.loadNextPage(tabName);
|
|
this.loadNextPage(tabName);
|
|
|
} else {
|
|
} else {
|
|
|
// 非首次切换,恢复滚动位置
|
|
// 非首次切换,恢复滚动位置
|
|
@@ -1057,15 +1234,8 @@ export default {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
this.scrLoading[tabName].next = true;
|
|
this.scrLoading[tabName].next = true;
|
|
|
- const queryParams = {
|
|
|
|
|
- liveId: this.liveId,
|
|
|
|
|
- pageNum: params.currentPage,
|
|
|
|
|
- pageSize: 20,
|
|
|
|
|
- online: tabName === 'online' ? 0 : 1,
|
|
|
|
|
- msgStatus: tabName === 'silenced' ? 1 : 0,
|
|
|
|
|
- all: tabName === 'al' ? 1 : 0,
|
|
|
|
|
- userName: this.searchKeyword
|
|
|
|
|
- };
|
|
|
|
|
|
|
+ const isFirstPage = params.currentPage === 1;
|
|
|
|
|
+ const queryParams = this.buildWatchUserQuery(tabName, params.currentPage);
|
|
|
// 调用接口加载对应状态的分页数据(需后端支持按状态筛选)
|
|
// 调用接口加载对应状态的分页数据(需后端支持按状态筛选)
|
|
|
dashBoardWatchUserList(queryParams).then(response => {
|
|
dashBoardWatchUserList(queryParams).then(response => {
|
|
|
this.scrLoading[tabName].next = false;
|
|
this.scrLoading[tabName].next = false;
|
|
@@ -1073,22 +1243,25 @@ export default {
|
|
|
|
|
|
|
|
const { rows, total } = response;
|
|
const { rows, total } = response;
|
|
|
params.total = total; // 记录总数据量
|
|
params.total = total; // 记录总数据量
|
|
|
- // 过滤重复数据(基于userId)
|
|
|
|
|
- const newRows = rows.filter(row =>
|
|
|
|
|
|
|
+ this.syncUserTotalFromList(tabName, total);
|
|
|
|
|
+ // 过滤重复数据(基于 userId)
|
|
|
|
|
+ const newRows = (rows || []).filter(row =>
|
|
|
!displayList.some(u => u.userId === row.userId)
|
|
!displayList.some(u => u.userId === row.userId)
|
|
|
);
|
|
);
|
|
|
- displayList.push(...newRows)
|
|
|
|
|
- // 添加新数据并限制最大长度(避免内存占用过大)
|
|
|
|
|
- if (displayList.length >= 40) { // 最大保留100条
|
|
|
|
|
- this[`${tabName}DisplayList`] = displayList.slice(-40);
|
|
|
|
|
- // 记录滚动位置(用于加载后校准)
|
|
|
|
|
- const scrollEl = this.getScrollElement(tabName);
|
|
|
|
|
- // 校准滚动位置(保持视觉连续性)
|
|
|
|
|
- this.$nextTick(() => {
|
|
|
|
|
- if (scrollEl) {
|
|
|
|
|
- scrollEl.scrollTop = scrollEl.scrollHeight * 0.5;
|
|
|
|
|
- }
|
|
|
|
|
- });
|
|
|
|
|
|
|
+ if (isFirstPage) {
|
|
|
|
|
+ this[`${tabName}DisplayList`] = newRows;
|
|
|
|
|
+ } else {
|
|
|
|
|
+ displayList.push(...newRows);
|
|
|
|
|
+ // 添加新数据并限制最大长度(避免内存占用过大)
|
|
|
|
|
+ if (displayList.length >= 40) {
|
|
|
|
|
+ this[`${tabName}DisplayList`] = displayList.slice(-40);
|
|
|
|
|
+ const scrollEl = this.getScrollElement(tabName);
|
|
|
|
|
+ this.$nextTick(() => {
|
|
|
|
|
+ if (scrollEl) {
|
|
|
|
|
+ scrollEl.scrollTop = scrollEl.scrollHeight * 0.5;
|
|
|
|
|
+ }
|
|
|
|
|
+ });
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
// 更新分页状态
|
|
// 更新分页状态
|
|
|
params.hasMore = params.currentPage * params.pageSize < total;
|
|
params.hasMore = params.currentPage * params.pageSize < total;
|
|
@@ -1104,37 +1277,28 @@ export default {
|
|
|
const params = this.pageParams[tabName];
|
|
const params = this.pageParams[tabName];
|
|
|
const displayList = this[`${tabName}DisplayList`];
|
|
const displayList = this[`${tabName}DisplayList`];
|
|
|
// 边界校验:无上一页/正在加载/当前页<=1
|
|
// 边界校验:无上一页/正在加载/当前页<=1
|
|
|
- console.log(`加载 ${tabName} 上一页`);
|
|
|
|
|
- console.log(!params.hasPrev || this.scrLoading[tabName].prev || params.currentPage <= 1)
|
|
|
|
|
if (!params.hasPrev || this.scrLoading[tabName].prev || params.currentPage <= 1) {
|
|
if (!params.hasPrev || this.scrLoading[tabName].prev || params.currentPage <= 1) {
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
this.scrLoading[tabName].prev = true;
|
|
this.scrLoading[tabName].prev = true;
|
|
|
const targetPage = params.prevPage > 0 ? params.prevPage : params.currentPage - 2;
|
|
const targetPage = params.prevPage > 0 ? params.prevPage : params.currentPage - 2;
|
|
|
- const queryParams = {
|
|
|
|
|
- liveId: this.liveId,
|
|
|
|
|
- pageNum: targetPage,
|
|
|
|
|
- pageSize: 20,
|
|
|
|
|
- online: tabName === 'online' ? 0 : 1,
|
|
|
|
|
- msgStatus: tabName === 'silenced' ? 1 : 0,
|
|
|
|
|
- all: tabName === 'al' ? 1 : 0,
|
|
|
|
|
- userName: this.searchKeyword
|
|
|
|
|
- };
|
|
|
|
|
|
|
+ const queryParams = this.buildWatchUserQuery(tabName, targetPage);
|
|
|
dashBoardWatchUserList(queryParams).then(response => {
|
|
dashBoardWatchUserList(queryParams).then(response => {
|
|
|
this.scrLoading[tabName].prev = false;
|
|
this.scrLoading[tabName].prev = false;
|
|
|
if (response.code !== 200) return;
|
|
if (response.code !== 200) return;
|
|
|
|
|
|
|
|
- const { rows } = response;
|
|
|
|
|
- if (rows.length === 0) {
|
|
|
|
|
|
|
+ const { rows, total } = response;
|
|
|
|
|
+ if (total != null) {
|
|
|
|
|
+ params.total = total;
|
|
|
|
|
+ this.syncUserTotalFromList(tabName, total);
|
|
|
|
|
+ }
|
|
|
|
|
+ if (!rows || rows.length === 0) {
|
|
|
params.hasPrev = false;
|
|
params.hasPrev = false;
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// 记录滚动位置(用于加载后校准)
|
|
// 记录滚动位置(用于加载后校准)
|
|
|
const scrollEl = this.getScrollElement(tabName);
|
|
const scrollEl = this.getScrollElement(tabName);
|
|
|
- const scrollTop = scrollEl?.scrollTop || 0;
|
|
|
|
|
- const itemHeight = 80; // 预估行高(根据实际样式调整)
|
|
|
|
|
- const newItemsHeight = rows.length * itemHeight;
|
|
|
|
|
|
|
|
|
|
// 过滤重复数据并添加到列表头部
|
|
// 过滤重复数据并添加到列表头部
|
|
|
const newRows = rows.filter(row => !displayList.some(u => u.userId === row.userId));
|
|
const newRows = rows.filter(row => !displayList.some(u => u.userId === row.userId));
|
|
@@ -1225,41 +1389,21 @@ export default {
|
|
|
}
|
|
}
|
|
|
})
|
|
})
|
|
|
},
|
|
},
|
|
|
- loadMsgList(){
|
|
|
|
|
- // 直播间消息
|
|
|
|
|
|
|
+ loadMsgList(fromResumeLatest = false){
|
|
|
|
|
+ // 初次/回到最新:拉最近 MSG_WINDOW_SIZE 条(desc → reverse 成正序)
|
|
|
listLiveSingleMsg({
|
|
listLiveSingleMsg({
|
|
|
- liveId:this.liveId,
|
|
|
|
|
- pageNum: this.msgParams.pageNum,
|
|
|
|
|
- pageSize: this.msgParams.pageSize
|
|
|
|
|
|
|
+ liveId: this.liveId,
|
|
|
|
|
+ pageNum: 1,
|
|
|
|
|
+ pageSize: this.MSG_WINDOW_SIZE
|
|
|
}).then(response => {
|
|
}).then(response => {
|
|
|
- let {code, rows,total} = response;
|
|
|
|
|
|
|
+ let { code, rows } = response
|
|
|
if (code === 200) {
|
|
if (code === 200) {
|
|
|
- let totalPage = (total % this.msgParams.pageSize == 0) ? Math.floor(total / this.msgParams.pageSize) : Math.floor(total / this.msgParams.pageSize + 1);
|
|
|
|
|
- rows.forEach(row => {
|
|
|
|
|
- if (!this.msgList.some(m => m.msgId === row.msgId)) {
|
|
|
|
|
- let user = this.alDisplayList.find(u => u.userId === row.userId)
|
|
|
|
|
- if (user) {
|
|
|
|
|
- row.msgStatus = user.msgStatus
|
|
|
|
|
- } else {
|
|
|
|
|
- row.msgStatus = 0
|
|
|
|
|
- }
|
|
|
|
|
- this.msgList.push(row)
|
|
|
|
|
- if (row.userId != null) {
|
|
|
|
|
- const uid = String(row.userId)
|
|
|
|
|
- if (!Object.prototype.hasOwnProperty.call(this.userSingleVisibleMap, uid)) {
|
|
|
|
|
- this.$set(this.userSingleVisibleMap, uid, Number(row.singleVisible) === 1 ? 1 : 0)
|
|
|
|
|
- } else {
|
|
|
|
|
- this.$set(row, 'singleVisible', Number(this.userSingleVisibleMap[uid]) === 1 ? 1 : 0)
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- })
|
|
|
|
|
-
|
|
|
|
|
- this.msgList.reverse()
|
|
|
|
|
- // 同步更新消息列表中相同用户的状态
|
|
|
|
|
- this.alDisplayList.forEach(u => {
|
|
|
|
|
- this.msgList.filter(m => m.userId === u.userId).forEach(m => m.msgStatus = u.msgStatus)
|
|
|
|
|
- })
|
|
|
|
|
|
|
+ let list = (rows || []).slice()
|
|
|
|
|
+ this.hasMoreOlder = list.length >= this.MSG_WINDOW_SIZE
|
|
|
|
|
+ this.hasMoreNewer = false
|
|
|
|
|
+ list.reverse()
|
|
|
|
|
+ this.decorateMsgRows(list)
|
|
|
|
|
+ this.msgList = list.slice(-this.MSG_WINDOW_SIZE)
|
|
|
Object.keys(this.userSingleVisibleMap).forEach(uid => {
|
|
Object.keys(this.userSingleVisibleMap).forEach(uid => {
|
|
|
const status = Number(this.userSingleVisibleMap[uid]) === 1 ? 1 : 0
|
|
const status = Number(this.userSingleVisibleMap[uid]) === 1 ? 1 : 0
|
|
|
this.msgList.forEach(m => {
|
|
this.msgList.forEach(m => {
|
|
@@ -1268,70 +1412,88 @@ export default {
|
|
|
}
|
|
}
|
|
|
})
|
|
})
|
|
|
})
|
|
})
|
|
|
-
|
|
|
|
|
- // 所有消息加载完成后,根据自动滚动状态决定是否滚动
|
|
|
|
|
this.$nextTick(() => {
|
|
this.$nextTick(() => {
|
|
|
- setTimeout(() => {
|
|
|
|
|
- // 重置加载状态
|
|
|
|
|
- this.isLoadingLatest = false;
|
|
|
|
|
-
|
|
|
|
|
- if (this.isAutoScrollEnabled) {
|
|
|
|
|
- // 如果启用自动滚动,强制滚动到底部并隐藏按钮
|
|
|
|
|
- this.scrollToBottom(true);
|
|
|
|
|
- } else {
|
|
|
|
|
- // 如果禁用自动滚动,检查是否在底部,决定是否显示按钮
|
|
|
|
|
- if (this.$refs.manageRightRef && this.$refs.manageRightRef.wrap) {
|
|
|
|
|
- const wrap = this.$refs.manageRightRef.wrap;
|
|
|
|
|
- const scrollHeight = wrap.scrollHeight;
|
|
|
|
|
- const clientHeight = wrap.clientHeight;
|
|
|
|
|
- const currentScrollTop = wrap.scrollTop;
|
|
|
|
|
- const maxScrollTop = scrollHeight - clientHeight;
|
|
|
|
|
-
|
|
|
|
|
- if (currentScrollTop < maxScrollTop - 50) {
|
|
|
|
|
- this.showLoadLatestBtn = true;
|
|
|
|
|
- } else {
|
|
|
|
|
- this.showLoadLatestBtn = false;
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- }, 300);
|
|
|
|
|
- });
|
|
|
|
|
|
|
+ // 回到最新:强制恢复跟随并滚到底,避免被中间的 scroll 事件再次 pause
|
|
|
|
|
+ if (fromResumeLatest || this.isAutoScrollEnabled) {
|
|
|
|
|
+ this.isAutoScrollEnabled = true
|
|
|
|
|
+ this.showLoadLatestBtn = false
|
|
|
|
|
+ this.scrollMsgToBottom()
|
|
|
|
|
+ this.$nextTick(() => {
|
|
|
|
|
+ this.scrollMsgToBottom()
|
|
|
|
|
+ this.isLoadingHistory = false
|
|
|
|
|
+ this.suppressScrollPause = false
|
|
|
|
|
+ })
|
|
|
|
|
+ } else {
|
|
|
|
|
+ this.isLoadingHistory = false
|
|
|
|
|
+ this.suppressScrollPause = false
|
|
|
|
|
+ this.showLoadLatestBtn = true
|
|
|
|
|
+ }
|
|
|
|
|
+ })
|
|
|
|
|
+ } else {
|
|
|
|
|
+ this.isLoadingHistory = false
|
|
|
|
|
+ this.suppressScrollPause = false
|
|
|
}
|
|
}
|
|
|
|
|
+ }).catch(() => {
|
|
|
|
|
+ this.isLoadingHistory = false
|
|
|
|
|
+ this.suppressScrollPause = false
|
|
|
})
|
|
})
|
|
|
|
|
|
|
|
- // 添加滚动监听
|
|
|
|
|
this.$nextTick(() => {
|
|
this.$nextTick(() => {
|
|
|
if (this.$refs.manageRightRef && this.$refs.manageRightRef.wrap) {
|
|
if (this.$refs.manageRightRef && this.$refs.manageRightRef.wrap) {
|
|
|
- this.$refs.manageRightRef.wrap.addEventListener("scroll", this.manageRightScroll)
|
|
|
|
|
|
|
+ this.$refs.manageRightRef.wrap.removeEventListener('scroll', this.manageRightScroll)
|
|
|
|
|
+ this.$refs.manageRightRef.wrap.addEventListener('scroll', this.manageRightScroll)
|
|
|
}
|
|
}
|
|
|
})
|
|
})
|
|
|
},
|
|
},
|
|
|
- // 消息滚动监听(带防抖)
|
|
|
|
|
|
|
+ // 消息滚动:暂停后顶/底触发游标加载;实时模式滚离底部则暂停
|
|
|
manageRightScroll() {
|
|
manageRightScroll() {
|
|
|
- // 清除之前的防抖定时器
|
|
|
|
|
|
|
+ if (this.suppressScrollPause || this.isLoadingHistory) {
|
|
|
|
|
+ return
|
|
|
|
|
+ }
|
|
|
if (this.scrollDebounceTimer) {
|
|
if (this.scrollDebounceTimer) {
|
|
|
- clearTimeout(this.scrollDebounceTimer);
|
|
|
|
|
|
|
+ clearTimeout(this.scrollDebounceTimer)
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
- // 设置防抖,300ms内只执行一次
|
|
|
|
|
this.scrollDebounceTimer = setTimeout(() => {
|
|
this.scrollDebounceTimer = setTimeout(() => {
|
|
|
- this.saveChatScrollPosition();
|
|
|
|
|
|
|
+ if (this.suppressScrollPause || this.isLoadingHistory) {
|
|
|
|
|
+ return
|
|
|
|
|
+ }
|
|
|
|
|
+ this.saveChatScrollPosition()
|
|
|
|
|
+ if (!this.$refs.manageRightRef || !this.$refs.manageRightRef.wrap) {
|
|
|
|
|
+ return
|
|
|
|
|
+ }
|
|
|
|
|
+ const wrap = this.$refs.manageRightRef.wrap
|
|
|
|
|
+ const scrollHeight = wrap.scrollHeight
|
|
|
|
|
+ const clientHeight = wrap.clientHeight
|
|
|
|
|
+ const currentScrollTop = wrap.scrollTop
|
|
|
|
|
+ const maxScrollTop = Math.max(0, scrollHeight - clientHeight)
|
|
|
|
|
+
|
|
|
|
|
+ if (this.isAutoScrollEnabled) {
|
|
|
|
|
+ // 用户主动上滑离开底部 → 暂停实时跟随
|
|
|
|
|
+ if (currentScrollTop < maxScrollTop - 50) {
|
|
|
|
|
+ this.pauseMsgAutoScroll()
|
|
|
|
|
+ }
|
|
|
|
|
+ return
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- // 检查是否滚动到底部
|
|
|
|
|
- if (this.$refs.manageRightRef && this.$refs.manageRightRef.wrap) {
|
|
|
|
|
- const wrap = this.$refs.manageRightRef.wrap;
|
|
|
|
|
- const scrollHeight = wrap.scrollHeight;
|
|
|
|
|
- const clientHeight = wrap.clientHeight;
|
|
|
|
|
- const currentScrollTop = wrap.scrollTop;
|
|
|
|
|
- const maxScrollTop = scrollHeight - clientHeight;
|
|
|
|
|
-
|
|
|
|
|
- // 如果滚动到底部(距离底部小于50px),隐藏按钮并恢复自动滚动
|
|
|
|
|
- if (currentScrollTop >= maxScrollTop - 50) {
|
|
|
|
|
- this.showLoadLatestBtn = false;
|
|
|
|
|
- this.isAutoScrollEnabled = true;
|
|
|
|
|
|
|
+ // 暂停态:到顶/到底各加载一次;离开边缘后重新武装,避免贴边连打
|
|
|
|
|
+ this.showLoadLatestBtn = true
|
|
|
|
|
+ const atTop = currentScrollTop <= 40
|
|
|
|
|
+ const atBottom = currentScrollTop >= maxScrollTop - 40
|
|
|
|
|
+ if (atTop) {
|
|
|
|
|
+ if (this.olderEdgeArmed) {
|
|
|
|
|
+ this.loadOlderMessages()
|
|
|
}
|
|
}
|
|
|
|
|
+ } else {
|
|
|
|
|
+ this.olderEdgeArmed = true
|
|
|
}
|
|
}
|
|
|
- }, 300);
|
|
|
|
|
|
|
+ if (atBottom) {
|
|
|
|
|
+ if (this.newerEdgeArmed) {
|
|
|
|
|
+ this.loadNewerMessages()
|
|
|
|
|
+ }
|
|
|
|
|
+ } else {
|
|
|
|
|
+ this.newerEdgeArmed = true
|
|
|
|
|
+ }
|
|
|
|
|
+ }, 200)
|
|
|
},
|
|
},
|
|
|
loadUserTotals() {
|
|
loadUserTotals() {
|
|
|
if (!this.liveId) return;
|
|
if (!this.liveId) return;
|
|
@@ -1418,14 +1580,16 @@ export default {
|
|
|
}
|
|
}
|
|
|
},
|
|
},
|
|
|
resetMsgParams() {
|
|
resetMsgParams() {
|
|
|
- // 消息参数保留
|
|
|
|
|
- this.msgList = [];
|
|
|
|
|
|
|
+ this.msgList = []
|
|
|
|
|
+ this.hasMoreOlder = true
|
|
|
|
|
+ this.hasMoreNewer = false
|
|
|
|
|
+ this.olderEdgeArmed = true
|
|
|
|
|
+ this.newerEdgeArmed = true
|
|
|
this.msgParams = {
|
|
this.msgParams = {
|
|
|
pageNum: 1,
|
|
pageNum: 1,
|
|
|
- pageSize: 30,
|
|
|
|
|
|
|
+ pageSize: this.MSG_WINDOW_SIZE,
|
|
|
liveId: this.liveId
|
|
liveId: this.liveId
|
|
|
- };
|
|
|
|
|
- // 重置时不改变按钮状态,由后续的滚动逻辑决定
|
|
|
|
|
|
|
+ }
|
|
|
this.taskParams = {
|
|
this.taskParams = {
|
|
|
currentPage: 1,
|
|
currentPage: 1,
|
|
|
pageSize: 20,
|
|
pageSize: 20,
|