feat: P2+P3 薪酬模板驱动计算 - SYSTEM注册表 + 前端动态化

P2: 社保/公积金/个税改为 SYSTEM 注册表驱动
- 新增 SystemCalcContext 和 systemCalculators 注册表
- ensureSocialHousingCalculated 缓存社保公积金计算
- calcTaxSystem 提取个税计算为系统函数
- calcBatchEntry 重构为模板拓扑排序调度

P3: 前端批次表格动态化 + 模板编辑器增强
- 后端模板 CRUD 支持 calcType/dependencies 字段
- TemplateTab 表格增加计算方式列
- TemplateTab 编辑表单增加 calcType 选择(公式/系统)
- BatchTab editableFields 从模板 isEditable 动态获取
This commit is contained in:
freedakgmail
2026-08-19 08:32:57 +08:00
parent 8bcf1460cf
commit 60951e7fd6
4 changed files with 302 additions and 197 deletions
+20 -4
View File
@@ -497,6 +497,13 @@ function BatchDetail({ batchId, onBack }: { batchId: string; onBack: () => void
},
})
const { data: templateItems } = useQuery<any[]>({
queryKey: ['payslip-template'],
queryFn: async () => {
return await payrollApi.template()
},
})
const updateEntryMutation = useMutation({
mutationFn: ({ employeeId, data }: { employeeId: string; data: any }) =>
payrollApi.updateBatchEntry(batchId, employeeId, data),
@@ -729,10 +736,19 @@ function BatchDetail({ batchId, onBack }: { batchId: string; onBack: () => void
}
}
// 可编辑的输入项字段
const editableFields = isBonus
? ['bonus']
: ['baseSalary', 'performanceSalary', 'overtimePay', 'allowance', 'deduction', 'bonus', 'socialEmp', 'housingEmp', 'socialOrg', 'housingOrg']
// 可编辑的输入项字段:从模板动态获取,回退到硬编码
const editableFields = (() => {
if (templateItems && templateItems.length > 0) {
const editable = templateItems.filter((i: any) => i.isEditable).map((i: any) => i.code)
// 奖金批次只允许编辑 bonus
if (isBonus) return ['bonus']
// 社保/公积金允许手动覆盖
return [...editable, 'socialEmp', 'housingEmp', 'socialOrg', 'housingOrg']
}
return isBonus
? ['bonus']
: ['baseSalary', 'performanceSalary', 'overtimePay', 'allowance', 'deduction', 'bonus', 'socialEmp', 'housingEmp', 'socialOrg', 'housingOrg']
})()
// 点击单元格进入编辑
const startEdit = (employeeId: string, field: string, currentValue: number) => {