import { Settings2, TrendingDown, RadioTower } from 'lucide-react' import { motion } from 'framer-motion' import { storage } from '@/lib/storage' // ===== 卡片尺寸 ===== export type CardSize = 'mini' | 'normal' | 'large' | 'hidden' export function loadCardSize(): CardSize { const v = storage.screenerCardSize.get('normal') if (v === 'mini' || v === 'normal' || v === 'large' || v === 'hidden') return v return 'normal' } const CARD_STYLES: Record = { mini: { wrap: 'gap-1', card: 'inline-flex items-center gap-1 px-2 py-0.5 rounded-full', name: 'text-[10px]', count: 'text-[11px]', desc: '', icon: 'h-3 w-3', }, normal: { wrap: 'gap-2', card: 'relative inline-flex items-center gap-2 pl-3 pr-12 py-1.5 rounded-lg', name: 'text-xs', count: 'text-xs', desc: 'text-[10px] text-muted leading-tight mt-0.5 line-clamp-1 max-w-[120px]', icon: 'h-3.5 w-3.5', }, large: { wrap: 'gap-2', card: 'relative inline-flex flex-col items-start pl-3.5 pr-12 py-2.5 rounded-btn min-w-[100px]', name: 'text-xs', count: 'text-lg font-mono font-bold tabular-nums', desc: 'text-[10px] text-muted leading-tight mt-0.5 line-clamp-2 max-w-[140px]', icon: 'h-3.5 w-3.5', }, hidden: { wrap: '', card: '', name: '', count: '', desc: '', icon: '', }, } export { CARD_STYLES } /** 获取卡片容器的 flex-wrap gap 样式 */ export function cardWrapCls(size: CardSize): string { return `flex flex-wrap ${CARD_STYLES[size].wrap}` } // ===== 来源标签 ===== const SRC_MAP: Record = { builtin: '内置', custom: '自定义', ai: 'AI' } const BADGE_CLS_MAP: Record = { builtin: 'bg-secondary/10 text-muted border-border', ai: 'bg-purple-500/10 text-purple-400 border-purple-500/30', custom: 'bg-amber-400/10 text-amber-400 border-amber-400/30', } // ===== 策略卡片 ===== interface StrategyCardProps { name: string description?: string source?: string active: boolean count?: number /** 今日曾命中总数 */ everMatched?: number /** 今日已失效数 (曾命中 - 当前命中) */ expiredCount?: number loading: boolean cardSize: CardSize onRun: () => void disabled: boolean onSettings: () => void /** 是否已加入策略监控 */ monitored?: boolean /** 切换策略监控 (点击 RadioTower 图标) */ onToggleMonitor?: () => void } export function StrategyCard({ name, description, source, active, count, expiredCount, loading, cardSize, onRun, disabled, onSettings, monitored, onToggleMonitor, }: StrategyCardProps) { const cs = CARD_STYLES[cardSize] const activeCls = active ? 'border-accent/50 bg-accent/10 shadow-[0_0_10px_rgba(59,130,246,0.1)]' : 'border-border bg-surface hover:border-accent/40 hover:bg-accent/[0.03]' const countCls = count === 0 ? 'text-muted' : 'bg-gradient-to-r from-amber-400 to-orange-500 bg-clip-text text-transparent' const srcLabel = cardSize === 'mini' ? (SRC_MAP[source ?? ''] ?? '内') : (SRC_MAP[source ?? ''] ?? '内置') const badgeCls = BADGE_CLS_MAP[source ?? 'builtin'] ?? BADGE_CLS_MAP.builtin // 失效数 > 0 时显示 const hasExpired = expiredCount != null && expiredCount > 0 return ( {cardSize === 'large' ? ( <> {onToggleMonitor && ( )} ) : cardSize === 'normal' ? ( <> {onToggleMonitor && ( )} ) : ( /* mini */ <> {onToggleMonitor && ( )} )} ) }