feat: 工作台合规评分优化、面包屑补全、花名册斑马纹
- 合规评分维度拆分:薪酬社保拆为薪酬工资+社保公积金两个独立维度 - 合同管理评分纳入待签署合同(signDate为null)扣分 - 维度评分hover显示得分依据findings和建议recommendations - 概览统计卡片支持点击跳转(在管员工/高风险/待办/工资条) - 面包屑补全10个缺失路由,统一分组名与侧边栏一致 - 移除子Tab中重复的PageGuide组件 - 花名册列表添加斑马纹隔行变色 - 薪酬结构模版表格列宽优化,计算公式列截断+title显示 Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
@@ -214,10 +214,10 @@ export default function Dashboard() {
|
||||
const yearCost = data.yearCostSummary
|
||||
|
||||
const stats = [
|
||||
{ label: '在管员工', value: data.stats.employeeCount, icon: Users, color: 'text-primary' },
|
||||
{ label: '高风险', value: data.stats.highRiskCount, icon: AlertTriangle, color: 'text-danger' },
|
||||
{ label: '待办事项', value: data.stats.todoCount, icon: CheckSquare, color: 'text-warning' },
|
||||
{ label: '工资条', value: payroll?.payslipCount ?? 0, icon: Receipt, color: 'text-safe' },
|
||||
{ label: '在管员工', value: data.stats.employeeCount, icon: Users, color: 'text-primary', to: '/roster' },
|
||||
{ label: '高风险', value: data.stats.highRiskCount, icon: AlertTriangle, color: 'text-danger', to: '/risk-center' },
|
||||
{ label: '待办事项', value: data.stats.todoCount, icon: CheckSquare, color: 'text-warning', to: '', tab: 'risk' as const },
|
||||
{ label: '工资条', value: payroll?.payslipCount ?? 0, icon: Receipt, color: 'text-safe', to: '/money' },
|
||||
]
|
||||
|
||||
// 当月人力成本
|
||||
@@ -385,16 +385,13 @@ export default function Dashboard() {
|
||||
{/* 概览 Tab */}
|
||||
{activeTab === 'overview' && (
|
||||
<div className="space-y-3">
|
||||
<PageGuide>
|
||||
概览页展示企业人力全局数据:在管员工数、待办事项、当月人力成本及年度累计成本。可点击各统计卡片快速跳转到对应详情页。右上角可自定义显示/隐藏模块。
|
||||
</PageGuide>
|
||||
{/* 统计卡片 */}
|
||||
{isSectionVisible('overview_stats') && (
|
||||
<div className="grid grid-cols-2 md:grid-cols-4 gap-2">
|
||||
{stats.map((stat) => {
|
||||
const Icon = stat.icon
|
||||
return (
|
||||
<Card key={stat.label} className="flex items-center gap-2.5">
|
||||
const inner = (
|
||||
<Card key={stat.label} className="flex items-center gap-2.5 hover:shadow-md transition-shadow cursor-pointer">
|
||||
<Icon className={`w-6 h-6 ${stat.color}`} />
|
||||
<div>
|
||||
<div className="text-base font-bold">{stat.value}</div>
|
||||
@@ -402,6 +399,10 @@ export default function Dashboard() {
|
||||
</div>
|
||||
</Card>
|
||||
)
|
||||
if (stat.tab) {
|
||||
return <div key={stat.label} onClick={() => setActiveTab(stat.tab)}>{inner}</div>
|
||||
}
|
||||
return <Link key={stat.label} to={stat.to}>{inner}</Link>
|
||||
})}
|
||||
</div>
|
||||
)}
|
||||
@@ -428,18 +429,46 @@ export default function Dashboard() {
|
||||
</ResponsiveContainer>
|
||||
<div className="absolute inset-0 flex flex-col items-center justify-center px-2 overflow-hidden">
|
||||
<span className={`text-2xl font-bold leading-none ${complianceScore?.level === 'safe' ? 'text-safe' : complianceScore?.level === 'warning' ? 'text-warning' : 'text-danger'}`}>{complianceScore?.overallScore ?? complianceScore?.totalScore ?? 0}</span>
|
||||
<span className="text-xs text-gray-500 mt-1 truncate max-w-full">{complianceScore?.levelLabel ?? ''}</span>
|
||||
<span className="text-xs text-gray-500 mt-1 truncate max-w-full">{complianceScore?.levelLabel ?? complianceScore?.summary ?? ''}</span>
|
||||
</div>
|
||||
</div>
|
||||
{/* 维度评分 */}
|
||||
<div className="flex-1 grid grid-cols-2 sm:grid-cols-3 lg:grid-cols-6 gap-2">
|
||||
{complianceScore?.dimensions?.map((dim: any) => (
|
||||
<Link key={dim.key} to={dim.key === 'contract' ? '/roster' : dim.key === 'policy' ? '/policies' : dim.key === 'attendance' ? '/attendance' : dim.key === 'salary' ? '/money' : '/social'} className="flex flex-col items-center p-1.5 rounded-lg hover:bg-gray-50 transition-colors">
|
||||
<span className={`text-lg font-bold ${dim.score >= 85 ? 'text-safe' : dim.score >= 60 ? 'text-warning' : 'text-danger'}`}>{dim.score}</span>
|
||||
<span className="text-xs text-gray-600">{dim.name}</span>
|
||||
{dim.todoCount > 0 && <span className="text-[10px] text-gray-400">{dim.todoCount}待办</span>}
|
||||
</Link>
|
||||
))}
|
||||
<div className="flex-1 grid grid-cols-2 sm:grid-cols-4 lg:grid-cols-7 gap-2">
|
||||
{complianceScore?.dimensions?.map((dim: any) => {
|
||||
const dimRouteMap: Record<string, string> = {
|
||||
contract: '/roster',
|
||||
salary: '/money',
|
||||
social: '/social',
|
||||
attendance: '/attendance',
|
||||
policy: '/policies',
|
||||
termination: '/termination',
|
||||
evidence: '/evidence',
|
||||
}
|
||||
return (
|
||||
<Link key={dim.key} to={dimRouteMap[dim.key] || '/roster'} className="flex flex-col items-center p-1.5 rounded-lg hover:bg-gray-50 transition-colors group relative">
|
||||
<span className={`text-lg font-bold ${dim.score >= 85 ? 'text-safe' : dim.score >= 60 ? 'text-warning' : 'text-danger'}`}>{dim.score}</span>
|
||||
<span className="text-xs text-gray-600">{dim.name}</span>
|
||||
{dim.todoCount > 0 && <span className="text-[10px] text-gray-400">{dim.todoCount}待办</span>}
|
||||
{/* hover 显示得分依据 */}
|
||||
{dim.findings && dim.findings.length > 0 && (
|
||||
<div className="hidden group-hover:block absolute top-full left-1/2 -translate-x-1/2 z-20 mt-1 w-56 bg-gray-900 text-white text-xs rounded-lg p-2.5 shadow-lg whitespace-normal">
|
||||
<div className="font-medium mb-1">得分依据</div>
|
||||
{dim.findings.map((f: string, i: number) => (
|
||||
<div key={i} className="text-gray-300 leading-relaxed mb-0.5">• {f}</div>
|
||||
))}
|
||||
{dim.recommendations && dim.recommendations.length > 0 && (
|
||||
<>
|
||||
<div className="font-medium mt-1.5 mb-0.5 text-amber-300">建议</div>
|
||||
{dim.recommendations.map((r: string, i: number) => (
|
||||
<div key={i} className="text-gray-300 leading-relaxed mb-0.5">• {r}</div>
|
||||
))}
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</Link>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
{/* 合同到期预警内联 */}
|
||||
@@ -575,9 +604,6 @@ export default function Dashboard() {
|
||||
{/* 人力成本 Tab */}
|
||||
{activeTab === 'cost' && (
|
||||
<div className="space-y-3">
|
||||
<PageGuide>
|
||||
人力成本页展示当月及年度累计的工资、社保、公积金、加班费、补偿金等各项成本明细。可导出薪税汇总表,点击月份卡片可查看历史趋势。
|
||||
</PageGuide>
|
||||
{/* 成本专属指标卡片 */}
|
||||
{isSectionVisible('cost_metrics') && (
|
||||
<div className="grid grid-cols-2 md:grid-cols-4 gap-2">
|
||||
@@ -842,9 +868,6 @@ export default function Dashboard() {
|
||||
{/* 人员分析 Tab */}
|
||||
{activeTab === 'workforce' && (
|
||||
<div className="space-y-3">
|
||||
<PageGuide>
|
||||
人员分析页展示本月入离职动态、员工分布及绩效统计。可按部门筛选查看人员构成,洞察团队变化趋势。
|
||||
</PageGuide>
|
||||
{/* 本月工作动态 */}
|
||||
{isSectionVisible('workforce_activities') && (
|
||||
<Card>
|
||||
@@ -977,11 +1000,6 @@ export default function Dashboard() {
|
||||
{/* 风险提醒 Tab */}
|
||||
{(activeTab === 'risk' || activeTab === 'task') && (
|
||||
<div className="space-y-3">
|
||||
<PageGuide>
|
||||
{activeTab === 'risk'
|
||||
? '风险提醒页汇总合同到期、未签合同、离职风险、退休预警等高风险待办事项。可批量处理或逐项解决,处理完成后自动归档至已办事项。'
|
||||
: '月度任务页汇总社保办理、发薪批次等周期性待办事项。可批量处理或逐项解决,处理完成后自动归档至已办事项。'}
|
||||
</PageGuide>
|
||||
{/* 风险分布饼图(仅风险提醒Tab) */}
|
||||
{activeTab === 'risk' && isSectionVisible('risk_distribution') && (
|
||||
<Card>
|
||||
|
||||
Reference in New Issue
Block a user