fix: 绩效/培训/违纪/工资条/加班/休假/专项扣除/薪酬批次列表姓名下显示完整身份证号

后端:
- roster.routes.ts: 绩效/培训/违纪列表查询加上 idCardNumber 并解密
- payroll.routes.ts: 加班/工资条查询加上 idCardNumber 并解密
- payroll2.routes.ts: 薪酬批次详情加上 idCardNumber 并解密
- leave.routes.ts: 休假审批列表加上 idCardNumber 并解密
- social.routes.ts: 专项附加扣除查询加上 idCardNumber 并解密

前端:
- PerformanceRecords.tsx: 姓名下显示身份证号
- TrainingRecords.tsx: 姓名下显示身份证号
- DisciplinaryRecords.tsx: 姓名下显示身份证号
- PayslipTab.tsx: 姓名下显示身份证号
- OvertimeTab.tsx: 姓名下显示身份证号
- LeaveApproval.tsx: 姓名下显示身份证号
- SpecialDeductionTab.tsx: 姓名下显示身份证号
- BatchTab.tsx: 姓名下显示身份证号
This commit is contained in:
freedakgmail
2026-08-18 07:42:24 +08:00
parent ef03b2e5f8
commit a58cc3f6f9
13 changed files with 126 additions and 31 deletions
+15 -2
View File
@@ -2,9 +2,18 @@ import { Router, Response, NextFunction } from 'express'
import { authMiddleware, AuthRequest } from '../middleware/auth'
import prisma from '../lib/prisma'
import { parsePagination } from '../lib/pagination'
import { decrypt } from '../lib/crypto'
const router = Router()
function safeDecryptStr(encrypted: string | null): string | null {
if (!encrypted) return null
try {
if (!encrypted.includes(':')) return encrypted
return decrypt(encrypted)
} catch { return null }
}
// 休假申请列表
router.get('/', authMiddleware, async (req: AuthRequest, res: Response, next: NextFunction) => {
try {
@@ -21,14 +30,18 @@ router.get('/', authMiddleware, async (req: AuthRequest, res: Response, next: Ne
const list = await prisma.leaveRequest.findMany({
where,
include: {
employee: { select: { id: true, name: true, department: true, position: true } },
employee: { select: { id: true, name: true, department: true, position: true, idCardNumber: true } },
},
orderBy: { createdAt: 'desc' },
skip: (page - 1) * pageSize,
take: pageSize,
})
res.json({ success: true, data: { list, total, page, pageSize } })
const data = list.map((r: any) => ({
...r,
employee: r.employee ? { ...r.employee, idCardNumber: safeDecryptStr(r.employee.idCardNumber) } : r.employee,
}))
res.json({ success: true, data: { list: data, total, page, pageSize } })
} catch (err) {
next(err)
}
+20 -4
View File
@@ -8,6 +8,14 @@ import { isInProbation } from '../services/contract.service'
const router = Router()
router.use(authMiddleware)
function safeDecryptStr(encrypted: string | null): string | null {
if (!encrypted) return null
try {
if (!encrypted.includes(':')) return encrypted
return decrypt(encrypted)
} catch { return null }
}
// ========== 加班费记录 ==========
const overtimeSchema = z.object({
@@ -29,10 +37,14 @@ router.get('/overtime', async (req: AuthRequest, res: Response, next: NextFuncti
...(employeeId ? { employeeId: String(employeeId) } : {}),
...(month ? { month: String(month) } : {}),
},
include: { employee: { select: { id: true, name: true, department: true } } },
include: { employee: { select: { id: true, name: true, department: true, idCardNumber: true } } },
orderBy: { createdAt: 'desc' },
})
res.json({ success: true, data: records })
const data = records.map((r: any) => ({
...r,
employee: r.employee ? { ...r.employee, idCardNumber: safeDecryptStr(r.employee.idCardNumber) } : r.employee,
}))
res.json({ success: true, data })
} catch (err) {
next(err)
}
@@ -236,10 +248,14 @@ router.get('/payslip', async (req: AuthRequest, res: Response, next: NextFunctio
...(month ? { month: String(month) } : {}),
...(employeeId ? { employeeId: String(employeeId) } : {}),
},
include: { employee: { select: { id: true, name: true, department: true } } },
include: { employee: { select: { id: true, name: true, department: true, idCardNumber: true } } },
orderBy: [{ month: 'desc' }, { employee: { name: 'asc' } }],
})
res.json({ success: true, data: payslips })
const data = payslips.map((p: any) => ({
...p,
employee: p.employee ? { ...p.employee, idCardNumber: safeDecryptStr(p.employee.idCardNumber) } : p.employee,
}))
res.json({ success: true, data })
} catch (err) {
next(err)
}
+18 -3
View File
@@ -13,6 +13,14 @@ import {
import { isInProbation } from '../services/contract.service'
import { getBonusByMonthAndEmployeeIds } from '../services/commission-bonus.service'
function safeDecryptStr(encrypted: string | null): string | null {
if (!encrypted) return null
try {
if (!encrypted.includes(':')) return encrypted
return decrypt(encrypted)
} catch { return null }
}
/**
* 查询上月递延扣款数据(上月已归档批次中该员工的递延金额)
* 用于本月创建批次时补扣上月未扣完的社保/公积金/最低工资补齐
@@ -209,18 +217,25 @@ router.get('/batches', async (req: AuthRequest, res: Response, next: NextFunctio
// 获取批次详情
router.get('/batches/:id', async (req: AuthRequest, res: Response, next: NextFunction) => {
try {
const batch = await prisma.payrollBatch.findFirst({
const rawBatch = await prisma.payrollBatch.findFirst({
where: { id: req.params.id, orgId: req.user!.orgId },
include: {
entries: {
include: {
employee: { select: { id: true, name: true, department: true, status: true, bankAccount: true, bankName: true } },
employee: { select: { id: true, name: true, department: true, status: true, bankAccount: true, bankName: true, idCardNumber: true } },
},
orderBy: { employee: { name: 'asc' } },
},
},
})
if (!batch) return res.status(404).json({ success: false, error: { code: 'NOT_FOUND', message: '批次不存在' } })
if (!rawBatch) return res.status(404).json({ success: false, error: { code: 'NOT_FOUND', message: '批次不存在' } })
const batch = {
...rawBatch,
entries: rawBatch.entries.map((e: any) => ({
...e,
employee: e.employee ? { ...e.employee, idCardNumber: safeDecryptStr(e.employee.idCardNumber) } : e.employee,
})),
}
res.json({ success: true, data: batch })
} catch (err) {
next(err)
+18 -6
View File
@@ -850,16 +850,20 @@ router.get('/training/list', authMiddleware, async (req: AuthRequest, res, next)
})
where.employeeId = { in: employees.map(e => e.id) }
}
const [records, total] = await Promise.all([
const [rawRecords, total] = await Promise.all([
prisma.trainingRecord.findMany({
where,
include: { employee: { select: { id: true, name: true, department: true } } },
include: { employee: { select: { id: true, name: true, department: true, idCardNumber: true } } },
orderBy: { trainingDate: 'desc' },
skip: (page - 1) * pageSize,
take: pageSize,
}),
prisma.trainingRecord.count({ where }),
])
const records = rawRecords.map((r: any) => ({
...r,
employee: r.employee ? { ...r.employee, idCardNumber: safeDecryptStr(r.employee.idCardNumber) } : r.employee,
}))
res.json({ success: true, data: { records, total, page, pageSize } })
} catch (err) { next(err) }
})
@@ -908,16 +912,20 @@ router.get('/performance/list', authMiddleware, async (req: AuthRequest, res, ne
})
where.employeeId = { in: employees.map(e => e.id) }
}
const [records, total] = await Promise.all([
const [rawRecords, total] = await Promise.all([
prisma.performanceRecord.findMany({
where,
include: { employee: { select: { id: true, name: true, department: true } } },
include: { employee: { select: { id: true, name: true, department: true, idCardNumber: true } } },
orderBy: { period: 'desc' },
skip: (page - 1) * pageSize,
take: pageSize,
}),
prisma.performanceRecord.count({ where }),
])
const records = rawRecords.map((r: any) => ({
...r,
employee: r.employee ? { ...r.employee, idCardNumber: safeDecryptStr(r.employee.idCardNumber) } : r.employee,
}))
res.json({ success: true, data: { records, total, page, pageSize } })
} catch (err) { next(err) }
})
@@ -937,16 +945,20 @@ router.get('/disciplinary/list', authMiddleware, async (req: AuthRequest, res, n
})
where.employeeId = { in: employees.map(e => e.id) }
}
const [records, total] = await Promise.all([
const [rawRecords, total] = await Promise.all([
prisma.disciplinaryRecord.findMany({
where,
include: { employee: { select: { id: true, name: true, department: true } } },
include: { employee: { select: { id: true, name: true, department: true, idCardNumber: true } } },
orderBy: { violationDate: 'desc' },
skip: (page - 1) * pageSize,
take: pageSize,
}),
prisma.disciplinaryRecord.count({ where }),
])
const records = rawRecords.map((r: any) => ({
...r,
employee: r.employee ? { ...r.employee, idCardNumber: safeDecryptStr(r.employee.idCardNumber) } : r.employee,
}))
res.json({ success: true, data: { records, total, page, pageSize } })
} catch (err) { next(err) }
})
+6 -2
View File
@@ -1744,10 +1744,14 @@ router.get('/special-deduction/batch', async (req: AuthRequest, res: Response, n
try {
const { month } = req.query
if (!month) return res.status(400).json({ success: false, message: '缺少 month' })
const records = await prisma.specialDeductionRecord.findMany({
const rawRecords = await prisma.specialDeductionRecord.findMany({
where: { orgId: req.user!.orgId, month: month as string },
include: { employee: { select: { name: true, department: true } } },
include: { employee: { select: { name: true, department: true, idCardNumber: true } } },
})
const records = rawRecords.map((r: any) => ({
...r,
employee: r.employee ? { ...r.employee, idCardNumber: decryptIdCard(r.employee.idCardNumber) } : r.employee,
}))
res.json({ success: true, data: records })
} catch (err) {
next(err)