'use client'; import Link from 'next/link'; import { useMemo, useState } from 'react'; import { useQuery, useQueryClient } from '@tanstack/react-query'; import { EmptyState } from '@/components/feedback/empty-state'; import { ErrorState } from '@/components/feedback/error-state'; import { LoadingState } from '@/components/feedback/loading-state'; import { PageHeader } from '@/components/layout/page-header'; import { AppCard } from '@/components/ui/app-card'; import { StatusBadge } from '@/components/ui/status-badge'; import { getAccessLogs } from '@/features/access-logs/api/access-logs'; import type { AccessLogItem } from '@/features/access-logs/types'; import { PrimaryButton, ResourceInput, SecondaryButton, } from '@/features/shared/components/resource-primitives'; import { formatDateTime, formatRelativeTime } from '@/lib/utils/date'; const accessLogsQueryKey = (nodeId: string) => ['access-logs', nodeId] as const; function getErrorMessage(error: unknown) { return error instanceof Error ? error.message : '请求失败,请稍后重试。'; } function buildSummary(totalRecord = 0, totalIP = 0) { return [ { label: '访问记录', value: totalRecord }, { label: '来源 IP', value: totalIP }, ]; } function getStatusMeta(statusCode: number) { if (statusCode >= 500) { return { label: String(statusCode), variant: 'danger' as const }; } if (statusCode >= 400) { return { label: String(statusCode), variant: 'warning' as const }; } return { label: String(statusCode), variant: 'success' as const }; } export function AccessLogsPage() { const queryClient = useQueryClient(); const [nodeFilterInput, setNodeFilterInput] = useState(''); const [nodeFilter, setNodeFilter] = useState(''); const [page, setPage] = useState(0); const logsQuery = useQuery({ queryKey: [...accessLogsQueryKey(nodeFilter), page], queryFn: () => getAccessLogs(page, nodeFilter), }); const logs = useMemo(() => logsQuery.data?.items ?? [], [logsQuery.data]); const hasMore = logsQuery.data?.has_more ?? false; const pageSize = logsQuery.data?.page_size ?? 50; const summary = useMemo( () => buildSummary( logsQuery.data?.total_record ?? 0, logsQuery.data?.total_ip ?? 0, ), [logsQuery.data?.total_ip, logsQuery.data?.total_record], ); return (
{item.label}
{item.value}
| 时间 | 原 IP | 访问域名 | 路径 | 节点 | 状态码 |
|---|---|---|---|---|---|
|
{formatDateTime(item.logged_at)}
{formatRelativeTime(item.logged_at)}
|
{item.remote_addr || '—'}
{item.region ? (
{item.region}
) : null}
|
{item.host || '—'} | {item.path || '—'} |
{item.node_name || item.node_id}
{item.node_id}
|
|
第 {page + 1} 页,每页 {pageSize} 条。