ui: 月度办理社保公积金区域改为可折叠卡片,添加统计摘要

This commit is contained in:
freedakgmail
2026-08-18 07:25:13 +08:00
parent 66ae5ff21f
commit b8e2ebe5ee
+53 -8
View File
@@ -2,7 +2,7 @@ import { useState, useEffect } from 'react'
import { useSearchParams } from 'react-router-dom' import { useSearchParams } from 'react-router-dom'
import { toast } from 'sonner' import { toast } from 'sonner'
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query' import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'
import { Calculator, Check, Plus, Download, AlertCircle, Clock } from 'lucide-react' import { Calculator, Check, Plus, Download, AlertCircle, Clock, ChevronDown, ChevronRight, Shield, Home } from 'lucide-react'
import { InlineAlert } from '../components/ui/InlineAlert' import { InlineAlert } from '../components/ui/InlineAlert'
import PageGuide from '../components/ui/PageGuide' import PageGuide from '../components/ui/PageGuide'
import { socialInsuranceApi, socialAccountApi } from '../lib/api-services' import { socialInsuranceApi, socialAccountApi } from '../lib/api-services'
@@ -460,14 +460,40 @@ export default function SocialInsurance() {
const sTable = renderSocialTable(city) const sTable = renderSocialTable(city)
const hTable = renderHousingTable(city) const hTable = renderHousingTable(city)
if (!sTable && !hTable) return null if (!sTable && !hTable) return null
const sAddCity = sAdd.filter((i: any) => i.city === city)
const sSubCity = sSub.filter((i: any) => i.city === city)
const sNormalCity = sNormal.filter((i: any) => i.city === city)
const hAddCity = hAdd.filter((i: any) => i.city === city)
const hSubCity = hSub.filter((i: any) => i.city === city)
const hNormalCity = hNormal.filter((i: any) => i.city === city)
const sTotal = [...sAddCity, ...sNormalCity].reduce((s: number, i: any) => s + (i.detail?.total || 0), 0)
const hTotal = [...hAddCity, ...hNormalCity].reduce((s: number, i: any) => s + (i.detail?.total || 0), 0)
return ( return (
<div key={city} className="border rounded-lg p-3"> <div key={city} className="border rounded-lg overflow-hidden">
<h3 className="text-sm font-medium mb-3 flex items-center gap-2"> <div className="bg-gray-50 px-4 py-2.5 flex items-center justify-between">
<span className="px-2 py-0.5 rounded bg-indigo-50 text-indigo-600 text-xs">{city}</span> <div className="flex items-center gap-2">
<span className="text-gray-400 text-xs">{city}/</span> <span className="px-2 py-0.5 rounded bg-indigo-50 text-indigo-600 text-xs font-medium">{city}</span>
</h3> <span className="text-gray-400 text-xs">{city}/</span>
{sTable && <div className="mb-3"><h4 className="text-xs font-medium text-gray-600 mb-1"></h4>{sTable}</div>} </div>
{hTable && <div><h4 className="text-xs font-medium text-gray-600 mb-1"></h4>{hTable}</div>} </div>
<div className="p-3 space-y-3">
<CollapsibleSection
title="社保"
icon={<Shield className="w-4 h-4 text-blue-500" />}
summary={`${sAddCity.length + sSubCity.length + sNormalCity.length} 人 | 企业 ¥${fmt([...sAddCity, ...sNormalCity].reduce((s: number, i: any) => s + (i.detail?.totalOrg || 0), 0))} + 个人 ¥${fmt([...sAddCity, ...sNormalCity].reduce((s: number, i: any) => s + (i.detail?.totalEmp || 0), 0))} = ¥${fmt(sTotal)}`}
defaultOpen={true}
>
{sTable}
</CollapsibleSection>
<CollapsibleSection
title="公积金"
icon={<Home className="w-4 h-4 text-green-500" />}
summary={`${hAddCity.length + hSubCity.length + hNormalCity.length} 人 | 企业 ¥${fmt([...hAddCity, ...hNormalCity].reduce((s: number, i: any) => s + (i.detail?.orgAmount || 0), 0))} + 个人 ¥${fmt([...hAddCity, ...hNormalCity].reduce((s: number, i: any) => s + (i.detail?.empAmount || 0), 0))} = ¥${fmt(hTotal)}`}
defaultOpen={true}
>
{hTable}
</CollapsibleSection>
</div>
</div> </div>
) )
})} })}
@@ -492,3 +518,22 @@ export default function SocialInsurance() {
) )
} }
function CollapsibleSection({ title, icon, summary, defaultOpen = false, children }: { title: string; icon: React.ReactNode; summary?: string; defaultOpen?: boolean; children: React.ReactNode }) {
const [open, setOpen] = useState(defaultOpen)
return (
<div className="border rounded-lg overflow-hidden">
<button
onClick={() => setOpen(!open)}
className="w-full flex items-center justify-between px-3 py-2 hover:bg-gray-50 transition-colors"
>
<div className="flex items-center gap-2">
{open ? <ChevronDown className="w-4 h-4 text-gray-400" /> : <ChevronRight className="w-4 h-4 text-gray-400" />}
{icon}
<span className="text-sm font-medium">{title}</span>
{summary && <span className="text-xs text-gray-400 ml-2">{summary}</span>}
</div>
</button>
{open && <div className="px-3 pb-3 pt-1">{children}</div>}
</div>
)
}