feat: 20260809 系统优化 - 全部28项问题修复(P0×6+P1×16+P2×6)
P0: 福利批量参保/离职证明下载防乱码/考勤模板合并Sheet/补卡修改/附件在线查看删除 P1: 分页pageSize修复/离职导出筛选/撤回删除草稿/加班费自动计算/考勤加班汇总/证据链异常详情/制度催办/模板导入Word/社保封顶保底/校验字段提示/职务字段/社保费用明细/弹窗防误关/身份证查重/证明员工下拉/培训批量 P2: 离职流程去重/社保基数覆盖输入/薪税入口改名/添加员工引导/绩效模板清理
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
import { Router, Response, NextFunction } from 'express'
|
||||
import { authMiddleware, AuthRequest } from '../middleware/auth'
|
||||
import { requireAdmin } from '../middleware/rbac'
|
||||
import { z } from 'zod'
|
||||
import prisma from '../lib/prisma'
|
||||
import {
|
||||
@@ -90,24 +91,26 @@ router.delete('/:id', authMiddleware, async (req: AuthRequest, res: Response, ne
|
||||
router.get('/:id/read-stats', authMiddleware, async (req: AuthRequest, res: Response, next: NextFunction) => {
|
||||
try {
|
||||
const orgId = req.user!.orgId
|
||||
const policy = await prisma.policyDocument.findFirst({ where: { id: req.params.id, orgId }, select: { id: true } })
|
||||
const policy = await prisma.policyDocument.findFirst({ where: { id: req.params.id, orgId }, select: { id: true, title: true } })
|
||||
if (!policy) {
|
||||
return res.status(404).json({ success: false, error: { code: 'NOT_FOUND', message: '制度不存在' } })
|
||||
}
|
||||
const [totalEmployees, readRecords] = await Promise.all([
|
||||
prisma.employee.count({ where: { orgId, status: 'ACTIVE' } }),
|
||||
const [allEmployees, readRecords] = await Promise.all([
|
||||
prisma.employee.findMany({ where: { orgId, status: 'ACTIVE' }, select: { id: true, name: true, department: true }, orderBy: { name: 'asc' } }),
|
||||
prisma.policyReadRecord.findMany({
|
||||
where: { policyId: req.params.id, orgId },
|
||||
include: { employee: { select: { id: true, name: true, department: true } } },
|
||||
orderBy: { readAt: 'desc' },
|
||||
}),
|
||||
])
|
||||
const readEmpIds = new Set(readRecords.map(r => r.employeeId))
|
||||
const unreadEmployees = allEmployees.filter(e => !readEmpIds.has(e.id))
|
||||
res.json({
|
||||
success: true,
|
||||
data: {
|
||||
total: totalEmployees,
|
||||
total: allEmployees.length,
|
||||
readCount: readRecords.length,
|
||||
unreadCount: totalEmployees - readRecords.length,
|
||||
unreadCount: unreadEmployees.length,
|
||||
records: readRecords.map(r => ({
|
||||
employeeId: r.employeeId,
|
||||
employeeName: r.employee.name,
|
||||
@@ -115,6 +118,11 @@ router.get('/:id/read-stats', authMiddleware, async (req: AuthRequest, res: Resp
|
||||
readAt: r.readAt.toISOString(),
|
||||
ip: r.ip,
|
||||
})),
|
||||
unreadEmployees: unreadEmployees.map(e => ({
|
||||
employeeId: e.id,
|
||||
employeeName: e.name,
|
||||
department: e.department,
|
||||
})),
|
||||
},
|
||||
})
|
||||
} catch (err) {
|
||||
@@ -122,4 +130,43 @@ router.get('/:id/read-stats', authMiddleware, async (req: AuthRequest, res: Resp
|
||||
}
|
||||
})
|
||||
|
||||
/** 催办未签收员工 */
|
||||
router.post('/:id/remind', authMiddleware, requireAdmin, async (req: AuthRequest, res: Response, next: NextFunction) => {
|
||||
try {
|
||||
const orgId = req.user!.orgId
|
||||
const policy = await prisma.policyDocument.findFirst({ where: { id: req.params.id, orgId }, select: { id: true, title: true } })
|
||||
if (!policy) {
|
||||
return res.status(404).json({ success: false, error: { code: 'NOT_FOUND', message: '制度不存在' } })
|
||||
}
|
||||
const { employeeIds } = req.body as { employeeIds?: string[] }
|
||||
const readRecords = await prisma.policyReadRecord.findMany({ where: { policyId: req.params.id, orgId }, select: { employeeId: true } })
|
||||
const readEmpIds = new Set(readRecords.map(r => r.employeeId))
|
||||
const targetEmployees = await prisma.employee.findMany({
|
||||
where: {
|
||||
orgId, status: 'ACTIVE',
|
||||
id: employeeIds && employeeIds.length > 0 ? { in: employeeIds } : undefined,
|
||||
},
|
||||
select: { id: true, name: true },
|
||||
})
|
||||
const unreadEmployees = targetEmployees.filter(e => !readEmpIds.has(e.id))
|
||||
// 创建催办通知
|
||||
for (const emp of unreadEmployees) {
|
||||
await prisma.notificationLog.create({
|
||||
data: {
|
||||
orgId,
|
||||
employeeId: emp.id,
|
||||
type: 'POLICY_REMIND',
|
||||
title: `制度签收提醒:${policy.title}`,
|
||||
content: `您有一项制度「${policy.title}」尚未签收,请尽快完成阅读确认。`,
|
||||
channel: 'IN_APP',
|
||||
status: 'SENT',
|
||||
},
|
||||
}).catch(() => {})
|
||||
}
|
||||
res.json({ success: true, data: { reminded: unreadEmployees.length } })
|
||||
} catch (err) {
|
||||
next(err)
|
||||
}
|
||||
})
|
||||
|
||||
export default router
|
||||
|
||||
Reference in New Issue
Block a user