@@ -21,13 +21,31 @@ interface DatasetFileTransferProps
2121 onSelectedFilesChange : ( filesMap : { [ key : string ] : DatasetFile } ) => void ;
2222 onDatasetSelect ?: ( dataset : Dataset | null ) => void ;
2323 datasetTypeFilter ?: DatasetType ;
24+ /**
25+ * 是否强制“单数据集模式”:
26+ * - 为 true 时,仅允许从同一个数据集选择文件;
27+ * - 当已选文件来自某个数据集时,尝试从其他数据集勾选文件会被阻止并提示。
28+ */
29+ singleDatasetOnly ?: boolean ;
30+ /**
31+ * 固定可选数据集 ID:
32+ * - 设置后,左侧数据集列表只展示该数据集;
33+ * - 主要用于“编辑任务数据集”场景,锁定为任务创建时的数据集。
34+ */
35+ fixedDatasetId ?: string | number ;
2436 /**
2537 * 锁定的文件ID集合:
2638 * - 在左侧文件列表中,这些文件的勾选框会变成灰色且不可交互;
2739 * - 点击整行也不会改变其选中状态;
2840 * - 主要用于“编辑任务数据集”场景下锁死任务初始文件。
2941 */
3042 lockedFileIds ?: string [ ] ;
43+ /**
44+ * 整体禁用开关:
45+ * - 为 true 时,禁止切换数据集和选择文件,仅用于展示当前配置;
46+ * - 可配合上层逻辑(如“需先选模板再选数据集”)使用。
47+ */
48+ disabled ?: boolean ;
3149}
3250
3351const fileCols = [
@@ -59,7 +77,10 @@ const DatasetFileTransfer: React.FC<DatasetFileTransferProps> = ({
5977 onSelectedFilesChange,
6078 onDatasetSelect,
6179 datasetTypeFilter,
80+ singleDatasetOnly,
81+ fixedDatasetId,
6282 lockedFileIds,
83+ disabled,
6384 ...props
6485} ) => {
6586 const [ datasets , setDatasets ] = React . useState < Dataset [ ] > ( [ ] ) ;
@@ -91,27 +112,57 @@ const DatasetFileTransfer: React.FC<DatasetFileTransferProps> = ({
91112 return new Set ( ( lockedFileIds || [ ] ) . map ( ( id ) => String ( id ) ) ) ;
92113 } , [ lockedFileIds ] ) ;
93114
115+ // 在单数据集模式下,根据已选文件反推“当前锁定的数据集ID”
116+ const lockedDatasetId = React . useMemo ( ( ) => {
117+ if ( ! singleDatasetOnly ) return undefined ;
118+ const ids = new Set (
119+ Object . values ( selectedFilesMap )
120+ . map ( ( file : any ) => file ?. datasetId )
121+ . filter ( ( id ) => id !== undefined && id !== null && id !== "" )
122+ . map ( ( id ) => String ( id ) )
123+ ) ;
124+ if ( ids . size === 1 ) {
125+ return Array . from ( ids ) [ 0 ] ;
126+ }
127+ return undefined ;
128+ } , [ singleDatasetOnly , selectedFilesMap ] ) ;
129+
94130 const fetchDatasets = async ( ) => {
95131 const { data } = await queryDatasetsUsingGet ( {
96132 // Ant Design Table pagination.current is 1-based; ensure backend also receives 1-based value
97133 page : datasetPagination . current ,
98134 size : datasetPagination . pageSize ,
99135 keyword : datasetSearch ,
100- // 仅在显式传入过滤类型时才按类型过滤;否则后端返回所有类型
136+ // 后端在大多数环境下支持按 type 过滤;若未生效,前端仍会基于 datasetTypeFilter 再做一次兜底筛选
101137 type : datasetTypeFilter ,
102138 } ) ;
103- setDatasets ( data . content . map ( mapDataset ) || [ ] ) ;
139+
140+ let mapped : any [ ] = ( data . content || [ ] ) . map ( mapDataset ) ;
141+
142+ // 兜底:在前端再按 datasetTypeFilter 过滤一次,确保只展示指定类型的数据集
143+ if ( datasetTypeFilter ) {
144+ mapped = mapped . filter (
145+ ( ds : any ) => ds . datasetType === datasetTypeFilter
146+ ) ;
147+ }
148+
149+ const filtered =
150+ fixedDatasetId !== undefined && fixedDatasetId !== null
151+ ? mapped . filter ( ( ds : Dataset ) => String ( ds . id ) === String ( fixedDatasetId ) )
152+ : mapped ;
153+
154+ setDatasets ( filtered ) ;
104155 setDatasetPagination ( ( prev ) => ( {
105156 ...prev ,
106- total : data . totalElements ,
157+ total : filtered . length ,
107158 } ) ) ;
108159 } ;
109160
110161 useDebouncedEffect (
111162 ( ) => {
112163 fetchDatasets ( ) ;
113164 } ,
114- [ datasetSearch , datasetPagination . pageSize , datasetPagination . current ] ,
165+ [ datasetSearch , datasetPagination . pageSize , datasetPagination . current , datasetTypeFilter ] ,
115166 300
116167 ) ;
117168
@@ -170,12 +221,40 @@ const DatasetFileTransfer: React.FC<DatasetFileTransferProps> = ({
170221 onDatasetSelect ?.( selectedDataset ) ;
171222 } , [ selectedDataset , onDatasetSelect ] ) ;
172223
224+ // 在 fixedDatasetId 场景下,数据集列表加载完成后自动选中该数据集
225+ useEffect ( ( ) => {
226+ if ( ! open ) return ;
227+ if ( fixedDatasetId === undefined || fixedDatasetId === null ) return ;
228+ if ( selectedDataset ) return ;
229+ if ( ! datasets . length ) return ;
230+
231+ const target = datasets . find ( ( ds ) => String ( ds . id ) === String ( fixedDatasetId ) ) ;
232+ if ( target ) {
233+ setSelectedDataset ( target ) ;
234+ }
235+ } , [ open , fixedDatasetId , datasets , selectedDataset ] ) ;
236+
173237 const handleSelectAllInDataset = useCallback ( async ( ) => {
174238 if ( ! selectedDataset ) {
175239 message . warning ( "请先选择一个数据集" ) ;
176240 return ;
177241 }
178242
243+ // 单数据集模式下,如果当前已选文件来自其他数据集,则阻止一键全选
244+ if ( singleDatasetOnly ) {
245+ const existingIds = new Set (
246+ Object . values ( selectedFilesMap )
247+ . map ( ( file : any ) => file ?. datasetId )
248+ . filter ( ( id ) => id !== undefined && id !== null && id !== "" )
249+ . map ( ( id ) => String ( id ) ) ,
250+ ) ;
251+ const currentId = String ( selectedDataset . id ) ;
252+ if ( existingIds . size > 0 && ( ! existingIds . has ( currentId ) || existingIds . size > 1 ) ) {
253+ message . warning ( "当前仅支持从一个数据集选择文件,请先清空已选文件后再切换数据集" ) ;
254+ return ;
255+ }
256+ }
257+
179258 try {
180259 setSelectingAll ( true ) ;
181260
@@ -246,6 +325,23 @@ const DatasetFileTransfer: React.FC<DatasetFileTransferProps> = ({
246325 if ( lockedIdSet . has ( String ( record . id ) ) ) {
247326 return ;
248327 }
328+
329+ // 单数据集模式:禁止从多个数据集混选文件
330+ if ( singleDatasetOnly && ! selectedFilesMap [ record . id ] ) {
331+ const recordDatasetId = ( record as any ) . datasetId ;
332+ const existingIds = new Set (
333+ Object . values ( selectedFilesMap )
334+ . map ( ( file : any ) => file ?. datasetId )
335+ . filter ( ( id ) => id !== undefined && id !== null && id !== "" )
336+ . map ( ( id ) => String ( id ) ) ,
337+ ) ;
338+ const recId = recordDatasetId !== undefined && recordDatasetId !== null ? String ( recordDatasetId ) : undefined ;
339+ if ( existingIds . size > 0 && recId && ! existingIds . has ( recId ) ) {
340+ message . warning ( "当前仅支持从一个数据集选择文件,请先清空已选文件后再切换数据集" ) ;
341+ return ;
342+ }
343+ }
344+
249345 if ( ! selectedFilesMap [ record . id ] ) {
250346 onSelectedFilesChange ( {
251347 ...selectedFilesMap ,
@@ -321,35 +417,60 @@ const DatasetFileTransfer: React.FC<DatasetFileTransferProps> = ({
321417 placeholder = "搜索数据集名称..."
322418 value = { datasetSearch }
323419 allowClear
324- onChange = { ( e ) => setDatasetSearch ( e . target . value ) }
420+ onChange = { ( e ) => ! disabled && setDatasetSearch ( e . target . value ) }
421+ disabled = { disabled }
325422 />
326423 </ div >
327424 < Table
328425 scroll = { { y : 400 } }
329426 rowKey = "id"
330427 size = "small"
331- rowClassName = { ( record ) =>
332- `cursor-pointer ${
333- selectedDataset ?. id === record . id ? "bg-blue-100" : ""
334- } `
335- }
428+ rowClassName = { ( record ) => {
429+ const isActive = selectedDataset ?. id === record . id ;
430+ const hasSelection = Object . keys ( selectedFilesMap ) . length > 0 ;
431+ const isLockedOtherDataset =
432+ ! ! singleDatasetOnly &&
433+ ! ! lockedDatasetId &&
434+ hasSelection &&
435+ String ( record . id ) !== lockedDatasetId ;
436+ return `cursor-pointer ${
437+ isActive ? "bg-blue-100" : ""
438+ } ${ isLockedOtherDataset ? "text-gray-400 cursor-not-allowed" : "" } `;
439+ } }
336440 onRow = { ( record : Dataset ) => ( {
337441 onClick : ( ) => {
338- setSelectedDataset ( record ) ;
339- if ( ! datasetSelections . find ( ( d ) => d . id === record . id ) ) {
340- setDatasetSelections ( [ ...datasetSelections , record ] ) ;
341- } else {
342- setDatasetSelections (
343- datasetSelections . filter ( ( d ) => d . id !== record . id )
344- ) ;
345- }
442+ if ( disabled ) return ;
443+
444+ // 单数据集模式:当已有选中文件且尝试切换到其他数据集时,直接提示并阻止切换
445+ const hasSelection =
446+ singleDatasetOnly &&
447+ Object . keys ( selectedFilesMap ) . length > 0 &&
448+ ! ! lockedDatasetId ;
449+ if (
450+ hasSelection &&
451+ String ( record . id ) !== String ( lockedDatasetId )
452+ ) {
453+ message . warning (
454+ "当前仅支持从一个数据集选择文件,请先清空已选文件后再切换数据集"
455+ ) ;
456+ return ;
457+ }
458+ setSelectedDataset ( record ) ;
459+ if ( ! datasetSelections . find ( ( d ) => d . id === record . id ) ) {
460+ setDatasetSelections ( [ ...datasetSelections , record ] ) ;
461+ } else {
462+ setDatasetSelections (
463+ datasetSelections . filter ( ( d ) => d . id !== record . id )
464+ ) ;
465+ }
346466 } ,
347467 } ) }
348468 dataSource = { datasets }
349469 columns = { datasetCols }
350470 pagination = { {
351471 ...datasetPagination ,
352472 onChange : ( page , pageSize ) =>
473+ ! disabled &&
353474 setDatasetPagination ( {
354475 current : page ,
355476 pageSize : pageSize || datasetPagination . pageSize ,
@@ -365,8 +486,8 @@ const DatasetFileTransfer: React.FC<DatasetFileTransferProps> = ({
365486 < Button
366487 type = "link"
367488 size = "small"
368- onClick = { handleSelectAllInDataset }
369- disabled = { ! selectedDataset }
489+ onClick = { ( ) => ! disabled && handleSelectAllInDataset ( ) }
490+ disabled = { ! selectedDataset || ! ! disabled }
370491 loading = { selectingAll }
371492 >
372493 全选当前数据集
@@ -388,6 +509,7 @@ const DatasetFileTransfer: React.FC<DatasetFileTransferProps> = ({
388509 pagination = { {
389510 ...filesPagination ,
390511 onChange : ( page , pageSize ) => {
512+ if ( disabled ) return ;
391513 const nextPageSize = pageSize || filesPagination . pageSize ;
392514 setFilesPagination ( ( prev ) => ( {
393515 ...prev ,
@@ -399,7 +521,10 @@ const DatasetFileTransfer: React.FC<DatasetFileTransferProps> = ({
399521 } ,
400522 } }
401523 onRow = { ( record : DatasetFile ) => ( {
402- onClick : ( ) => toggleSelectFile ( record ) ,
524+ onClick : ( ) => {
525+ if ( disabled ) return ;
526+ toggleSelectFile ( record ) ;
527+ } ,
403528 } ) }
404529 rowSelection = { {
405530 type : "checkbox" ,
@@ -408,11 +533,13 @@ const DatasetFileTransfer: React.FC<DatasetFileTransferProps> = ({
408533
409534 // 单选
410535 onSelect : ( record : DatasetFile ) => {
536+ if ( disabled ) return ;
411537 toggleSelectFile ( record ) ;
412538 } ,
413539
414540 // 全选 - 改为全选整个数据集而不是当前页
415541 onSelectAll : ( selected , selectedRows : DatasetFile [ ] ) => {
542+ if ( disabled ) return ;
416543 if ( selected ) {
417544 // 点击表头“全选”时,改为一键全选当前数据集的全部文件
418545 // 而不是只选中当前页
@@ -437,7 +564,7 @@ const DatasetFileTransfer: React.FC<DatasetFileTransferProps> = ({
437564
438565 getCheckboxProps : ( record : DatasetFile ) => ( {
439566 name : record . fileName ,
440- disabled : lockedIdSet . has ( String ( record . id ) ) ,
567+ disabled : ! ! disabled || lockedIdSet . has ( String ( record . id ) ) ,
441568 } ) ,
442569 } }
443570 />
0 commit comments