feat: 优化退休提醒功能 - 个性化退休年龄计算
- 添加 FemaleWorkerType enum (CADRE/WORKER) 和 Employee.femaleWorkerType 字段 - 新增 calcIndividualRetireAge: 按个人出生日期逐人计算退休年龄 - 重写 calcRetirementDaysLeft: 基于个人出生日期+性别+岗位类型 - updateEmployeesRetirementDays 使用 femaleWorkerType 区分女干部/女工人 - 前端新增/编辑员工表单添加女性岗位类型选择器 - 前端政策展示改为改革规则卡片(基准→目标年龄) - 前端距退休天数改为退休日期显示(XXXX年XX月XX日) - 移除AI退休政策计算相关代码和手动刷新路由 - 导入支持女性岗位类型列
This commit is contained in:
@@ -246,6 +246,8 @@ router.post('/excel', authMiddleware, requireAdmin, upload.single('file'), async
|
||||
orgId, name, department: dept, hireDate,
|
||||
monthlySalary: encrypt(salary),
|
||||
gender: val(r['性别']) || (idCard ? extractGenderFromIdCard(idCard) : null),
|
||||
femaleWorkerType: (val(r['女性岗位类型']) === '工人' || val(r['女性岗位类型']) === 'WORKER') ? 'WORKER'
|
||||
: (val(r['女性岗位类型']) === '干部' || val(r['女性岗位类型']) === 'CADRE') ? 'CADRE' : null,
|
||||
phone: val(r['手机号']) || null,
|
||||
idCardNumber: idCard ? encrypt(idCard) : null,
|
||||
idCardHash: idCard ? sha256(idCard) : null,
|
||||
|
||||
@@ -241,57 +241,3 @@ router.post('/retirement-policy/:id/confirm', requireAdmin, async (req: AuthRequ
|
||||
}
|
||||
})
|
||||
|
||||
// 手动触发获取最新退休政策(SSE 流式)
|
||||
router.post('/retirement-policy/refresh', requireAdmin, async (req: AuthRequest, res, next) => {
|
||||
try {
|
||||
const orgId = req.user!.orgId
|
||||
res.setHeader('Content-Type', 'text/event-stream')
|
||||
res.setHeader('Cache-Control', 'no-cache')
|
||||
res.setHeader('Connection', 'keep-alive')
|
||||
|
||||
const { fetchRetirementPolicyStream } = await import('../services/ai.service')
|
||||
const crypto = await import('crypto')
|
||||
|
||||
let fullContent = ''
|
||||
for await (const chunk of fetchRetirementPolicyStream()) {
|
||||
fullContent += chunk
|
||||
res.write(`data: ${JSON.stringify({ type: 'chunk', content: chunk })}\n\n`)
|
||||
}
|
||||
|
||||
// 解析 JSON
|
||||
let maleRetireAge = 60
|
||||
let femaleRetireAge = 55
|
||||
let femaleWorkerAge = 50
|
||||
const jsonMatch = fullContent.match(/<JSON>([\s\S]*?)<\/JSON>/)
|
||||
if (jsonMatch) {
|
||||
try {
|
||||
const parsed = JSON.parse(jsonMatch[1].trim())
|
||||
if (parsed.maleRetireAge) maleRetireAge = Number(parsed.maleRetireAge)
|
||||
if (parsed.femaleRetireAge) femaleRetireAge = Number(parsed.femaleRetireAge)
|
||||
if (parsed.femaleWorkerAge) femaleWorkerAge = Number(parsed.femaleWorkerAge)
|
||||
} catch {}
|
||||
}
|
||||
|
||||
const contentHash = crypto.createHash('sha256').update(fullContent).digest('hex')
|
||||
const latestPolicy = await prisma.retirementPolicy.findFirst({ where: { orgId }, orderBy: { createdAt: 'desc' } })
|
||||
|
||||
if (latestPolicy && latestPolicy.contentHash === contentHash) {
|
||||
res.write(`data: ${JSON.stringify({ type: 'done', message: '政策内容未变化' })}\n\n`)
|
||||
res.end()
|
||||
return
|
||||
}
|
||||
|
||||
const version = latestPolicy ? latestPolicy.version + 1 : 1
|
||||
const policy = await prisma.retirementPolicy.create({
|
||||
data: {
|
||||
orgId, version, content: fullContent, contentHash, status: 'PENDING',
|
||||
maleRetireAge, femaleRetireAge, femaleWorkerAge,
|
||||
},
|
||||
})
|
||||
res.write(`data: ${JSON.stringify({ type: 'done', data: policy, message: '已获取新政策,待确认' })}\n\n`)
|
||||
res.end()
|
||||
} catch (err) {
|
||||
res.write(`data: ${JSON.stringify({ type: 'error', message: '获取失败' })}\n\n`)
|
||||
res.end()
|
||||
}
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user