feat: 解聘Step3合规检查增强 — 系统自动预填+建议

后端:
- getChecklistForReason 接收 employee 数据,支持自动检查
- 医疗期是否届满:根据 isInMedicalPeriod 自动判断
- 是否经过培训/调岗:根据 trainingRecords 自动判断
- 经济补偿金/代通知金:系统给建议(suggestion + suggestionType)
- checklist 接口改为 async,获取员工 profile 传入

前端:
- checklist 查询传入 employeeId
- useEffect 自动预填系统判断结果到 checklist state
- Step 3 UI 重写:显示系统判断标签、来源说明、建议提示
- 建议按类型显示不同颜色(warning/required/info)
This commit is contained in:
freedakgmail
2026-07-23 16:56:28 +08:00
parent fa7aa01c48
commit 1b05facc92
3 changed files with 175 additions and 39 deletions
+60 -15
View File
@@ -1,4 +1,4 @@
import { useState, useMemo } from 'react'
import { useState, useMemo, useEffect } from 'react'
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'
import { AlertTriangle, Check, ChevronRight, ChevronLeft, Shield, Info, Calculator, FileText, Printer } from 'lucide-react'
import api from '../lib/api'
@@ -136,15 +136,29 @@ export default function Termination() {
return list
}, [profile])
const { data: checklistItems } = useQuery<{ key: string; label: string }[]>({
queryKey: ['checklist', reason],
const { data: checklistItems } = useQuery<{
key: string; label: string; autoChecked?: boolean | null; autoSource?: string; suggestion?: string; suggestionType?: string
}[]>({
queryKey: ['checklist', reason, employeeId],
queryFn: async () => {
const res = await api.get(`/termination/checklist/${reason}`) as any
const res = await api.get(`/termination/checklist/${reason}`, { params: { employeeId } }) as any
return res.data
},
enabled: !!reason && step >= 2,
enabled: !!reason && !!employeeId && step >= 2,
})
// checklist 加载后自动预填系统判断结果
useEffect(() => {
if (checklistItems) {
const prefilled: Record<string, boolean> = {}
checklistItems.forEach((item) => {
if (item.autoChecked === true) prefilled[item.key] = true
else if (item.autoChecked === false) prefilled[item.key] = false
})
setChecklist(prefilled)
}
}, [checklistItems])
const { data: riskAssessment } = useQuery<{ level: string; warnings: string[] }>({
queryKey: ['assess', employeeId, reason],
queryFn: async () => {
@@ -409,16 +423,47 @@ export default function Termination() {
{/* Step 3: 合规检查 */}
{step === 2 && (
<div className="space-y-3">
{checklistItems?.map((item) => (
<label key={item.key} className="flex items-center gap-3 p-3 rounded-md border cursor-pointer hover:bg-gray-50">
<input
type="checkbox"
checked={checklist[item.key] || false}
onChange={(e) => setChecklist({ ...checklist, [item.key]: e.target.checked })}
/>
<span className="text-xs">{item.label}</span>
</label>
))}
<div className="bg-blue-50 text-blue-700 text-xs px-3 py-2 rounded-md flex items-start gap-2">
<Info className="w-4 h-4 mt-0.5 shrink-0" />
<div></div>
</div>
{checklistItems?.map((item) => {
const checked = checklist[item.key] || false
const isAutoChecked = item.autoChecked !== null && item.autoChecked !== undefined
const suggestionColor =
item.suggestionType === 'warning' ? 'bg-amber-50 text-amber-700' :
item.suggestionType === 'required' ? 'bg-red-50 text-red-700' :
'bg-gray-50 text-gray-600'
return (
<div key={item.key} className="border rounded-md p-3 space-y-2">
<label className="flex items-center gap-3 cursor-pointer">
<input
type="checkbox"
checked={checked}
onChange={(e) => setChecklist({ ...checklist, [item.key]: e.target.checked })}
/>
<span className="text-xs font-medium">{item.label}</span>
{isAutoChecked && (
<span className={`px-1.5 py-0.5 rounded text-xs ${item.autoChecked ? 'bg-green-50 text-safe' : 'bg-red-50 text-danger'}`}>
{item.autoChecked ? '是' : '否'}
</span>
)}
</label>
{item.autoSource && (
<div className="text-xs text-gray-500 pl-7 flex items-start gap-1">
<Info className="w-3 h-3 mt-0.5 shrink-0" />
<span>{item.autoSource}</span>
</div>
)}
{item.suggestion && (
<div className={`text-xs px-2 py-1.5 rounded-md ml-7 flex items-start gap-1 ${suggestionColor}`}>
<AlertTriangle className="w-3 h-3 mt-0.5 shrink-0" />
<span>{item.suggestion}</span>
</div>
)}
</div>
)
})}
</div>
)}