import { useState } from 'react' import { Table, Button, Modal, Form, Input, Tag, Typography, Tabs, DatePicker } from 'antd' import { PlusOutlined, EditOutlined, SafetyOutlined, CheckOutlined } from '@ant-design/icons' import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query' import { api } from '@/services/http-client' import { complianceStatusLabels } from '@/constants/labels' import { message } from 'antd' import dayjs from 'dayjs' const { Title } = Typography const { TextArea } = Input const statusColors: Record = { pending: 'blue', approved: 'green', rejected: 'red', PENDING: 'blue', APPROVED: 'green', REJECTED: 'red' } export default function ComplianceAdmin() { const [modalOpen, setModalOpen] = useState(false) const [modalType, setModalType] = useState('') const [editing, setEditing] = useState(null) const [form] = Form.useForm() const qc = useQueryClient() const { data: policies, isLoading: pLoading } = useQuery({ queryKey: ['compliance', 'policies'], queryFn: () => api.get('/admin-api/compliance/privacy-policies').then(d => d ?? []), }) const { data: agreements, isLoading: aLoading } = useQuery({ queryKey: ['compliance', 'agreements'], queryFn: () => api.get('/admin-api/compliance/user-agreements').then(d => d ?? []), }) const { data: filings, isLoading: fLoading } = useQuery({ queryKey: ['compliance', 'filings'], queryFn: () => api.get('/admin-api/compliance/filings').then(d => d ?? []), }) const { data: deletions, isLoading: dLoading } = useQuery({ queryKey: ['compliance', 'deletions'], queryFn: () => api.get('/admin-api/compliance/deletion-requests').then(d => d ?? []), }) const { data: exports_, isLoading: eLoading } = useQuery({ queryKey: ['compliance', 'exports'], queryFn: () => api.get('/admin-api/compliance/export-requests').then(d => d ?? []), }) const { data: securityEvents, isLoading: sLoading } = useQuery({ queryKey: ['compliance', 'security-events'], queryFn: () => api.get('/admin-api/compliance/security-events').then(d => d ?? []), }) const saveMutation = useMutation({ mutationFn: (values: any) => { if (modalType === 'policy') return editing ? api.patch(`/admin-api/compliance/privacy-policies/${editing.id}`, values) : api.post('/admin-api/compliance/privacy-policies', values) if (modalType === 'agreement') return editing ? api.patch(`/admin-api/compliance/user-agreements/${editing.id}`, values) : api.post('/admin-api/compliance/user-agreements', values) return api.post('/admin-api/compliance/filings', values) }, onSuccess: () => { message.success('已保存') qc.invalidateQueries({ queryKey: ['compliance'] }) setModalOpen(false); setEditing(null) }, }) const approveDeletion = useMutation({ mutationFn: (id: string) => api.post(`/admin-api/compliance/deletion-requests/${id}/approve`), onSuccess: () => { message.success('已批准'); qc.invalidateQueries({ queryKey: ['compliance', 'deletions'] }) }, }) const openCreate = (type: string) => { setModalType(type); setEditing(null); form.resetFields(); setModalOpen(true) } const docColumns = [ { title: '版本', dataIndex: 'version', width: 80 }, { title: '标题', dataIndex: 'title', width: 200, ellipsis: true }, { title: '生效时间', dataIndex: 'effectiveAt', width: 110, render: (d: string) => d ? new Date(d).toLocaleDateString() : '-' }, { title: '状态', dataIndex: 'published', width: 60, render: (p: boolean) => {p ? '已发布' : '草稿'} }, { title: '操作', width: 60, render: (_: any, r: any) => : null }, ] const securityColumns = [ { title: '类型', dataIndex: 'eventType', width: 100 }, { title: '严重程度', dataIndex: 'severity', width: 80, render: (s: string) => {s} }, { title: '已处理', dataIndex: 'handled', width: 60, render: (h: boolean) => h ? '是' : '否' }, { title: '时间', dataIndex: 'createdAt', width: 110, render: (d: string) => d ? new Date(d).toLocaleString() : '-' }, ] const tabs = [ { key: 'policies', label: '隐私政策', children:
}, { key: 'agreements', label: '用户协议', children:
}, { key: 'filings', label: '备案台账', children:
}, { key: 'deletions', label: '数据删除', children:
}, { key: 'exports', label: '数据导出', children:
r.userName || r.userId }, { title: '状态', dataIndex: 'status', width: 70, render: (s: string) => {complianceStatusLabels[s] || s} }, { title: '创建时间', dataIndex: 'createdAt', width: 110, render: (d: string) => new Date(d).toLocaleDateString() }, ]} rowKey="id" loading={eLoading} size="small" /> }, { key: 'security', label: '安全事件', children:
}, ] return (
<SafetyOutlined /> 合规与安全 { setModalOpen(false); setEditing(null) }} onOk={() => form.submit()} confirmLoading={saveMutation.isPending}>
{modalType === 'filing' && } {modalType !== 'filing' &&