diff --git a/backend/src/services/risk.service.ts b/backend/src/services/risk.service.ts index 8400f5d..1e8da3f 100644 --- a/backend/src/services/risk.service.ts +++ b/backend/src/services/risk.service.ts @@ -167,7 +167,7 @@ export async function detectContractRisks(orgId: string) { level: 'HIGH', title: `${emp.name}入职${Math.round(days / 30)}个月未签合同,已视为无固定期限`, description: `入职日期 ${emp.hireDate.toISOString().slice(0, 10)},超过1年未签订书面合同,法律上已视为无固定期限劳动合同。`, - actionUrl: `/contracts?employee=${encodeURIComponent(emp.name)}`, + actionUrl: `/roster?employee=${encodeURIComponent(emp.name)}`, }) } else if (days > 30) { risks.push({ @@ -176,7 +176,7 @@ export async function detectContractRisks(orgId: string) { level: 'HIGH', title: `${emp.name}入职${Math.round(days / 30)}个月未签合同`, description: `入职日期 ${emp.hireDate.toISOString().slice(0, 10)},超过30天未签订书面合同,需尽快补签。`, - actionUrl: `/contracts?employee=${encodeURIComponent(emp.name)}`, + actionUrl: `/roster?employee=${encodeURIComponent(emp.name)}`, }) } else { risks.push({ @@ -185,7 +185,7 @@ export async function detectContractRisks(orgId: string) { level: 'LOW', title: `${emp.name}入职${Math.round(days / 30)}个月,尚未签合同`, description: `入职日期 ${emp.hireDate.toISOString().slice(0, 10)},30天内需签订书面合同。`, - actionUrl: `/contracts?employee=${encodeURIComponent(emp.name)}`, + actionUrl: `/roster?employee=${encodeURIComponent(emp.name)}`, }) } continue @@ -200,7 +200,7 @@ export async function detectContractRisks(orgId: string) { level: 'HIGH', title: `${emp.name}的合同已到期${Math.abs(daysToExpire)}天未续签`, description: `合同到期日 ${latestContract.endDate.toISOString().slice(0, 10)},已过期未续签。`, - actionUrl: `/contracts?employee=${encodeURIComponent(emp.name)}`, + actionUrl: `/roster?employee=${encodeURIComponent(emp.name)}`, }) } else if (daysToExpire <= 30) { risks.push({ @@ -209,7 +209,7 @@ export async function detectContractRisks(orgId: string) { level: 'MEDIUM', title: `${emp.name}的合同即将到期(${daysToExpire}天)`, description: `合同到期日 ${latestContract.endDate.toISOString().slice(0, 10)},需提前准备续签或终止。`, - actionUrl: `/contracts?employee=${encodeURIComponent(emp.name)}`, + actionUrl: `/roster?employee=${encodeURIComponent(emp.name)}`, }) } } @@ -230,7 +230,7 @@ export async function detectContractRisks(orgId: string) { level: 'MEDIUM', title: `${emp.name}试用期${latestContract.probationMonths}个月可能不合法`, description: `${contractMonths}个月合同试用期最多${maxProbation}个月,当前${latestContract.probationMonths}个月超出法定上限。`, - actionUrl: `/contracts?employee=${encodeURIComponent(emp.name)}`, + actionUrl: `/roster?employee=${encodeURIComponent(emp.name)}`, }) } } diff --git a/frontend/src/pages/Roster.tsx b/frontend/src/pages/Roster.tsx index 048dac1..8b299da 100644 --- a/frontend/src/pages/Roster.tsx +++ b/frontend/src/pages/Roster.tsx @@ -1,4 +1,5 @@ -import { useState, useMemo } from 'react' +import { useState, useMemo, 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' @@ -20,6 +21,7 @@ import { ImportSettings } from './Settings' export default function Roster() { const queryClient = useQueryClient() const confirm = useConfirm() + const [searchParams, setSearchParams] = useSearchParams() const [selectedId, setSelectedId] = useState(null) const [search, setSearch] = useState('') const debouncedSearch = useDebouncedValue(search, 300) @@ -67,6 +69,18 @@ export default function Roster() { }) const pagination = rosterData?.pagination || { page, pageSize, total: 0, totalPages: 0 } + // 从 URL query 参数自动定位员工(从待办跳转时) + useEffect(() => { + const emp = searchParams.get('employee') + if (emp) { + setSearch(emp) + // 搜索结果加载后自动打开第一个匹配的员工 + if (!isLoading && employees.length > 0 && !selectedId) { + setSelectedId(employees[0].id) + } + } + }, [searchParams, isLoading, employees, selectedId]) + const addMutation = useMutation({ mutationFn: (data: any) => api.post('/employees', data), onSuccess: () => {