import { useState } from 'react' import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query' import { Link } from 'react-router-dom' import { Search, Plus, Edit2, Trash2, X } from 'lucide-react' import { toast } from 'sonner' import { rosterApi, employeeApi } from '../../lib/api-services' import { usePageSize } from '../../hooks/usePageSize' import { Input, Label, Select } from '../../components/ui/Input' import Button from '../../components/ui/Button' const ACK_LABELS: Record = { PENDING: '待签收', SIGNED: '已签收', REFUSED: '拒绝签收' } const ACK_COLORS: Record = { PENDING: 'bg-amber-50 text-amber-700', SIGNED: 'bg-green-50 text-green-700', REFUSED: 'bg-red-50 text-red-700' } function fmtDate(d: string | Date | null): string { if (!d) return '-' return new Date(d).toLocaleDateString('zh-CN') } export default function TrainingRecords() { const queryClient = useQueryClient() const pageSize = usePageSize() const [page, setPage] = useState(1) const [keyword, setKeyword] = useState('') const [showCreate, setShowCreate] = useState(false) const [editRecord, setEditRecord] = useState(null) const { data, isLoading } = useQuery({ queryKey: ['training-list', page, pageSize, keyword], queryFn: () => rosterApi.trainingList({ page, pageSize, keyword }), }) const { data: employees } = useQuery({ queryKey: ['employees-active'], queryFn: () => employeeApi.list({ status: 'ACTIVE' }), }) const createMut = useMutation({ mutationFn: (data: any) => { const empId = data.employeeId delete data.employeeId return fetch(`/api/v1/roster/${empId}/training`, { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${localStorage.getItem('token')}` }, body: JSON.stringify(data), }).then(r => r.json()) }, onSuccess: () => { toast.success('培训记录已添加') queryClient.invalidateQueries({ queryKey: ['training-list'] }) setShowCreate(false) }, onError: () => toast.error('添加失败'), }) const updateMut = useMutation({ mutationFn: (data: any) => { const empId = data.employeeId const recordId = data.recordId delete data.employeeId delete data.recordId return fetch(`/api/v1/roster/${empId}/training/${recordId}`, { method: 'PUT', headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${localStorage.getItem('token')}` }, body: JSON.stringify(data), }).then(r => r.json()) }, onSuccess: () => { toast.success('培训记录已更新') queryClient.invalidateQueries({ queryKey: ['training-list'] }) setEditRecord(null) }, onError: () => toast.error('更新失败'), }) const deleteMut = useMutation({ mutationFn: ({ employeeId, recordId }: { employeeId: string; recordId: string }) => fetch(`/api/v1/roster/${employeeId}/training/${recordId}`, { method: 'DELETE', headers: { 'Authorization': `Bearer ${localStorage.getItem('token')}` }, }).then(r => r.json()), onSuccess: () => { toast.success('记录已删除') queryClient.invalidateQueries({ queryKey: ['training-list'] }) }, }) const records = data?.records || [] const total = data?.total || 0 const totalPages = Math.ceil(total / pageSize) return (

培训记录

管理全员培训记录及签收状态

{ setKeyword(e.target.value); setPage(1) }} placeholder="搜索员工姓名" className="pl-9" />
{isLoading ? ( ) : records.length === 0 ? ( ) : records.map((r: any) => ( ))}
员工 部门 培训日期 主题 讲师 时长(小时) 签收状态 操作
加载中...
暂无培训记录
{r.employee?.name} {r.employee?.department || '-'} {fmtDate(r.trainingDate)} {r.topic} {r.trainer || '-'} {r.duration} {ACK_LABELS[r.ackStatus] || r.ackStatus}
{totalPages > 1 && (
共 {total} 条
{page} / {totalPages}
)} {(showCreate || editRecord) && ( { if (editRecord) { updateMut.mutate({ ...data, employeeId: editRecord.employeeId, recordId: editRecord.id }) } else { createMut.mutate(data) } }} onClose={() => { setShowCreate(false); setEditRecord(null) }} /> )}
) } function TrainingForm({ employees, record, onSubmit, onClose }: { employees: any[] record: any onSubmit: (data: any) => void onClose: () => void }) { const [form, setForm] = useState({ employeeId: record?.employeeId || '', trainingDate: record?.trainingDate ? new Date(record.trainingDate).toISOString().slice(0, 10) : new Date().toISOString().slice(0, 10), topic: record?.topic || '', content: record?.content || '', trainer: record?.trainer || '', duration: record?.duration || 0, ackStatus: record?.ackStatus || 'PENDING', remark: record?.remark || '', }) return (
e.stopPropagation()}>

{record ? '编辑培训记录' : '新增培训记录'}

{!record && (
)}
setForm({ ...form, trainingDate: e.target.value })} />
setForm({ ...form, topic: e.target.value })} placeholder="培训主题" />
setForm({ ...form, content: e.target.value })} placeholder="培训内容" />
setForm({ ...form, trainer: e.target.value })} placeholder="讲师姓名" />
setForm({ ...form, duration: Number(e.target.value) })} />
setForm({ ...form, remark: e.target.value })} placeholder="备注" />
) }