import { useState } from 'react' import { useMutation, useQueryClient } from '@tanstack/react-query' import { Loader2 } from 'lucide-react' import { api } from '@/lib/api' import { QK } from '@/lib/queryKeys' import { MissingCapChip } from '@/lib/capability-labels' import { DatePicker } from '@/components/DatePicker' function pad(n: number) { return String(n).padStart(2, '0') } function todayStr() { const d = new Date() return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}` } /** 往前推 N 天 */ function daysAgo(n: number): string { const d = new Date() d.setDate(d.getDate() - n) return `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}` } export function RepairDailyPanel({ caps, isRunning, latestDate, onStart }: { caps: { label: string; capabilities: Record } | undefined isRunning: boolean latestDate: string | null onStart: () => void }) { const qc = useQueryClient() const hasBatchCap = !!caps?.capabilities?.['kline.daily.batch'] // 默认起始日期: 最新数据往前推 30 天 (兼顾补缺口 + 复核近期数据, 成本不高) const [startDate, setStartDate] = useState(daysAgo(30)) const repair = useMutation({ mutationFn: () => api.repairDaily(startDate), onSuccess: () => { onStart() qc.invalidateQueries({ queryKey: QK.pipelineJobs }) }, }) const today = todayStr() const canSubmit = hasBatchCap && !isRunning && !repair.isPending && startDate <= today const gapDays = latestDate ? Math.max(0, Math.round((Date.parse(today) - Date.parse(latestDate)) / 86400000)) : null return (
当数据出现缺口时(漏跑、停服),从这里重拉选定区间到今天的全部数据并重算。
完整复用盘后管道流程 (A股日K · 除权因子 · 指标重算 · 指数),新数据按 (个股, 日期) 覆盖旧值,不会重复,也无需先清除。
{/* 起始日期 — 用户主要操作,放上面 */}
起始日期
{/* 本地最新数据 — 参考信息,放下面 */}
本地最新数据 {latestDate ?? '—'} {gapDays !== null && gapDays > 0 && ( 已落后 {gapDays} 天 )}
将重拉 {startDate} {' → '}{today}(今天) 的 A股日K · 除权 · 指数并重算指标
{!hasBatchCap && ( )}
) }