import { useState } from 'react' import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query' import { Link } from 'react-router-dom' import { Search, Plus, Edit2, Trash2, X, Download } from 'lucide-react' import { toast } from 'sonner' import { rosterApi, employeeApi } from '../../lib/api-services' import api from '../../lib/api' import { usePageSize } from '../../hooks/usePageSize' import { Input, Label, Select } from '../../components/ui/Input' import Button from '../../components/ui/Button' const TYPE_LABELS: Record = { LATE: '迟到', ABSENT: '旷工', INSUBORDINATION: '不服从管理', MISCONDUCT: '违纪', VIOLATE_POLICY: '违反规章制度', OTHER: '其他' } const SEVERITY_LABELS: Record = { WARNING: '警告', SERIOUS: '严重', SEVERE: '极其严重' } const SEVERITY_COLORS: Record = { WARNING: 'bg-amber-50 text-amber-700', SERIOUS: 'bg-orange-50 text-orange-700', SEVERE: 'bg-red-50 text-red-700' } const ACTION_LABELS: Record = { ORAL_WARNING: '口头警告', WRITTEN_WARNING: '书面警告', DEDUCTION: '扣款', DEMOTION: '降职', TERMINATION: '解除劳动合同' } function fmtDate(d: string | Date | null): string { if (!d) return '-' return new Date(d).toLocaleDateString('zh-CN') } export default function DisciplinaryRecords() { 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: ['disciplinary-list', page, pageSize, keyword], queryFn: () => rosterApi.disciplinaryList({ page, pageSize, keyword }), }) const { data: employees } = useQuery({ queryKey: ['employees-active'], queryFn: () => employeeApi.list({ status: 'ACTIVE' }), }) const saveMut = useMutation({ mutationFn: (data: any) => { const empId = data.employeeId delete data.employeeId const isEdit = !!data.recordId const recordId = data.recordId delete data.recordId if (isEdit) { return api.put(`/roster/${empId}/disciplinary/${recordId}`, data) } return api.post(`/roster/${empId}/disciplinary`, data) }, onSuccess: () => { toast.success('违纪记录已保存') queryClient.invalidateQueries({ queryKey: ['disciplinary-list'] }) setShowCreate(false) setEditRecord(null) }, onError: () => toast.error('保存失败'), }) const deleteMut = useMutation({ mutationFn: ({ employeeId, recordId }: { employeeId: string; recordId: string }) => api.delete(`/roster/${employeeId}/disciplinary/${recordId}`), onSuccess: () => { toast.success('记录已删除') queryClient.invalidateQueries({ queryKey: ['disciplinary-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.violationDate)} {TYPE_LABELS[r.violationType] || r.violationType} {r.description} {SEVERITY_LABELS[r.severity] || r.severity} {ACTION_LABELS[r.action] || r.action} {r.actionDetail || '-'} {r.employeeAck ? ( 已签字 ) : ( 待签字 )}
{r.employeeAck && ( )}
{totalPages > 1 && (
共 {total} 条
{page} / {totalPages}
)} {(showCreate || editRecord) && ( saveMut.mutate(data)} onClose={() => { setShowCreate(false); setEditRecord(null) }} /> )}
) } function DisciplinaryForm({ employees, record, onSubmit, onClose }: { employees: any[] record: any onSubmit: (data: any) => void onClose: () => void }) { const [form, setForm] = useState({ employeeId: record?.employeeId || '', violationDate: record?.violationDate ? new Date(record.violationDate).toISOString().slice(0, 10) : new Date().toISOString().slice(0, 10), violationType: record?.violationType || 'OTHER', description: record?.description || '', severity: record?.severity || 'WARNING', action: record?.action || 'ORAL_WARNING', actionDetail: record?.actionDetail || '', witness: record?.witness || '', }) return (
e.stopPropagation()}>

{record ? '编辑违纪记录' : '新增违纪记录'}

{!record && (
)}
setForm({ ...form, violationDate: e.target.value })} />
setForm({ ...form, description: e.target.value })} placeholder="详细描述违纪事实" />