/** * 员工离职申请入口 — 员工端提交离职申请、查看申请状态、撤回申请 */ import { useState, useRef } from 'react' import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query' import { toast } from 'sonner' import { UserX, Clock, FileText, Camera, X, Image as ImageIcon, Download } from 'lucide-react' import { portalApi } from '../../lib/api-services' import Card from '../../components/ui/Card' import Button from '../../components/ui/Button' import { Input, Label, Select } from '../../components/ui/Input' import { InlineAlert } from '../../components/ui/InlineAlert' /** 离职原因选项 */ const RESIGN_REASONS = [ { value: '个人发展', label: '个人发展' }, { value: '薪资待遇', label: '薪资待遇' }, { value: '家庭原因', label: '家庭原因' }, { value: '健康原因', label: '健康原因' }, { value: '工作环境', label: '工作环境' }, { value: '其他', label: '其他' }, ] /** 状态映射 */ const STATUS_MAP: Record = { DRAFT: { label: '草稿', color: 'bg-gray-100 text-gray-600' }, PENDING_APPROVAL: { label: '待审批', color: 'bg-amber-50 text-amber-700' }, APPROVED: { label: '已审批', color: 'bg-blue-50 text-blue-700' }, REJECTED: { label: '已驳回', color: 'bg-red-50 text-red-700' }, COMPLETED: { label: '已完成', color: 'bg-green-50 text-safe' }, CANCELLED: { label: '已撤回', color: 'bg-gray-100 text-gray-400' }, } export default function ResignationApply() { const queryClient = useQueryClient() const [form, setForm] = useState({ reason: '', expectedDate: '', remark: '', }) const [attachments, setAttachments] = useState([]) const fileInputRef = useRef(null) /** 查询离职申请状态 */ const { data: records = [], isLoading } = useQuery({ queryKey: ['portal-resignation-status'], queryFn: async () => { return await portalApi.resignationStatus() }, }) /** 提交离职申请 */ const submitMutation = useMutation({ mutationFn: async (data: { reason: string; expectedDate: string; remark: string; attachments?: string[] }) => { return await portalApi.resignationSubmit(data) }, onSuccess: () => { toast.success('离职申请已提交,请等待HR审批') queryClient.invalidateQueries({ queryKey: ['portal-resignation-status'] }) setForm({ reason: '', expectedDate: '', remark: '' }) setAttachments([]) }, onError: (err: any) => { toast.error(err?.response?.data?.error?.message || '提交失败') }, }) /** 撤回离职申请 */ const withdrawMutation = useMutation({ mutationFn: async (id: string) => { return await portalApi.resignationWithdraw(id) }, onSuccess: () => { toast.success('离职申请已撤回') queryClient.invalidateQueries({ queryKey: ['portal-resignation-status'] }) }, onError: (err: any) => { toast.error(err?.response?.data?.error?.message || '撤回失败') }, }) const handleSubmit = () => { if (!form.reason) { toast.error('请选择离职原因'); return } if (!form.expectedDate) { toast.error('请选择预计离职日期'); return } submitMutation.mutate({ ...form, attachments }) } const handleFileUpload = (e: React.ChangeEvent) => { const files = e.target.files if (!files) return Array.from(files).forEach(file => { if (file.size > 5 * 1024 * 1024) { toast.error(`${file.name} 超过5MB限制`) return } const reader = new FileReader() reader.onload = () => { setAttachments(prev => [...prev, reader.result as string]) } reader.readAsDataURL(file) }) if (fileInputRef.current) fileInputRef.current.value = '' } const hasPending = records.some((r: any) => r.status === 'DRAFT' || r.status === 'PENDING_APPROVAL') return (

离职申请

提交离职申请后,HR将在3个工作日内审批。提前30天提交为法定要求,请合理选择离职日期。 {/* 申请表单 */} {!hasPending ? (

填写离职申请

setForm({ ...form, expectedDate: e.target.value })} />
法定要求提前30天通知
setForm({ ...form, remark: e.target.value })} placeholder="补充说明(选填)" />
{attachments.map((img, i) => (
{`附件${i
))}
支持上传辞职信照片,HR审批时可查看
) : ( 您已有一个待处理的离职申请,请等待审批结果或撤回后重新提交。 )} {/* 申请记录 */}

申请记录

{isLoading ? (
加载中...
) : records.length === 0 ? (
暂无离职申请记录
) : (
{records.map((r: any) => { const statusCfg = STATUS_MAP[r.status] || STATUS_MAP.DRAFT const canWithdraw = r.status === 'DRAFT' || r.status === 'PENDING_APPROVAL' const canDownload = r.status === 'COMPLETED' return (
{statusCfg.label} {new Date(r.createdAt).toLocaleDateString('zh-CN')}
预计离职日期 {r.terminationDate ? new Date(r.terminationDate).toLocaleDateString('zh-CN') : '—'}
{r.remark && (
{r.remark}
)}
{canDownload && (
)} {canWithdraw && (
)}
) })}
)}
) }