feat: Sprint 1 — 设计Token系统 + 新导航5分组 + AppShell/PageHeader/FilterBar/DataTable组件 + 花名册导出扩充19字段 + 社保/公积金不缴纳选项 + 个税申报表导出 + 入离职/绩效统计看板

This commit is contained in:
selfrelease
2026-07-31 17:40:49 +08:00
parent c15e11ec22
commit 821a62e3f8
16 changed files with 3177 additions and 55 deletions
+21 -19
View File
@@ -30,31 +30,36 @@ interface NavGroup {
const navGroups: NavGroup[] = [
{
title: '工作台',
title: '首页',
items: [
{ path: '/', label: '总览', icon: LayoutDashboard },
{ path: '/', label: '工作台', icon: LayoutDashboard },
{ path: '/calendar', label: '工作日历', icon: CalendarDays },
],
},
{
title: '员工管理',
title: '团队',
items: [
{ path: '/roster', label: '花名册', icon: Users },
{ path: '/work-process', label: '用工办理', icon: ClipboardList },
{ path: '/attendance', label: '考勤确认', icon: CalendarCheck },
{ path: '/termination', label: '解聘补偿', icon: UserX },
{ path: '/termination', label: '离职管理', icon: UserX },
{ path: '/special-status', label: '特殊状态', icon: Heart },
],
},
{
title: '薪税社保',
title: '薪',
items: [
{ path: '/money', label: '薪税管理', icon: Calculator },
{ path: '/social', label: '社保公积金', icon: Shield },
],
},
{
title: '合规风控',
title: '时间',
items: [
{ path: '/attendance', label: '考勤排班', icon: CalendarCheck },
],
},
{
title: '合规',
items: [
{ path: '/evidence', label: '证据链', icon: FileSearch },
{ path: '/policies', label: '规章制度', icon: FileText },
@@ -64,15 +69,10 @@ const navGroups: NavGroup[] = [
],
},
{
title: 'AI 辅助',
title: '更多',
items: [
{ path: '/ai-assistant', label: 'AI 顾问', icon: Bot },
{ path: '/templates', label: '文本模板', icon: BookMarked },
],
},
{
title: '系统',
items: [
{ path: '/notifications', label: '通知管理', icon: Bell },
{ path: '/audit', label: '操作日志', icon: ScrollText },
{ path: '/settings', label: '设置', icon: Settings },
@@ -85,7 +85,14 @@ const navGroups: NavGroup[] = [
*/
export default function SidebarNav({ mobileOpen, onClose }: { mobileOpen: boolean; onClose: () => void }) {
const location = useLocation()
const [expandedGroups, setExpandedGroups] = useState<Set<string>>(new Set(navGroups.map(g => g.title)))
const isActive = (path: string) => {
if (path === '/') return location.pathname === '/'
return location.pathname.startsWith(path)
}
const activeGroup = navGroups.find(g => g.items.some(item => isActive(item.path)))
const [expandedGroups, setExpandedGroups] = useState<Set<string>>(
new Set(activeGroup ? [activeGroup.title] : ['首页'])
)
const toggleGroup = (title: string) => {
setExpandedGroups(prev => {
@@ -96,11 +103,6 @@ export default function SidebarNav({ mobileOpen, onClose }: { mobileOpen: boolea
})
}
const isActive = (path: string) => {
if (path === '/') return location.pathname === '/'
return location.pathname.startsWith(path)
}
return (
<>
{/* 移动端遮罩 */}