import { computed, ref } from 'vue' import { useStore } from 'vuex' import { getNotificationsApi, markAsReadApi, markAllAsReadApi, deleteNotificationApi, clearNotificationsApi } from '@/utils/api.js' const GROUPS = [ { type: 'activity', label: '活动通知' }, { type: 'feedback_replied', label: '反馈回复' }, { type: 'report_resolved', label: '举报结果' }, { type: 'target_reported', label: '被举报' }, ] export function useMailboxCenter() { const store = useStore() const itemsByType = computed(() => store.state.mailbox.itemsByType) const unreadByType = computed(() => store.state.mailbox.unreadByType) const loading = computed(() => store.state.mailbox.loading) const hasAny = computed(() => GROUPS.some(g => (itemsByType.value[g.type] || []).length > 0)) const hasMore = computed(() => Object.values(store.state.mailbox.noMoreByType).some(v => !v)) const collapsedMap = ref({}) collapsedMap.value = (() => { try { return uni.getStorageSync('mailbox_collapsed') || {} } catch (e) { return {} } })() // 列表页 onShow 时并发 4 个 type 各拉首页 async function loadAll() { store.commit('mailbox/SET_LOADING', true) try { await Promise.all(GROUPS.map(g => getNotificationsApi({ type: g.type, page: 1, page_size: 20 }) .then((resp) => { const items = resp.data?.items || [] store.commit('mailbox/SET_ITEMS', { type: g.type, items, sortUnreadFirst: true }) store.commit('mailbox/SET_NO_MORE', { type: g.type, value: items.length < 20 }) if (resp.data?.unreadByType) store.commit('mailbox/REPLACE_UNREAD_BY_TYPE', resp.data.unreadByType) }) )) } finally { store.commit('mailbox/SET_LOADING', false) } } function onScrollLower() { const target = GROUPS.find(g => !store.state.mailbox.noMoreByType[g.type]) if (target) loadMore(target.type) } async function loadMore(type) { const page = Math.floor((itemsByType.value[type].length / 20) + 1) const resp = await getNotificationsApi({ type, page, page_size: 20 }) const items = resp.data?.items || [] store.commit('mailbox/APPEND_ITEMS', { type, items }) store.commit('mailbox/SET_NO_MORE', { type, value: items.length < 20 }) } async function onMarkRead(nid, type) { await markAsReadApi(nid) store.commit('mailbox/UPDATE_ITEM', { type, id: nid, patch: { is_read: true } }) store.commit('mailbox/DECREMENT_TYPE', type) store.commit('mailbox/RESORT_ITEMS', type) // 已读排后 } async function onMarkAllRead() { await Promise.all(GROUPS.map(g => markAllAsReadApi(g.type))) store.commit('mailbox/MARK_ALL_READ') } async function onDeleteOne(nid, type) { await deleteNotificationApi(nid) store.commit('mailbox/REMOVE_ITEM', { type, id: nid }) } async function onClearAll() { const ok = await new Promise((resolve) => { uni.showModal({ title: '提示', content: '清空所有通知?', success: (r) => resolve(r.confirm) }) }) if (!ok) return await clearNotificationsApi('all') store.commit('mailbox/CLEAR_ALL') } function onSelectItem(n) { if (!n || !n.id) return onMarkRead(n.id, n.type) uni.navigateTo({ url: `/pages/mailbox/detail?nid=${n.id}&type=${n.type}` }) } function onLongPress(n) { if (!n || !n.id) return uni.showActionSheet({ itemList: ['标已读', '删除'], success: (res) => { if (res.tapIndex === 0) onMarkRead(n.id, n.type) else if (res.tapIndex === 1) onDeleteOne(n.id, n.type) } }) } function isCollapsed(type) { return !!collapsedMap.value[type] } function toggleCollapse(type) { const next = { ...collapsedMap.value, [type]: !collapsedMap.value[type] } collapsedMap.value = next try { uni.setStorageSync('mailbox_collapsed', next) } catch (e) {} } return { GROUPS, itemsByType, unreadByType, loading, hasAny, hasMore, loadAll, onScrollLower, loadMore, onMarkRead, onMarkAllRead, onDeleteOne, onClearAll, onSelectItem, onLongPress, isCollapsed, toggleCollapse, } }