优化了消息数量,筛选和顶部部分
This commit is contained in:
@@ -52,6 +52,16 @@ export async function fetchChats(page = 1, pageSize = 20) {
|
||||
return data.data
|
||||
}
|
||||
|
||||
export async function fetchUnreadChatCount() {
|
||||
const { data } = await apiClient.get<ApiResponse<{ unread_count: number }>>(
|
||||
'/chats/unread-count',
|
||||
{
|
||||
silent: true,
|
||||
}
|
||||
)
|
||||
return data.data.unread_count
|
||||
}
|
||||
|
||||
export async function fetchChat(id: number) {
|
||||
const { data } = await apiClient.get<ApiResponse<ChatConversation>>(`/chats/${id}`)
|
||||
return data.data
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
import { computed, onBeforeUnmount, onMounted, ref, watch } from 'vue'
|
||||
import type { RouteLocationNormalizedLoaded } from 'vue-router'
|
||||
|
||||
import { fetchUnreadChatCount } from '@/features/chats/api/chats'
|
||||
import { useSessionStore } from '@/stores/session'
|
||||
|
||||
export function useChatUnreadCount(route: RouteLocationNormalizedLoaded) {
|
||||
const session = useSessionStore()
|
||||
const unreadCount = ref(0)
|
||||
let timer: number | null = null
|
||||
let requestID = 0
|
||||
|
||||
const unreadLabel = computed(() => (unreadCount.value > 99 ? '99+' : String(unreadCount.value)))
|
||||
|
||||
function stopPolling() {
|
||||
if (timer) {
|
||||
window.clearInterval(timer)
|
||||
timer = null
|
||||
}
|
||||
}
|
||||
|
||||
async function loadUnreadCount() {
|
||||
if (!session.isLoggedIn) {
|
||||
unreadCount.value = 0
|
||||
return
|
||||
}
|
||||
|
||||
const currentID = ++requestID
|
||||
try {
|
||||
const count = await fetchUnreadChatCount()
|
||||
if (currentID === requestID) {
|
||||
unreadCount.value = count
|
||||
}
|
||||
} catch {
|
||||
// 底部导航不弹错误提示,保持上一次未读数即可。
|
||||
}
|
||||
}
|
||||
|
||||
function startPolling() {
|
||||
stopPolling()
|
||||
void loadUnreadCount()
|
||||
timer = window.setInterval(loadUnreadCount, 30_000)
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
if (session.isLoggedIn) {
|
||||
startPolling()
|
||||
}
|
||||
})
|
||||
|
||||
onBeforeUnmount(stopPolling)
|
||||
|
||||
watch(
|
||||
() => session.isLoggedIn,
|
||||
loggedIn => {
|
||||
if (loggedIn) {
|
||||
startPolling()
|
||||
return
|
||||
}
|
||||
stopPolling()
|
||||
unreadCount.value = 0
|
||||
}
|
||||
)
|
||||
|
||||
watch(
|
||||
() => route.fullPath,
|
||||
() => {
|
||||
void loadUnreadCount()
|
||||
}
|
||||
)
|
||||
|
||||
return {
|
||||
unreadCount,
|
||||
unreadLabel,
|
||||
refreshUnreadCount: loadUnreadCount,
|
||||
}
|
||||
}
|
||||
@@ -33,6 +33,7 @@ const emit = defineEmits<{
|
||||
'update:show': [value: boolean]
|
||||
'update:selectedFilters': [value: SelectedFilters]
|
||||
'update:rangeFilters': [value: RangeFilters]
|
||||
reset: []
|
||||
}>()
|
||||
|
||||
const activeCount = computed(() => {
|
||||
@@ -105,8 +106,7 @@ function isRangePresetActive(sectionKey: string, min: string, max: string) {
|
||||
}
|
||||
|
||||
function resetFilters() {
|
||||
emit('update:selectedFilters', {})
|
||||
emit('update:rangeFilters', {})
|
||||
emit('reset')
|
||||
}
|
||||
|
||||
function scrollToSection(sectionKey: string) {
|
||||
|
||||
@@ -3,15 +3,12 @@
|
||||
max-width: 430px;
|
||||
min-height: 100vh;
|
||||
margin: 0 auto;
|
||||
padding-bottom: 68px;
|
||||
padding-bottom: calc(72px + env(safe-area-inset-bottom));
|
||||
background: #f6f8fb;
|
||||
color: #17233d;
|
||||
}
|
||||
|
||||
.mobile-hero {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
z-index: 20;
|
||||
padding: 12px 12px 10px;
|
||||
background: #fff;
|
||||
box-shadow: 0 1px 0 rgba(15, 23, 42, 0.06);
|
||||
|
||||
@@ -825,6 +825,7 @@ syncMobileHomeQuery()
|
||||
v-model:range-filters="rangeFilters"
|
||||
:sections="filterSections"
|
||||
:range-presets="rangePresets"
|
||||
@reset="clearFilters"
|
||||
/>
|
||||
|
||||
<button
|
||||
|
||||
Reference in New Issue
Block a user