feat: 完成23项系统优化 - 花名册社保状态列/身份证复制/附件类型扩展, 用工办理姓名检索/直接提交/文书查看/批量证明, 风险中心跳转筛选+批量处理, 日历7/15/35天分组+逾期统计, 考勤单条编辑+按人导出, 工资条查看状态+工资流水导出, 辞职申请附件上传, 交接清单PDF下载, 操作完成下一步引导, 休假审批入口, 人效成本分部门
This commit is contained in:
@@ -1,10 +1,10 @@
|
||||
/**
|
||||
* 员工离职申请入口 — 员工端提交离职申请、查看申请状态、撤回申请
|
||||
*/
|
||||
import { useState } from 'react'
|
||||
import { useState, useRef } from 'react'
|
||||
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'
|
||||
import { toast } from 'sonner'
|
||||
import { UserX, Clock, FileText } from 'lucide-react'
|
||||
import { UserX, Clock, FileText, Camera, X, Image as ImageIcon } from 'lucide-react'
|
||||
import { portalApi } from '../../lib/api-services'
|
||||
import Card from '../../components/ui/Card'
|
||||
import Button from '../../components/ui/Button'
|
||||
@@ -38,6 +38,8 @@ export default function ResignationApply() {
|
||||
expectedDate: '',
|
||||
remark: '',
|
||||
})
|
||||
const [attachments, setAttachments] = useState<string[]>([])
|
||||
const fileInputRef = useRef<HTMLInputElement>(null)
|
||||
|
||||
/** 查询离职申请状态 */
|
||||
const { data: records = [], isLoading } = useQuery<any[]>({
|
||||
@@ -49,13 +51,14 @@ export default function ResignationApply() {
|
||||
|
||||
/** 提交离职申请 */
|
||||
const submitMutation = useMutation({
|
||||
mutationFn: async (data: { reason: string; expectedDate: string; remark: string }) => {
|
||||
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 || '提交失败')
|
||||
@@ -79,7 +82,24 @@ export default function ResignationApply() {
|
||||
const handleSubmit = () => {
|
||||
if (!form.reason) { toast.error('请选择离职原因'); return }
|
||||
if (!form.expectedDate) { toast.error('请选择预计离职日期'); return }
|
||||
submitMutation.mutate(form)
|
||||
submitMutation.mutate({ ...form, attachments })
|
||||
}
|
||||
|
||||
const handleFileUpload = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
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')
|
||||
@@ -125,6 +145,40 @@ export default function ResignationApply() {
|
||||
placeholder="补充说明(选填)"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<Label>辞职信照片(选填,最多5张)</Label>
|
||||
<input
|
||||
ref={fileInputRef}
|
||||
type="file"
|
||||
accept="image/*"
|
||||
multiple
|
||||
className="hidden"
|
||||
onChange={handleFileUpload}
|
||||
/>
|
||||
<div className="flex items-center gap-2 flex-wrap">
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => fileInputRef.current?.click()}
|
||||
className="flex items-center gap-1 px-3 py-2 rounded-md border border-dashed border-gray-300 text-sm text-gray-500 hover:border-primary hover:text-primary transition-colors"
|
||||
>
|
||||
<Camera className="w-4 h-4" />
|
||||
上传照片
|
||||
</button>
|
||||
{attachments.map((img, i) => (
|
||||
<div key={i} className="relative w-16 h-16 rounded-md overflow-hidden border">
|
||||
<img src={img} alt={`附件${i + 1}`} className="w-full h-full object-cover" />
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setAttachments(prev => prev.filter((_, idx) => idx !== i))}
|
||||
className="absolute top-0 right-0 bg-black/50 text-white rounded-bl p-0.5"
|
||||
>
|
||||
<X className="w-3 h-3" />
|
||||
</button>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
<div className="text-xs text-gray-400 mt-1">支持上传辞职信照片,HR审批时可查看</div>
|
||||
</div>
|
||||
<Button onClick={handleSubmit} disabled={submitMutation.isPending} className="w-full">
|
||||
{submitMutation.isPending ? '提交中...' : '提交离职申请'}
|
||||
</Button>
|
||||
|
||||
Reference in New Issue
Block a user