diff --git a/frontend/src/components/SurveyModal.tsx b/frontend/src/components/SurveyModal.tsx new file mode 100644 index 0000000..2e3474e --- /dev/null +++ b/frontend/src/components/SurveyModal.tsx @@ -0,0 +1,185 @@ +import { useState, useMemo } from 'react' +import { Star, ChevronDown, ChevronRight, Check, Search, ClipboardList, Send } from 'lucide-react' +import Modal from './ui/Modal' +import { toast } from 'sonner' +import api from '../lib/api' +import { surveyPages, totalFeatures } from '../data/surveyData' + +interface FeatureScore { + score: number + useful: '' | 'yes' | 'no' | 'maybe' + remark: string +} + +export default function SurveyModal({ open, onClose }: { open: boolean; onClose: () => void }) { + const [expandedPage, setExpandedPage] = useState(1) + const [scores, setScores] = useState>({}) + const [searchQuery, setSearchQuery] = useState('') + const [submitting, setSubmitting] = useState(false) + + const setScore = (id: string, score: number) => { + setScores(prev => ({ + ...prev, + [id]: { ...prev[id], score: prev[id]?.score === score ? 0 : score }, + })) + } + + const setUseful = (id: string, useful: 'yes' | 'no' | 'maybe') => { + setScores(prev => ({ + ...prev, + [id]: { ...prev[id], useful: prev[id]?.useful === useful ? '' : useful }, + })) + } + + const setRemark = (id: string, remark: string) => { + setScores(prev => ({ + ...prev, + [id]: { ...prev[id], remark }, + })) + } + + const ratedCount = useMemo(() => Object.values(scores).filter(s => s.score > 0).length, [scores]) + + const filteredPages = useMemo(() => { + if (!searchQuery.trim()) return surveyPages + const q = searchQuery.toLowerCase() + return surveyPages.map(p => ({ + ...p, + features: p.features.filter(f => f.name.toLowerCase().includes(q) || f.desc.toLowerCase().includes(q)), + })).filter(p => p.features.length > 0) + }, [searchQuery]) + + const handleSubmit = async () => { + const items = Object.entries(scores) + .filter(([, v]) => v.score > 0 || v.useful || v.remark) + .map(([id, v]) => ({ featureId: id, score: v.score, useful: v.useful, remark: v.remark })) + if (items.length === 0) { + toast.info('请至少对一项功能进行评分') + return + } + setSubmitting(true) + try { + await api.post('/survey/submit', { items }) + toast.success(`已提交 ${items.length} 项评分,感谢您的反馈!`) + onClose() + } catch { + localStorage.setItem('survey-results', JSON.stringify({ items, submittedAt: new Date().toISOString() })) + toast.success(`已保存 ${items.length} 项评分到本地`) + onClose() + } finally { + setSubmitting(false) + } + } + + return ( + +
+
+ + 对 {totalFeatures} 项功能打分(1=无用 ~ 5=非常有用),帮助我们改进产品 + 已评 {ratedCount}/{totalFeatures} +
+
+ + setSearchQuery(e.target.value)} + className="w-full pl-8 pr-3 py-1.5 text-sm border border-gray-200 rounded-md focus:outline-none focus:border-primary" + /> +
+
+ + {/* 页面列表 */} +
+ {filteredPages.map(page => { + const isExpanded = expandedPage === page.id || !!searchQuery.trim() + const pageRated = page.features.filter(f => scores[f.id]?.score).length + return ( +
+ + {isExpanded && ( +
+ {page.features.map(f => { + const s = scores[f.id] + return ( +
+
+
{f.name}
+
{f.desc}
+
+ {[1, 2, 3, 4, 5].map(n => ( + + ))} +
+ {([['yes', '有用', 'text-emerald-600 border-emerald-200 bg-emerald-50'], ['no', '无用', 'text-rose-600 border-rose-200 bg-rose-50'], ['maybe', '待定', 'text-amber-600 border-amber-200 bg-amber-50']] as const).map(([val, label, cls]) => ( + + ))} +
+
+ {(s?.score > 0 || s?.useful) && ( + setRemark(f.id, e.target.value)} + className="mt-1.5 w-full text-xs px-2 py-1 border border-gray-200 rounded focus:outline-none focus:border-primary" + /> + )} +
+
+ ) + })} +
+ )} +
+ ) + })} +
+ + {/* 底部提交 */} +
+ 已评分 {ratedCount} / {totalFeatures} 项 +
+ + +
+
+
+ ) +} diff --git a/frontend/src/components/layout/TopNav.tsx b/frontend/src/components/layout/TopNav.tsx index 19973bd..cd19d9b 100644 --- a/frontend/src/components/layout/TopNav.tsx +++ b/frontend/src/components/layout/TopNav.tsx @@ -1,5 +1,5 @@ import { Link, useNavigate } from 'react-router-dom' -import { ChevronDown, Settings as SettingsIcon, Bell, Menu, HelpCircle, Smartphone } from 'lucide-react' +import { ChevronDown, Settings as SettingsIcon, Bell, Menu, HelpCircle, Smartphone, ClipboardList } from 'lucide-react' import { useState } from 'react' import { useQuery } from '@tanstack/react-query' import { useAuthStore } from '../../store/authStore' @@ -7,6 +7,7 @@ import api from '../../lib/api' import Breadcrumb from './Breadcrumb' import HelpModal from '../HelpModal' import PortalQRModal from '../PortalQRModal' +import SurveyModal from '../SurveyModal' export default function TopNav({ onMenuClick }: { onMenuClick?: () => void }) { const navigate = useNavigate() @@ -14,6 +15,7 @@ export default function TopNav({ onMenuClick }: { onMenuClick?: () => void }) { const [menuOpen, setMenuOpen] = useState(false) const [helpOpen, setHelpOpen] = useState(false) const [portalQROpen, setPortalQROpen] = useState(false) + const [surveyOpen, setSurveyOpen] = useState(false) const { data: dashboardData } = useQuery({ queryKey: ['dashboard'], @@ -58,6 +60,14 @@ export default function TopNav({ onMenuClick }: { onMenuClick?: () => void }) { setHelpOpen(false)} /> + + setSurveyOpen(false)} /> diff --git a/frontend/src/data/surveyData.ts b/frontend/src/data/surveyData.ts new file mode 100644 index 0000000..89b4211 --- /dev/null +++ b/frontend/src/data/surveyData.ts @@ -0,0 +1,453 @@ +/** 功能调查问卷数据 — 来源:docs/前端页面功能分析.md */ + +export interface SurveyFeature { + id: string + name: string + desc: string +} + +export interface SurveyPage { + id: number + name: string + file: string + features: SurveyFeature[] +} + +export const surveyPages: SurveyPage[] = [ + { + id: 1, name: 'Settings(设置页面)', file: 'frontend/src/pages/Settings.tsx', + features: [ + { id: '1.1', name: '组织信息管理', desc: '编辑公司名称、联系人、薪资发放频率等基本信息' }, + { id: '1.2', name: '退休政策提醒', desc: '设置退休政策提醒,显示退休人员名单及确认状态' }, + { id: '1.3', name: '用户管理', desc: '添加、编辑、禁用系统用户账号' }, + { id: '1.4', name: '计划设置(Plan)', desc: '查看当前套餐计划信息' }, + { id: '1.5', name: '通知设置', desc: '配置系统通知偏好' }, + { id: '1.6', name: '数据导入', desc: '批量导入员工或其他数据' }, + { id: '1.7', name: '数据导出', desc: '导出系统数据到文件' }, + ], + }, + { + id: 2, name: 'Evidence(证据管理页面)', file: 'frontend/src/pages/Evidence.tsx', + features: [ + { id: '2.1', name: '证据链列表', desc: '展示所有证据记录,含分类、状态等信息' }, + { id: '2.2', name: '分类筛选', desc: '按证据类别筛选记录' }, + { id: '2.3', name: '全局完整性验证', desc: '一键验证所有证据链的完整性' }, + ], + }, + { + id: 3, name: 'EvidenceChain(员工证据链详情)', file: 'frontend/src/pages/roster/EvidenceChain.tsx', + features: [ + { id: '3.1', name: '证据链详情展示', desc: '展示员工个人证据链,按类别分组显示' }, + { id: '3.2', name: '风险提醒', desc: '显示证据链中的风险提示信息' }, + { id: '3.3', name: '证据导出', desc: '将证据链导出为纯文本格式' }, + { id: '3.4', name: '签署状态显示', desc: '显示每条证据的签署状态' }, + ], + }, + { + id: 4, name: 'Policies(政策管理页面)', file: 'frontend/src/pages/Policies.tsx', + features: [ + { id: '4.1', name: '政策列表', desc: '展示所有公司政策及其当前流程阶段' }, + { id: '4.2', name: '创建政策', desc: '新建政策,填写标题和内容' }, + { id: '4.3', name: '民主程序推进', desc: '支持四步流程:起草→讨论→协商→公示' }, + { id: '4.4', name: '政策详情查看', desc: '查看政策完整内容和流程状态' }, + { id: '4.5', name: '员工签收统计', desc: '展示已公示政策的员工阅读和确认统计' }, + ], + }, + { + id: 5, name: 'MyPolicies(员工端政策页面)', file: 'frontend/src/pages/portal/MyPolicies.tsx', + features: [ + { id: '5.1', name: '政策列表展示', desc: '展示已公示的政策列表' }, + { id: '5.2', name: '待签收提醒', desc: '显示待确认阅读的政策数量' }, + { id: '5.3', name: '政策阅读', desc: '查看政策详细内容' }, + { id: '5.4', name: '签收确认', desc: '员工确认已阅读政策' }, + ], + }, + { + id: 6, name: 'Money(财务/薪资页面)', file: 'frontend/src/pages/Money.tsx', + features: [ + { id: '6.1', name: '加班费计算器', desc: '配置加班计算规则,导入考勤数据,生成加班费记录' }, + { id: '6.2', name: '考勤数据导入', desc: '通过 CSV 导入考勤数据用于加班计算' }, + { id: '6.3', name: '导入数据预览', desc: '导入前预览数据内容' }, + { id: '6.4', name: '加班记录查看', desc: '展示已生成的加班费记录列表' }, + { id: '6.5', name: '薪资模板管理', desc: '创建、编辑、删除薪资模板项目(输入型/计算型)' }, + { id: '6.6', name: '公式配置', desc: '为计算型薪资项配置计算公式' }, + { id: '6.7', name: '批量加班处理', desc: '批量处理多条加班记录' }, + ], + }, + { + id: 7, name: 'AttendanceOvertimeInfo(员工考勤加班详情)', file: 'frontend/src/pages/roster/AttendanceOvertimeInfo.tsx', + features: [ + { id: '7.1', name: '考勤记录展示', desc: '展示员工个人考勤记录(Tab 切换)' }, + { id: '7.2', name: '加班记录展示', desc: '展示员工个人加班记录' }, + { id: '7.3', name: '培训记录展示', desc: '展示员工培训记录' }, + { id: '7.4', name: '添加考勤记录', desc: '手动添加单条考勤记录' }, + { id: '7.5', name: '添加培训记录', desc: '手动添加单条培训记录' }, + { id: '7.6', name: '删除记录', desc: '删除考勤或培训记录' }, + { id: '7.7', name: '加班汇总', desc: '显示加班总时长和加班费汇总' }, + ], + }, + { + id: 8, name: 'Attendance(考勤确认页面)', file: 'frontend/src/pages/Attendance.tsx', + features: [ + { id: '8.1', name: '月度考勤列表', desc: '展示员工月度考勤数据(出勤天数、加班时长等)' }, + { id: '8.2', name: '统计概览', desc: '显示总数、待确认、已确认、有争议的数量统计' }, + { id: '8.3', name: '月份筛选', desc: '按月份筛选考勤记录' }, + { id: '8.4', name: '考勤状态管理', desc: '支持待确认/已确认/有争议三种状态' }, + { id: '8.5', name: '争议备注', desc: '显示考勤争议的备注信息' }, + ], + }, + { + id: 9, name: 'Templates(文档模板页面)', file: 'frontend/src/pages/Templates.tsx', + features: [ + { id: '9.1', name: '模板分类浏览', desc: '按类别浏览文档模板' }, + { id: '9.2', name: '模板选择', desc: '选择模板进行编辑和渲染' }, + { id: '9.3', name: '变量输入', desc: '填写模板变量(如员工姓名、日期等)' }, + { id: '9.4', name: '模板渲染', desc: '根据输入变量渲染模板内容' }, + { id: '9.5', name: '复制渲染结果', desc: '一键复制渲染后的文本' }, + ], + }, + { + id: 10, name: 'AuditLog(系统操作日志页面)', file: 'frontend/src/pages/AuditLog.tsx', + features: [ + { id: '10.1', name: '操作日志列表', desc: '展示系统操作记录(操作人、动作、对象、时间)' }, + { id: '10.2', name: '动作类型筛选', desc: '按操作类型筛选日志' }, + { id: '10.3', name: '实体类型筛选', desc: '按操作对象类型筛选日志' }, + { id: '10.4', name: '日期范围筛选', desc: '按时间范围筛选日志' }, + { id: '10.5', name: '统计概览', desc: '显示日志统计信息' }, + { id: '10.6', name: '分页', desc: '日志列表分页展示' }, + ], + }, + { + id: 11, name: 'Dashboard(工作台)', file: 'frontend/src/pages/Dashboard.tsx', + features: [ + { id: '11.1', name: '关键指标卡片', desc: '展示员工总数、风险数、待办数、月度薪资总额' }, + { id: '11.2', name: '紧急风险横幅', desc: '高亮显示即将到期的合同、未签合同等紧急风险' }, + { id: '11.3', name: '合规健康评分', desc: '展示合规健康分数及 AI 改进建议' }, + { id: '11.4', name: '月度人工成本分析', desc: '展示当月社保、公积金、薪资等成本构成' }, + { id: '11.5', name: '年度人工成本趋势', desc: '展示全年人工成本变化趋势图' }, + { id: '11.6', name: '合同到期预警', desc: '列出即将到期和已过期的合同' }, + { id: '11.7', name: '月度动态列表', desc: '展示本月入职、离职、调薪等关键人事动态' }, + { id: '11.8', name: '风险分布下钻', desc: '按风险类型展示分布,支持下钻查看详情' }, + { id: '11.9', name: '月度 HR 日历', desc: '以日历形式展示本月关键 HR 节点' }, + ], + }, + { + id: 12, name: 'Roster(员工花名册)', file: 'frontend/src/pages/Roster.tsx', + features: [ + { id: '12.1', name: '员工列表', desc: '展示所有员工的基本信息、状态、合同状态' }, + { id: '12.2', name: '搜索功能', desc: '按姓名、手机号搜索员工' }, + { id: '12.3', name: '状态筛选', desc: '按在职/离职状态筛选' }, + { id: '12.4', name: '合同状态筛选', desc: '按合同状态(正常/即将到期/已到期/未签)筛选' }, + { id: '12.5', name: '添加员工', desc: '弹窗表单添加新员工' }, + { id: '12.6', name: '批量导入', desc: '通过 CSV 文件批量导入员工' }, + { id: '12.7', name: '批量续签', desc: '选中多个员工批量发起合同续签' }, + { id: '12.8', name: '批量解聘', desc: '选中多个员工批量发起解聘流程' }, + { id: '12.9', name: '调薪操作', desc: '对单个员工发起调薪' }, + { id: '12.10', name: '调岗操作', desc: '对单个员工发起部门调岗' }, + { id: '12.11', name: '离职处理', desc: '对单个员工发起离职流程' }, + { id: '12.12', name: '重新入职', desc: '对已离职员工发起重新入职' }, + { id: '12.13', name: '撤销离职', desc: '撤销已发起的离职流程' }, + { id: '12.14', name: '查看员工档案', desc: '跳转到员工详情档案页' }, + ], + }, + { + id: 13, name: 'Contracts(合同管理)', file: 'frontend/src/pages/Contracts.tsx', + features: [ + { id: '13.1', name: '合同列表', desc: '展示员工合同状态列表(含特殊状态标记:孕期、医疗期、工伤)' }, + { id: '13.2', name: '搜索员工', desc: '按姓名/手机号搜索' }, + { id: '13.3', name: '添加员工', desc: '弹窗添加新员工(含合同信息)' }, + { id: '13.4', name: '合同详情抽屉', desc: '侧边抽屉展示员工合同详细信息' }, + { id: '13.5', name: '附件管理', desc: '上传、预览、下载、删除合同附件(身份证、银行卡、合同扫描件等)' }, + ], + }, + { + id: 14, name: 'Termination(解聘补偿)', file: 'frontend/src/pages/Termination.tsx', + features: [ + { id: '14.1', name: '解聘草稿列表', desc: '展示所有解聘草稿及状态' }, + { id: '14.2', name: '多步解聘向导', desc: '选择员工→选择原因→合规检查→费用结算→工作交接→确认提交' }, + { id: '14.3', name: '解聘原因选择', desc: '选择解聘原因并展示法律依据和建议' }, + { id: '14.4', name: '合规检查', desc: '自动检查解聘流程的合规性' }, + { id: '14.5', name: '补偿计算', desc: '自动计算经济补偿金、代通知金、双倍工资等' }, + { id: '14.6', name: '工作交接清单', desc: '管理交接事项清单' }, + { id: '14.7', name: '草稿详情查看', desc: '查看解聘草稿完整详情' }, + { id: '14.8', name: '审批操作', desc: '审批通过/驳回解聘草稿' }, + { id: '14.9', name: '执行解聘', desc: '执行已审批通过的解聘' }, + { id: '14.10', name: '撤销解聘', desc: '撤销已发起的解聘流程' }, + ], + }, + { + id: 15, name: 'Compensation(补偿计算器)', file: 'frontend/src/pages/Compensation.tsx', + features: [ + { id: '15.1', name: '经济补偿计算', desc: '根据入职日期、离职日期、月均工资计算经济补偿金' }, + { id: '15.2', name: '双倍工资计算', desc: '根据入职日期和合同签订日期计算未签合同双倍工资' }, + { id: '15.3', name: '员工选择', desc: '选择已有员工自动填充信息' }, + { id: '15.4', name: '手动输入', desc: '手动输入各项参数进行计算' }, + { id: '15.5', name: '社平工资封顶', desc: '按当地社平工资三倍封顶计算' }, + { id: '15.6', name: '违法解除倍数', desc: '支持违法解除双倍补偿计算' }, + { id: '15.7', name: '法律依据展示', desc: '展示计算结果对应的法律条文' }, + ], + }, + { + id: 16, name: 'SocialInsurance(社保公积金)', file: 'frontend/src/pages/SocialInsurance.tsx', + features: [ + { id: '16.1', name: '月度处理', desc: '查看月度增减员变化,处理社保/公积金申报' }, + { id: '16.2', name: '社保政策配置', desc: '按城市配置社保缴纳比例和基数上下限' }, + { id: '16.3', name: '公积金政策配置', desc: '按城市配置公积金缴纳比例和基数上下限' }, + { id: '16.4', name: '专项扣除配置', desc: '配置个人所得税专项扣除信息' }, + { id: '16.5', name: '新版本创建', desc: '创建新的社保/公积金政策版本' }, + { id: '16.6', name: '缴纳计算', desc: '根据员工工资和政策计算缴纳金额' }, + { id: '16.7', name: 'AI 政策建议', desc: 'AI 辅助建议政策更新' }, + ], + }, + { + id: 17, name: 'Notifications(通知管理)', file: 'frontend/src/pages/Notifications.tsx', + features: [ + { id: '17.1', name: '通知概览', desc: '展示已启用的通知类型及数量' }, + { id: '17.2', name: '通知日志', desc: '展示已发送通知的历史记录' }, + { id: '17.3', name: '合同到期检查', desc: '手动触发合同到期检查' }, + { id: '17.4', name: '提醒天数配置', desc: '配置合同到期提前提醒天数' }, + { id: '17.5', name: '薪资/社保/公积金/税务日配置', desc: '配置各项事务的提醒日期' }, + { id: '17.6', name: '微信通知配置', desc: '配置企业微信 Webhook URL' }, + { id: '17.7', name: '邮件通知配置', desc: '配置邮件通知开关和参数' }, + ], + }, + { + id: 18, name: 'AIAssistant(AI 助手)', file: 'frontend/src/pages/AIAssistant.tsx', + features: [ + { id: '18.1', name: '智能问答', desc: '劳动法相关问题的 AI 对话' }, + { id: '18.2', name: '风险预测', desc: 'AI 分析预测潜在用工风险' }, + { id: '18.3', name: '合同审查', desc: 'AI 审查合同条款合规性' }, + { id: '18.4', name: '案例匹配', desc: '根据情况匹配相关法律案例' }, + { id: '18.5', name: '知识库', desc: '查询劳动法合规知识库' }, + { id: '18.6', name: '对话历史', desc: '查看和继续历史对话' }, + { id: '18.7', name: '语音输入', desc: '支持语音输入提问' }, + { id: '18.8', name: '新建对话', desc: '发起新的 AI 对话' }, + ], + }, + { + id: 19, name: 'Login(HR 端登录)', file: 'frontend/src/pages/auth/Login.tsx', + features: [ + { id: '19.1', name: '手机号+密码登录', desc: 'HR 端账号密码登录' }, + { id: '19.2', name: '表单校验', desc: '手机号格式和密码非空校验' }, + { id: '19.3', name: '密码显示切换', desc: '显示/隐藏密码' }, + { id: '19.4', name: '忘记密码链接', desc: '跳转重置密码页面' }, + { id: '19.5', name: '注册链接', desc: '跳转注册新企业页面' }, + ], + }, + { + id: 20, name: 'ForgotPassword(忘记密码)', file: 'frontend/src/pages/auth/ForgotPassword.tsx', + features: [ + { id: '20.1', name: '发送验证码', desc: '输入手机号发送验证码' }, + { id: '20.2', name: '验证码+新密码重置', desc: '输入验证码和新密码完成重置' }, + { id: '20.3', name: '密码显示切换', desc: '显示/隐藏新密码' }, + { id: '20.4', name: '重新获取验证码', desc: '返回第一步重新获取验证码' }, + ], + }, + { + id: 21, name: 'Register(注册新企业)', file: 'frontend/src/pages/auth/Register.tsx', + features: [ + { id: '21.1', name: '企业注册', desc: '填写企业名称、手机号、密码注册新企业' }, + { id: '21.2', name: '表单校验', desc: '企业名称长度、手机号格式、密码长度、两次密码一致性校验' }, + { id: '21.3', name: '密码显示切换', desc: '显示/隐藏密码' }, + { id: '21.4', name: '注册后自动登录', desc: '注册成功后自动登录并跳转工作台' }, + ], + }, + { + id: 22, name: 'PortalLogin(员工端登录)', file: 'frontend/src/pages/portal/PortalLogin.tsx', + features: [ + { id: '22.1', name: '密码登录', desc: '员工手机号+密码登录' }, + { id: '22.2', name: '验证码登录', desc: '员工手机号+短信验证码登录' }, + { id: '22.3', name: '登录模式切换', desc: '密码登录/验证码登录切换' }, + { id: '22.4', name: '发送验证码', desc: '向员工手机发送验证码' }, + ], + }, + { + id: 23, name: 'AutoLogin(员工端自动登录)', file: 'frontend/src/pages/portal/AutoLogin.tsx', + features: [ + { id: '23.1', name: '扫码自动登录', desc: '通过一次性 Token 自动登录员工端' }, + { id: '23.2', name: '登录状态展示', desc: '展示加载中/成功/失败状态' }, + { id: '23.3', name: '失败回退', desc: '登录失败时提供手动登录入口' }, + ], + }, + { + id: 24, name: 'Onboarding(入职信息填报)', file: 'frontend/src/pages/portal/Onboarding.tsx', + features: [ + { id: '24.1', name: '入职表单填写', desc: '填写姓名、手机号、身份证号、紧急联系人等' }, + { id: '24.2', name: '入职材料上传', desc: '上传身份证、学历证明、银行卡等材料' }, + { id: '24.3', name: '文件类型选择', desc: '选择上传文件的类型(身份证正反面、学历、银行卡、其他)' }, + { id: '24.4', name: '已传文件管理', desc: '查看和删除已上传文件' }, + { id: '24.5', name: '提交成功页', desc: '提交后展示成功提示' }, + ], + }, + { + id: 25, name: 'Payslip(员工端工资条)', file: 'frontend/src/pages/portal/Payslip.tsx', + features: [ + { id: '25.1', name: '月度工资条', desc: '展示当月工资明细(基本工资、加班费、津贴、扣款)' }, + { id: '25.2', name: '月份切换', desc: '上月/下月切换查看历史工资条' }, + { id: '25.3', name: '工资趋势图', desc: '展示近几个月工资趋势条形图' }, + { id: '25.4', name: '确认查收', desc: '员工确认已阅当月工资条' }, + { id: '25.5', name: '导出 CSV', desc: '导出历史工资条为 CSV 文件' }, + ], + }, + { + id: 26, name: 'MyContract(我的劳动合同 - 员工端)', file: 'frontend/src/pages/portal/MyContract.tsx', + features: [ + { id: '26.1', name: '合同概览', desc: '展示合同类型、签订方式、起止日期、试用期等信息' }, + { id: '26.2', name: '到期提醒', desc: '合同30天内到期时展示提醒横幅' }, + { id: '26.3', name: '签署确认状态', desc: '展示合同是否已确认签署' }, + { id: '26.4', name: '重发确认链接', desc: '未确认时可重发合同签署确认链接' }, + ], + }, + { + id: 27, name: 'ContractConfirm(合同签署确认)', file: 'frontend/src/pages/portal/ContractConfirm.tsx', + features: [ + { id: '27.1', name: '合同信息展示', desc: '展示合同类型、期限、起止日期、试用期等' }, + { id: '27.2', name: '阅读确认', desc: '勾选确认已阅读合同内容' }, + { id: '27.3', name: '验证码验证', desc: '发送验证码并验证身份' }, + { id: '27.4', name: '签署确认', desc: '确认签署并记录时间、IP、设备信息' }, + { id: '27.5', name: '成功页面', desc: '确认成功后展示成功提示' }, + ], + }, + { + id: 28, name: 'PortalNav(员工端导航栏)', file: 'frontend/src/pages/portal/PortalNav.tsx', + features: [ + { id: '28.1', name: '页面导航', desc: '工资条/我的合同/规章制度三个导航入口' }, + { id: '28.2', name: '当前页高亮', desc: '高亮显示当前所在页面' }, + { id: '28.3', name: '退出登录', desc: '员工端退出登录' }, + ], + }, + { + id: 29, name: 'EmployeeProfile(员工详情档案)', file: 'frontend/src/pages/roster/EmployeeProfile.tsx', + features: [ + { id: '29.1', name: 'Tab 分组导航', desc: '按分组展示 Tab:人事信息、薪酬、考勤绩效、风险合规、变更历史' }, + { id: '29.2', name: 'Tab 计数徽标', desc: '每个 Tab 显示对应记录数量' }, + { id: '29.3', name: '离职员工 Tab 隐藏', desc: '离职员工自动隐藏考勤和绩效 Tab' }, + { id: '29.4', name: '员工状态展示', desc: '展示员工姓名和在职/离职状态' }, + ], + }, + { + id: 30, name: 'BasicInfo(基本信息 Tab)', file: 'frontend/src/pages/roster/BasicInfo.tsx', + features: [ + { id: '30.1', name: '基本信息展示', desc: '展示员工部门、性别、手机号、入职日期、月薪等' }, + { id: '30.2', name: '信息编辑', desc: '编辑员工基本信息(部门、薪资、联系方式等)' }, + { id: '30.3', name: '特殊状态标记', desc: '标记三期/医疗期/工伤状态' }, + { id: '30.4', name: '社保公积金基数', desc: '设置社保基数、公积金基数、专项扣除' }, + { id: '30.5', name: '城市设置', desc: '设置员工所在城市(影响社保政策)' }, + { id: '30.6', name: '附件上传', desc: '上传身份证、银行卡、学历证书等附件' }, + { id: '30.7', name: '附件管理', desc: '查看和删除已上传附件' }, + { id: '30.8', name: '入职二维码', desc: '生成员工端自动登录二维码' }, + ], + }, + { + id: 31, name: 'ContractInfo(劳动合同 Tab)', file: 'frontend/src/pages/roster/ContractInfo.tsx', + features: [ + { id: '31.1', name: '合同列表', desc: '展示员工所有合同记录' }, + { id: '31.2', name: '添加合同', desc: '新增合同(类型、期限、试用期、签署方式等)' }, + { id: '31.3', name: '合同附件上传', desc: '上传合同扫描件等附件' }, + { id: '31.4', name: '合同删除', desc: '删除合同记录' }, + { id: '31.5', name: '续签建议', desc: '根据合同次数和工龄自动建议合同类型(无固定期限等)' }, + { id: '31.6', name: '合同签署确认链接', desc: '发送电子合同签署确认链接' }, + ], + }, + { + id: 32, name: 'PayslipSocialInfo(薪酬社保 Tab)', file: 'frontend/src/pages/roster/PayslipSocialInfo.tsx', + features: [ + { id: '32.1', name: '工资条列表', desc: '展示员工所有月度工资条(含合计行)' }, + { id: '32.2', name: '缴纳记录', desc: '展示社保/公积金月度缴纳记录' }, + { id: '32.3', name: '城市变更历史', desc: '展示员工城市变更记录' }, + ], + }, + { + id: 33, name: 'DisciplinaryInfo(违纪记录 Tab)', file: 'frontend/src/pages/roster/DisciplinaryInfo.tsx', + features: [ + { id: '33.1', name: '违纪记录列表', desc: '展示员工违纪记录' }, + { id: '33.2', name: '新增违纪记录', desc: '录入违纪类型、事实描述、严重程度、处理结果' }, + { id: '33.3', name: '员工签字确认', desc: '标记员工是否已签字确认违纪处理' }, + { id: '33.4', name: '删除违纪记录', desc: '删除违纪记录' }, + ], + }, + { + id: 34, name: 'PerformanceInfo(绩效考核 Tab)', file: 'frontend/src/pages/roster/PerformanceInfo.tsx', + features: [ + { id: '34.1', name: '绩效记录列表', desc: '展示员工绩效考核记录' }, + { id: '34.2', name: '新增绩效记录', desc: '录入考核周期、得分、等级、结果、评语、改进计划' }, + { id: '34.3', name: '员工签字确认', desc: '标记员工是否已签字确认考核结果' }, + { id: '34.4', name: '删除绩效记录', desc: '删除绩效记录' }, + ], + }, + { + id: 35, name: 'TerminationInfo(离职/解聘 Tab)', file: 'frontend/src/pages/roster/TerminationInfo.tsx', + features: [ + { id: '35.1', name: '离职记录列表', desc: '展示员工离职/解聘记录' }, + { id: '35.2', name: '解聘通知书打印', desc: '生成并打印解除劳动合同通知书' }, + { id: '35.3', name: '费用结算明细', desc: '展示补偿金、代通知金等费用结算' }, + { id: '35.4', name: '证据链关联', desc: '关联展示解聘相关证据链' }, + { id: '35.5', name: '已撤销记录', desc: '展示已撤销的解聘记录' }, + ], + }, + { + id: 36, name: 'AttachmentInfo(附件管理 Tab)', file: 'frontend/src/pages/roster/AttachmentInfo.tsx', + features: [ + { id: '36.1', name: '附件列表', desc: '展示员工所有附件文件' }, + { id: '36.2', name: '按类型上传', desc: '选择文件类型(身份证/银行卡/学历/其他)上传' }, + { id: '36.3', name: '附件预览', desc: '预览已上传的附件' }, + { id: '36.4', name: '附件下载', desc: '下载附件文件' }, + { id: '36.5', name: '附件删除', desc: '删除附件' }, + ], + }, + { + id: 37, name: 'ChangeHistoryTab(变更历史 Tab)', file: 'frontend/src/pages/roster/ChangeHistoryTab.tsx', + features: [ + { id: '37.1', name: '薪资变更历史', desc: '展示薪资调整记录(原薪资、新薪资、变动额、原因)' }, + { id: '37.2', name: '部门变更历史', desc: '展示部门调岗记录' }, + { id: '37.3', name: '社保变更历史', desc: '展示社保缴纳变更记录' }, + { id: '37.4', name: '公积金变更历史', desc: '展示公积金缴纳变更记录' }, + { id: '37.5', name: '离职/解聘历史', desc: '展示离职解聘记录' }, + ], + }, + { + id: 38, name: 'AnnualValueReport(年度价值报告)', file: 'frontend/src/pages/tools/AnnualValueReport.tsx', + features: [ + { id: '38.1', name: '价值指标卡片', desc: '展示规避损失、节约工时、节约成本、总价值' }, + { id: '38.2', name: '年度统计', desc: '展示处理风险数、AI咨询数、合同审查数等年度统计' }, + { id: '38.3', name: '月度时间轴', desc: '展示全年月度价值变化趋势图' }, + { id: '38.4', name: '年份切换', desc: '切换查看不同年份的价值报告' }, + { id: '38.5', name: '报告保存', desc: '保存当前年度价值报告' }, + { id: '38.6', name: '历史报告', desc: '查看已保存的历史报告' }, + ], + }, + { + id: 39, name: 'HealthCheck(用工体检诊断)', file: 'frontend/src/pages/tools/HealthCheck.tsx', + features: [ + { id: '39.1', name: '总体健康评分', desc: '展示用工合规总体评分和等级(健康/中等风险/高风险)' }, + { id: '39.2', name: '6 维度诊断', desc: '从6个维度深度诊断用工合规状况' }, + { id: '39.3', name: '维度展开详情', desc: '展开查看每个维度的详细问题' }, + { id: '39.4', name: '报告保存', desc: '保存当前诊断报告' }, + { id: '39.5', name: '历史报告', desc: '查看已保存的历史诊断报告' }, + ], + }, + { + id: 40, name: 'MedicalPeriodCalculator(医疗期计算器)', file: 'frontend/src/pages/tools/MedicalPeriodCalculator.tsx', + features: [ + { id: '40.1', name: '医疗期计算', desc: '根据工龄、地区、病休天数计算法定医疗期' }, + { id: '40.2', name: '上海特殊规定', desc: '支持上海地区特殊医疗期计算规则' }, + { id: '40.3', name: '全国通用规定', desc: '支持全国通用医疗期计算(劳部发[1994]479号)' }, + { id: '40.4', name: '法律依据展示', desc: '展示计算结果对应的法律条文' }, + { id: '40.5', name: '注意事项提示', desc: '展示医疗期相关注意事项' }, + ], + }, + { + id: 41, name: 'RosterModals(花名册弹窗组件)', file: 'frontend/src/pages/roster/modals.tsx', + features: [ + { id: '41.1', name: '调薪弹窗', desc: '输入新薪资、生效日期、原因发起调薪' }, + { id: '41.2', name: '调岗弹窗', desc: '输入新部门、生效日期、原因发起调岗' }, + { id: '41.3', name: '离职弹窗', desc: '发起员工离职流程' }, + { id: '41.4', name: '重新入职弹窗', desc: '对已离职员工发起重新入职' }, + { id: '41.5', name: '添加员工弹窗', desc: '录入新员工基本信息' }, + { id: '41.6', name: '批量导入弹窗', desc: '上传 CSV 批量导入员工' }, + ], + }, +] + +/** 总功能数 */ +export const totalFeatures = surveyPages.reduce((sum, p) => sum + p.features.length, 0)