import { useState } from 'react' import { AnimatePresence, motion } from 'framer-motion' import { Activity, Settings } from 'lucide-react' import { Skeleton } from './Skeleton' export function QuoteConfigCard({ enabled, running, isTrading, lastFetchMs, intervalS, intervalMin, intervalMax, loading, onToggle, toggling, showIntervalEdit, onShowIntervalEdit, onIntervalChange }: { enabled: boolean running: boolean isTrading: boolean lastFetchMs: number | null intervalS: number intervalMin: number intervalMax: number loading: boolean onToggle: (enabled: boolean) => void toggling: boolean showIntervalEdit: boolean onShowIntervalEdit: () => void onIntervalChange: (v: number) => void }) { const statusColor = running && isTrading ? 'bg-accent shadow-[0_0_6px_rgba(61,214,140,0.5)]' : enabled && running ? 'bg-warning/60' : 'bg-muted' const statusText = !enabled ? '已关闭' : !isTrading ? '非交易时段' : running ? '行情运行中' : '已停止' const lastFetchTime = lastFetchMs ? new Date(lastFetchMs).toLocaleString('zh-CN', { month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit', second: '2-digit' }) : null return (

实时行情

{loading ? (
) : (
状态
{statusText}
交易时段 {isTrading ? '交易中' : '休市'}
轮询间隔
{intervalS}s
最后获取 {lastFetchTime ?? '—'}
)} {showIntervalEdit && ( )}
) } function IntervalEditor({ min, max, value, onChange }: { min: number; max: number; value: number; onChange: (v: number) => void }) { const [draft, setDraft] = useState(value) const clamped = Math.max(min, Math.min(max, draft)) const step = min < 1 ? 0.1 : min < 3 ? 0.5 : 1 const presets = min <= 3 ? [3, 5, 10, 30, 60] : [5, 10, 15, 30, 60] return (
轮询间隔 ({min}s ~ {max}s)
{presets.map(p => ( ))}
{ const v = parseFloat(e.target.value); setDraft(v); onChange(v) }} className="flex-1 h-1 accent-accent cursor-pointer" /> {clamped < 1 ? clamped.toFixed(1) : clamped.toFixed(0)}s
) }