feat: 社保公积金版本管理 + 员工基数调整 + 加班费计算优化 + UI组件改进

- SocialInsuranceConfig 版本化(effectiveFrom/effectiveTo/isCurrent/adjustmentDone)
- 社保配置版本管理接口(列表/新建/按月获取/当前版本)
- 员工基数调整:预览全部在职员工、上年月均工资计算建议基数、可编辑表格、确认后批量保存
- payroll.service 按批次月份匹配对应版本社保配置
- risk.service / seed.ts 同步更新
- 前端社保tab重构为版本管理+调整+试算
- 加班费计算三步流程、CSV导入、批次导入
- UI组件、Dashboard、合同、薪酬等页面优化
This commit is contained in:
freedakgmail
2026-07-23 16:32:46 +08:00
parent 2a09d31ccc
commit c618710a52
31 changed files with 2245 additions and 745 deletions
@@ -48,7 +48,7 @@ export default function ContractConfirm() {
<div className="min-h-screen flex items-center justify-center bg-gray-50 px-4">
<div className="max-w-sm w-full text-center">
<Check className="w-16 h-16 text-safe mx-auto mb-4" />
<h1 className="text-lg font-semibold mb-2"></h1>
<h1 className="text-sm font-semibold mb-2"></h1>
<p className="text-sm text-gray-500"> IP </p>
</div>
</div>
@@ -60,7 +60,7 @@ export default function ContractConfirm() {
<div className="max-w-md mx-auto">
<div className="flex items-center gap-2 mb-6">
<PenTool className="w-6 h-6 text-primary" />
<h1 className="text-lg font-semibold"></h1>
<h1 className="text-sm font-semibold"></h1>
</div>
{loading ? (
@@ -74,7 +74,7 @@ export default function ContractConfirm() {
</Card>
) : data ? (
<Card>
<div className="space-y-4">
<div className="space-y-3">
<div className="text-sm text-gray-600">
{data.orgName} {data.employeeName}
</div>
+2 -2
View File
@@ -37,7 +37,7 @@ export default function MyContract() {
<div className="flex items-center justify-between mb-6">
<div className="flex items-center gap-2">
<FileText className="w-6 h-6 text-primary" />
<h1 className="text-lg font-semibold"></h1>
<h1 className="text-sm font-semibold"></h1>
</div>
<div className="flex items-center gap-3">
<span className="text-sm text-gray-500">{employee.name}</span>
@@ -51,7 +51,7 @@ export default function MyContract() {
) : !contract ? (
<EmptyState title="暂无合同" description="HR 尚未录入您的合同信息" />
) : (
<div className="space-y-4">
<div className="space-y-3">
{/* 到期提醒 */}
{daysToExpire !== null && daysToExpire <= 30 && daysToExpire >= 0 && (
<div className="flex items-center gap-2 px-3 py-2 rounded-md bg-yellow-50 text-yellow-700 text-sm">
+3 -3
View File
@@ -53,7 +53,7 @@ export default function Onboarding() {
<div className="min-h-screen flex items-center justify-center bg-gray-50 px-4">
<div className="max-w-sm w-full text-center">
<Check className="w-16 h-16 text-safe mx-auto mb-4" />
<h1 className="text-lg font-semibold mb-2"></h1>
<h1 className="text-sm font-semibold mb-2"></h1>
<p className="text-sm text-gray-500">HR </p>
</div>
</div>
@@ -65,7 +65,7 @@ export default function Onboarding() {
<div className="max-w-md mx-auto">
<div className="flex items-center gap-2 mb-6">
<ClipboardList className="w-6 h-6 text-primary" />
<h1 className="text-lg font-semibold"></h1>
<h1 className="text-sm font-semibold"></h1>
</div>
{orgName && (
@@ -79,7 +79,7 @@ export default function Onboarding() {
)}
<Card>
<div className="space-y-4">
<div className="space-y-3">
<div>
<Label> *</Label>
<Input value={form.name} onChange={(e) => setForm({ ...form, name: e.target.value })} placeholder="请输入姓名" />
+2 -2
View File
@@ -42,7 +42,7 @@ export default function Payslip() {
<div className="flex items-center justify-between mb-6">
<div className="flex items-center gap-2">
<DollarSign className="w-6 h-6 text-primary" />
<h1 className="text-lg font-semibold"></h1>
<h1 className="text-sm font-semibold"></h1>
</div>
<div className="flex items-center gap-3">
<span className="text-sm text-gray-500">{employee.name}</span>
@@ -93,7 +93,7 @@ export default function Payslip() {
<div className="border-t pt-3">
<div className="flex justify-between">
<span className="font-medium"></span>
<span className="text-xl font-bold text-primary">¥{fmt(Number(data.totalPay))}</span>
<span className="text-base font-bold text-primary">¥{fmt(Number(data.totalPay))}</span>
</div>
</div>
+3 -3
View File
@@ -64,7 +64,7 @@ export default function PortalLogin() {
<div className="w-full max-w-sm">
<div className="flex items-center justify-center gap-2 mb-8">
<Building2 className="w-8 h-8 text-primary" />
<span className="text-xl font-bold"> </span>
<span className="text-base font-bold"> </span>
</div>
<div className="card">
@@ -82,7 +82,7 @@ export default function PortalLogin() {
{error && <div className="mb-4 px-3 py-2 rounded-md bg-red-50 text-red-700 text-sm">{error}</div>}
{mode === 'password' ? (
<div className="space-y-4">
<div className="space-y-3">
<div>
<Label></Label>
<Input type="tel" placeholder="请输入手机号" value={phone} onChange={(e) => setPhone(e.target.value)} maxLength={11} />
@@ -96,7 +96,7 @@ export default function PortalLogin() {
</Button>
</div>
) : (
<div className="space-y-4">
<div className="space-y-3">
<div>
<Label></Label>
<Input type="tel" placeholder="请输入手机号" value={phone} onChange={(e) => setPhone(e.target.value)} maxLength={11} />