diff --git a/20260816-优化.md b/20260816-优化.md index 7704b89..97c006a 100644 --- a/20260816-优化.md +++ b/20260816-优化.md @@ -3,6 +3,8 @@ > 来源:用户测试反馈(编号 4-13,共 10 项) > 结合 TurboHR 当期代码梳理,按模块归类,标注根因 / 修复方向 / 优先级 / 涉及文件。 > 优先级:P0 紧急(影响业务正确性/合规)|P1 高(流程阻塞或合规风险)|P2 中(体验/增强)|P3 规划(新模块) +> +> **✅ 全部 10 项已于 20260816 完成实现,前后端 tsc 均通过。完成明细见"五、已完成优化"章节(编号 5-15)。** --- @@ -186,25 +188,34 @@ ## 优先级汇总 -| 优先级 | 问题 | 说明 | -|--------|------|------| -| **P0 紧急** | 10A | 风险提醒反向引导(三期/医疗期/工伤提醒跳转到解聘页面) | -| **P1 高** | 4、5、6、7、8、9、11 | 花名册添加雇员合规校验 + 工作台待办跳转 + 试用期工资判定修正 | -| **P2 中** | 10B、13 | 风险提醒规则优化 + 薪资批次获取提成奖金(13 依赖 12) | -| **P3 规划** | 12 | 提成奖金新模块(需单独排期 + DB migration) | +| 优先级 | 问题 | 说明 | 状态 | +|--------|------|------|------| +| **P0 紧急** | 10A | 风险提醒反向引导(三期/医疗期/工伤提醒跳转到解聘页面) | ✅ 已完成 | +| **P1 高** | 4 | 合同状态增加待签署判定 | ✅ 已完成 | +| **P1 高** | 5 | 社保状态派生字段(待办/正常/停缴) | ✅ 已完成 | +| **P1 高** | 6 | 证件号码有效性校验(校验位+出生日期) | ✅ 已完成 | +| **P1 高** | 7 | 超龄人员合同类型限制(禁止选劳动合同) | ✅ 已完成 | +| **P1 高** | 8 | 劳务协议社保联动(选 LABOR 社保基数置 0 禁用) | ✅ 已完成 | +| **P1 高** | 9 | 待办跳转 actionUrl 修正 + 空值降级 | ✅ 已完成 | +| **P1 高** | 11 | 试用期工资判定修正(抽取 isInProbation 工具函数) | ✅ 已完成 | +| **P2 中** | 10B | 风险提醒规则优化(到期 30→60 天分级 + 去重排序) | ✅ 已完成 | +| **P2 中** | 13 | 薪资批次获取提成奖金(依赖 12) | ✅ 已完成 | +| **P3 规划** | 12 | 提成奖金新模块(DB migration + 全栈实现) | ✅ 已完成 | --- ## 建议执行顺序 -1. **第一批(P0 + P1,立即)**: +> ✅ 全部 10 项已于 20260816 完成实现,前后端 tsc 均通过。 + +1. **第一批(P0 + P1,立即)** ✅: - 问题 10A(风险提醒反向引导,改 actionUrl)← 最先,改动小风险高 - 问题 11(试用期工资判定修正)← 纯后端逻辑修正,抽取 `isInProbation` 工具函数 - 问题 6(证件号码有效性校验)→ 问题 7(超龄人员合同类型限制)→ 问题 8(劳务协议社保联动)→ 问题 4(合同状态待签署)→ 问题 5(社保状态待办)→ 问题 9(待办跳转) - 问题 6/7/8 均在 `roster/modals.tsx` 添加雇员表单,可一并修改;问题 4/5 在后端 `contract.service.ts`/`employee.service.ts` 派生字段,前后端协同。 -2. **第二批(P2,本迭代)**: +2. **第二批(P2,本迭代)** ✅: - 问题 10B(风险提醒规则梳理)→ 问题 13(获取提成奖金,依赖问题 12) -3. **第三批(P3,规划)**: +3. **第三批(P3,规划)** ✅: - 问题 12(提成奖金新模块,含 DB migration)→ 问题 13(获取提成奖金,依赖 12 完成) --- diff --git a/backend/src/services/risk.service.ts b/backend/src/services/risk.service.ts index ce95df5..19ffe25 100644 --- a/backend/src/services/risk.service.ts +++ b/backend/src/services/risk.service.ts @@ -435,10 +435,10 @@ export async function detectMonthlyTasks(orgId: string) { const today = now.getDate() const tasks = [ - { day: setting.payrollDay, title: `${currentMonth}月 发放工资`, desc: `每月${setting.payrollDay}日前完成工资发放`, url: '/money' }, - { day: setting.socialInsDay, title: `${currentMonth}月 缴纳社保`, desc: `每月${setting.socialInsDay}日前完成社保缴纳`, url: '/money' }, - { day: setting.housingFundDay, title: `${currentMonth}月 缴纳公积金`, desc: `每月${setting.housingFundDay}日前完成公积金缴纳`, url: '/money' }, - { day: setting.taxDay, title: `${currentMonth}月 申报个税`, desc: `每月${setting.taxDay}日前完成个税申报`, url: '/money' }, + { day: setting.payrollDay, title: `${currentMonth}月 发放工资`, desc: `每月${setting.payrollDay}日前完成工资发放`, url: '/money?tab=batch' }, + { day: setting.socialInsDay, title: `${currentMonth}月 缴纳社保`, desc: `每月${setting.socialInsDay}日前完成社保缴纳`, url: '/social?tab=monthly' }, + { day: setting.housingFundDay, title: `${currentMonth}月 缴纳公积金`, desc: `每月${setting.housingFundDay}日前完成公积金缴纳`, url: '/social?tab=monthly' }, + { day: setting.taxDay, title: `${currentMonth}月 申报个税`, desc: `每月${setting.taxDay}日前完成个税申报`, url: '/money?tab=batch' }, ] const risks: { employeeId: null; type: RiskType; level: RiskLevel; title: string; description: string; actionUrl: string }[] = [] diff --git a/frontend/src/pages/Money.tsx b/frontend/src/pages/Money.tsx index 89a1372..fad6366 100644 --- a/frontend/src/pages/Money.tsx +++ b/frontend/src/pages/Money.tsx @@ -13,7 +13,8 @@ type Tab = 'batch' | 'template' | 'overtime' | 'payslip' export default function Money() { const [searchParams] = useSearchParams() const initialEmployeeId = searchParams.get('employeeId') || '' - const [tab, setTab] = useState(initialEmployeeId ? 'payslip' : 'batch') + const initialTab = (searchParams.get('tab') as Tab) || (initialEmployeeId ? 'payslip' : 'batch') + const [tab, setTab] = useState(initialTab) const tabs: { key: Tab; label: string; icon: React.ReactNode }[] = [ { key: 'batch', label: '发薪批次', icon: }, diff --git a/frontend/src/pages/SocialInsurance.tsx b/frontend/src/pages/SocialInsurance.tsx index 197b58d..0731f8b 100644 --- a/frontend/src/pages/SocialInsurance.tsx +++ b/frontend/src/pages/SocialInsurance.tsx @@ -1,4 +1,5 @@ import { useState, useEffect } from 'react' +import { useSearchParams } from 'react-router-dom' import { toast } from 'sonner' import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query' import { useConfirm } from '../hooks/useConfirm' @@ -19,7 +20,9 @@ const fmt = (n: number) => (n || 0).toLocaleString('zh-CN', { minimumFractionDig export default function SocialInsurance() { const queryClient = useQueryClient() const confirm = useConfirm() - const [tab, setTab] = useState<'monthly' | 'social' | 'housing' | 'deduction' | 'enrollment'>('monthly') + const [searchParams] = useSearchParams() + const initialTab = (searchParams.get('tab') as 'monthly' | 'social' | 'housing' | 'deduction' | 'enrollment') || 'monthly' + const [tab, setTab] = useState<'monthly' | 'social' | 'housing' | 'deduction' | 'enrollment'>(initialTab) const [city, setCity] = useState('北京') const [showAddCity, setShowAddCity] = useState(false) const [newCityName, setNewCityName] = useState('')