blob: 55f0ec531388b7f2f7d65fb206ca8e8b67478f18 [file] [log] [blame]
'use client';
import React, { useEffect, useRef, useState } from 'react';
import axios from 'axios';
import { DataTable } from 'primereact/datatable';
import { Column } from 'primereact/column';
import { Sidebar } from 'primereact/sidebar';
import { Button } from 'primereact/button';
import { Tag } from 'primereact/tag';
import { Toast } from 'primereact/toast';
import { Paginator, PaginatorPageChangeEvent } from 'primereact/paginator';
import { Card } from 'primereact/card';
import { TabView, TabPanel } from 'primereact/tabview'; // ✅ TabView 导入
import { useLocalStorage } from '../hook/useLocalStorage';
import './notification.scss';
interface User {
Id: number;
}
interface Notification {
notificationId: number;
title: string;
content: string;
createAt: string;
isRead: boolean;
triggeredBy: number;
relatedId: number;
}
export default function NotificationPage() {
const user = useLocalStorage<User>('user');
const userId: number = user?.Id ?? -1;
const toast = useRef<Toast>(null);
const [notifications, setNotifications] = useState<Notification[]>([]);
const [selectedNotification, setSelectedNotification] = useState<Notification | null>(null);
const [visible, setVisible] = useState<boolean>(false);
const [activeTab, setActiveTab] = useState<number>(0); // ✅ 当前 Tab 下标
// 分页相关
const [first, setFirst] = useState<number>(0);
const [rows, setRows] = useState<number>(5);
const [totalRecords, setTotalRecords] = useState<number>(0);
// 加载数据
const fetchNotifications = async () => {
try {
const pageNumber = first / rows + 1;
const res = await axios.get(process.env.PUBLIC_URL + '/notification', {
params: { pageNumber, rows, userId },
});
const { records, total } = res.data;
setNotifications(records);
setTotalRecords(total);
} catch (error) {
console.error('无法获取通知数据', error);
toast.current?.show({ severity: 'error', summary: '加载失败', detail: '无法获取通知数据' });
}
};
useEffect(() => {
fetchNotifications();
}, [first, rows]); // ✅ 加入分页依赖
const handleRead = async (id: number) => {
try {
await axios.post(process.env.PUBLIC_URL + '/notification/read', { notificationId: id });
setNotifications(prev =>
prev.map(n => (n.notificationId === id ? { ...n, isRead: true } : n))
);
} catch (error) {
console.error('已读失败', error);
toast.current?.show({ severity: 'error', summary: '设置已读失败' });
}
};
const handleDelete = async (id: number) => {
try {
await axios.delete(process.env.PUBLIC_URL + '/notification', { data: { notificationId: id } });
setNotifications(prev => prev.filter(n => n.notificationId !== id));
toast.current?.show({ severity: 'success', summary: '删除成功' });
} catch (error) {
console.error('删除失败', error);
toast.current?.show({ severity: 'error', summary: '删除失败' });
}
};
const openSidebar = (notification: Notification) => {
if (!notification.isRead) handleRead(notification.notificationId);
setSelectedNotification(notification);
setVisible(true);
};
const readTemplate = (rowData: Notification) => (
<Tag value={rowData.isRead ? '已读' : '未读'} severity={rowData.isRead ? undefined : 'warning'} />
);
const actionTemplate = (rowData: Notification) => (
<div className="actions">
{!rowData.isRead && (
<Button
icon="pi pi-check"
text
severity="success"
onClick={() => handleRead(rowData.notificationId)}
tooltip="标记为已读"
/>
)}
<Button icon="pi pi-times" severity="danger" text onClick={() => handleDelete(rowData.notificationId)} />
</div>
);
const onPageChange = (e: PaginatorPageChangeEvent) => {
setFirst(e.first);
setRows(e.rows);
};
const unreadNotifications = notifications.filter(n => !n.isRead);
const readNotifications = notifications.filter(n => n.isRead);
return (
<div className="notification-page">
<Toast ref={toast} />
<h2>系统通知</h2>
<TabView activeIndex={activeTab} onTabChange={(e) => setActiveTab(e.index)}>
<TabPanel header="未读通知">
<DataTable value={unreadNotifications} paginator={false} emptyMessage="暂无未读通知">
<Column field="title" header="标题" body={(row) => (
<span className="title-link" onClick={() => openSidebar(row)}>{row.title}</span>
)} />
<Column field="createAt" header="时间" />
<Column field="isRead" header="状态" body={readTemplate} />
<Column header="操作" style={{ width: '120px', textAlign: 'center' }} body={actionTemplate} />
</DataTable>
</TabPanel>
<TabPanel header="已读通知">
<DataTable value={readNotifications} paginator={false} emptyMessage="暂无已读通知">
<Column field="title" header="标题" body={(row) => (
<span className="title-link" onClick={() => openSidebar(row)}>{row.title}</span>
)} />
<Column field="createAt" header="时间" />
<Column field="isRead" header="状态" body={readTemplate} />
<Column header="操作" style={{ width: '120px', textAlign: 'center' }} body={actionTemplate} />
</DataTable>
</TabPanel>
</TabView>
<Paginator
className="Paginator"
first={first}
rows={rows}
totalRecords={totalRecords}
onPageChange={onPageChange}
rowsPerPageOptions={[5, 10, 20]}
/>
<Sidebar visible={visible} position="right" onHide={() => setVisible(false)} className="p-sidebar-md">
{selectedNotification && (
<Card title={selectedNotification.title} subTitle={selectedNotification.createAt}>
<p className="m-0">{selectedNotification.content}</p>
</Card>
)}
</Sidebar>
</div>
);
}