import { useState } from "react" import { useNavigate } from "react-router-dom" import { toast } from "sonner" import { useMutation, useQueryClient } from "@tanstack/react-query" import { socialInsuranceApi } from '../../lib/api-services' import Card from "../../components/ui/Card" import Button from "../../components/ui/Button" import { Input, Label, Select } from "../../components/ui/Input" import Modal from "../../components/ui/Modal" import { fmt } from "./shared" import { ExternalLink } from "lucide-react" /** 薪酬社保合并组件(工资条 / 缴纳记录) */ export default function PayslipSocialInfo({ payslips, monthlyProcessRecords, employeeId }: { payslips: any[]; socialInsRecords: any[]; housingFundRecords: any[]; monthlyProcessRecords: any[]; employeeId?: string }) { const [subTab, setSubTab] = useState<'payslip' | 'monthly'>('payslip') const navigate = useNavigate() return (
{employeeId && ( )}
{subTab === 'payslip' && ( <> {!payslips?.length ? (
暂无工资条记录
) : ( {payslips.map((p) => ( ))}
月份 基本工资 加班费 津贴 扣款 应发合计 确认状态
{p.month} ¥{fmt(p.baseSalary)} {p.overtimePay > 0 ? `¥${fmt(p.overtimePay)}` : '-'} {p.allowance > 0 ? `¥${fmt(p.allowance)}` : '-'} {p.deduction > 0 ? `-¥${fmt(p.deduction)}` : '-'} ¥{fmt(p.totalPay)} {p.confirmedAt ? ( 已确认 ) : ( 未确认 )}
合计 ¥{fmt(payslips.reduce((s, p) => s + (p.baseSalary || 0), 0))} {payslips.reduce((s, p) => s + (p.overtimePay || 0), 0) > 0 ? `¥${fmt(payslips.reduce((s, p) => s + (p.overtimePay || 0), 0))}` : '-'} {payslips.reduce((s, p) => s + (p.allowance || 0), 0) > 0 ? `¥${fmt(payslips.reduce((s, p) => s + (p.allowance || 0), 0))}` : '-'} {payslips.reduce((s, p) => s + (p.deduction || 0), 0) > 0 ? `-¥${fmt(payslips.reduce((s, p) => s + (p.deduction || 0), 0))}` : '-'} ¥{fmt(payslips.reduce((s, p) => s + (p.totalPay || 0), 0))}
)} )} {subTab === 'monthly' && ( <> {!monthlyProcessRecords?.length ? (
暂无缴纳记录
) : ( {monthlyProcessRecords.map((r, idx) => { const d = r.detail const isSocial = r.type === 'SOCIAL' const orgAmt = isSocial ? d?.totalOrg : d?.orgAmount const empAmt = isSocial ? d?.totalEmp : d?.empAmount const total = isSocial ? d?.total : d?.total return ( ) })}
办理月份 类型 城市 状态 缴费基数 企业部分 个人部分 合计 变动 办理时间
{r.month} {isSocial ? '社保' : '公积金'} {r.city || '-'} 已缴纳 ¥{fmt(r.base)} {orgAmt != null ? `¥${fmt(orgAmt)}` : '-'} {empAmt != null ? `¥${fmt(empAmt)}` : '-'} {total != null ? `¥${fmt(total)}` : '-'} {r.changeType} {new Date(r.processedAt).toLocaleString('zh-CN')}
)} )}
) } /** 参保城市变更历史组件(含修正功能) */ export function CityHistoryTab({ socialInsRecords, housingFundRecords, changeTypeMap, changeTypeColor }: { socialInsRecords: any[]; housingFundRecords: any[]; changeTypeMap: Record; changeTypeColor: Record }) { const queryClient = useQueryClient() const [editing, setEditing] = useState(null) const [correctForm, setCorrectForm] = useState({ city: '', base: '', startMonth: '', endMonth: '', changeType: '', remark: '', reason: '' }) const correctMutation = useMutation({ mutationFn: async (data: any) => { const cat = editing.cat const type = cat === '社保' ? 'social' : 'housing' return await socialInsuranceApi.correctRecord(type, editing.id, data) }, onSuccess: () => { toast.success('记录已修正') queryClient.invalidateQueries({ queryKey: ['roster-profile'] }) setEditing(null) }, onError: () => toast.error('修正失败'), }) const handleCorrect = () => { correctMutation.mutate({ city: correctForm.city || undefined, base: correctForm.base ? Number(correctForm.base) : undefined, startMonth: correctForm.startMonth || undefined, endMonth: correctForm.endMonth || undefined, changeType: correctForm.changeType || undefined, remark: correctForm.remark || undefined, reason: correctForm.reason || '数据修正', }) } const openCorrect = (r: any) => { setEditing(r) setCorrectForm({ city: r.city || '', base: String(r.base || ''), startMonth: r.startMonth || '', endMonth: r.endMonth || '', changeType: r.changeType || '', remark: r.remark || '', reason: '', }) } const allRecords = [ ...(socialInsRecords || []).map((r: any) => ({ ...r, cat: '社保' })), ...(housingFundRecords || []).map((r: any) => ({ ...r, cat: '公积金' })), ].sort((a, b) => b.startMonth.localeCompare(a.startMonth)) if (!allRecords.length) return
暂无参保记录
return ( <>
参保城市变更历史(社保 + 公积金记录按时间倒序,点击「修正」可直接修改错误数据并记录审计日志)
{allRecords.map((r, idx) => ( ))}
开始年月 截止年月 类型 参保城市 缴费基数 变动类型 备注 操作
{r.startMonth} {r.endMonth || '至今'} {r.cat} {r.city || '-'} ¥{fmt(r.base)} {changeTypeMap[r.changeType] || r.changeType} {r.remark || '-'}
{editing && ( setEditing(null)} title={`修正${editing.cat}记录`}>
此操作将直接修改记录并写入审计日志(记录修改前后的值和修正原因),不会创建新记录。
setCorrectForm({ ...correctForm, city: e.target.value })} placeholder="如 北京" />
setCorrectForm({ ...correctForm, base: e.target.value })} />
setCorrectForm({ ...correctForm, startMonth: e.target.value })} />
setCorrectForm({ ...correctForm, endMonth: e.target.value })} placeholder="留空=至今" />
setCorrectForm({ ...correctForm, remark: e.target.value })} />
setCorrectForm({ ...correctForm, reason: e.target.value })} placeholder="如:城市录入错误" />
)} ) }