fix: 统一风险中心及全应用身份证号显示

后端:
- employee.routes.ts: all-lite 接口加上 idCardNumber 并解密
- special-status.routes.ts: 列表和详情查询加上 idCardNumber 并解密
- esign.routes.ts: 列表/pending/detail/remind 接口加上 idCardNumber 并解密
- risk.service.ts: getMonthlyCalendar 所有事件加上 employeeIdCardNumber
- termination.service.ts: batchTerminatePreview 加上 employeeIdCardNumber
- employee.routes.ts: preview-renew 加上 employeeIdCardNumber

前端:
- Roster.tsx: 批量续签/解聘预检结果加上身份证号
- SpecialStatus.tsx: 列表/下拉/删除确认加上身份证号
- Calendar.tsx: 日历事件姓名后显示身份证号
- ESign.tsx: 签署列表/详情/员工列表/提醒弹窗/下拉加上身份证号
- CommercialInsuranceTab.tsx: 参保选择列表加上身份证号
- OvertimeTab.tsx: 导入预览加上身份证号
This commit is contained in:
freedakgmail
2026-08-18 08:14:26 +08:00
parent 4d78eac5c2
commit eb91c2d8fb
11 changed files with 64 additions and 26 deletions
+1
View File
@@ -377,6 +377,7 @@ export default function Calendar() {
<div className="text-xs text-gray-800 mt-0.5 truncate">
{ev.title}
{ev.employeeName && <span className="text-gray-400 ml-1"> {ev.employeeName}</span>}
{ev.employeeIdCardNumber && <span className="text-gray-400 ml-1 font-mono text-[10px]">{ev.employeeIdCardNumber}</span>}
</div>
{ev.type === 'CONTRACT_EXPIRY' && ev.employeeName ? (
<Link to={`/roster?employee=${encodeURIComponent(ev.employeeName)}`} className="text-[10px] text-primary hover:underline mt-0.5 inline-block">
+11 -5
View File
@@ -263,7 +263,12 @@ export default function ESign() {
</div>
{r.remark && <div className="text-xs text-gray-400 mt-0.5">{r.remark}</div>}
</td>
<td className="py-2 px-3">{r.employee?.name || '—'}</td>
<td className="py-2 px-3">
<div className="flex flex-col gap-0.5">
<span>{r.employee?.name || '—'}</span>
{r.employee?.idCardNumber && <span className="text-gray-400 text-[11px] font-mono">{r.employee.idCardNumber}</span>}
</div>
</td>
<td className="py-2 px-3 text-gray-500">{r.employee?.department || '—'}</td>
<td className="py-2 px-3">
<span className={`px-1.5 py-0.5 rounded text-xs ${(SIGN_METHOD_CONFIG[r.signMethod] || SIGN_METHOD_CONFIG.ELECTRONIC).color}`}>
@@ -334,7 +339,7 @@ export default function ESign() {
>
<option value=""></option>
{rosterData.map((emp: any) => (
<option key={emp.id} value={emp.id}>{emp.name} - {emp.department}</option>
<option key={emp.id} value={emp.id}>{emp.name}{emp.idCardNumber ? `${emp.idCardNumber}` : ''} - {emp.department}</option>
))}
</select>
</div>
@@ -496,7 +501,7 @@ function PaperSignModal({ onClose, onSuccess, initialEmployeeId, initialScene, i
>
<option value=""></option>
{rosterData.map((emp: any) => (
<option key={emp.id} value={emp.id}>{emp.name} - {emp.department}</option>
<option key={emp.id} value={emp.id}>{emp.name}{emp.idCardNumber ? `${emp.idCardNumber}` : ''} - {emp.department}</option>
))}
</select>
</div>
@@ -654,7 +659,7 @@ function ESignDetail({ id, onBack }: { id: string; onBack: () => void }) {
{(SIGN_METHOD_CONFIG[detail.signMethod] || SIGN_METHOD_CONFIG.ELECTRONIC).label}
</span>
</div>
<div className="text-xs text-gray-400 mt-0.5">{detail.employee?.name} · {detail.employee?.department}</div>
<div className="text-xs text-gray-400 mt-0.5">{detail.employee?.name} · {detail.employee?.department}{detail.employee?.idCardNumber && <span className="ml-1 font-mono">{detail.employee.idCardNumber}</span>}</div>
</div>
<span className={`inline-flex items-center gap-1 px-2.5 py-1 rounded text-xs ${statusCfg.color}`}>
{statusCfg.icon}{statusCfg.label}
@@ -868,6 +873,7 @@ function PendingTab({ pendingList, loading, onRemind, remindLoading, remindData,
<User className="w-3.5 h-3.5 text-primary" />
</div>
<span className="font-medium">{emp.name}</span>
{emp.idCardNumber && <span className="text-xs text-gray-400 font-mono ml-1">{emp.idCardNumber}</span>}
</div>
</td>
<td className="py-2 px-3 text-gray-500">{emp.department || '—'}</td>
@@ -993,7 +999,7 @@ function PendingTab({ pendingList, loading, onRemind, remindLoading, remindData,
<QRCodeSVG value={remindData.url} size={200} level="M" />
</div>
<p className="mt-3 text-xs text-gray-600 text-center">
<span className="font-medium">{remindData.employeeName}</span>
<span className="font-medium">{remindData.employeeName}</span>{remindData.employeeIdCardNumber && <span className="font-mono text-gray-500 ml-1">{remindData.employeeIdCardNumber}</span>}
</p>
<p className="mt-1 text-xs text-gray-400"> 24 </p>
<div className="mt-3 w-full">
+2 -2
View File
@@ -1378,7 +1378,7 @@ export default function Roster() {
{previewData.results.map((r: any) => (
<div key={r.contractId} className={`p-2 rounded text-xs ${r.warning ? 'bg-amber-50 border border-amber-200' : 'bg-gray-50'}`}>
<div className="flex items-center justify-between">
<span className="font-medium">{r.employeeName}</span>
<span className="font-medium">{r.employeeName}{r.employeeIdCardNumber ? <span className="ml-1 font-mono text-gray-400 text-[10px]">{r.employeeIdCardNumber}</span> : null}</span>
<span className="text-gray-400">{r.department}</span>
</div>
<div className="text-gray-500 mt-1">
@@ -1477,7 +1477,7 @@ export default function Roster() {
{terminatePreviewData.results.map((r: any) => (
<div key={r.employeeId} className={`p-2 rounded text-xs ${r.warnings.length > 0 ? 'bg-red-50 border border-red-200' : 'bg-gray-50'}`}>
<div className="flex items-center justify-between">
<span className="font-medium">{r.employeeName}</span>
<span className="font-medium">{r.employeeName}{r.employeeIdCardNumber ? <span className="ml-1 font-mono text-gray-400 text-[10px]">{r.employeeIdCardNumber}</span> : null}</span>
<span className="text-gray-400">{r.department}</span>
</div>
<div className="text-gray-500 mt-1">
+4 -3
View File
@@ -38,7 +38,7 @@ interface SpecialStatus {
reminderDate: string | null
alertLevel: 'red' | 'yellow' | 'green'
employee: {
id: string; name: string; department: string; phone: string; gender: string; status: string
id: string; name: string; department: string; phone: string; gender: string; status: string; idCardNumber?: string | null
}
}
@@ -367,6 +367,7 @@ export default function SpecialStatus() {
{/* 员工信息 */}
<div className="mb-3">
<Link to={`/roster?employeeId=${item.employee.id}`} className="font-medium text-gray-900 hover:text-primary hover:underline">{item.employee.name}</Link>
{item.employee.idCardNumber && <span className="text-xs text-gray-400 font-mono ml-1">{item.employee.idCardNumber}</span>}
<span className="text-sm text-gray-500 ml-2">{item.employee.department}</span>
{item.employee.status === 'RESIGNED' && (
<span className="ml-2 text-xs text-gray-400"></span>
@@ -458,7 +459,7 @@ export default function SpecialStatus() {
}} disabled={!!editing}>
<option value=""></option>
{employees.map((emp) => (
<option key={emp.id} value={emp.id}>{emp.name} - {emp.department}</option>
<option key={emp.id} value={emp.id}>{emp.name}{emp.idCardNumber ? `${emp.idCardNumber}` : ''} - {emp.department}</option>
))}
</Select>
</div>
@@ -620,7 +621,7 @@ export default function SpecialStatus() {
</div>
</div>
<p className="text-sm text-gray-600 mb-4">
<b>{deleteTarget.employee.name}</b> <b>{TYPE_LABELS[deleteTarget.type]}</b>
<b>{deleteTarget.employee.name}{deleteTarget.employee.idCardNumber ? `${deleteTarget.employee.idCardNumber}` : ''}</b> <b>{TYPE_LABELS[deleteTarget.type]}</b>
</p>
<div className="flex gap-2">
<Button className="flex-1 bg-red-500 hover:bg-red-600" onClick={handleDelete}></Button>
+1 -1
View File
@@ -323,7 +323,7 @@ export function OvertimeCalculator() {
<tbody>
{previewData.map((d, i) => (
<tr key={i} className="border-b last:border-0">
<td className="py-2">{d.employeeName}</td>
<td className="py-2">{d.employeeName}{d.idCardNumber ? <span className="ml-1 text-xs text-gray-400 font-mono">{d.idCardNumber}</span> : ''}</td>
<td className="py-2 text-gray-500">{d.department}</td>
<td className="py-2 text-right">{d.weekdayHours}</td>
<td className="py-2 text-right">{d.weekendHours}</td>
@@ -267,7 +267,7 @@ export default function CommercialInsuranceTab() {
else setEnrollEmployeeIds(enrollEmployeeIds.filter((id) => id !== emp.id))
}} />
</td>
<td className="py-2 px-3 font-medium">{emp.name}</td>
<td className="py-2 px-3 font-medium">{emp.name}{emp.idCardNumber ? <span className="ml-1 text-xs text-gray-400 font-mono">{emp.idCardNumber}</span> : ''}</td>
<td className="py-2 px-3 text-gray-500">{emp.department}</td>
<td className="py-2 px-3">
<span className="px-2 py-0.5 rounded text-xs bg-green-50 text-safe"></span>