import { useEffect, useState, useCallback } from 'react'; import { adminApi } from '../lib/api'; import type { LoginAnomaly, Team } from '../types'; import { showToast } from '../components/Toast'; import { DatePicker } from '../components/DatePicker'; import { Select } from '../components/Select'; import styles from './AuditLogsPage.module.css'; const RULE_OPTIONS = [ { label: '全部规则', value: '' }, { label: 'R1 登录地区不对', value: 'region_mismatch' }, { label: 'R2 不可能的旅行', value: 'impossible_travel' }, { label: 'R3 登录太频繁', value: 'login_frequency' }, { label: 'R4 团队遍地开花', value: 'multi_city' }, { label: 'R5 海外IP太杂', value: 'overseas_ip_diversity' }, ]; const LEVEL_OPTIONS = [ { label: '全部级别', value: '' }, { label: '警告', value: 'warning' }, { label: '严重', value: 'critical' }, ]; const RULE_LABELS: Record = { region_mismatch: 'R1 登录地区不对', impossible_travel: 'R2 不可能的旅行', login_frequency: 'R3 登录太频繁', multi_city: 'R4 团队遍地开花', overseas_ip_diversity: 'R5 海外IP太杂', }; export function AnomalyLogPage() { const [anomalies, setAnomalies] = useState([]); const [total, setTotal] = useState(0); const [page, setPage] = useState(1); const [ruleFilter, setRuleFilter] = useState(''); const [levelFilter, setLevelFilter] = useState(''); const [teamFilter, setTeamFilter] = useState(''); const [startDate, setStartDate] = useState(''); const [endDate, setEndDate] = useState(''); const [loading, setLoading] = useState(true); const [teams, setTeams] = useState([]); const pageSize = 20; useEffect(() => { adminApi.getTeams().then(({ data }) => setTeams(data.results)).catch(() => {}); }, []); const fetchAnomalies = useCallback(async () => { setLoading(true); try { const { data } = await adminApi.getLoginAnomalies({ page, page_size: pageSize, rule: ruleFilter || undefined, level: levelFilter || undefined, team_id: teamFilter ? Number(teamFilter) : undefined, start_date: startDate || undefined, end_date: endDate || undefined, }); setAnomalies(data.results); setTotal(data.total); } catch { showToast('加载安全日志失败'); } finally { setLoading(false); } }, [page, ruleFilter, levelFilter, teamFilter, startDate, endDate]); useEffect(() => { fetchAnomalies(); }, [fetchAnomalies]); const handleSearch = () => { setPage(1); fetchAnomalies(); }; const totalPages = Math.ceil(total / pageSize); const teamOptions = [ { label: '全部团队', value: '' }, ...teams.map((t) => ({ label: t.name, value: String(t.id) })), ]; return (

安全日志

{ setLevelFilter(v); setPage(1); }} placeholder="全部级别" options={LEVEL_OPTIONS} />