feat: 发薪批次表格动态化 - 根据薪酬模板动态生成列
- schema: BatchEntry 增加 extraItems Json 字段存储自定义模板项 - calcBatchEntry: 新增 extraItems 参数,合并自定义 INPUT 项取值 - 后端编辑接口: 动态校验自定义字段,预置字段走固定列,自定义走 extraItems - 所有 calcBatchEntry 调用处传入并写回 extraItems - 前端表头/单元格从 templateItems 动态生成,排除 netPay 重复列 - 前端 saveEdit 动态化: 预置字段走固定列,自定义字段走 extraItems - renderCell 支持从 extraItems 取值 - 表格列左右锁定: 员工/合同类型左锁,实发/递延/风险/操作右锁 - 合理列宽 + 横向滚动 + hover 效果
This commit is contained in:
@@ -401,9 +401,10 @@ export async function calcBatchEntry(
|
||||
orgId: string,
|
||||
employeeId: string,
|
||||
month: string,
|
||||
inputs: { baseSalary: number; overtimePay: number; allowance: number; deduction: number; bonus: number; positionSalary?: number; performanceSalary?: number; senioritySalary?: number; transportAllowance?: number; mealAllowance?: number; housingAllowance?: number; communicationAllowance?: number; otherDeduction?: number },
|
||||
inputs: { baseSalary: number; overtimePay: number; allowance: number; deduction: number; bonus: number; positionSalary?: number; performanceSalary?: number; senioritySalary?: number; transportAllowance?: number; mealAllowance?: number; housingAllowance?: number; communicationAllowance?: number; otherDeduction?: number; [key: string]: any },
|
||||
batchType: string = 'REGULAR',
|
||||
options?: { skipSocial?: boolean; overrideSocial?: { socialEmp?: number; socialOrg?: number; housingEmp?: number; housingOrg?: number }; prevDeferred?: { socialEmp?: number; housingEmp?: number; minWage?: number } },
|
||||
extraItems?: Record<string, number> | null,
|
||||
) {
|
||||
const employee = await prisma.employee.findFirst({
|
||||
where: { id: employeeId, orgId },
|
||||
@@ -469,10 +470,10 @@ export async function calcBatchEntry(
|
||||
_socialCalculated: false,
|
||||
}
|
||||
|
||||
// 1. 初始化输入项
|
||||
// 1. 初始化输入项:先从固定列 inputs 取,再从 extraItems 补充自定义项
|
||||
for (const item of templateItems) {
|
||||
if (item.type === 'INPUT') {
|
||||
ctx.values[item.code] = (inputs as any)[item.code] || 0
|
||||
ctx.values[item.code] = (inputs as any)[item.code] ?? (extraItems?.[item.code] ?? 0)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -601,6 +602,15 @@ export async function calcBatchEntry(
|
||||
}
|
||||
}
|
||||
|
||||
// 提取非预置项的计算结果到 extraItems
|
||||
const presetCodes = new Set(DEFAULT_ITEMS.map(i => i.code))
|
||||
const resultExtraItems: Record<string, number> = {}
|
||||
for (const item of templateItems) {
|
||||
if (!presetCodes.has(item.code) && ctx.values[item.code] !== undefined) {
|
||||
resultExtraItems[item.code] = Math.round((ctx.values[item.code] || 0) * 100) / 100
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
socialEmp: Math.round(socialEmp * 100) / 100,
|
||||
socialOrg: Math.round(socialOrg * 100) / 100,
|
||||
@@ -627,6 +637,7 @@ export async function calcBatchEntry(
|
||||
prevDeferredSocialEmp: options?.prevDeferred?.socialEmp || 0,
|
||||
prevDeferredHousingEmp: options?.prevDeferred?.housingEmp || 0,
|
||||
prevDeferredMinWage,
|
||||
extraItems: resultExtraItems,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user