// Copyright 2026 Arctel.net // SPDX-License-Identifier: Apache-2.0 "use client" import * as React from "react" import {useQuery} from "@tanstack/react-query" import {ChevronLeft, ChevronRight, History, RefreshCw, Search,} from "lucide-react" import {Button} from "@/components/ui/button" import {Input} from "@/components/ui/input" import {Badge} from "@/components/ui/badge" import {Table, TableBody, TableCell, TableHead, TableHeader, TableRow,} from "@/components/ui/table" import {Select, SelectContent, SelectItem, SelectTrigger, SelectValue,} from "@/components/ui/select" import {ErrorInline} from "@/components/layout/error" import {LoadingStateWithBorder} from "@/components/layout/loading" import {cn} from "@/lib/utils" import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, } from "@/components/ui/dialog" import type {PushHistory} from "@/lib/services/push" import {PushService} from "@/lib/services/push" function getLevelBadgeVariant(level: string): "outline" | "secondary" | "destructive" | "default" { switch (level) { case "CRITICAL": return "destructive" case "IMPORTANT": return "default" default: return "outline" } } export function HistoriesTab() { const [historyPage, setHistoryPage] = React.useState(1) const [historySearch, setHistorySearch] = React.useState("") const [historyStatus, setHistoryStatus] = React.useState("all") const [detailOpen, setDetailOpen] = React.useState(false) const [selectedHistory, setSelectedHistory] = React.useState(null) const handleRowClick = (hist: PushHistory) => { setSelectedHistory(hist) setDetailOpen(true) } const historiesQuery = useQuery({ queryKey: ["admin", "push-histories", historyPage, historySearch, historyStatus], queryFn: () => PushService.listHistories({ page: historyPage, page_size: 10, event_key: historySearch || undefined, status: historyStatus === "all" ? undefined : historyStatus, }), }) return (
{ setHistorySearch(e.target.value) setHistoryPage(1) }} />
事件 渠道 目标 标题 等级 状态 时间 {historiesQuery.isLoading ? ( ) : historiesQuery.isError ? ( historiesQuery.refetch()} className="justify-center" /> ) : (historiesQuery.data?.results ?? []).length === 0 ? ( 无推送历史数据 ) : ( (historiesQuery.data?.results ?? []).map(hist => ( handleRowClick(hist)} > {hist.event_key} {hist.channel === "email" ? "邮件" : hist.channel} {hist.target} {hist.title} {hist.level} {hist.status === "success" ? "成功" : "失败"} {hist.status !== "success" && hist.error_msg && (
{hist.error_msg}
)}
{new Date(hist.created_at).toLocaleString()}
)) )}
{historiesQuery.data && historiesQuery.data.total > 0 && (
共 {historiesQuery.data.total} 条历史记录
{historyPage}
)} {/* ==================== 对话框:推送详情 ==================== */} 推送通知详情 查看该条通知发送的详细审计信息与内容 {selectedHistory && (
事件标识
{selectedHistory.event_key}
发送渠道
{selectedHistory.channel === "email" ? "邮件推送" : selectedHistory.channel}
推送目标
{selectedHistory.target}
发送时间
{new Date(selectedHistory.created_at).toLocaleString()}
通知等级
{selectedHistory.level}
发送状态
{selectedHistory.status === "success" ? "成功" : "失败"}
{selectedHistory.status === "failed" && selectedHistory.error_msg && (
失败原因
{selectedHistory.error_msg}
)}
通知标题
{selectedHistory.title}
通知内容
{selectedHistory.content}
)}
) }