/** * 数据任务超时配置卡片 — 从 DataSources 抽出, 放在系统设置页。 */ import { useState } from 'react' import { useMutation, useQueryClient } from '@tanstack/react-query' import { Clock3 } from 'lucide-react' import { api, type Preferences } from '@/lib/api' import { QK } from '@/lib/queryKeys' import { usePreferences } from '@/lib/useSharedQueries' import { toast } from '@/components/Toast' type TimeoutUnit = 'second' | 'minute' | 'hour' const TIMEOUT_UNIT_SECONDS: Record = { second: 1, minute: 60, hour: 3600, } function preferredTimeoutUnit(seconds: number): TimeoutUnit { if (seconds >= 3600 && seconds % 1800 === 0) return 'hour' if (seconds % 60 === 0) return 'minute' return 'second' } function formatTimeoutValue(seconds: number, unit: TimeoutUnit): string { if (!Number.isFinite(seconds)) return '' const value = seconds / TIMEOUT_UNIT_SECONDS[unit] return String(Number(value.toFixed(4))) } export function JobTimeoutCard() { const qc = useQueryClient() const prefs = usePreferences() const [timeoutDraft, setTimeoutDraft] = useState<{ regular: string; long: string } | null>(null) const [regularUnitOverride, setRegularUnitOverride] = useState(null) const [longUnitOverride, setLongUnitOverride] = useState(null) const currentRegularTimeout = prefs.data?.data_source_job_timeout_s ?? 1200 const currentLongTimeout = prefs.data?.data_source_long_job_timeout_s ?? 1800 const regularTimeoutUnit = regularUnitOverride ?? preferredTimeoutUnit(currentRegularTimeout) const longTimeoutUnit = longUnitOverride ?? preferredTimeoutUnit(currentLongTimeout) const regularTimeoutInput = timeoutDraft?.regular ?? formatTimeoutValue(currentRegularTimeout, regularTimeoutUnit) const longTimeoutInput = timeoutDraft?.long ?? formatTimeoutValue(currentLongTimeout, longTimeoutUnit) const regularInputNumber = Number(regularTimeoutInput) const longInputNumber = Number(longTimeoutInput) const regularTimeout = Math.round(regularInputNumber * TIMEOUT_UNIT_SECONDS[regularTimeoutUnit]) const longTimeout = Math.round(longInputNumber * TIMEOUT_UNIT_SECONDS[longTimeoutUnit]) const timeoutValuesValid = Number.isFinite(regularInputNumber) && regularInputNumber > 0 && Number.isFinite(longInputNumber) && longInputNumber > 0 && regularTimeout >= 60 && longTimeout >= 60 const timeoutValuesChanged = regularTimeout !== currentRegularTimeout || longTimeout !== currentLongTimeout const saveJobTimeouts = useMutation({ mutationFn: () => api.updateDataSourceJobTimeouts(regularTimeout, longTimeout), onSuccess: (saved) => { qc.setQueryData(QK.preferences, current => ( current ? { ...current, ...saved } : current )) setTimeoutDraft(null) toast('任务超时配置已保存', 'success') }, onError: (e: Error) => toast(`保存失败: ${e.message}`, 'error'), }) return (

超时设置

后台任务运行超过对应时间后将判定为疑似卡死。保存时自动换算为秒,修改后对新建任务生效。

) }