feat: 工作日历/考勤管理重构/AI人力报告/工作台员工分布/筛选优化/导入导出增强

- 新增工作日历页面(月历视图、事件管理、自定义事件)
- 考勤管理重构为6 Tab模块(班次/排班/每日出勤/月度报表/休假记录)
- AI顾问新增人力报告Tab,支持流式生成+Word导出
- 工作台总览新增员工分布统计(性别/年龄/学历/司龄饼图)+部门成本拆分
- 花名册/合同/解聘补偿新增部门和状态筛选
- 薪税管理新增工资表导入模板下载、银行代发CSV导出
- 社保公积金支持多公积金账户类型显示
- 数据导出新增花名册/解聘记录导出,中文文件名编码修复
- 数据导入新增模板下载(员工/增减员/工资表)+错误日志导出
- 移除工作台日历卡片(已迁移至独立工作日历页面)
- 新增20260728/20260729更新测试指导文档
This commit is contained in:
freedakgmail
2026-07-29 08:35:29 +08:00
parent d020d04a8a
commit fb36b10402
45 changed files with 3756 additions and 169 deletions
+126 -1
View File
@@ -166,6 +166,11 @@ model Organization {
healthCheckReports HealthCheckReport[]
annualValueReports AnnualValueReport[]
specialDeductionRecords SpecialDeductionRecord[]
shifts Shift[]
shiftAssignments ShiftAssignment[]
leaveRecords LeaveRecord[]
calendarEvents CalendarEvent[]
consultations Consultation[]
}
model User {
@@ -216,6 +221,7 @@ model Employee {
specialDeduction Float @default(0) // 专项附加扣除(子女教育、赡养老人等,员工portal端填报)
city String? // 员工社保参保城市
birthDate DateTime? // 出生日期(从身份证号提取)
education String? // 学历(博士/硕士/本科/大专/高中/其他)
femaleWorkerType FemaleWorkerType? // 女性岗位类型(CADRE=干部/WORKER=工人,仅女性需要区分)
retirementDaysLeft Int? // 距退休天数(便捷字段,定期计算)
createdBy String
@@ -242,6 +248,9 @@ model Employee {
attendanceConfirmations AttendanceConfirmation[]
policyReadRecords PolicyReadRecord[]
specialDeductionRecords SpecialDeductionRecord[]
shiftAssignments ShiftAssignment[]
leaveRecords LeaveRecord[]
calendarEvents CalendarEvent[]
@@unique([orgId, idCardHash])
}
@@ -410,6 +419,7 @@ model HousingFundConfig {
orgId String
org Organization @relation(fields: [orgId], references: [id], onDelete: Cascade)
city String @default("北京")
accountType String @default("BASIC") // BASIC=基本公积金, SUPPLEMENTARY=补充公积金
housingOrg Float @default(12) // 公积金 企业比例 %
housingEmp Float @default(12) // 公积金 个人比例 %
baseMin Float @default(6326) // 公积金缴费基数下限
@@ -422,7 +432,7 @@ model HousingFundConfig {
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@unique([orgId, city, effectiveFrom])
@@unique([orgId, city, accountType, effectiveFrom])
@@index([orgId, isCurrent])
}
@@ -668,6 +678,15 @@ model BatchEntry {
allowance Float @default(0)
deduction Float @default(0)
bonus Float @default(0)
// 细化薪资项
positionSalary Float @default(0) // 岗位工资
performanceSalary Float @default(0) // 绩效工资
senioritySalary Float @default(0) // 工龄工资
transportAllowance Float @default(0) // 交通补贴
mealAllowance Float @default(0) // 餐补
housingAllowance Float @default(0) // 住房补贴
communicationAllowance Float @default(0) // 通讯补贴
otherDeduction Float @default(0) // 其他扣款
// 自动计算项
socialEmp Float @default(0)
socialOrg Float @default(0)
@@ -1045,3 +1064,109 @@ model SpecialDeductionRecord {
@@unique([employeeId, month])
@@index([orgId, month])
}
// ========== 班次管理 ==========
model Shift {
id String @id @default(cuid())
orgId String
org Organization @relation(fields: [orgId], references: [id], onDelete: Cascade)
name String // 班次名称,如"早班"、"白班"、"夜班"
startTime String // 上班时间 HH:mm
endTime String // 下班时间 HH:mm
flexibleMinutes Int @default(0) // 弹性时长(分钟)
restMinutes Int @default(0) // 休息时长(分钟)
color String @default("#3b82f6") // 日历显示颜色
createdBy String
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
assignments ShiftAssignment[]
@@index([orgId])
}
// ========== 排班记录 ==========
model ShiftAssignment {
id String @id @default(cuid())
orgId String
org Organization @relation(fields: [orgId], references: [id], onDelete: Cascade)
employeeId String
employee Employee @relation(fields: [employeeId], references: [id], onDelete: Cascade)
shiftId String
shift Shift @relation(fields: [shiftId], references: [id], onDelete: Cascade)
date DateTime // 排班日期
createdBy String
createdAt DateTime @default(now())
@@unique([employeeId, date])
@@index([orgId, date])
@@index([orgId, employeeId])
}
// ========== 休假记录(直接记录,无审批流程) ==========
model LeaveRecord {
id String @id @default(cuid())
orgId String
org Organization @relation(fields: [orgId], references: [id], onDelete: Cascade)
employeeId String
employee Employee @relation(fields: [employeeId], references: [id], onDelete: Cascade)
leaveType String // SICK=病假 / PERSONAL=事假 / ANNUAL=年假 / MATERNITY=产假 / OTHER=其他
startDate DateTime
endDate DateTime
days Float // 请假天数
reason String?
remark String?
createdBy String
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@index([orgId, employeeId])
@@index([orgId, startDate])
}
// ========== 自定义日历事件 ==========
model CalendarEvent {
id String @id @default(cuid())
orgId String
org Organization @relation(fields: [orgId], references: [id], onDelete: Cascade)
title String
date DateTime
endDate DateTime?
type String @default("CUSTOM") // CUSTOM=自定义, MEETING=会议, TEAM_BUILDING=团建, TRAINING=培训, INTERVIEW=面试
priority String @default("medium") // high/medium/low
location String?
description String?
employeeId String?
employee Employee? @relation(fields: [employeeId], references: [id], onDelete: SetNull)
createdBy String
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@index([orgId, date])
@@index([orgId, type])
}
// ========== 人工咨询服务 ==========
model Consultation {
id String @id @default(cuid())
orgId String
org Organization @relation(fields: [orgId], references: [id], onDelete: Cascade)
type String // LEGAL=法律咨询, ARBITRATION=仲裁代理, COURT=出庭服务
title String
description String
contactName String
contactPhone String
status String @default("PENDING") // PENDING=待处理, CONTACTED=已联系, COMPLETED=已完成, CANCELLED=已取消
aiConversationId String? // 关联 AI 会话
remark String?
createdBy String
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@index([orgId, status])
@@index([orgId, type])
}