import React, { useMemo, useState } from "react"; import { Badge, Card, Input, Progress, Button, DatePicker, Select } from "antd"; import { BarChart3, Filter, Clock } from "lucide-react"; import type { Dataset } from "@/pages/DataManagement/dataset.model.ts"; import dayjs from 'dayjs'; const { RangePicker } = DatePicker; const { Option } = Select; const TIME_RANGE_OPTIONS = [ { label: '最近1天', value: 1 }, { label: '最近3天', value: 3 }, { label: '最近7天', value: 7 }, { label: '最近15天', value: 15 }, { label: '最近30天', value: 30 }, ]; interface RatioConfigItem { id: string; name: string; type: "dataset" | "label"; quantity: number; percentage: number; source: string; labelFilter?: string; dateRange?: string; } interface RatioConfigProps { ratioType: "dataset" | "label"; selectedDatasets: string[]; datasets: Dataset[]; totalTargetCount: number; distributions: Record>; onChange?: (configs: RatioConfigItem[]) => void; } const RatioConfig: React.FC = ({ ratioType, selectedDatasets, datasets, totalTargetCount, distributions, onChange, }) => { const [ratioConfigs, setRatioConfigs] = useState([]); const [datasetFilters, setDatasetFilters] = useState>({}); // 配比项总数 const totalConfigured = useMemo( () => ratioConfigs.reduce((sum, c) => sum + (c.quantity || 0), 0), [ratioConfigs] ); // 获取数据集的标签列表 const getDatasetLabels = (datasetId: string): string[] => { const dist = distributions[String(datasetId)] || {}; return Object.keys(dist); }; // 自动平均分配 const generateAutoRatio = () => { const selectedCount = selectedDatasets.length; if (selectedCount === 0) return; const baseQuantity = Math.floor(totalTargetCount / selectedCount); const remainder = totalTargetCount % selectedCount; const newConfigs = selectedDatasets.map((datasetId, index) => { const dataset = datasets.find((d) => String(d.id) === datasetId); const quantity = baseQuantity + (index < remainder ? 1 : 0); return { id: datasetId, name: dataset?.name || datasetId, type: ratioType, quantity, percentage: Math.round((quantity / totalTargetCount) * 100), source: datasetId, labelFilter: datasetFilters[datasetId]?.labelFilter, dateRange: datasetFilters[datasetId]?.dateRange, }; }); setRatioConfigs(newConfigs); onChange?.(newConfigs); }; // 更新数据集配比项 const updateDatasetQuantity = (datasetId: string, quantity: number) => { setRatioConfigs((prev) => { const existingIndex = prev.findIndex( (config) => config.source === datasetId ); const totalOtherQuantity = prev .filter((config) => config.source !== datasetId) .reduce((sum, config) => sum + config.quantity, 0); const dataset = datasets.find((d) => String(d.id) === datasetId); const newConfig: RatioConfigItem = { id: datasetId, name: dataset?.name || datasetId, type: ratioType, quantity: Math.min(quantity, totalTargetCount - totalOtherQuantity), percentage: Math.round((quantity / totalTargetCount) * 100), source: datasetId, labelFilter: datasetFilters[datasetId]?.labelFilter, dateRange: datasetFilters[datasetId]?.dateRange, }; let newConfigs; if (existingIndex >= 0) { newConfigs = [...prev]; newConfigs[existingIndex] = newConfig; } else { newConfigs = [...prev, newConfig]; } onChange?.(newConfigs); return newConfigs; }); }; // 更新筛选条件 const updateFilters = (datasetId: string, updates: { labelFilter?: string; dateRange?: [string, string]; }) => { setDatasetFilters(prev => ({ ...prev, [datasetId]: { ...prev[datasetId], ...updates, } })); }; // 渲染筛选器 const renderFilters = (datasetId: string) => { const labels = getDatasetLabels(datasetId); const config = ratioConfigs.find(c => c.source === datasetId); const filters = datasetFilters[datasetId] || {}; return (
筛选条件
标签筛选
标签更新时间
); }; // 选中数据集变化时,初始化筛选条件 React.useEffect(() => { const initialFilters: Record = {}; selectedDatasets.forEach(datasetId => { const config = ratioConfigs.find(c => c.source === datasetId); if (config) { initialFilters[datasetId] = { labelFilter: config.labelFilter, dateRange: config.dateRange, }; } }); setDatasetFilters(prev => ({ ...prev, ...initialFilters })); }, [selectedDatasets]); return (
配比配置 (已配置:{totalConfigured}/{totalTargetCount}条)
{selectedDatasets.length === 0 ? (

请先选择数据集

) : (
{/* 配比预览 */} {ratioConfigs.length > 0 && (
总配比数量: {ratioConfigs .reduce((sum, config) => sum + config.quantity, 0) .toLocaleString()}
目标数量: {totalTargetCount.toLocaleString()}
)}
{selectedDatasets.map((datasetId) => { const dataset = datasets.find((d) => String(d.id) === datasetId); const config = ratioConfigs.find((c) => c.source === datasetId); const currentQuantity = config?.quantity || 0; if (!dataset) return null; return (
{dataset.name} {dataset.fileCount}条
{config?.percentage || 0}%
{/* 筛选条件 */} {renderFilters(datasetId)}
数量: updateDatasetQuantity( datasetId, Number(e.target.value) ) } style={{ width: 100 }} min={0} max={Math.min( dataset.fileCount || 0, totalTargetCount )} />
); })}
)}
); }; export default RatioConfig;