From 8283b538e5d10d9458e5ceec7a0fcbeaabf8c63f Mon Sep 17 00:00:00 2001 From: freedakgmail Date: Thu, 23 Jul 2026 18:25:37 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96:=20=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=E5=91=98=E5=B7=A5=E5=BC=B9=E7=AA=97-=E8=BA=AB=E4=BB=BD?= =?UTF-8?q?=E8=AF=81=E5=8F=B7=E5=BF=85=E5=A1=AB+=E6=80=A7=E5=88=AB?= =?UTF-8?q?=E8=87=AA=E5=8A=A8=E8=AF=86=E5=88=AB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. 身份证号必填(18位),后端加密存储 2. 性别由身份证号第17位自动计算(奇数=男,偶数=女),无需手动选择 3. 移除添加员工时的孕期/医疗期/工伤复选框(这些状态后续在员工档案中维护) --- backend/src/services/contract.service.ts | 1 + frontend/src/pages/Roster.tsx | 26 ++++++++++++++++-------- 2 files changed, 18 insertions(+), 9 deletions(-) diff --git a/backend/src/services/contract.service.ts b/backend/src/services/contract.service.ts index 5454b80..c0530c8 100644 --- a/backend/src/services/contract.service.ts +++ b/backend/src/services/contract.service.ts @@ -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, diff --git a/frontend/src/pages/Roster.tsx b/frontend/src/pages/Roster.tsx index 768bdf5..86d60f9 100644 --- a/frontend/src/pages/Roster.tsx +++ b/frontend/src/pages/Roster.tsx @@ -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 }: {
setForm({ ...form, name: e.target.value })} placeholder="员工姓名" />
setForm({ ...form, department: e.target.value })} placeholder="如:技术部" />
+
+
handleIdCardChange(e.target.value)} placeholder="18位身份证号" maxLength={18} />
+
{form.idCardNumber.length >= 17 ? form.gender : '由身份证号自动识别'}
+
setForm({ ...form, hireDate: e.target.value })} />
setForm({ ...form, monthlySalary: e.target.value })} placeholder="元" />
-
setForm({ ...form, phone: e.target.value })} placeholder="选填" maxLength={11} />
-
- - - -