# AIHR 前端 UI/UX 梳理与优化方向 > 针对中小微企业人事/财务人员的使用场景,对现有前端进行全面梳理并提出优化建议。 > > 日期:2026-07-24 --- ## 〇、竞品参考标杆 ### 0.1 选型逻辑 AIHR 定位为"中小微企业用工合规助手",核心用户是 1-2 人的 HR/财务兼管人员。选参考标杆时,排除北森(太重、实施 3-6 个月)、Rippling(HR+IT 一体化,偏离核心场景),聚焦以下 4 个标杆产品: ### 0.2 标杆产品矩阵 | 产品 | 定位 | 参考价值 | UI/UX 特点 | |------|------|----------|------------| | **BambooHR** | 中端市场 HRIS(50-500 人) | **UI/UX 黄金标准** | 46% 用户评价中专门提及界面质量;简洁现代,非 HR 人员也能快速上手;员工自助体验最佳 | | **Gusto** | 美国小企业薪税合规(<50 人) | **薪税+合规体验** | "set it and forget it" 自动化薪税;界面极简,创始人自己就能跑薪税;$49+$6/人,性价比最高 | | **飞书人事** | 中国协同办公生态 HR 模块 | **本土化+集成体验** | 与 IM/文档/审批原生打通;组织架构拖拉拽调整;员工点击头像即看全档案;零学习成本 | | **薪人薪事** | 中国中小企业薪酬社保 SaaS | **薪酬社保深度** | 薪酬社保为核心优势;50-200 人企业首选;界面操作直观,部署速度快 | ### 0.3 各标杆关键设计借鉴 #### BambooHR — UI/UX 第一梯队 | 设计要点 | 借鉴方向 | |----------|----------| | 左侧导航栏(非顶部 tab) | 信息层级清晰,可折叠,不占垂直空间 | | 员工档案卡片式布局 | 头照 + 基本信息 + 标签,视觉温度 | | Onboarding Checklist | 新员工入职清单,进度条可视化 | | PTO 申请日历视图 | 请假/考勤用日历而非表格 | | 报表 + 人员分析 Dashboard | 图表驱动,非纯数字 | | 移动端体验 | 员工自助(查工资条/请假/签合同)流畅 | #### Gusto — 薪税合规极简体验 | 设计要点 | 借鉴方向 | |----------|----------| | 薪税运行向导(Run Payroll) | 3 步引导:确认人数 → 核对金额 → 一键发放 | | 合规提醒卡片 | "你需要在本月 15 日前完成社保申报" 式主动提醒 | | 自动报税 + 状态追踪 | 薪税计算后显示"已申报/待申报/已完成"状态 | | 透明定价展示 | 套餐/额度在设置页面清晰展示 | | 员工自助入职 | 员工自己填信息+传材料,HR 只需审核 | #### 飞书人事 — 本土化集成 | 设计要点 | 借鉴方向 | |----------|----------| | 组织架构树 + 拖拽调整 | 部门管理可视化,非纯文本 | | 人事流程无代码配置 | 审批/通知可自定义,适应不同企业 | | 全生命周期数据汇聚 | 入职→在职→离职数据在一个档案页 | | 与 IM 消息打通 | 审批/通知推送到微信/钉钉/飞书 | | 移动端 = 桌面端功能对等 | 不阉割功能,移动端可完成所有操作 | #### 薪人薪事 — 薪酬社保深度 | 设计要点 | 借鉴方向 | |----------|----------| | 薪酬结构可视化编辑 | 薪酬项拖拽排序,公式可视化 | | 社保基数自动核定 | 按城市/基数上下限自动计算,非手动填 | | 工资条一键群发 + 员工确认 | 批量发送 → 员工端查看确认 → 状态追踪 | | 薪酬变更历史时间线 | 调薪记录以时间线展示,可追溯 | | 社保公积金月度申报表 | 自动生成申报表,导出 Excel/PDF | ### 0.4 AIHR 对标差距与借鉴优先级 | 维度 | 标杆 | AIHR 现状 | 差距 | 借鉴优先级 | |------|------|-----------|------|------------| | **导航架构** | BambooHR(左侧栏) | 顶部 6 tab 平铺 | 无层级、认知负担重 | 高 | | **字号/间距** | BambooHR / Gusto | text-xs 全局 | 过小,阅读疲劳 | 高 | | **薪税向导** | Gusto(3 步引导) | 4 个子 tab 手动操作 | 缺少引导式流程 | 高 | | **合规提醒** | Gusto(主动卡片) | Dashboard 待办列表 | 有但不够突出 | 中 | | **员工档案** | 飞书人事(全生命周期) | 11 个 tab 平铺 | 信息分散,缺概览 | 中 | | **组织架构** | 飞书人事(可视化树) | 无 | 完全缺失 | 低(中小微部门少) | | **数据可视化** | BambooHR(图表驱动) | 纯数字+图标 | 无趋势/分布图 | 中 | | **员工自助端** | BambooHR / 飞书 | 有但无导航 | 页面间无法跳转 | 中 | | **Toast 反馈** | 所有标杆 | 无 | 操作无即时反馈 | 高 | | **移动端体验** | BambooHR(功能对等) | 底部 6 tab 拥挤 | 表格不响应式 | 高 | ### 0.5 推荐设计方向总结 > **以 BambooHR 的 UI 质量为视觉标杆,以 Gusto 的薪税合规向导为交互范式,以飞书人事的全生命周期档案为信息架构参考,以薪人薪事的薪酬社保深度为功能标杆。** 具体而言: 1. **导航** → 参考 BambooHR 改为左侧栏(桌面端)+ 底部 4 tab(移动端) 2. **薪税流程** → 参考 Gusto 改为引导式向导,而非 4 个 tab 手动切换 3. **员工档案** → 参考飞书人事,增加"概览"首 tab,汇总关键信息 4. **合规提醒** → 参考 Gusto,在 Dashboard 突出"本月必做"卡片 5. **视觉风格** → 参考 BambooHR,提升字号/间距/色彩温度 --- ## 一、现状概览 ### 1.1 技术栈 | 层面 | 技术 | |------|------| | 框架 | React 18 + TypeScript | | 构建 | Vite 5 | | 样式 | Tailwind CSS 3(自定义 token:primary/danger/warning/safe/surface) | | 路由 | React Router v6 | | 状态 | Zustand(auth)+ TanStack Query(服务端数据) | | 表单 | react-hook-form + zod | | 图标 | lucide-react | | 其他 | qrcode.react, jsPDF, xlsx | ### 1.2 页面结构 ``` 管理端(AdminLayout) ├── TopNav(顶部导航 h-14,6 个 tab) ├── PageContainer(max-w-content, px-4) ├── MobileTabBar(移动端底部 tab bar) └── OnboardingGuide(首次引导遮罩) 路由页面: ├── / Dashboard(总览:概览/薪税/风险/任务 4 tab) ├── /roster Roster(花名册:员工列表 + 11 个详情 tab) ├── /money Money(薪税:发薪批次/薪酬模版/加班费/工资条 4 tab) ├── /social SocialInsurance(社保公积金:社保/公积金/月度 3 tab) ├── /termination Termination(解聘补偿:5 步向导) ├── /ai-assistant AIAssistant(AI 顾问:问答/预测/审查/案例/知识库 5 tab) ├── /settings Settings(设置:企业/用户/套餐/通知/导入 5 tab) 员工端(PortalLayout, max-w-md) ├── /portal/login 员工登录 ├── /portal/payslip 工资条查看 ├── /portal/contract 合同查看 ├── /portal/onboarding 入职引导 └── /portal/contract-confirm 合同确认 未挂载页面(文件存在但未路由): ├── Compensation.tsx 薪酬调整 └── Contracts.tsx 合同管理 ``` ### 1.3 组件库 | 组件 | 说明 | |------|------| | Button | 3 variant(primary/secondary/danger)× 3 size | | Card | 白底圆角阴影,p-3 | | Input / Select / Label | 基础表单控件,text-xs | | Modal | 4 size,居中弹窗 | | Pagination | 分页 | | EmptyState | 空状态 | | Signal | 信号灯(风险指示) | ### 1.4 设计 Token ```js colors: { primary: { DEFAULT: '#2563EB', light: '#3B82F6', dark: '#1D4ED8' }, danger: '#DC2626', warning: '#F59E0B', safe: '#16A34A', surface: '#F8FAFC', } maxWidth: { content: 'none' } // 宽屏不限制 ``` --- ## 二、问题诊断 ### 2.1 信息架构 | 问题 | 影响 | 严重度 | |------|------|--------| | **导航扁平,6 个 tab 平铺** | 中小微 HR 只有 1-2 人,6 个顶级 tab + 每页 3-5 个子 tab = 认知负担重 | 高 | | **Contracts / Compensation 页面未挂载** | 合同管理和薪酬调整功能用户无法访问 | 高 | | **Dashboard 内嵌薪税 tab** | 与 /money 页面功能重叠,用户困惑入口 | 中 | | **设置入口隐蔽** | 仅在右上角下拉菜单,中小微用户不易发现 | 中 | | **员工端无统一导航** | Portal 页面间无法跳转,只能通过链接进入 | 中 | ### 2.2 视觉设计 | 问题 | 影响 | 严重度 | |------|------|--------| | **全局字号过小(text-xs 为主)** | 人事/财务人员长时间盯屏疲劳,35+ 用户阅读困难 | 高 | | **卡片间距紧凑(p-3, gap-2)** | 信息密度过高,缺乏呼吸感,重要信息不突出 | 高 | | **主色 #2563EB 偏冷** | B 端工具感强,缺乏温度,与"中小微企业友好"定位不符 | 中 | | **max-w-content 为 none** | 超宽屏内容无限拉伸,1920px+ 屏幕阅读体验差 | 中 | | **无数据可视化** | Dashboard 仅数字+图标卡片,无图表,趋势不直观 | 中 | | **状态色未体系化** | 各页面自行定义颜色(blue-50/amber-50/cyan-50),未统一 token | 低 | ### 2.3 交互体验 | 问题 | 影响 | 严重度 | |------|------|--------| | **无全局 Toast/通知** | 操作成功/失败无即时反馈,用户不确定操作是否生效 | 高 | | **无 Loading 骨架屏** | 仅"加载中..."文字,长列表加载时白屏 | 中 | | **Modal 无过渡动画** | 弹窗突现突消失,体验生硬 | 中 | | **表单无防离开提示** | 填写一半误点导航数据丢失 | 中 | | **批量操作无确认** | 批量解聘/续签缺少二次确认,误操作风险高 | 高 | | **搜索无防抖** | 花名册搜索每次按键触发请求,浪费资源 | 低 | | **无快捷键支持** | 高频操作(搜索/新建/保存)无键盘快捷方式 | 低 | ### 2.4 移动端适配 | 问题 | 影响 | 严重度 | |------|------|--------| | **MobileTabBar 6 个 tab 拥挤** | iPhone SE 上每个 tab 仅 53px,图标+文字挤压 | 高 | | **表格无响应式方案** | 花名册等列表页在手机上横向滚动体验差 | 高 | | **Modal 在小屏溢出** | max-w-4xl 弹窗在手机上内容拥挤 | 中 | | **员工端 max-w-md 偏窄** | 工资条信息在 tablet 上浪费空间 | 低 | ### 2.5 可访问性(a11y) | 问题 | 影响 | 严重度 | |------|------|--------| | **div onClick 模式** | TopNav 下拉菜单等用 div+onClick,键盘不可达 | 中 | | **无 aria-label** | 图标按钮无语义标签,屏幕阅读器无法识别 | 中 | | **对比度不足** | text-gray-400 on bg-white 对比度 ~2.5:1,低于 WCAG AA 4.5:1 | 中 | | **无 focus-visible 样式** | 键盘导航时无法识别当前焦点元素 | 低 | ### 2.6 性能 | 问题 | 影响 | 严重度 | |------|------|--------| | **单文件过大** | Roster.tsx 140KB / Money.tsx 63KB / Termination.tsx 55KB,首屏加载慢 | 高 | | **无代码分割** | 所有页面打包在一个 chunk,无 lazy loading | 高 | | **无虚拟列表** | 花名册大量员工时 DOM 节点过多 | 中 | --- ## 三、优化方向 ### 3.1 信息架构重组(优先级:高) **目标:降低认知负担,让 HR 3 秒找到功能入口。** #### 方案:二级导航 + 功能聚合 ``` 顶部导航(h-14) ├── Logo + 企业名 ├── 主导航(4 个入口,合并相关功能) │ ├── 总览 → Dashboard(保留概览+风险+任务,移除薪税 tab) │ ├── 员工管理 → Roster + Contracts(合并,花名册内增加合同 tab) │ ├── 薪税社保 → Money + SocialInsurance(合并为一个页面组) │ └── AI 顾问 → AIAssistant ├── 右侧:通知铃铛(badge) + 设置齿轮 + 用户头像 移动端底部导航(4 个 tab) ├── 总览 ├── 员工 ├── 薪税 └── AI ``` #### 具体调整 1. **合并 Contracts → Roster**:花名册详情中已有合同 tab,Contracts.tsx 独立页面无入口,应删除或合并 2. **合并 Compensation → Money**:薪酬调整功能应作为薪税页面的一个子 tab 3. **Dashboard 去掉薪税 tab**:避免与 /money 重复,保留概览/风险/任务 3 个 tab 4. **设置入口可见化**:齿轮图标直接放在导航栏,而非藏在下拉菜单 ### 3.2 视觉设计升级(优先级:高) #### 3.2.1 字号体系 ``` 当前:全局 text-xs (12px) → 目标:text-sm (14px) 为正文基准 层级 当前 目标 用途 h1 (页面标题) text-xs text-base 页面顶部标题 h2 (区块标题) text-sm text-sm 卡片标题 正文/表格 text-xs text-sm 列表、表格、表单 辅助文字 text-xs text-xs 时间戳、备注(保持) 数字大屏 无 text-2xl Dashboard 统计数字 ``` #### 3.2.2 间距体系 ``` 当前:p-3 / gap-2 → 目标:p-4 / gap-3(增加呼吸感) 组件 当前 目标 Card p-3 p-4 页面间距 gap-2 gap-4 表格行高 紧凑 py-2.5(增加行高) ``` #### 3.2.3 主色调暖 ```js // 当前:冷蓝 #2563EB // 建议:indigo-600 #4F46E5,略带温度,专业且亲和 colors: { primary: { DEFAULT: '#4F46E5', light: '#6366F1', dark: '#4338CA' }, } ``` #### 3.2.4 内容最大宽度 ```js // 当前:max-w-content = none(无限拉伸) // 建议:限制 1280px,超宽屏居中 maxWidth: { content: '1280px' } ``` #### 3.2.5 数据可视化 - Dashboard 概览增加 **迷你折线图**(月度薪税趋势) - 风险分布增加 **环形图**(高/中/低风险占比) - 引入 `recharts`(轻量,~40KB gzip) ### 3.3 交互体验增强(优先级:高) #### 3.3.1 全局 Toast ```tsx // 引入 sonner(~5KB gzip) import { toast } from 'sonner' // 成功/失败/警告 统一调用 toast.success('员工已添加') toast.error('删除失败,请重试') toast.warning('该操作不可撤销') ``` #### 3.3.2 批量操作二次确认 ```tsx // 危险操作(批量解聘/删除)必须 Dialog 二次确认 确认对 {selectedIds.size} 名员工执行解聘操作? 此操作不可撤销。 ``` #### 3.3.3 骨架屏 ```tsx // 替换"加载中..."文字 function TableSkeleton() { return Array.from({ length: 5 }).map(i => (
)) } ``` #### 3.3.4 搜索防抖 ```tsx // 使用 useDeferredValue 或 lodash.debounce const debouncedSearch = useDeferredValue(search) // queryKey 使用 debouncedSearch ``` #### 3.3.5 表单防离开 ```tsx // react-hook-form 已支持 const form = useForm({ mode: 'onChange' }) useEffect(() => { const handler = (e: BeforeUnloadEvent) => { if (form.formState.isDirty) { e.preventDefault() e.returnValue = '' } } window.addEventListener('beforeunload', handler) return () => window.removeEventListener('beforeunload', handler) }, [form.formState.isDirty]) ``` ### 3.4 移动端优化(优先级:高) #### 3.4.1 底部导航精简为 4 个 ``` 当前 6 个:总览 / 花名册 / 薪税 / 社保 / 解聘补偿 / AI 目标 4 个:总览 / 员工 / 薪税 / AI (社保、解聘补偿归入对应主页面子功能) ``` #### 3.4.2 表格响应式 - 手机端:卡片列表模式(每行一个卡片,字段竖排) - 平板端:紧凑表格(隐藏低优先级列) - 桌面端:完整表格 #### 3.4.3 Modal 移动端全屏 ```tsx // 移动端 Modal 全屏展示 className={clsx( 'relative bg-white shadow-xl w-full max-h-[90vh] overflow-y-auto', isMobile ? 'h-screen rounded-none' : 'rounded-lg', sizeClass, )} ``` ### 3.5 可访问性(优先级:中) - **替换 div onClick**:下拉菜单用 `
) } ``` **替换清单**(所有 `confirm()` 调用): | 文件 | 行号 | 当前代码 | 替换为 | |------|------|----------|--------| | Money.tsx | L284 | `confirm('确认删除批次?')` | `` | | Money.tsx | L493 | `confirm('确认归档?')` | `` | | Money.tsx | L506 | `confirm('确认删除批次?')` | `` | | Money.tsx | L1255 | `confirm('确认生成工资条?')` | `` | | Roster.tsx | L400 | `confirm('确认撤回离职记录?')` | `` | **验收标准**:危险操作弹出 Dialog 而非浏览器原生 confirm,有明确文案说明后果。 #### P1.5 对比度修复 | 文件 | 当前 | 目标 | 说明 | |------|------|------|------| | 全局 `text-gray-400` | `text-gray-400` (#9CA3AF) | `text-gray-500` (#6B7280) | 对比度 2.5:1 → 4.6:1 | | `src/components/ui/Pagination.tsx` | L61, L69 `text-gray-400` | `text-gray-500` | 翻页按钮 | | `src/pages/Dashboard.tsx` | L229 `text-gray-400` | `text-gray-500` | "等人"文字 | | `src/components/layout/TopNav.tsx` | L50 `text-gray-400` | `text-gray-500` | ChevronDown 图标 | **验收标准**:所有文字对比度 ≥ 4.5:1(WCAG AA),使用 axe DevTools 验证。 #### P1.6 内容宽度限制 | 文件 | 修改 | |------|------| | `tailwind.config.js` | `maxWidth: { content: '1280px' }`(当前 `none`) | **验收标准**:1920px 屏幕内容居中,最大宽度 1280px,两侧留白。 --- ### Phase 2:信息架构调整(2-3 天) #### P2.1 顶部导航精简为 4 入口 **修改文件**:`src/components/layout/TopNav.tsx` ```tsx // 当前 6 个 tab const tabs = [ { path: '/', label: '总览' }, { path: '/roster', label: '花名册' }, { path: '/money', label: '薪税' }, { path: '/social', label: '社保公积金' }, { path: '/termination', label: '解聘补偿' }, { path: '/ai-assistant', label: 'AI顾问' }, ] // 目标 4 个 tab const tabs = [ { path: '/', label: '总览' }, { path: '/roster', label: '员工管理' }, { path: '/money', label: '薪税社保' }, { path: '/ai-assistant', label: 'AI顾问' }, ] ``` **右侧操作区修改**: ```tsx // 当前:仅用户下拉菜单 // 目标:通知铃铛(badge) + 设置齿轮 + 用户头像
{/* 用户菜单保持 */}
``` #### P2.2 移动端底部导航精简为 4 **修改文件**:`src/components/layout/MobileTabBar.tsx` ```tsx // 当前 6 个 → 目标 4 个 const tabs = [ { path: '/', label: '总览', icon: Home }, { path: '/roster', label: '员工', icon: Users }, { path: '/money', label: '薪税', icon: Calculator }, { path: '/ai-assistant', label: 'AI', icon: Bot }, ] ``` #### P2.3 路由调整 **修改文件**:`src/App.tsx` | 变更 | 说明 | |------|------| | `/social` 路由保留但导航不直接暴露 | 作为 `/money` 的子 tab 或独立路由通过页面内跳转 | | `/termination` 路由保留但导航不直接暴露 | 作为 `/roster` 内的功能入口(花名册 → 解聘操作) | | Dashboard 移除薪税 tab | `activeTab` 类型从 `'overview' \| 'payroll' \| 'risk' \| 'task'` → `'overview' \| 'risk' \| 'task'` | **Dashboard.tsx 修改**: ```tsx // 移除 payroll tab const tabs = [ { key: 'overview' as const, label: '概览', icon: LayoutDashboard, badge: data.stats.todoCount }, { key: 'risk' as const, label: '风险提醒', icon: AlertTriangle, badge: riskTodos.length }, { key: 'task' as const, label: '月度任务', icon: ListTodo, badge: taskTodos.length }, ] // 删除 activeTab === 'payroll' 相关的所有 JSX 块 ``` #### P2.4 合并未挂载页面 | 操作 | 文件 | 说明 | |------|------|------| | Compensation → Money | `src/pages/Money.tsx` | 在 tabs 数组增加 `{ key: 'adjust', label: '薪酬调整' }`,渲染 `` | | Contracts → Roster | `src/pages/Contracts.tsx` | Roster 详情已有合同 tab,删除独立 Contracts.tsx 或将其逻辑合并到 Roster 详情的合同 tab | **Money.tsx 修改**: ```tsx type Tab = 'batch' | 'template' | 'overtime' | 'payslip' | 'adjust' const tabs = [ { key: 'batch', label: '发薪批次' }, { key: 'template', label: '薪酬模版' }, { key: 'overtime', label: '加班费计算' }, { key: 'payslip', label: '工资条管理' }, { key: 'adjust', label: '薪酬调整' }, // 新增 ] // {tab === 'adjust' && } ``` **验收标准**:顶部导航 4 个 tab,移动端 4 个 tab,无重复入口,Contracts/Compensation 功能可访问。 --- ### Phase 3:性能与组件化(2-3 天) #### P3.1 路由懒加载 **修改文件**:`src/App.tsx` ```tsx import { lazy, Suspense } from 'react' import { Loader2 } from 'lucide-react' const Dashboard = lazy(() => import('./pages/Dashboard')) const Roster = lazy(() => import('./pages/Roster')) const Money = lazy(() => import('./pages/Money')) const SocialInsurance = lazy(() => import('./pages/SocialInsurance')) const Termination = lazy(() => import('./pages/Termination')) const AIAssistant = lazy(() => import('./pages/AIAssistant')) const Settings = lazy(() => import('./pages/Settings')) const Login = lazy(() => import('./pages/auth/Login')) // ... 其他页面同理 function PageSkeleton() { return (
) } export default function App() { return ( }> ... ) } ``` **验收标准**:首屏仅加载 Dashboard chunk,其他页面按需加载,Network 面板可见独立 chunk。 #### P3.2 大文件拆分 **Roster.tsx(140KB)拆分方案**: ``` src/pages/roster/ ├── Roster.tsx # 主页面:列表 + 搜索 + 筛选 + 分页 ├── EmployeeDetail.tsx # 详情面板:tab 切换容器 ├── tabs/ │ ├── BasicInfoTab.tsx # 基本信息 │ ├── ContractTab.tsx # 合同信息 │ ├── PayslipTab.tsx # 工资条 │ ├── OvertimeTab.tsx # 加班记录 │ ├── DisciplinaryTab.tsx # 违纪记录 │ ├── AttendanceTab.tsx # 考勤记录 │ ├── TrainingTab.tsx # 培训记录 │ ├── PerformanceTab.tsx # 绩效记录 │ ├── TerminationTab.tsx # 解聘记录 │ ├── AttachmentTab.tsx # 附件管理 │ └── EvidenceTab.tsx # 仲裁证据链 ├── AddEmployeeModal.tsx # 新增员工弹窗 ├── ResignModal.tsx # 离职弹窗 ├── RehireModal.tsx # 重新入职弹窗 ├── SalaryModal.tsx # 调薪弹窗 ├── DeptModal.tsx # 调岗弹窗 └── BatchRenewModal.tsx # 批量续签弹窗 ``` **Money.tsx(63KB)拆分方案**: ``` src/pages/money/ ├── Money.tsx # 主页面:tab 切换 ├── BatchManager.tsx # 发薪批次 ├── TemplateManager.tsx # 薪酬模版 ├── OvertimeCalculator.tsx # 加班费计算 ├── PayslipManager.tsx # 工资条管理 └── CompensationManager.tsx # 薪酬调整(从 Compensation.tsx 合入) ``` **Termination.tsx(55KB)拆分方案**: ``` src/pages/termination/ ├── Termination.tsx # 主页面:向导容器 ├── StepSelectEmployee.tsx # 步骤1:选择员工 ├── StepSelectReason.tsx # 步骤2:解聘方式 ├── StepCompliance.tsx # 步骤3:合规检查 ├── StepSettlement.tsx # 步骤4:费用结算 └── StepConfirm.tsx # 步骤5:确认完成 ``` **Settings.tsx(46KB)拆分方案**: ``` src/pages/settings/ ├── Settings.tsx # 主页面:section 切换 ├── OrgSettings.tsx # 企业信息 ├── UserSettings.tsx # 用户管理 ├── PlanSettings.tsx # 套餐 ├── NotificationSettings.tsx # 通知设置 └── ImportSettings.tsx # 数据导入 ``` **验收标准**:单个文件不超过 500 行,每个子组件独立可测。 #### P3.3 骨架屏组件 **新增文件**:`src/components/ui/Skeleton.tsx` ```tsx export function TableSkeleton({ rows = 5 }: { rows?: number }) { return (
{Array.from({ length: rows }).map((_, i) => (
))}
) } export function CardSkeleton() { return (
) } export function DetailSkeleton() { return (
) } ``` **替换清单**(13 处 "加载中..."): | 文件 | 行号 | 替换为 | |------|------|--------| | Dashboard.tsx | L112 | `` | | Roster.tsx | L249, L702 | `` | | Money.tsx | L239, L371, L719, L933, L1268 | `` | | SocialInsurance.tsx | L314, L623 | `` | | AIAssistant.tsx | L773 | `` | | portal/Payslip.tsx | L131 | `` | | portal/MyContract.tsx | L70 | `` | | portal/ContractConfirm.tsx | L85 | `` | | Contracts.tsx | L82 | `` | **验收标准**:加载时显示骨架屏动画,无白屏或纯文字"加载中..."。 #### P3.4 搜索防抖 **修改文件**:`src/pages/Roster.tsx`(及任何有搜索的页面) ```tsx import { useDeferredValue } from 'react' const [search, setSearch] = useState('') const deferredSearch = useDeferredValue(search) // queryKey 使用 deferredSearch 而非 search const { data: rosterData } = useQuery({ queryKey: ['roster', page, pageSize, deferredSearch, filterStatus, filterContractStatus], // ... }) ``` **验收标准**:快速输入时不会每次按键触发 API 请求,停止输入 ~200ms 后才发请求。 --- ### Phase 4:视觉与数据可视化(2-3 天) #### P4.1 主色调暖 **修改文件**:`tailwind.config.js` ```js // 当前 primary: { DEFAULT: '#2563EB', light: '#3B82F6', dark: '#1D4ED8' } // 目标(indigo-600,略带紫调,专业且亲和) primary: { DEFAULT: '#4F46E5', light: '#6366F1', dark: '#4338CA' } ``` **影响范围**:所有使用 `text-primary`、`bg-primary`、`border-primary` 的组件自动生效,无需逐文件修改。 **验收标准**:主色从冷蓝变为 indigo,视觉感受更温暖,与 Tailwind indigo-600 色卡一致。 #### P4.2 Dashboard 数据可视化 **安装**:`npm install recharts` **修改文件**:`src/pages/Dashboard.tsx` 在概览 tab 的统计卡片下方增加: ```tsx import { LineChart, Line, ResponsiveContainer, XAxis, YAxis, Tooltip, PieChart, Pie, Cell } from 'recharts' // 月度薪税趋势迷你折线图

