hookehuyr

feat(消息列表): 添加消息轮询功能以实时更新消息列表

添加轮询机制,每隔30秒自动获取最新消息
在搜索和切换标签时自动重启轮询
页面卸载时清理定时器防止内存泄漏
...@@ -96,7 +96,7 @@ ...@@ -96,7 +96,7 @@
96 </template> 96 </template>
97 97
98 <script setup> 98 <script setup>
99 -import { ref, computed, onMounted, markRaw } from 'vue' 99 +import { ref, computed, onMounted, onUnmounted, markRaw } from 'vue'
100 import { Search2, Notice } from '@nutui/icons-vue-taro' 100 import { Search2, Notice } from '@nutui/icons-vue-taro'
101 import TabBar from '@/components/TabBar.vue' 101 import TabBar from '@/components/TabBar.vue'
102 import MessageDetail from '@/components/MessageDetail.vue' 102 import MessageDetail from '@/components/MessageDetail.vue'
...@@ -125,6 +125,8 @@ const onBlurSearch = async () => { ...@@ -125,6 +125,8 @@ const onBlurSearch = async () => {
125 hasMore.value = true 125 hasMore.value = true
126 // 重新获取数据 126 // 重新获取数据
127 await initData() 127 await initData()
128 + // 重新启动轮询以适应新的搜索条件
129 + startPolling()
128 } 130 }
129 // 当前激活的Tab 131 // 当前激活的Tab
130 const activeTab = ref('all') 132 const activeTab = ref('all')
...@@ -137,6 +139,10 @@ const pageSize = 10 ...@@ -137,6 +139,10 @@ const pageSize = 10
137 // 是否还有更多数据 139 // 是否还有更多数据
138 const hasMore = ref(true) 140 const hasMore = ref(true)
139 141
142 +// 轮询相关
143 +const pollingTimer = ref(null)
144 +const POLLING_INTERVAL = 30000 // 30秒
145 +
140 // 对话数据 146 // 对话数据
141 const conversations = ref([]) 147 const conversations = ref([])
142 148
...@@ -147,6 +153,79 @@ const selectedConversation = ref(null) ...@@ -147,6 +153,79 @@ const selectedConversation = ref(null)
147 // 模拟消息历史记录 153 // 模拟消息历史记录
148 const mockMessages = ref([]) 154 const mockMessages = ref([])
149 155
156 +/**
157 + * 轮询获取消息列表
158 + */
159 +const pollMessages = async () => {
160 + try {
161 + // 静默获取数据,不显示loading状态
162 + const params = {
163 + page: 0,
164 + limit: pageSize
165 + }
166 +
167 + // 根据activeTab设置过滤参数
168 + if (activeTab.value === 'unread') {
169 + params.status = 3 // 未读
170 + } else if (activeTab.value === 'system') {
171 + params.type = 'system' // 系统消息
172 + }
173 +
174 + // 如果有搜索关键词
175 + if (searchValue.value) {
176 + params.keyword = searchValue.value
177 + }
178 +
179 + const response = await getMessagesListAPI(params)
180 +
181 + if (response.code && response.data && response.data.list) {
182 + // 转换API数据格式为组件需要的格式
183 + const transformedData = response.data.list.map(item => ({
184 + id: item.id,
185 + name: item.type === 'system' ? '系统通知' : (item.partner_nickname || '未知用户'),
186 + avatar: item.type === 'chat' ? (item.partner_avatar_url || defaultAvatar) : '',
187 + icon: item.type === 'system' ? markRaw(Notice) : null,
188 + lastMessage: item.note || '',
189 + time: item.created_time_desc || '',
190 + unread: item.status === 3, // 3=未读,5=已读
191 + type: item.type,
192 + create_time: item.create_time
193 + }))
194 +
195 + // 更新消息列表,保持当前页面状态
196 + conversations.value = transformedData
197 + }
198 + } catch (error) {
199 + console.error('轮询获取消息列表失败:', error)
200 + // 轮询失败时不显示错误提示,避免干扰用户
201 + }
202 +}
203 +
204 +/**
205 + * 启动轮询
206 + */
207 +const startPolling = () => {
208 + // 清除现有定时器
209 + if (pollingTimer.value) {
210 + clearInterval(pollingTimer.value)
211 + }
212 +
213 + // 启动新的定时器
214 + pollingTimer.value = setInterval(() => {
215 + pollMessages()
216 + }, POLLING_INTERVAL)
217 +}
218 +
219 +/**
220 + * 停止轮询
221 + */
222 +const stopPolling = () => {
223 + if (pollingTimer.value) {
224 + clearInterval(pollingTimer.value)
225 + pollingTimer.value = null
226 + }
227 +}
228 +
150 // 初始化数据 229 // 初始化数据
151 const initData = async () => { 230 const initData = async () => {
152 try { 231 try {
...@@ -256,6 +335,8 @@ const setActiveTab = async (tabKey) => { ...@@ -256,6 +335,8 @@ const setActiveTab = async (tabKey) => {
256 }, 50); 335 }, 50);
257 // 重新获取数据 336 // 重新获取数据
258 await initData(); 337 await initData();
338 + // 重新启动轮询以适应新的筛选条件
339 + startPolling();
259 340
260 // 添加淡入效果 341 // 添加淡入效果
261 setTimeout(() => { 342 setTimeout(() => {
...@@ -426,6 +507,13 @@ onMounted(async () => { ...@@ -426,6 +507,13 @@ onMounted(async () => {
426 } 507 }
427 }, 500); 508 }, 500);
428 await initData() 509 await initData()
510 + // 启动轮询
511 + startPolling()
512 +})
513 +
514 +// 页面卸载时清理轮询
515 +onUnmounted(() => {
516 + stopPolling()
429 }) 517 })
430 </script> 518 </script>
431 519
......