Fix: dataset tag file setting cannot be saved (#17428)

This commit is contained in:
euvre
2026-08-05 15:55:34 +08:00
committed by GitHub
parent a55a438b42
commit 0a444343b9
48 changed files with 266 additions and 171 deletions

View File

@@ -81,7 +81,7 @@ const ExtractorForm = ({
const ownerTenantId = useOwnerTenantId();
const { treeData, loadData } = useTagFileTree();
const { treeData, loadData } = useTagFileTree(form.watch('tag_file_id'));
return (
<Form {...form}>

View File

@@ -2,9 +2,10 @@ import { TreeNodeType } from '@/components/ui/async-tree-select';
import { useFetchPureFileList } from '@/hooks/use-file-request';
import { IFile } from '@/interfaces/database/file-manager';
import { isFolderType } from '@/pages/files/util';
import fileManagerService from '@/services/file-manager-service';
import { getExtension } from '@/utils/document-util';
import { uniqBy } from 'lodash';
import { useCallback, useState } from 'react';
import { useCallback, useEffect, useRef, useState } from 'react';
const AllowedExtensions = ['xlsx', 'xls', 'csv', 'txt'];
@@ -12,41 +13,77 @@ export function canSelectTagFile(node: TreeNodeType) {
return Boolean(node.isLeaf);
}
export function useTagFileTree() {
function toTreeNode(x: IFile): TreeNodeType {
return {
id: x.id,
parentId: x.parent_id,
title: x.name,
// has_child_folder only counts child folders, so folders
// must always be expandable to reach files inside them
isLeaf: !isFolderType(x.type),
};
}
export function useTagFileTree(value?: string) {
const { fetchList } = useFetchPureFileList();
const [treeData, setTreeData] = useState<TreeNodeType[]>([]);
const appendFiles = useCallback((files: IFile[]) => {
setTreeData((tree) =>
uniqBy(
tree.concat(
files
.filter(
(x) =>
(isFolderType(x.type) && x.name.toLowerCase() !== 'skills') ||
AllowedExtensions.includes(getExtension(x.name)),
)
.map(toTreeNode),
),
'id',
),
);
}, []);
const loadData = useCallback(
async ({ id }: TreeNodeType) => {
const ret = await fetchList(id as string);
if (ret.code === 0) {
setTreeData((tree) =>
uniqBy(
tree.concat(
ret.data.files
.filter(
(x: IFile) =>
(isFolderType(x.type) &&
x.name.toLowerCase() !== 'skills') ||
AllowedExtensions.includes(getExtension(x.name)),
)
.map((x: IFile) => ({
id: x.id,
parentId: x.parent_id,
title: x.name,
// has_child_folder only counts child folders, so folders
// must always be expandable to reach files inside them
isLeaf: !isFolderType(x.type),
})),
),
'id',
),
);
appendFiles(ret.data.files);
}
},
[fetchList],
[fetchList, appendFiles],
);
// Resolve a previously saved selection: the tree is lazy-loaded, so a file
// nested in subfolders is not in treeData on mount and its title cannot be
// displayed. Walk the ancestor chain top-down and load each level.
const resolvedValueRef = useRef<string>('');
useEffect(() => {
if (
!value ||
resolvedValueRef.current === value ||
treeData.some((x) => x.id === value)
) {
return;
}
resolvedValueRef.current = value;
(async () => {
const { data } = await fileManagerService.getAllParentFolder(
{},
`${value}/ancestors`,
);
const folders: IFile[] = data?.data?.parent_folders?.toReversed() ?? [];
setTreeData((tree) => uniqBy(tree.concat(folders.map(toTreeNode)), 'id'));
for (const folder of folders) {
const ret = await fetchList(folder.id);
if (ret.code === 0) {
appendFiles(ret.data.files);
}
}
})();
}, [value, treeData, fetchList, appendFiles]);
return { treeData, loadData };
}

View File

@@ -10,10 +10,7 @@ import {
TooltipTrigger,
} from '@/components/ui/tooltip';
import { GenerateStatus, GenerateType } from '@/constants/knowledge';
import {
ITraceInfo,
useGenerateStatus,
} from '@/hooks/use-dataset-generate';
import { ITraceInfo, useGenerateStatus } from '@/hooks/use-dataset-generate';
import { UpdateRunProgress } from './update-run-progress';

View File

@@ -10,7 +10,8 @@ type UseWikiUpdateOptions = {
export function useWikiUpdate({ onUpdate }: UseWikiUpdateOptions = {}) {
const { data, loading: queryLoading } = useFetchArtifactAlteration('wiki');
const { runArtifactIndex, loading: mutationLoading } = useRunArtifactIndex('wiki');
const { runArtifactIndex, loading: mutationLoading } =
useRunArtifactIndex('wiki');
const newlyUploaded = data?.newly_uploaded ?? 0;
const removed = data?.removed ?? 0;

View File

@@ -2,10 +2,7 @@ import { ConfirmDeleteDialog } from '@/components/confirm-delete-dialog';
import { Button } from '@/components/ui/button';
import { Tabs, TabsList, TabsTrigger } from '@/components/ui/tabs';
import { GenerateStatus, GenerateType } from '@/constants/knowledge';
import {
ITraceInfo,
useGenerateStatus,
} from '@/hooks/use-dataset-generate';
import { ITraceInfo, useGenerateStatus } from '@/hooks/use-dataset-generate';
import { IArtifact } from '@/interfaces/database/dataset';
import { Trash2 } from 'lucide-react';
import { useCallback } from 'react';

View File

@@ -138,7 +138,13 @@ const ChatCard = forwardRef(function ChatCard(
// resend with the card's model settings (llm_id, temperature, ...).
const sendCardMessage = useCallback(
({ message, messages }: { message: IMessage; messages?: IMessage[] }) =>
sendMessage({ message, messages, ...form.getValues(), storeHistoryMessages: false, omitSessionId: true }),
sendMessage({
message,
messages,
...form.getValues(),
storeHistoryMessages: false,
omitSessionId: true,
}),
[sendMessage, form],
);
@@ -181,7 +187,12 @@ const ChatCard = forwardRef(function ChatCard(
useImperativeHandle(
ref,
(): HandlePressEnterType => (params) =>
handlePressEnter({ ...params, ...form.getValues(), storeHistoryMessages: false, omitSessionId: true }),
handlePressEnter({
...params,
...form.getValues(),
storeHistoryMessages: false,
omitSessionId: true,
}),
);
useEffect(() => {