import { onShow, onUnload } from '@dcloudio/uni-app' import { computed, ref } from 'vue' import { fetchMessagePage, markAllMessagesRead, markMessageRead } from '@/api/message' import { refreshUnreadMessageCount } from '@/hooks/use-message-inbox' import { getErrorMessage } from '@/utils/api-error' import { onMessagePush } from '@/utils/message-socket' import type { AppMessageVo } from '@/types/message' import { formatNotifyTime, isUnreadMessage, normalizeMessageId } from './notify.utils' const PAGE_SIZE = 20 export function useNotify() { const messages = ref([]) const loading = ref(false) const loadingMore = ref(false) const pageNum = ref(1) const total = ref(0) const sectionTitle = ref('全部家庭') const hasMore = computed(() => messages.value.length < total.value) let unsubscribePush: (() => void) | null = null async function loadMessages(reset = false) { if (loading.value || loadingMore.value) return if (reset) { pageNum.value = 1 loading.value = true } else { if (!hasMore.value && messages.value.length > 0) return loadingMore.value = true } try { const { rows, total: nextTotal } = await fetchMessagePage({ pageNum: pageNum.value, pageSize: PAGE_SIZE, }) total.value = nextTotal if (reset) { messages.value = rows } else { const map = new Map() for (const item of [...messages.value, ...rows]) { const id = normalizeMessageId(item) if (id) map.set(id, item) } messages.value = Array.from(map.values()) } const homeName = rows.find((item) => item.homeName)?.homeName if (homeName) sectionTitle.value = homeName if (rows.length > 0) { pageNum.value += 1 } } catch (err) { uni.showToast({ title: getErrorMessage(err, '加载通知失败'), icon: 'none' }) } finally { loading.value = false loadingMore.value = false } } async function onRefresh() { await loadMessages(true) await refreshUnreadMessageCount() } async function onLoadMore() { await loadMessages(false) } async function onItemTap(message: AppMessageVo) { const messageId = normalizeMessageId(message) if (!messageId) return if (isUnreadMessage(message)) { try { await markMessageRead(messageId) messages.value = messages.value.map((item) => normalizeMessageId(item) === messageId ? { ...item, readFlag: '1' } : item, ) await refreshUnreadMessageCount() } catch (err) { uni.showToast({ title: getErrorMessage(err, '标记已读失败'), icon: 'none' }) } } const deviceId = message.deviceId if (deviceId !== undefined && deviceId !== null && deviceId !== '') { uni.navigateTo({ url: `/pages/device/detail/index?deviceId=${encodeURIComponent(String(deviceId))}`, }) } } async function onMarkAllRead() { try { await markAllMessagesRead() messages.value = messages.value.map((item) => ({ ...item, readFlag: '1' })) await refreshUnreadMessageCount() uni.showToast({ title: '已全部标为已读', icon: 'none' }) } catch (err) { uni.showToast({ title: getErrorMessage(err, '操作失败'), icon: 'none' }) } } onShow(() => { void onRefresh() unsubscribePush = onMessagePush(() => { void onRefresh() }) }) onUnload(() => { unsubscribePush?.() unsubscribePush = null }) return { messages, loading, loadingMore, hasMore, sectionTitle, formatNotifyTime, isUnreadMessage, onRefresh, onLoadMore, onItemTap, onMarkAllRead, } }