133 lines
3.7 KiB
TypeScript
133 lines
3.7 KiB
TypeScript
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<AppMessageVo[]>([])
|
|
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<string, AppMessageVo>()
|
|
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,
|
|
}
|
|
}
|