diff --git a/backend/src/services/contract.service.ts b/backend/src/services/contract.service.ts index c0530c8..de7f813 100644 --- a/backend/src/services/contract.service.ts +++ b/backend/src/services/contract.service.ts @@ -232,9 +232,9 @@ export async function rehireEmployee(orgId: string, userId: string, id: string, data: { hireDate: newHireDate, status: 'ACTIVE', - isPregnant: data.isPregnant || false, - isInMedicalPeriod: data.isInMedicalPeriod || false, - isWorkInjured: data.isWorkInjured || false, + isPregnant: false, + isInMedicalPeriod: false, + isWorkInjured: false, }, }) diff --git a/frontend/src/pages/Roster.tsx b/frontend/src/pages/Roster.tsx index 86d60f9..7fd7703 100644 --- a/frontend/src/pages/Roster.tsx +++ b/frontend/src/pages/Roster.tsx @@ -789,26 +789,101 @@ function RehireModal({ employee, onClose, onSubmit, loading, error }: { loading: boolean error: any }) { + const todayStr = new Date().toISOString().slice(0, 10) + const defaultEndDate = (() => { + const d = new Date() + d.setFullYear(d.getFullYear() + 3) + d.setDate(d.getDate() - 1) + return d.toISOString().slice(0, 10) + })() const [form, setForm] = useState({ - hireDate: new Date().toISOString().slice(0, 10), - isPregnant: false, - isInMedicalPeriod: false, - isWorkInjured: false, + hireDate: todayStr, contractType: 'FIXED' as 'FIXED' | 'UNFIXED' | 'UNSIGNED', signDate: '', - startDate: '', - endDate: '', + startDate: todayStr, + endDate: defaultEndDate, contractYears: 3, probationMonths: 0, probationSalary: 0, }) + // 计算合同月数 + const contractMonths = (() => { + if (form.contractType !== 'FIXED' || !form.startDate) return 0 + if (form.endDate) { + const start = new Date(form.startDate) + const end = new Date(form.endDate) + return Math.round((end.getTime() - start.getTime()) / (1000 * 60 * 60 * 24 * 30.44)) + } + return form.contractYears * 12 + })() + + // 试用期上限(劳动合同法第19条) + const probationMax = (() => { + if (contractMonths >= 36) return 6 + if (contractMonths >= 12) return 2 + if (contractMonths >= 3) return 1 + return 0 + })() + + const probationError = (() => { + if (form.probationMonths <= 0) return '' + if (contractMonths > 0 && contractMonths < 3) return '合同不足3个月,不得约定试用期' + if (form.probationMonths > probationMax) return `合同${contractMonths}个月,试用期最多${probationMax}个月` + return '' + })() + + const monthlySalaryNum = employee?.monthlySalary || 0 + const probationSalaryError = (() => { + if (form.probationMonths <= 0) return '' + if (form.probationSalary <= 0) return '有试用期时试用期工资必填' + if (monthlySalaryNum > 0 && form.probationSalary < monthlySalaryNum * 0.8) { + return `试用期工资不得低于转正工资的80%(最低¥${(monthlySalaryNum * 0.8).toFixed(0)})` + } + return '' + })() + + // 合同结束日期自动计算 + const handleContractYearsChange = (years: number) => { + if (!form.startDate || years <= 0) { + setForm({ ...form, contractYears: years, endDate: '' }) + return + } + const start = new Date(form.startDate) + const end = new Date(start) + end.setFullYear(end.getFullYear() + years) + end.setDate(end.getDate() - 1) + setForm({ ...form, contractYears: years, endDate: end.toISOString().slice(0, 10) }) + } + + // 合同结束日期变更 → 自动计算签约年限 + const handleEndDateChange = (endDate: string) => { + if (!form.startDate || !endDate) { + setForm({ ...form, endDate, contractYears: 0 }) + return + } + const start = new Date(form.startDate) + const end = new Date(endDate) + const months = Math.round((end.getTime() - start.getTime()) / (1000 * 60 * 60 * 24 * 30.44)) + setForm({ ...form, endDate, contractYears: Math.max(1, Math.round(months / 12)) }) + } + + // 开始日期变更 → 重新计算结束日期 + const handleStartDateChange = (startDate: string) => { + if (form.contractType === 'FIXED' && form.contractYears > 0 && startDate) { + const start = new Date(startDate) + const end = new Date(start) + end.setFullYear(end.getFullYear() + form.contractYears) + end.setDate(end.getDate() - 1) + setForm({ ...form, startDate, endDate: end.toISOString().slice(0, 10) }) + } else { + setForm({ ...form, startDate }) + } + } + const handleSubmit = () => { const data: any = { hireDate: new Date(form.hireDate).toISOString(), - isPregnant: form.isPregnant, - isInMedicalPeriod: form.isInMedicalPeriod, - isWorkInjured: form.isWorkInjured, } if (form.contractType !== 'UNSIGNED' && form.startDate) { data.contract = { @@ -824,78 +899,79 @@ function RehireModal({ employee, onClose, onSubmit, loading, error }: { onSubmit(data) } + const canSubmit = form.hireDate + && (form.contractType === 'UNSIGNED' || form.startDate) + && !probationError && !probationSalaryError + return (
- 复用员工已有基本信息(姓名、部门、手机等),只需填写新入职日期和劳动合同。 + 复用员工已有基本信息(姓名、部门、身份证号等),只需填写新入职日期和劳动合同。 +
+
+
+ +
{employee.name}
+
+
+ +
{employee.department}
+
- -
{employee.name} - {employee.department}
-
-
- - setForm({ ...form, hireDate: e.target.value })} - /> -
-
- - - + + setForm({ ...form, hireDate: e.target.value })} />
- - setForm({ ...form, contractType: e.target.value as any, endDate: e.target.value === 'UNFIXED' ? '' : form.endDate })}>
{form.contractType !== 'UNSIGNED' && ( -
-
+
+
setForm({ ...form, signDate: e.target.value })} /> +
留空表示尚未签订
-
- - setForm({ ...form, startDate: e.target.value })} /> -
+
handleStartDateChange(e.target.value)} />
{form.contractType === 'FIXED' && ( -
-
- - setForm({ ...form, endDate: e.target.value })} /> + <> +
+
+ + handleContractYearsChange(parseInt(e.target.value) || 0)} min={1} /> +
+
+ + handleEndDateChange(e.target.value)} /> +
-
- - setForm({ ...form, contractYears: parseInt(e.target.value) || 3 })} /> -
-
+
修改签约时长自动计算结束日期,修改结束日期自动计算签约时长
+ )} -
+
- setForm({ ...form, probationMonths: parseInt(e.target.value) || 0 })} /> + setForm({ ...form, probationMonths: parseInt(e.target.value) || 0 })} min={0} max={6} /> + {contractMonths > 0 && ( +
法定上限:{probationMax}个月
+ )} + {probationError &&
{probationError}
}
- - setForm({ ...form, probationSalary: parseFloat(e.target.value) || 0 })} /> + + setForm({ ...form, probationSalary: parseFloat(e.target.value) || 0 })} disabled={form.probationMonths <= 0} /> + {monthlySalaryNum > 0 && form.probationMonths > 0 && ( +
不低于转正工资80%(≥¥{(monthlySalaryNum * 0.8).toFixed(0)})
+ )} + {probationSalaryError &&
{probationSalaryError}
}
@@ -907,9 +983,7 @@ function RehireModal({ employee, onClose, onSubmit, loading, error }: { )}
- +