优化: 添加员工弹窗-身份证号必填+性别自动识别

1. 身份证号必填(18位),后端加密存储
2. 性别由身份证号第17位自动计算(奇数=男,偶数=女),无需手动选择
3. 移除添加员工时的孕期/医疗期/工伤复选框(这些状态后续在员工档案中维护)
This commit is contained in:
freedakgmail
2026-07-23 18:25:37 +08:00
parent 43186d3dd8
commit 8283b538e5
2 changed files with 18 additions and 9 deletions
+1
View File
@@ -164,6 +164,7 @@ export async function createEmployee(orgId: string, userId: string, data: any) {
monthlySalary: encrypt(data.monthlySalary),
gender: data.gender,
phone: data.phone,
idCardNumber: data.idCardNumber ? encrypt(data.idCardNumber) : null,
isPregnant: data.isPregnant || false,
isInMedicalPeriod: data.isInMedicalPeriod || false,
isWorkInjured: data.isWorkInjured || false,
+17 -9
View File
@@ -931,13 +931,22 @@ function AddEmployeeModal({ onClose, onSubmit, loading, error }: {
})()
const [form, setForm] = useState({
name: '', department: '', hireDate: todayStr, monthlySalary: '',
gender: '男' as '男' | '女', phone: '',
isPregnant: false, isInMedicalPeriod: false, isWorkInjured: false,
idCardNumber: '', gender: '男' as '男' | '女', phone: '',
contractType: 'FIXED' as 'FIXED' | 'UNFIXED' | 'UNSIGNED',
signDate: '', startDate: todayStr, endDate: defaultEndDate,
contractYears: 3, probationMonths: 0, probationSalary: 0,
})
// 根据身份证号自动计算性别(第17位:奇数=男,偶数=女)
const handleIdCardChange = (idCard: string) => {
let gender = form.gender
if (idCard.length >= 17) {
const digit = parseInt(idCard[16])
if (!isNaN(digit)) gender = digit % 2 === 1 ? '男' : '女'
}
setForm({ ...form, idCardNumber: idCard, gender })
}
// 计算合同月数
const contractMonths = (() => {
if (form.contractType !== 'FIXED' || !form.startDate) return 0
@@ -1017,8 +1026,8 @@ function AddEmployeeModal({ onClose, onSubmit, loading, error }: {
name: form.name, department: form.department,
hireDate: new Date(form.hireDate).toISOString(),
monthlySalary: form.monthlySalary, gender: form.gender,
idCardNumber: form.idCardNumber || undefined,
phone: form.phone || undefined,
isPregnant: form.isPregnant, isInMedicalPeriod: form.isInMedicalPeriod, isWorkInjured: form.isWorkInjured,
}
if (form.contractType !== 'UNSIGNED' && form.startDate) {
data.contract = {
@@ -1033,6 +1042,7 @@ function AddEmployeeModal({ onClose, onSubmit, loading, error }: {
}
const canSubmit = form.name && form.department && form.hireDate && form.monthlySalary
&& form.idCardNumber.length >= 18
&& (form.contractType === 'UNSIGNED' || form.startDate)
&& !probationError && !probationSalaryError
@@ -1048,19 +1058,17 @@ function AddEmployeeModal({ onClose, onSubmit, loading, error }: {
<div><Label> *</Label><Input value={form.name} onChange={(e) => setForm({ ...form, name: e.target.value })} placeholder="员工姓名" /></div>
<div><Label> *</Label><Input value={form.department} onChange={(e) => setForm({ ...form, department: e.target.value })} placeholder="如:技术部" /></div>
</div>
<div className="grid grid-cols-2 gap-3">
<div><Label> *</Label><Input value={form.idCardNumber} onChange={(e) => handleIdCardChange(e.target.value)} placeholder="18位身份证号" maxLength={18} /></div>
<div><Label></Label><div className="text-xs text-gray-600 py-1.5">{form.idCardNumber.length >= 17 ? form.gender : '由身份证号自动识别'}</div></div>
</div>
<div className="grid grid-cols-2 gap-3">
<div><Label> *</Label><Input type="date" value={form.hireDate} onChange={(e) => setForm({ ...form, hireDate: e.target.value })} /></div>
<div><Label> *</Label><Input type="number" value={form.monthlySalary} onChange={(e) => setForm({ ...form, monthlySalary: e.target.value })} placeholder="元" /></div>
</div>
<div className="grid grid-cols-2 gap-3">
<div><Label></Label><Select value={form.gender} onChange={(e) => setForm({ ...form, gender: e.target.value as '男' | '女' })}><option value="男"></option><option value="女"></option></Select></div>
<div><Label></Label><Input value={form.phone} onChange={(e) => setForm({ ...form, phone: e.target.value })} placeholder="选填" maxLength={11} /></div>
</div>
<div className="flex gap-4">
<label className="flex items-center gap-1.5 text-xs"><input type="checkbox" checked={form.isPregnant} onChange={(e) => setForm({ ...form, isPregnant: e.target.checked })} />/</label>
<label className="flex items-center gap-1.5 text-xs"><input type="checkbox" checked={form.isInMedicalPeriod} onChange={(e) => setForm({ ...form, isInMedicalPeriod: e.target.checked })} /></label>
<label className="flex items-center gap-1.5 text-xs"><input type="checkbox" checked={form.isWorkInjured} onChange={(e) => setForm({ ...form, isWorkInjured: e.target.checked })} /></label>
</div>
<div className="border-t pt-3">
<Label></Label>
<Select value={form.contractType} onChange={(e) => setForm({ ...form, contractType: e.target.value as any, endDate: e.target.value === 'UNFIXED' ? '' : form.endDate })}>