fix: 全面优化安全、性能和代码质量
P0: 环境变量校验/事务保护/RBAC权限 P1: 花名册分页/密码重置验证码/ErrorBoundary/N+1查询优化 P2: 导出限制/自定义错误类/body大小限制/代码去重 P3: 自定义确认弹窗替换window.confirm
This commit is contained in:
@@ -40,13 +40,31 @@ router.get('/', authMiddleware, async (req: AuthRequest, res, next) => {
|
||||
]
|
||||
}
|
||||
|
||||
const [total, employees] = await Promise.all([
|
||||
// 状态过滤在 DB 层完成(contractStatus 需要后处理计算,仍需内存过滤)
|
||||
if (status === 'RESIGNED') {
|
||||
whereBase.status = 'RESIGNED'
|
||||
} else if (status === 'PRE_HIRE') {
|
||||
whereBase.status = 'ACTIVE'
|
||||
whereBase.hireDate = { gt: today }
|
||||
} else if (status === 'ACTIVE') {
|
||||
whereBase.status = 'ACTIVE'
|
||||
whereBase.hireDate = { lte: today }
|
||||
}
|
||||
|
||||
// unsigned 合同状态可以在 DB 层过滤
|
||||
if (contractStatus === 'unsigned') {
|
||||
whereBase.contracts = { none: {} }
|
||||
}
|
||||
|
||||
// 当有 contractStatus(非 unsigned)筛选时,需要先查全部再过滤后分页
|
||||
const needPostFilter = !!contractStatus && contractStatus !== 'unsigned'
|
||||
|
||||
const [dbTotal, employees] = await Promise.all([
|
||||
prisma.employee.count({ where: whereBase }),
|
||||
prisma.employee.findMany({
|
||||
where: whereBase,
|
||||
orderBy: { createdAt: 'desc' },
|
||||
skip,
|
||||
take: pageSize,
|
||||
...(needPostFilter ? {} : { skip, take: pageSize }),
|
||||
include: {
|
||||
contracts: { orderBy: { createdAt: 'desc' }, take: 1 },
|
||||
terminations: { orderBy: { terminationDate: 'desc' }, take: 1 },
|
||||
@@ -107,22 +125,25 @@ router.get('/', authMiddleware, async (req: AuthRequest, res, next) => {
|
||||
}
|
||||
})
|
||||
|
||||
// 前端过滤:状态和合同状态(因为合同状态需要后处理,不适合放 Prisma where)
|
||||
if (status) {
|
||||
result = result.filter((e) => e.status === status)
|
||||
}
|
||||
if (contractStatus) {
|
||||
// 前端过滤:合同状态(非 unsigned 的需要后处理计算)
|
||||
if (contractStatus && contractStatus !== 'unsigned') {
|
||||
result = result.filter((e) => e.contractStatus === contractStatus)
|
||||
}
|
||||
|
||||
// 计算过滤后的总数和分页
|
||||
const filteredTotal = needPostFilter ? result.length : dbTotal
|
||||
if (needPostFilter) {
|
||||
result = result.slice(skip, skip + pageSize)
|
||||
}
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
data: result,
|
||||
pagination: {
|
||||
page,
|
||||
pageSize,
|
||||
total,
|
||||
totalPages: Math.ceil(total / pageSize),
|
||||
total: filteredTotal,
|
||||
totalPages: Math.ceil(filteredTotal / pageSize),
|
||||
},
|
||||
})
|
||||
} catch (err) {
|
||||
|
||||
Reference in New Issue
Block a user