import React, { useState, useEffect } from 'react' import { View, Text, ActionSheet } from '@tarojs/components' import Taro from '@tarojs/taro' import { usePullDownRefresh } from '@tarojs/taro' import { pageNotification, getUnreadCount, markAsRead, markAllAsRead, deleteNotification, } from '@/api/developer/developer' import type { Notification, NotificationParam, NotificationType } from '@/types/developer' import './index.scss' // 通知类型配置 const TYPE_CONFIG: Record = { system: { label: '系统通知', icon: '🔔', color: '#1890ff' }, app: { label: '应用通知', icon: '📱', color: '#52c41a' }, member: { label: '成员通知', icon: '👥', color: '#722ed1' }, order: { label: '订单通知', icon: '💰', color: '#fa8c16' }, developer: { label: '开发通知', icon: '🛠️', color: '#13c2c2' }, } const NotificationPage: React.FC = () => { const [loading, setLoading] = useState(false) const [refreshing, setRefreshing] = useState(false) const [list, setList] = useState([]) const [page, setPage] = useState(1) const [hasMore, setHasMore] = useState(true) const [unreadCount, setUnreadCount] = useState(0) const [currentTab, setCurrentTab] = useState('all') // 加载数据 const loadData = async (pageNum: number = 1, isRefresh = false) => { if (loading) return setLoading(true) if (isRefresh) setRefreshing(true) try { const params: NotificationParam = { page: pageNum, limit: 20, type: currentTab === 'all' ? undefined : currentTab, } const data = await pageNotification(params) if (pageNum === 1) { setList(data?.records || []) } else { setList(prev => [...prev, ...(data?.records || [])]) } const total = data?.total || 0 const records = data?.records || [] setHasMore(records.length > 0 && (pageNum * 20) < total) setPage(pageNum) } catch (err) { console.error('加载失败', err) } finally { setLoading(false) setRefreshing(false) } } // 加载未读数 const loadUnreadCount = async () => { try { const data = await getUnreadCount() setUnreadCount(data?.count || 0) } catch (err) { console.error('获取未读数失败', err) } } useEffect(() => { loadData(1) loadUnreadCount() }, [currentTab]) // 下拉刷新 usePullDownRefresh(() => { loadData(1, true) loadUnreadCount() }) // 加载更多 const onReachBottom = () => { if (hasMore && !loading) { loadData(page + 1) } } // 标记已读 const handleRead = async (item: Notification) => { if (item.isRead) return try { await markAsRead(item.id!) setList(prev => prev.map(n => (n.id === item.id ? { ...n, isRead: true } : n)) ) setUnreadCount(prev => Math.max(0, prev - 1)) } catch (err) { console.error('标记已读失败', err) } } // 全部已读 const handleMarkAllRead = async () => { try { await markAllAsRead() setList(prev => prev.map(n => ({ ...n, isRead: true }))) setUnreadCount(0) Taro.showToast({ title: '已全部已读', icon: 'success' }) } catch (err) { console.error('标记全部已读失败', err) Taro.showToast({ title: '操作失败', icon: 'none' }) } } // 删除 const handleDelete = (item: Notification) => { ActionSheet({ alertText: '确定删除这条通知吗?', actions: [{ name: '删除', color: '#ff4d4f', type: 'warn' as const }], confirmText: '取消', }).then(res => { if (res.confirm) { doDelete(item) } }).catch(() => {}) } const doDelete = async (item: Notification) => { try { await deleteNotification(item.id!) setList(prev => prev.filter(n => n.id !== item.id)) if (!item.isRead) { setUnreadCount(prev => Math.max(0, prev - 1)) } Taro.showToast({ title: '已删除', icon: 'success' }) } catch (err) { console.error('删除失败', err) Taro.showToast({ title: '删除失败', icon: 'none' }) } } // 点击通知 const handleClick = (item: Notification) => { handleRead(item) // 根据通知类型和内容跳转 if (item.data?.url) { Taro.navigateTo({ url: item.data.url }) } else if (item.data?.appId) { Taro.navigateTo({ url: `/developer/app/${item.data.appId}/index` }) } else if (item.data?.projectId) { Taro.navigateTo({ url: `/developer/project/${item.data.projectId}/index` }) } } // 格式化日期 const formatDate = (dateStr?: string) => { if (!dateStr) return '' const date = new Date(dateStr) const now = new Date() const diff = now.getTime() - date.getTime() const days = Math.floor(diff / (1000 * 60 * 60 * 24)) if (days === 0) { return `今天 ${String(date.getHours()).padStart(2, '0')}:${String(date.getMinutes()).padStart(2, '0')}` } else if (days === 1) { return '昨天' } else if (days < 7) { return `${days}天前` } else { return `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, '0')}-${String(date.getDate()).padStart(2, '0')}` } } // Tab 配置 const tabs: { key: NotificationType | 'all'; label: string }[] = [ { key: 'all', label: '全部' }, { key: 'system', label: '系统' }, { key: 'app', label: '应用' }, { key: 'member', label: '成员' }, { key: 'order', label: '订单' }, ] return ( {/* 头部 */} 🔔 消息通知 {unreadCount > 0 && ( {unreadCount > 99 ? '99+' : unreadCount} )} {unreadCount > 0 && ( 全部已读 )} {/* Tab */} {tabs.map((tab) => ( setCurrentTab(tab.key)} > {tab.label} ))} {/* 列表 */} {list.length === 0 && !loading ? ( 📭 暂无通知 ) : ( list.map((item) => ( handleClick(item)} > {TYPE_CONFIG[item.type || 'system']?.icon} {item.title} {!item.isRead && } {item.content} {formatDate(item.createTime)} { e.stopPropagation() handleDelete(item) }} > × )) )} {/* 加载状态 */} {loading && list.length > 0 && ( 加载中... )} {!hasMore && list.length > 0 && ( 没有更多了 )} ) } export default NotificationPage