fb36b10402
- 新增工作日历页面(月历视图、事件管理、自定义事件) - 考勤管理重构为6 Tab模块(班次/排班/每日出勤/月度报表/休假记录) - AI顾问新增人力报告Tab,支持流式生成+Word导出 - 工作台总览新增员工分布统计(性别/年龄/学历/司龄饼图)+部门成本拆分 - 花名册/合同/解聘补偿新增部门和状态筛选 - 薪税管理新增工资表导入模板下载、银行代发CSV导出 - 社保公积金支持多公积金账户类型显示 - 数据导出新增花名册/解聘记录导出,中文文件名编码修复 - 数据导入新增模板下载(员工/增减员/工资表)+错误日志导出 - 移除工作台日历卡片(已迁移至独立工作日历页面) - 新增20260728/20260729更新测试指导文档
121 lines
3.9 KiB
TypeScript
121 lines
3.9 KiB
TypeScript
import { Router, Response, NextFunction } from 'express'
|
|
import prisma from '../lib/prisma'
|
|
import { authMiddleware, AuthRequest } from '../middleware/auth'
|
|
import { z } from 'zod'
|
|
|
|
const router = Router()
|
|
|
|
const createEventSchema = z.object({
|
|
title: z.string().min(1).max(100),
|
|
date: z.string(), // ISO date string
|
|
endDate: z.string().optional(),
|
|
type: z.enum(['CUSTOM', 'MEETING', 'TEAM_BUILDING', 'TRAINING', 'INTERVIEW']).default('CUSTOM'),
|
|
priority: z.enum(['high', 'medium', 'low']).default('medium'),
|
|
location: z.string().optional(),
|
|
description: z.string().optional(),
|
|
employeeId: z.string().optional(),
|
|
})
|
|
|
|
// 获取当月日历事件(自定义 + 系统自动)
|
|
router.get('/', authMiddleware, async (req: AuthRequest, res: Response, next: NextFunction) => {
|
|
try {
|
|
const orgId = req.user!.orgId
|
|
const month = (req.query.month as string) || new Date().toISOString().slice(0, 7)
|
|
const typeFilter = req.query.type as string | undefined
|
|
|
|
const [year, mon] = month.split('-').map(Number)
|
|
const monthStart = new Date(year, mon - 1, 1)
|
|
const monthEnd = new Date(year, mon, 0, 23, 59, 59)
|
|
|
|
const where: any = {
|
|
orgId,
|
|
date: { gte: monthStart, lte: monthEnd },
|
|
}
|
|
if (typeFilter) where.type = typeFilter
|
|
|
|
const events = await prisma.calendarEvent.findMany({
|
|
where,
|
|
include: { employee: { select: { id: true, name: true } } },
|
|
orderBy: { date: 'asc' },
|
|
})
|
|
|
|
res.json({ success: true, data: events })
|
|
} catch (err) {
|
|
next(err)
|
|
}
|
|
})
|
|
|
|
// 获取事件详情
|
|
router.get('/:id', authMiddleware, async (req: AuthRequest, res: Response, next: NextFunction) => {
|
|
try {
|
|
const event = await prisma.calendarEvent.findFirst({
|
|
where: { id: req.params.id, orgId: req.user!.orgId },
|
|
include: { employee: { select: { id: true, name: true } } },
|
|
})
|
|
if (!event) return res.status(404).json({ success: false, message: '事件不存在' })
|
|
res.json({ success: true, data: event })
|
|
} catch (err) {
|
|
next(err)
|
|
}
|
|
})
|
|
|
|
// 创建日历事件
|
|
router.post('/', authMiddleware, async (req: AuthRequest, res: Response, next: NextFunction) => {
|
|
try {
|
|
const data = createEventSchema.parse(req.body)
|
|
const event = await prisma.calendarEvent.create({
|
|
data: {
|
|
orgId: req.user!.orgId,
|
|
title: data.title,
|
|
date: new Date(data.date),
|
|
endDate: data.endDate ? new Date(data.endDate) : null,
|
|
type: data.type,
|
|
priority: data.priority,
|
|
location: data.location || null,
|
|
description: data.description || null,
|
|
employeeId: data.employeeId || null,
|
|
createdBy: req.user!.id,
|
|
},
|
|
})
|
|
res.json({ success: true, data: event })
|
|
} catch (err) {
|
|
next(err)
|
|
}
|
|
})
|
|
|
|
// 更新日历事件
|
|
router.patch('/:id', authMiddleware, async (req: AuthRequest, res: Response, next: NextFunction) => {
|
|
try {
|
|
const updateSchema = createEventSchema.partial()
|
|
const data = updateSchema.parse(req.body)
|
|
const updateData: any = { ...data }
|
|
if (data.date) updateData.date = new Date(data.date)
|
|
if (data.endDate) updateData.endDate = new Date(data.endDate)
|
|
if (data.endDate === undefined) delete updateData.endDate
|
|
|
|
const event = await prisma.calendarEvent.updateMany({
|
|
where: { id: req.params.id, orgId: req.user!.orgId },
|
|
data: updateData,
|
|
})
|
|
if (event.count === 0) return res.status(404).json({ success: false, message: '事件不存在' })
|
|
res.json({ success: true })
|
|
} catch (err) {
|
|
next(err)
|
|
}
|
|
})
|
|
|
|
// 删除日历事件
|
|
router.delete('/:id', authMiddleware, async (req: AuthRequest, res: Response, next: NextFunction) => {
|
|
try {
|
|
const result = await prisma.calendarEvent.deleteMany({
|
|
where: { id: req.params.id, orgId: req.user!.orgId },
|
|
})
|
|
if (result.count === 0) return res.status(404).json({ success: false, message: '事件不存在' })
|
|
res.json({ success: true })
|
|
} catch (err) {
|
|
next(err)
|
|
}
|
|
})
|
|
|
|
export default router
|