/** * 按业务域分组的 DWD 表选择器。 * * 从 /api/tasks/dwd-tables 获取 DWD 表定义,按业务域折叠展示, * 支持全选/反选。仅在 Flow 包含 DWD 层时由父组件渲染。 */ import React, { useEffect, useState, useMemo, useCallback } from "react"; import { Collapse, Checkbox, Spin, Alert, Button, Space, Typography, } from "antd"; import type { CheckboxChangeEvent } from "antd/es/checkbox"; import { fetchDwdTables } from "../api/tasks"; const { Text } = Typography; /* ------------------------------------------------------------------ */ /* Props */ /* ------------------------------------------------------------------ */ export interface DwdTableSelectorProps { /** 已选中的 DWD 表名列表 */ selectedTables: string[]; /** 选中表变化回调 */ onTablesChange: (tables: string[]) => void; } /* ------------------------------------------------------------------ */ /* 组件 */ /* ------------------------------------------------------------------ */ const DwdTableSelector: React.FC = ({ selectedTables, onTablesChange, }) => { /** 按业务域分组的 DWD 表 */ const [tableGroups, setTableGroups] = useState>({}); const [loading, setLoading] = useState(false); const [error, setError] = useState(null); /* ---------- 加载 DWD 表定义 ---------- */ useEffect(() => { let cancelled = false; setLoading(true); setError(null); fetchDwdTables() .then((data) => { if (!cancelled) setTableGroups(data); }) .catch((err) => { if (!cancelled) setError(err?.message ?? "获取 DWD 表列表失败"); }) .finally(() => { if (!cancelled) setLoading(false); }); return () => { cancelled = true; }; }, []); /** 所有表名的扁平列表 */ const allTableNames = useMemo( () => Object.values(tableGroups).flat(), [tableGroups], ); /* ---------- 事件处理 ---------- */ /** 单个业务域的勾选变化 */ const handleDomainChange = useCallback( (domain: string, checkedTables: string[]) => { const domainTables = new Set(tableGroups[domain] ?? []); const otherSelected = selectedTables.filter((t) => !domainTables.has(t)); onTablesChange([...otherSelected, ...checkedTables]); }, [selectedTables, tableGroups, onTablesChange], ); /** 全选 */ const handleSelectAll = useCallback(() => { onTablesChange(allTableNames); }, [allTableNames, onTablesChange]); /** 反选 */ const handleInvertSelection = useCallback(() => { const currentSet = new Set(selectedTables); const inverted = allTableNames.filter((t) => !currentSet.has(t)); onTablesChange(inverted); }, [allTableNames, selectedTables, onTablesChange]); /* ---------- 渲染 ---------- */ if (loading) { return ; } if (error) { return ; } const domainEntries = Object.entries(tableGroups); if (domainEntries.length === 0) { return 无可选 DWD 表; } const selectedCount = selectedTables.filter((t) => allTableNames.includes(t), ).length; return (
{/* 全选 / 反选 */} 已选 {selectedCount} / {allTableNames.length} d)} items={domainEntries.map(([domain, tables]) => { const domainSelected = selectedTables.filter((t) => tables.includes(t), ); const allChecked = domainSelected.length === tables.length; const indeterminate = domainSelected.length > 0 && !allChecked; const handleDomainCheckAll = (e: CheckboxChangeEvent) => { handleDomainChange(domain, e.target.checked ? tables : []); }; return { key: domain, label: ( e.stopPropagation()}> {domain} ({domainSelected.length}/{tables.length}) ), children: ( handleDomainChange(domain, checked as string[]) } > {tables.map((table) => ( {table} ))} ), }; })} />
); }; export default DwdTableSelector;