月度薪税趋势

// 风险分布环形图

风险分布

{riskData.map((entry, i) => )}
``` **验收标准**:Dashboard 概览页有折线图和环形图,图表响应式,tooltip 正常显示。 #### P4.3 Modal 过渡动画 **修改文件**:`src/components/ui/Modal.tsx` ```tsx // 添加 CSS transition // 方案:利用 Tailwind 的 transition + opacity + scale // 遮罩层:opacity 0 → 100 // 内容层:scale-95 opacity-0 → scale-100 opacity-100 // 新增 state 控制动画 const [show, setShow] = useState(false) useEffect(() => { if (open) { setShow(true) } else { const timer = setTimeout(() => setShow(false), 200) return () => clearTimeout(timer) } }, [open]) if (!show && !open) return null return (
{/* 内容不变 */}
) ``` **验收标准**:弹窗有淡入+缩放动画,关闭有淡出动画,~200ms。 #### P4.4 移动端表格响应式 **新增组件**:`src/components/ui/ResponsiveTable.tsx` ```tsx interface Column { key: string label: string render?: (row: T) => React.ReactNode priority: 'high' | 'medium' | 'low' // 高优先级在手机端显示 className?: string } interface ResponsiveTableProps { columns: Column[] data: T[] rowKey: (row: T) => string onRowClick?: (row: T) => void } // 桌面端:表格(显示所有列) // 平板端:表格(隐藏 low priority 列,用 hidden md:table-cell) // 手机端:卡片列表(仅显示 high priority 字段,竖排) ``` **应用页面**:Roster、Money(工资条列表)、SocialInsurance(月度申报表) **验收标准**:iPhone SE 上列表为卡片模式,iPad 上为紧凑表格,桌面端完整表格。 --- ### Phase 5:a11y 与细节打磨(1-2 天) #### P5.1 div onClick → button + aria **修改文件**:`src/components/layout/TopNav.tsx` ```tsx // 当前(L46-50):div + onClick