diff --git a/frontend/src/pages/money/BatchTab.tsx b/frontend/src/pages/money/BatchTab.tsx index 93eb967..199cd2e 100644 --- a/frontend/src/pages/money/BatchTab.tsx +++ b/frontend/src/pages/money/BatchTab.tsx @@ -753,6 +753,19 @@ function BatchDetail({ batchId, onBack }: { batchId: string; onBack: () => void // 预置字段集合(固定列存储) const PRESET_FIELDS = new Set(['baseSalary', 'performanceSalary', 'overtimePay', 'allowance', 'deduction', 'bonus', 'socialEmp', 'socialOrg', 'housingEmp', 'housingOrg', 'positionSalary', 'senioritySalary', 'transportAllowance', 'mealAllowance', 'housingAllowance', 'communicationAllowance', 'otherDeduction']) + // 表格列宽计算(table-layout: fixed 需要精确宽度) + const COL_W = { employee: 140, contract: 100, dynamic: 90, netPay: 110, deferred: 110, risk: 50, action: 60 } + const dynamicCols = (templateItems || []).filter((t: any) => (!isBonus || t.code === 'bonus') && t.code !== 'netPay') + const rightLockedWidth = COL_W.netPay + COL_W.deferred + COL_W.risk + (isArchived ? 0 : COL_W.action) + const tableMinWidth = COL_W.employee + COL_W.contract + dynamicCols.length * COL_W.dynamic + rightLockedWidth + // 右侧锁定列偏移量(从右到左累加) + const rightOffsets = { + action: 0, + risk: isArchived ? 0 : COL_W.action, + deferred: isArchived ? COL_W.risk : COL_W.action + COL_W.risk, + netPay: isArchived ? COL_W.risk + COL_W.deferred : COL_W.action + COL_W.risk + COL_W.deferred, + } + // 点击单元格进入编辑 const startEdit = (employeeId: string, field: string, currentValue: number) => { if (isArchived || !editableFields.includes(field)) return @@ -1235,27 +1248,27 @@ function BatchDetail({ batchId, onBack }: { batchId: string; onBack: () => void {/* 人员表格 */}
- +
- - + + {/* 动态生成模板项列(排除 netPay,由固定实发列显示) */} - {(templateItems || []).filter((t: any) => (!isBonus || t.code === 'bonus') && t.code !== 'netPay').map((t: any) => ( - ))} - - - - {!isArchived && } + + + + {!isArchived && } {batch.entries.slice((page - 1) * pageSize, page * pageSize).map((entry: any) => ( - - {/* 动态生成模板项单元格(排除 netPay) */} - {(templateItems || []).filter((t: any) => (!isBonus || t.code === 'bonus') && t.code !== 'netPay').map((t: any) => { + {dynamicCols.map((t: any) => { // 绩效工资:保留特殊渲染(显示绩效等级) if (t.code === 'performanceSalary') { const perfVal = entry.performanceSalary || 0 @@ -1354,12 +1367,12 @@ function BatchDetail({ batchId, onBack }: { batchId: string; onBack: () => void return renderCell(entry, t.code, t.type === 'CALCULATED' ? 'font-medium text-gray-600' : '') })} {/* 实发:最低工资保护触发时高亮显示 */} - {/* 递延扣款明细 */} - - {!isArchived && ( -
员工合同类型员工合同类型 + {dynamicCols.map((t: any) => ( + {t.name} 实发递延扣款风险操作实发递延扣款风险操作
+
{entry.employee.name}
{entry.employee.idCardNumber && {entry.employee.idCardNumber}} @@ -1265,7 +1278,7 @@ function BatchDetail({ batchId, onBack }: { batchId: string; onBack: () => void )}
+ {(() => { const ct = entry.employee.contracts?.[0]?.contractType const cfg: Record = { @@ -1289,7 +1302,7 @@ function BatchDetail({ batchId, onBack }: { batchId: string; onBack: () => void })()} 0 ? 'text-amber-600' : 'text-safe'}`} style={{ width: 110, right: isArchived ? 160 : 210 }} title={(entry.minWageApplied || 0) > 0 ? `最低工资保护已触发\n应发 ¥${fmt(entry.totalPay)} → 实发补齐到 ¥${fmt(entry.minWage)}\n免扣社保 ¥${fmt(entry.deferredSocialEmp || 0)} + 免扣公积金 ¥${fmt(entry.deferredHousingEmp || 0)} + 额外补齐 ¥${fmt(entry.deferredMinWage || 0)} = 递延 ¥${fmt((entry.deferredSocialEmp || 0) + (entry.deferredHousingEmp || 0) + (entry.deferredMinWage || 0))}(次月补扣)` : ''}> + 0 ? 'text-amber-600' : 'text-safe'}`} style={{ width: COL_W.netPay, right: rightOffsets.netPay }} title={(entry.minWageApplied || 0) > 0 ? `最低工资保护已触发\n应发 ¥${fmt(entry.totalPay)} → 实发补齐到 ¥${fmt(entry.minWage)}\n免扣社保 ¥${fmt(entry.deferredSocialEmp || 0)} + 免扣公积金 ¥${fmt(entry.deferredHousingEmp || 0)} + 额外补齐 ¥${fmt(entry.deferredMinWage || 0)} = 递延 ¥${fmt((entry.deferredSocialEmp || 0) + (entry.deferredHousingEmp || 0) + (entry.deferredMinWage || 0))}(次月补扣)` : ''}> {fmt(entry.netPay)} {(entry.minWageApplied || 0) > 0 && } + {(() => { const deferred = (entry.deferredSocialEmp || 0) + (entry.deferredHousingEmp || 0) + (entry.deferredMinWage || 0) const prevDeferred = (entry.prevDeferredSocialEmp || 0) + (entry.prevDeferredHousingEmp || 0) + (entry.prevDeferredMinWage || 0) @@ -1372,7 +1385,7 @@ function BatchDetail({ batchId, onBack }: { batchId: string; onBack: () => void return })()} + {entry.riskWarnings && entry.riskWarnings.length > 0 ? ( @@ -1386,7 +1399,7 @@ function BatchDetail({ batchId, onBack }: { batchId: string; onBack: () => void )} +