// dashboard/src/components/sync/MetadataSyncCard.tsx import { SlidersHorizontal, RefreshCw, Loader, Play, Info, CheckCircle, Lightbulb } from 'lucide-react'; import { CustomSelect } from '../CustomSelect'; import type { HarvestStatus } from '../../hooks/useSyncState'; interface MetadataSyncCardProps { query: string; setQuery: (q: string) => void; source: 'all' | 'ads' | 'arxiv'; setSource: (s: 'all' | 'ads' | 'arxiv') => void; limit: number; setLimit: (l: number) => void; estimating: boolean; estimatedCount: number | null; status: HarvestStatus; showBuilder: boolean; setShowBuilder: (show: boolean) => void; rules: Array<{ field: string; op: string; val: string }>; handleAddRule: () => void; handleRemoveRule: (idx: number) => void; handleRuleChange: (idx: number, key: 'field' | 'op' | 'val', value: string) => void; handleEstimate: () => Promise; handleStartHarvest: () => Promise; } export function MetadataSyncCard({ query, setQuery, source, setSource, limit, setLimit, estimating, estimatedCount, status, showBuilder, setShowBuilder, rules, handleAddRule, handleRemoveRule, handleRuleChange, handleEstimate, handleStartHarvest, }: MetadataSyncCardProps) { const percent = status.total > 0 ? Math.min(100, Math.round((status.synced / status.total) * 100)) : 0; return (
{/* 控制面板卡片 */}
setQuery(e.target.value)} disabled={status.active} placeholder="例如: hot subdwarf, Gaia BH1..." className="w-full px-4 py-2 rounded-md bg-slate-50 border border-slate-300 text-slate-900 placeholder-slate-400 focus:outline-none focus:border-blueprint focus:bg-white transition-all text-xs font-medium" />
高级格式: author:"Althaus" AND year:2020-2023
{[ { id: 'all', label: '全部' }, { id: 'ads', label: 'NASA ADS' }, { id: 'arxiv', label: 'arXiv 预印本' }, ].map(src => ( ))}
{/* 动态表单生成器 */} {showBuilder && (
高级条件生成器
{rules.map((rule, idx) => (
{idx > 0 ? ( handleRuleChange(idx, 'op', val)} className="w-24" options={[ { value: 'AND', label: '并且 (AND)' }, { value: 'OR', label: '或者 (OR)' }, { value: 'NOT', label: '排除 (NOT)' }, ]} /> ) : (
筛选条件
)} handleRuleChange(idx, 'field', val)} className="w-32" options={[ { value: 'all', label: '任意字段' }, { value: 'title', label: '标题' }, { value: 'author', label: '作者' }, { value: 'abs', label: '摘要' }, { value: 'year', label: '年份' }, ]} /> handleRuleChange(idx, 'val', e.target.value)} placeholder={ rule.field === 'year' ? '例如: 2020-2023 或 2022' : rule.field === 'author' ? '例如: Althaus' : '请输入检索词...' } className="flex-1 px-3 py-1.5 rounded-md bg-white border border-slate-300 text-slate-900 placeholder-slate-450 focus:outline-none focus:border-blueprint text-xs font-medium" /> {rules.length > 1 && ( )}
))}
)}
setLimit(Math.max(1, parseInt(e.target.value) || 0))} className="w-full px-4 py-2 rounded-md bg-slate-50 border border-slate-300 text-slate-900 focus:outline-none focus:border-blueprint transition-all text-xs font-medium" />
{/* 预估结果 */} {estimatedCount !== null && !status.active && (
检索库中估计有约 {estimatedCount} 篇文献记录。 {estimatedCount > limit ? ` 限制最大同步前 ${limit} 篇元数据。` : ' 将全部进行同步。'}
)}
{/* 实时同步进度 */} {(status.active || status.synced > 0) && (

{status.active ? ( <> 正在同步学术元数据... ) : ( <> 元数据目录同步完成 )}

检索条件: {status.query} • 平台: {status.source === 'all' ? '全部' : status.source === 'ads' ? 'NASA ADS' : 'arXiv'}

{status.synced} / {status.total} 篇
{status.active && (status.source === 'all' || status.source === 'arxiv') ? (
同步 arXiv 文献时系统会自动加设 3000 毫秒的安全限流延迟以规避服务器封锁。
) : null}
)}
); }