优化: 大文件拆分+代码分割+按需加载+console清理+any类型替换
- Money.tsx (2260行→54行): 拆分为 money/ 子目录4个组件, React.lazy二级分割 - AIAssistant.tsx (2038行→63行): 拆分为 ai-assistant/ 子目录6个组件, React.lazy二级分割 - xlsx改为动态导入, OvertimeTab从345KB降至12.7KB - api-services.ts: 请求参数 any→Record<string,unknown> - 移除前端3处console.log残留 - 后端console替换为pino logger - 前后端未使用import/变量清理 - Zod schema验证: termination/platform/special-status/work-process - 新增 leave.routes.ts, acceptance-test.routes.ts - UI组件: PageGuide, QueryError, Stepper
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
import { Router } from 'express'
|
||||
import { authMiddleware, AuthRequest } from '../middleware/auth'
|
||||
import { auditLog } from '../middleware/auditLog'
|
||||
import { terminationChecklistSchema } from '../schemas/termination.schema'
|
||||
import { terminationChecklistSchema, resignationSchema, batchTerminatePreviewSchema, batchTerminateSchema, createTerminationDraftSchema, updateTerminationDraftSchema } from '../schemas/termination.schema'
|
||||
import { createTermination, createResignation, revokeTermination, getTerminations, getChecklistForReason, assessRisk, batchTerminatePreview, batchTerminate, createDraft, updateDraft, submitForApproval, approveTermination, rejectTermination, executeTermination, cancelTermination, getDrafts, getTerminationDetail, getDefaultHandoverItems, validateTerminationStep } from '../services/termination.service'
|
||||
import prisma from '../lib/prisma'
|
||||
import { createEvidence } from '../services/evidence.service'
|
||||
@@ -80,10 +80,7 @@ router.post('/', authMiddleware, async (req: AuthRequest, res, next) => {
|
||||
|
||||
router.post('/resignation', authMiddleware, async (req: AuthRequest, res, next) => {
|
||||
try {
|
||||
const { employeeId, terminationDate, resignationReason, remark } = req.body
|
||||
if (!employeeId || !terminationDate) {
|
||||
return res.status(400).json({ success: false, error: { code: 'VALIDATION_ERROR', message: '缺少必填字段' } })
|
||||
}
|
||||
const { employeeId, terminationDate, resignationReason, remark } = resignationSchema.parse(req.body)
|
||||
const result = await createResignation(req.user!.orgId, req.user!.id, { employeeId, terminationDate, resignationReason, remark })
|
||||
await auditLog(req, 'RESIGN', 'EMPLOYEE', employeeId, { resignationReason })
|
||||
res.json({ success: true, data: result })
|
||||
@@ -120,12 +117,7 @@ router.delete('/:id/revoke', authMiddleware, async (req: AuthRequest, res, next)
|
||||
// 批量解聘预检
|
||||
router.post('/batch/preview', authMiddleware, async (req: AuthRequest, res, next) => {
|
||||
try {
|
||||
const { items } = req.body as {
|
||||
items: Array<{ employeeId: string; reason: string; terminationDate: string }>
|
||||
}
|
||||
if (!items || !Array.isArray(items) || items.length === 0) {
|
||||
return res.status(400).json({ success: false, error: { code: 'BAD_REQUEST', message: '缺少 items' } })
|
||||
}
|
||||
const { items } = batchTerminatePreviewSchema.parse(req.body)
|
||||
const results = await batchTerminatePreview(req.user!.orgId, items)
|
||||
res.json({ success: true, data: { total: results.length, warnings: results.filter(r => r.warnings.length > 0).length, results } })
|
||||
} catch (err) {
|
||||
@@ -136,12 +128,7 @@ router.post('/batch/preview', authMiddleware, async (req: AuthRequest, res, next
|
||||
// 批量解聘执行
|
||||
router.post('/batch', authMiddleware, async (req: AuthRequest, res, next) => {
|
||||
try {
|
||||
const { items } = req.body as {
|
||||
items: Array<{ employeeId: string; reason: string; terminationDate: string; compensation?: number }>
|
||||
}
|
||||
if (!items || !Array.isArray(items) || items.length === 0) {
|
||||
return res.status(400).json({ success: false, error: { code: 'BAD_REQUEST', message: '缺少 items' } })
|
||||
}
|
||||
const { items } = batchTerminateSchema.parse(req.body)
|
||||
const result = await batchTerminate(req.user!.orgId, req.user!.id, items)
|
||||
for (const id of result.success) {
|
||||
await auditLog(req, 'TERMINATE', 'EMPLOYEE', id, { batch: true })
|
||||
@@ -192,15 +179,16 @@ router.get('/handover-template', authMiddleware, async (req: AuthRequest, res) =
|
||||
// 创建草稿
|
||||
router.post('/draft', authMiddleware, async (req: AuthRequest, res, next) => {
|
||||
try {
|
||||
const result = await createDraft(req.user!.orgId, req.user!.id, req.body)
|
||||
const emp = await prisma.employee.findFirst({ where: { id: req.body.employeeId }, select: { name: true, department: true } })
|
||||
const data = createTerminationDraftSchema.parse(req.body)
|
||||
const result = await createDraft(req.user!.orgId, req.user!.id, data)
|
||||
const emp = await prisma.employee.findFirst({ where: { id: data.employeeId }, select: { name: true, department: true } })
|
||||
await auditLog(req, 'CREATE_DRAFT', 'TERMINATION_RECORD', result.id, {
|
||||
employeeName: emp?.name || '',
|
||||
department: emp?.department || '',
|
||||
reason: req.body.reason || '',
|
||||
type: req.body.type || 'TERMINATION',
|
||||
terminationDate: req.body.terminationDate || '',
|
||||
compensation: req.body.compensation || 0,
|
||||
reason: data.reason || '',
|
||||
type: data.type || 'TERMINATION',
|
||||
terminationDate: data.terminationDate || '',
|
||||
compensation: data.compensation || 0,
|
||||
})
|
||||
res.json({ success: true, data: result })
|
||||
} catch (err: any) {
|
||||
@@ -214,7 +202,8 @@ router.post('/draft', authMiddleware, async (req: AuthRequest, res, next) => {
|
||||
// 更新草稿
|
||||
router.put('/draft/:id', authMiddleware, async (req: AuthRequest, res, next) => {
|
||||
try {
|
||||
const result = await updateDraft(req.user!.orgId, req.params.id, req.user!.id, req.body)
|
||||
const data = updateTerminationDraftSchema.parse(req.body)
|
||||
const result = await updateDraft(req.user!.orgId, req.params.id, req.user!.id, data)
|
||||
res.json({ success: true, data: result })
|
||||
} catch (err: any) {
|
||||
if (err?.code === 'CONFLICT' || err?.code === 'NOT_FOUND') {
|
||||
|
||||
Reference in New Issue
Block a user