feat: 完成23项系统优化 - 花名册社保状态列/身份证复制/附件类型扩展, 用工办理姓名检索/直接提交/文书查看/批量证明, 风险中心跳转筛选+批量处理, 日历7/15/35天分组+逾期统计, 考勤单条编辑+按人导出, 工资条查看状态+工资流水导出, 辞职申请附件上传, 交接清单PDF下载, 操作完成下一步引导, 休假审批入口, 人效成本分部门
This commit is contained in:
@@ -1,80 +1,144 @@
|
||||
import { useState, useEffect } from 'react'
|
||||
import { X, ArrowRight } from 'lucide-react'
|
||||
import { useNavigate } from 'react-router-dom'
|
||||
import { X, ArrowRight, Home, Users, Calculator, CalendarCheck, ShieldAlert, Bot } from 'lucide-react'
|
||||
|
||||
const STORAGE_KEY = 'hr-onboarding-completed'
|
||||
const STORAGE_KEY = 'hr-onboarding-dismissed'
|
||||
|
||||
const steps = [
|
||||
const modules = [
|
||||
{
|
||||
icon: '🏠',
|
||||
title: '这里看风险',
|
||||
description: '首页展示企业用工风险总览,红色代表高风险项,点击「去处理」直接跳转操作。',
|
||||
icon: Home,
|
||||
color: 'text-blue-600',
|
||||
bg: 'bg-blue-50',
|
||||
title: '工作台',
|
||||
desc: '风险总览、待办事项、日历事件',
|
||||
path: '/',
|
||||
},
|
||||
{
|
||||
icon: '�',
|
||||
title: '这里管花名册',
|
||||
description: '花名册页面管理员工档案、劳动合同、附件,以及违纪、考勤、培训、绩效记录,可生成仲裁证据链。',
|
||||
icon: Users,
|
||||
color: 'text-indigo-600',
|
||||
bg: 'bg-indigo-50',
|
||||
title: '团队管理',
|
||||
desc: '花名册、用工办理、离职管理、特殊状态',
|
||||
path: '/roster',
|
||||
},
|
||||
{
|
||||
icon: '💰',
|
||||
title: '这里算薪税',
|
||||
description: '薪税页面提供加班费、双倍工资、社保公积金计算器和工资条管理,输入参数实时计算。',
|
||||
icon: Calculator,
|
||||
color: 'text-amber-600',
|
||||
bg: 'bg-amber-50',
|
||||
title: '薪酬管理',
|
||||
desc: '发薪批次、工资条、社保公积金、薪酬分析',
|
||||
path: '/money',
|
||||
},
|
||||
{
|
||||
icon: CalendarCheck,
|
||||
color: 'text-green-600',
|
||||
bg: 'bg-green-50',
|
||||
title: '考勤时间',
|
||||
desc: '考勤打卡、排班管理、休假审批',
|
||||
path: '/attendance',
|
||||
},
|
||||
{
|
||||
icon: ShieldAlert,
|
||||
color: 'text-red-600',
|
||||
bg: 'bg-red-50',
|
||||
title: '合规风控',
|
||||
desc: '风险中心、证据链、规章制度、用工体检',
|
||||
path: '/risk-center',
|
||||
},
|
||||
{
|
||||
icon: Bot,
|
||||
color: 'text-purple-600',
|
||||
bg: 'bg-purple-50',
|
||||
title: 'AI 助手',
|
||||
desc: '智能咨询、合同审查、判赔预测、人力分析',
|
||||
path: '/ai-assistant',
|
||||
},
|
||||
]
|
||||
|
||||
export function isOnboardingDismissed() {
|
||||
return localStorage.getItem(STORAGE_KEY) === '1'
|
||||
}
|
||||
|
||||
export function dismissOnboarding() {
|
||||
localStorage.setItem(STORAGE_KEY, '1')
|
||||
}
|
||||
|
||||
export function resetOnboarding() {
|
||||
localStorage.removeItem(STORAGE_KEY)
|
||||
}
|
||||
|
||||
export default function OnboardingGuide() {
|
||||
const [visible, setVisible] = useState(false)
|
||||
const [step, setStep] = useState(0)
|
||||
const [dontShow, setDontShow] = useState(false)
|
||||
const navigate = useNavigate()
|
||||
|
||||
useEffect(() => {
|
||||
const completed = localStorage.getItem(STORAGE_KEY)
|
||||
if (!completed) {
|
||||
if (!isOnboardingDismissed()) {
|
||||
setVisible(true)
|
||||
}
|
||||
}, [])
|
||||
|
||||
const close = () => {
|
||||
localStorage.setItem(STORAGE_KEY, '1')
|
||||
if (dontShow) dismissOnboarding()
|
||||
setVisible(false)
|
||||
}
|
||||
|
||||
const goTo = (path: string) => {
|
||||
if (dontShow) dismissOnboarding()
|
||||
setVisible(false)
|
||||
navigate(path)
|
||||
}
|
||||
|
||||
if (!visible) return null
|
||||
|
||||
const current = steps[step]
|
||||
const isLast = step === steps.length - 1
|
||||
|
||||
return (
|
||||
<div className="fixed inset-0 z-50 flex items-center justify-center bg-black/40">
|
||||
<div className="bg-white rounded-xl shadow-xl max-w-sm w-full mx-4 overflow-hidden">
|
||||
<div className="flex justify-end p-2">
|
||||
<div className="bg-white rounded-xl shadow-xl max-w-lg w-full mx-4 overflow-hidden">
|
||||
<div className="flex items-center justify-between px-5 py-3 border-b border-gray-100">
|
||||
<h2 className="text-base font-semibold">欢迎使用企业用工专家</h2>
|
||||
<button onClick={close} className="text-gray-400 hover:text-gray-600">
|
||||
<X className="w-5 h-5" />
|
||||
</button>
|
||||
</div>
|
||||
<div className="px-6 pb-6">
|
||||
<div className="text-5xl text-center mb-4">{current.icon}</div>
|
||||
<h2 className="text-lg font-semibold text-center mb-2">{current.title}</h2>
|
||||
<p className="text-sm text-gray-600 text-center mb-6">{current.description}</p>
|
||||
|
||||
{/* 进度指示器 */}
|
||||
<div className="flex justify-center gap-1.5 mb-6">
|
||||
{steps.map((_, i) => (
|
||||
<div
|
||||
key={i}
|
||||
className={`h-1.5 rounded-full transition-all ${i === step ? 'w-6 bg-primary' : 'w-1.5 bg-gray-300'}`}
|
||||
/>
|
||||
))}
|
||||
<div className="px-5 py-4">
|
||||
<p className="text-sm text-gray-500 mb-4">系统包含以下 6 大模块,点击任意模块可直接前往体验:</p>
|
||||
<div className="grid grid-cols-2 gap-3">
|
||||
{modules.map((m) => {
|
||||
const Icon = m.icon
|
||||
return (
|
||||
<button
|
||||
key={m.title}
|
||||
onClick={() => goTo(m.path)}
|
||||
className="flex items-start gap-3 p-3 rounded-lg border border-gray-100 hover:border-primary/30 hover:bg-primary/[0.02] transition-all text-left"
|
||||
>
|
||||
<div className={`flex items-center justify-center w-9 h-9 rounded-lg ${m.bg} ${m.color} shrink-0`}>
|
||||
<Icon className="w-4.5 h-4.5" />
|
||||
</div>
|
||||
<div className="flex-1 min-w-0">
|
||||
<div className="text-sm font-medium text-gray-800">{m.title}</div>
|
||||
<div className="text-xs text-gray-500 mt-0.5 leading-relaxed">{m.desc}</div>
|
||||
</div>
|
||||
</button>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
|
||||
<div className="flex justify-between">
|
||||
{step > 0 ? (
|
||||
<button onClick={() => setStep(step - 1)} className="text-sm text-gray-500">上一步</button>
|
||||
) : <span />}
|
||||
<div className="mt-4 flex items-center justify-between">
|
||||
<label className="flex items-center gap-2 text-sm text-gray-500 cursor-pointer">
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={dontShow}
|
||||
onChange={(e) => setDontShow(e.target.checked)}
|
||||
className="w-4 h-4 rounded border-gray-300 text-primary focus:ring-primary/10"
|
||||
/>
|
||||
不再自动显示
|
||||
</label>
|
||||
<button
|
||||
onClick={() => isLast ? close() : setStep(step + 1)}
|
||||
className="flex items-center gap-1 text-sm font-medium text-primary"
|
||||
onClick={close}
|
||||
className="flex items-center gap-1 px-4 py-2 text-sm font-medium text-white bg-primary rounded-lg hover:bg-primary/90 transition-colors"
|
||||
>
|
||||
{isLast ? '开始使用' : '下一步'}
|
||||
{!isLast && <ArrowRight className="w-4 h-4" />}
|
||||
开始使用
|
||||
<ArrowRight className="w-4 h-4" />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user