diff --git a/backend/src/routes/dashboard.routes.ts b/backend/src/routes/dashboard.routes.ts index d6a3f78..133ec39 100644 --- a/backend/src/routes/dashboard.routes.ts +++ b/backend/src/routes/dashboard.routes.ts @@ -546,7 +546,7 @@ router.get('/risks', authMiddleware, async (req: AuthRequest, res: Response, nex actionUrl: t.actionUrl || '', estimatedLoss: t.estimatedLoss || 0, deadline: t.deadline || null, - employee: t.employeeName ? { name: t.employeeName, department: t.employeeDepartment || '' } : null, + employee: t.employeeName ? { name: t.employeeName, department: t.employeeDepartment || '', idCardNumber: t.employeeIdCardNumber || null } : null, })) res.json({ success: true, data: risks }) } catch (err) { diff --git a/backend/src/routes/employee.routes.ts b/backend/src/routes/employee.routes.ts index a9cee3f..9ef590f 100644 --- a/backend/src/routes/employee.routes.ts +++ b/backend/src/routes/employee.routes.ts @@ -141,12 +141,12 @@ router.get('/check-phone', authMiddleware, async (req: AuthRequest, res, next) = // 手机号加密存储,需遍历匹配(量小可接受) const employees = await prisma.employee.findMany({ where: { orgId: req.user!.orgId }, - select: { id: true, name: true, department: true, status: true, phone: true }, + select: { id: true, name: true, department: true, status: true, phone: true, idCardNumber: true }, }) const matched = employees.find(e => { try { return e.phone ? decrypt(e.phone) === phone : false } catch { return false } }) - res.json({ success: true, data: { exists: !!matched, employee: matched ? { id: matched.id, name: matched.name, department: matched.department, status: matched.status } : undefined } }) + res.json({ success: true, data: { exists: !!matched, employee: matched ? { id: matched.id, name: matched.name, department: matched.department, status: matched.status, idCardNumber: (() => { try { return matched.idCardNumber ? (matched.idCardNumber.includes(':') ? decrypt(matched.idCardNumber) : matched.idCardNumber) : null } catch { return null } })() } : undefined } }) } catch (err) { next(err) } diff --git a/backend/src/services/risk.service.ts b/backend/src/services/risk.service.ts index 6502d41..d2fa739 100644 --- a/backend/src/services/risk.service.ts +++ b/backend/src/services/risk.service.ts @@ -699,7 +699,7 @@ export async function getDashboardData(orgId: string) { prisma.riskItem.count({ where: { orgId, status: 'PENDING' } }), prisma.riskItem.findMany({ where: { orgId, status: 'PENDING' }, - include: { employee: { select: { id: true, name: true, department: true, idCardHash: true } } }, + include: { employee: { select: { id: true, name: true, department: true, idCardHash: true, idCardNumber: true } } }, orderBy: [{ level: 'asc' }, { estimatedLoss: 'desc' }], }), prisma.riskItem.findMany({ @@ -930,6 +930,7 @@ export async function getDashboardData(orgId: string) { employeeName: r.employee?.name || null, employeeDepartment: r.employee?.department || null, employeeIdCardHash: r.employee?.idCardHash || null, + employeeIdCardNumber: r.employee?.idCardNumber ? (() => { try { return r.employee.idCardNumber.includes(':') ? decrypt(r.employee.idCardNumber) : r.employee.idCardNumber } catch { return null } })() : null, } }) diff --git a/frontend/src/components/ui/SignMethodChoice.tsx b/frontend/src/components/ui/SignMethodChoice.tsx index ba87c36..7ecb2a8 100644 --- a/frontend/src/components/ui/SignMethodChoice.tsx +++ b/frontend/src/components/ui/SignMethodChoice.tsx @@ -23,6 +23,8 @@ interface SignMethodChoiceProps { employeeId: string /** 员工姓名(用于显示) */ employeeName: string + /** 员工身份证号(用于显示) */ + employeeIdCardNumber?: string /** 签署场景 */ scene: 'CONTRACT' | 'RESIGNATION' | 'POLICY' | 'PAYSLIP' | 'ONBOARDING' /** 文件标题 */ @@ -48,6 +50,7 @@ export default function SignMethodChoice({ onClose, employeeId, employeeName, + employeeIdCardNumber, scene, documentTitle, contractId, @@ -107,7 +110,7 @@ export default function SignMethodChoice({
-
{employeeName} · {SCENE_LABELS[scene] || scene}
+
{employeeName} · {SCENE_LABELS[scene] || scene}{employeeIdCardNumber && {employeeIdCardNumber}}
{documentTitle}
diff --git a/frontend/src/pages/Contracts.tsx b/frontend/src/pages/Contracts.tsx index ae97414..23493c1 100644 --- a/frontend/src/pages/Contracts.tsx +++ b/frontend/src/pages/Contracts.tsx @@ -371,7 +371,7 @@ function AddEmployeeModal({ open, onClose, onSubmit, loading, error }: { {phoneDuplicate?.exists && (
- 该手机号已存在:{phoneDuplicate.employee?.name}({phoneDuplicate.employee?.department}),请确认是否重复录入 + 该手机号已存在:{phoneDuplicate.employee?.name}({phoneDuplicate.employee?.department}){phoneDuplicate.employee?.idCardNumber && `(${phoneDuplicate.employee.idCardNumber})` },请确认是否重复录入
)} diff --git a/frontend/src/pages/Roster.tsx b/frontend/src/pages/Roster.tsx index 00e0bbb..0e68d24 100644 --- a/frontend/src/pages/Roster.tsx +++ b/frontend/src/pages/Roster.tsx @@ -101,6 +101,7 @@ export default function Roster() { open: boolean employeeId: string employeeName: string + employeeIdCardNumber?: string scene: 'CONTRACT' | 'RESIGNATION' | 'POLICY' | 'PAYSLIP' | 'ONBOARDING' documentTitle: string contractId?: string @@ -226,6 +227,7 @@ export default function Roster() { open: true, employeeId: rehireEmployee?.id || '', employeeName: rehireEmployee?.name || '', + employeeIdCardNumber: rehireEmployee?.idCardNumber, scene: 'CONTRACT', documentTitle: `${rehireEmployee?.name || ''}的劳动合同`, remark: '重新入职时发起', @@ -247,6 +249,7 @@ export default function Roster() { open: true, employeeId: salaryEmployee?.id || '', employeeName: salaryEmployee?.name || '', + employeeIdCardNumber: salaryEmployee?.idCardNumber, scene: 'POLICY', documentTitle: `${salaryEmployee?.name || ''}的薪酬调整确认书`, remark: '薪酬变更时发起', @@ -268,6 +271,7 @@ export default function Roster() { open: true, employeeId: deptEmployee?.id || '', employeeName: deptEmployee?.name || '', + employeeIdCardNumber: deptEmployee?.idCardNumber, scene: 'POLICY', documentTitle: `${deptEmployee?.name || ''}的调岗确认书`, remark: '部门/岗位调动时发起', @@ -294,6 +298,7 @@ export default function Roster() { open: true, employeeId: variables.employeeId, employeeName: confirmEmployee?.name || '', + employeeIdCardNumber: confirmEmployee?.idCardNumber, scene: 'POLICY', documentTitle: `${confirmEmployee?.name || ''}的转正薪酬调整确认书`, remark: `转正薪资调整:¥${originalSalary || 0} → ¥${newSalary}`, @@ -404,6 +409,7 @@ export default function Roster() { open: true, employeeId: renewEmployee?.id || '', employeeName: renewEmployee?.name || '', + employeeIdCardNumber: renewEmployee?.idCardNumber, scene: 'CONTRACT', documentTitle: `${renewEmployee?.name || ''}的续签劳动合同`, remark: '合同续签时发起', @@ -1186,7 +1192,7 @@ export default function Roster() { {/* 开具证明弹窗 */} {showCertModal && certEmployee && ( - { setShowCertModal(false); setCertEmployee(null) }} title={`为 ${certEmployee.name} 开具证明`}> + { setShowCertModal(false); setCertEmployee(null) }} title={`为 ${certEmployee.name}${certEmployee.idCardNumber ? `(${certEmployee.idCardNumber})` : ''} 开具证明`}>
@@ -1228,7 +1234,7 @@ export default function Roster() { {/* 续签合同弹窗 */} {showRenewModal && renewEmployee && ( - { setShowRenewModal(false); setRenewEmployee(null) }} title={`为 ${renewEmployee.name} 续签合同`}> + { setShowRenewModal(false); setRenewEmployee(null) }} title={`为 ${renewEmployee.name}${renewEmployee.idCardNumber ? `(${renewEmployee.idCardNumber})` : ''} 续签合同`}>
原合同到期日:{renewEmployee.latestContract?.endDate ? new Date(renewEmployee.latestContract.endDate).toISOString().slice(0, 10) : '无'} @@ -1523,6 +1529,7 @@ export default function Roster() { onClose={() => setSignChoice(null)} employeeId={signChoice.employeeId} employeeName={signChoice.employeeName} + employeeIdCardNumber={signChoice.employeeIdCardNumber} scene={signChoice.scene} documentTitle={signChoice.documentTitle} contractId={signChoice.contractId} diff --git a/frontend/src/pages/Termination.tsx b/frontend/src/pages/Termination.tsx index cfc504b..f824264 100644 --- a/frontend/src/pages/Termination.tsx +++ b/frontend/src/pages/Termination.tsx @@ -230,6 +230,7 @@ export default function Termination() { id: string employeeId: string name: string + idCardNumber?: string department: string reason: string reasonLabel: string @@ -758,6 +759,7 @@ export default function Termination() { id: `saved-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`, employeeId, name: selectedEmployee.name, + idCardNumber: selectedEmployee.idCardNumber, department: selectedEmployee.department, reason, reasonLabel, @@ -1284,13 +1286,13 @@ ${items}
{selectedEmployee && (
-
{selectedEmployee.name}({selectedEmployee.department})
+
{selectedEmployee.name}({selectedEmployee.department}){selectedEmployee.idCardNumber && {selectedEmployee.idCardNumber}}
入职日期:{selectedEmployee.hireDate?.toString().slice(0, 10)}
月工资:¥{fmt(selectedEmployee.monthlySalary)}
{selectedEmployee.hasTermination && selectedEmployee.latestTerminationStatus !== 'CANCELLED' && selectedEmployee.latestTerminationStatus !== 'COMPLETED' && ( @@ -1667,7 +1669,7 @@ ${items}
{/* 员工概况 */}
-
{selectedEmployee?.name}({selectedEmployee?.department})
+
{selectedEmployee?.name}({selectedEmployee?.department}){selectedEmployee?.idCardNumber && {selectedEmployee.idCardNumber}}
工作年限:{costResult.years}年{costResult.remainingMonths}个月
月工资:¥{fmt(costResult.wage)}/月
{costResult.capped && ( @@ -1988,7 +1990,7 @@ ${items}
{/* 汇总信息 */}
-
{selectedEmployee?.name}({selectedEmployee?.department})
+
{selectedEmployee?.name}({selectedEmployee?.department}){selectedEmployee?.idCardNumber && {selectedEmployee.idCardNumber}}
解聘原因:{reasonLabel}
解聘日期:{terminationDate}
社保截止:{socialInsEndMonth || terminationDate.slice(0, 7)}
@@ -2100,7 +2102,7 @@ ${items}

解除劳动合同通知书

-

{selectedEmployee?.name} 先生/女士:

+

{selectedEmployee?.name} 先生/女士(证件号码:{selectedEmployee?.idCardNumber || '—'}):

您于 {selectedEmployee?.hireDate?.toString().slice(0, 10)} 入职我公司{selectedEmployee?.department}部门。 因 {reasonLabel} 原因,公司决定于 {terminationDate} 起解除与您的劳动合同。 @@ -2293,7 +2295,7 @@ ${items} savedItems.forEach((item, i) => { if (y > 270) { doc.addPage(); y = 20 } doc.setFontSize(11) - doc.text(`${i + 1}. ${item.name} (${item.department})`, 14, y) + doc.text(`${i + 1}. ${item.name} (${item.department}) ${item.idCardNumber || ''}`, 14, y) y += 6 doc.setFontSize(9) doc.text(`解聘原因: ${item.reason || '-'}`, 20, y); y += 5 diff --git a/frontend/src/pages/compliance/RiskCenter.tsx b/frontend/src/pages/compliance/RiskCenter.tsx index 45f8763..5b86fa6 100644 --- a/frontend/src/pages/compliance/RiskCenter.tsx +++ b/frontend/src/pages/compliance/RiskCenter.tsx @@ -282,6 +282,7 @@ export default function RiskCenter() { {r.employee && (

{r.employee.name} · {r.employee.department || ''} + {r.employee.idCardNumber && {r.employee.idCardNumber}}
)}