fix: portal端token过期后自动跳转登录页,避免显示空数据

- portalAxios 401 响应拦截器:清除 token 并跳转 /portal/login
- PortalLayoutWrapper:检查 token 是否存在,不存在则跳转登录页
- 排除 /portal/login 和 /portal/auto-login 页面避免重复跳转

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
selfrelease
2026-08-17 15:06:46 +08:00
parent c66ea290eb
commit 5196d7c80a
23 changed files with 812 additions and 74 deletions
+79 -1
View File
@@ -3,7 +3,7 @@ import { usePageSize } from '../../hooks/usePageSize'
import { toast } from 'sonner'
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'
import { useConfirm } from '../../hooks/useConfirm'
import { Calculator, AlertCircle, Info, Upload, Layers, Settings as SettingsIcon, Archive, Plus, Trash2, AlertTriangle, Download, FileText, X, ChevronLeft, Clock, Users, TrendingDown, TrendingUp, BadgeCheck, DollarSign } from 'lucide-react'
import { Calculator, AlertCircle, Info, Upload, Layers, Settings as SettingsIcon, Archive, Plus, Trash2, AlertTriangle, Download, FileText, X, ChevronLeft, Clock, Users, TrendingDown, TrendingUp, BadgeCheck, DollarSign, CalendarCheck } from 'lucide-react'
import { Stepper, type Step } from '../../components/ui/Stepper'
import { InlineAlert } from '../../components/ui/InlineAlert'
import PageGuide from '../../components/ui/PageGuide'
@@ -597,6 +597,54 @@ function BatchDetail({ batchId, onBack }: { batchId: string; onBack: () => void
},
})
const fetchPerformanceMutation = useMutation({
mutationFn: () => payrollApi.fetchPerformanceToBatch(batchId),
onSuccess: (res: any) => {
queryClient.invalidateQueries({ queryKey: ['batch-detail'] })
queryClient.invalidateQueries({ queryKey: ['batches'] })
if (res.data?.filled > 0) {
toast.success(res.data.message)
} else {
toast.info(res.data?.message || '无绩效工资数据')
}
},
onError: () => {
toast.error('获取绩效工资失败')
},
})
const fetchDisciplinaryMutation = useMutation({
mutationFn: () => payrollApi.fetchDisciplinaryToBatch(batchId),
onSuccess: (res: any) => {
queryClient.invalidateQueries({ queryKey: ['batch-detail'] })
queryClient.invalidateQueries({ queryKey: ['batches'] })
if (res.data?.filled > 0) {
toast.success(res.data.message)
} else {
toast.info(res.data?.message || '无违纪扣款数据')
}
},
onError: () => {
toast.error('获取违纪扣款失败')
},
})
const fetchAttendanceDeductionMutation = useMutation({
mutationFn: () => payrollApi.fetchAttendanceDeductionToBatch(batchId),
onSuccess: (res: any) => {
queryClient.invalidateQueries({ queryKey: ['batch-detail'] })
queryClient.invalidateQueries({ queryKey: ['batches'] })
if (res.data?.filled > 0) {
toast.success(res.data.message)
} else {
toast.info(res.data?.message || '无考勤扣款数据')
}
},
onError: () => {
toast.error('获取考勤扣款失败')
},
})
const importPayrollMutation = useMutation({
mutationFn: async (file: File) => {
const token = useAuthStore.getState().accessToken
@@ -825,6 +873,36 @@ function BatchDetail({ batchId, onBack }: { batchId: string; onBack: () => void
<DollarSign className="w-4 h-4 mr-1" />
{fetchBonusMutation.isPending ? '获取中...' : '获取提成奖金'}
</Button>
<Button
variant="secondary"
size="sm"
onClick={() => fetchPerformanceMutation.mutate()}
disabled={fetchPerformanceMutation.isPending || isArchived}
title="按考核等级系数计算绩效工资(A=1.2/B=1.0/C=0.8/D=0.6),无考核记录按1.0"
>
<TrendingUp className="w-4 h-4 mr-1" />
{fetchPerformanceMutation.isPending ? '获取中...' : '获取绩效工资'}
</Button>
<Button
variant="secondary"
size="sm"
onClick={() => fetchDisciplinaryMutation.mutate()}
disabled={fetchDisciplinaryMutation.isPending || isArchived}
title="按批次月份从违纪记录中汇总扣款金额(action=DEDUCTION"
>
<AlertTriangle className="w-4 h-4 mr-1" />
{fetchDisciplinaryMutation.isPending ? '获取中...' : '获取违纪扣款'}
</Button>
<Button
variant="secondary"
size="sm"
onClick={() => fetchAttendanceDeductionMutation.mutate()}
disabled={fetchAttendanceDeductionMutation.isPending || isArchived}
title="按批次月份从考勤确认中获取扣款金额(需先在考勤确认中填写)"
>
<CalendarCheck className="w-4 h-4 mr-1" />
{fetchAttendanceDeductionMutation.isPending ? '获取中...' : '获取考勤扣款'}
</Button>
<Button
size="sm"
onClick={async () => {